diff --git a/src/mesa/drivers/dri/i965/brw_sampler_state.c b/src/mesa/drivers/dri/i965/brw_sampler_state.c index 26bf0cb3e2d..6ae7d0b3aea 100644 --- a/src/mesa/drivers/dri/i965/brw_sampler_state.c +++ b/src/mesa/drivers/dri/i965/brw_sampler_state.c @@ -624,24 +624,6 @@ brw_upload_sampler_state_table(struct brw_context *brw, } } -static void -brw_upload_fs_samplers(struct brw_context *brw) -{ - /* BRW_NEW_FRAGMENT_PROGRAM */ - struct gl_program *fs = (struct gl_program *) brw->fragment_program; - brw_upload_sampler_state_table(brw, fs, &brw->wm.base); -} - -const struct brw_tracked_state brw_fs_samplers = { - .dirty = { - .mesa = _NEW_TEXTURE, - .brw = BRW_NEW_BATCH | - BRW_NEW_BLORP | - BRW_NEW_FRAGMENT_PROGRAM, - }, - .emit = brw_upload_fs_samplers, -}; - static void brw_upload_vs_samplers(struct brw_context *brw) { diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index 5f5ba647f75..3520bbe4100 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -53,7 +53,6 @@ extern const struct brw_tracked_state brw_cs_pull_constants; extern const struct brw_tracked_state brw_constant_buffer; extern const struct brw_tracked_state brw_curbe_offsets; extern const struct brw_tracked_state brw_invariant_state; -extern const struct brw_tracked_state brw_fs_samplers; extern const struct brw_tracked_state brw_gs_unit; extern const struct brw_tracked_state brw_binding_table_pointers; extern const struct brw_tracked_state brw_depthbuffer; diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c index 16b7b25e8ba..3bc0f4cf5f1 100644 --- a/src/mesa/drivers/dri/i965/genX_state_upload.c +++ b/src/mesa/drivers/dri/i965/genX_state_upload.c @@ -51,11 +51,13 @@ #include "main/fbobject.h" #include "main/framebuffer.h" #include "main/glformats.h" +#include "main/samplerobj.h" #include "main/shaderapi.h" #include "main/stencil.h" #include "main/transformfeedback.h" #include "main/varray.h" #include "main/viewport.h" +#include "util/half_float.h" UNUSED static void * emit_dwords(struct brw_context *brw, unsigned n) @@ -4218,6 +4220,540 @@ genX(emit_mi_report_perf_count)(struct brw_context *brw, /* ---------------------------------------------------------------------- */ +/** + * Emit a 3DSTATE_SAMPLER_STATE_POINTERS_{VS,HS,GS,DS,PS} packet. + */ +static void +genX(emit_sampler_state_pointers_xs)(struct brw_context *brw, + struct brw_stage_state *stage_state) +{ +#if GEN_GEN >= 7 + static const uint16_t packet_headers[] = { + [MESA_SHADER_VERTEX] = 43, + [MESA_SHADER_TESS_CTRL] = 44, + [MESA_SHADER_TESS_EVAL] = 45, + [MESA_SHADER_GEOMETRY] = 46, + [MESA_SHADER_FRAGMENT] = 47, + }; + + /* Ivybridge requires a workaround flush before VS packets. */ + if (GEN_GEN == 7 && !GEN_IS_HASWELL && + stage_state->stage == MESA_SHADER_VERTEX) { + gen7_emit_vs_workaround_flush(brw); + } + + brw_batch_emit(brw, GENX(3DSTATE_SAMPLER_STATE_POINTERS_VS), ptr) { + ptr._3DCommandSubOpcode = packet_headers[stage_state->stage]; + ptr.PointertoVSSamplerState = stage_state->sampler_offset; + } +#endif +} + +static bool +has_component(mesa_format format, int i) +{ + if (_mesa_is_format_color_format(format)) + return _mesa_format_has_color_component(format, i); + + /* depth and stencil have only one component */ + return i == 0; +} + +/** + * Upload SAMPLER_BORDER_COLOR_STATE. + */ +static void +upload_default_color(struct brw_context *brw, + const struct gl_sampler_object *sampler, + mesa_format format, GLenum base_format, + bool is_integer_format, bool is_stencil_sampling, + uint32_t *sdc_offset) +{ + union gl_color_union color; + + switch (base_format) { + case GL_DEPTH_COMPONENT: + /* GL specs that border color for depth textures is taken from the + * R channel, while the hardware uses A. Spam R into all the + * channels for safety. + */ + color.ui[0] = sampler->BorderColor.ui[0]; + color.ui[1] = sampler->BorderColor.ui[0]; + color.ui[2] = sampler->BorderColor.ui[0]; + color.ui[3] = sampler->BorderColor.ui[0]; + break; + case GL_ALPHA: + color.ui[0] = 0u; + color.ui[1] = 0u; + color.ui[2] = 0u; + color.ui[3] = sampler->BorderColor.ui[3]; + break; + case GL_INTENSITY: + color.ui[0] = sampler->BorderColor.ui[0]; + color.ui[1] = sampler->BorderColor.ui[0]; + color.ui[2] = sampler->BorderColor.ui[0]; + color.ui[3] = sampler->BorderColor.ui[0]; + break; + case GL_LUMINANCE: + color.ui[0] = sampler->BorderColor.ui[0]; + color.ui[1] = sampler->BorderColor.ui[0]; + color.ui[2] = sampler->BorderColor.ui[0]; + color.ui[3] = float_as_int(1.0); + break; + case GL_LUMINANCE_ALPHA: + color.ui[0] = sampler->BorderColor.ui[0]; + color.ui[1] = sampler->BorderColor.ui[0]; + color.ui[2] = sampler->BorderColor.ui[0]; + color.ui[3] = sampler->BorderColor.ui[3]; + break; + default: + color.ui[0] = sampler->BorderColor.ui[0]; + color.ui[1] = sampler->BorderColor.ui[1]; + color.ui[2] = sampler->BorderColor.ui[2]; + color.ui[3] = sampler->BorderColor.ui[3]; + break; + } + + /* In some cases we use an RGBA surface format for GL RGB textures, + * where we've initialized the A channel to 1.0. We also have to set + * the border color alpha to 1.0 in that case. + */ + if (base_format == GL_RGB) + color.ui[3] = float_as_int(1.0); + + if (brw->gen >= 8) { + /* On Broadwell, the border color is represented as four 32-bit floats, + * integers, or unsigned values, interpreted according to the surface + * format. This matches the sampler->BorderColor union exactly; just + * memcpy the values. + */ + uint32_t *sdc = brw_state_batch(brw, 4 * 4, 64, sdc_offset); + memcpy(sdc, color.ui, 4 * 4); + } else if (brw->is_haswell && (is_integer_format || is_stencil_sampling)) { + /* Haswell's integer border color support is completely insane: + * SAMPLER_BORDER_COLOR_STATE is 20 DWords. The first four are + * for float colors. The next 12 DWords are MBZ and only exist to + * pad it out to a 64 byte cacheline boundary. DWords 16-19 then + * contain integer colors; these are only used if SURFACE_STATE + * has the "Integer Surface Format" bit set. Even then, the + * arrangement of the RGBA data devolves into madness. + */ + uint32_t *sdc = brw_state_batch(brw, 20 * 4, 512, sdc_offset); + memset(sdc, 0, 20 * 4); + sdc = &sdc[16]; + + bool stencil = format == MESA_FORMAT_S_UINT8 || is_stencil_sampling; + const int bits_per_channel = + _mesa_get_format_bits(format, stencil ? GL_STENCIL_BITS : GL_RED_BITS); + + /* From the Haswell PRM, "Command Reference: Structures", Page 36: + * "If any color channel is missing from the surface format, + * corresponding border color should be programmed as zero and if + * alpha channel is missing, corresponding Alpha border color should + * be programmed as 1." + */ + unsigned c[4] = { 0, 0, 0, 1 }; + for (int i = 0; i < 4; i++) { + if (has_component(format, i)) + c[i] = color.ui[i]; + } + + switch (bits_per_channel) { + case 8: + /* Copy RGBA in order. */ + for (int i = 0; i < 4; i++) + ((uint8_t *) sdc)[i] = c[i]; + break; + case 10: + /* R10G10B10A2_UINT is treated like a 16-bit format. */ + case 16: + ((uint16_t *) sdc)[0] = c[0]; /* R -> DWord 0, bits 15:0 */ + ((uint16_t *) sdc)[1] = c[1]; /* G -> DWord 0, bits 31:16 */ + /* DWord 1 is Reserved/MBZ! */ + ((uint16_t *) sdc)[4] = c[2]; /* B -> DWord 2, bits 15:0 */ + ((uint16_t *) sdc)[5] = c[3]; /* A -> DWord 3, bits 31:16 */ + break; + case 32: + if (base_format == GL_RG) { + /* Careful inspection of the tables reveals that for RG32 formats, + * the green channel needs to go where blue normally belongs. + */ + sdc[0] = c[0]; + sdc[2] = c[1]; + sdc[3] = 1; + } else { + /* Copy RGBA in order. */ + for (int i = 0; i < 4; i++) + sdc[i] = c[i]; + } + break; + default: + assert(!"Invalid number of bits per channel in integer format."); + break; + } + } else if (brw->gen == 5 || brw->gen == 6) { + struct gen5_sampler_default_color *sdc; + + sdc = brw_state_batch(brw, sizeof(*sdc), 32, sdc_offset); + + memset(sdc, 0, sizeof(*sdc)); + + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color.f[0]); + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color.f[1]); + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color.f[2]); + UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color.f[3]); + + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color.f[0]); + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color.f[1]); + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color.f[2]); + UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color.f[3]); + + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color.f[0]); + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color.f[1]); + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color.f[2]); + UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color.f[3]); + + sdc->hf[0] = _mesa_float_to_half(color.f[0]); + sdc->hf[1] = _mesa_float_to_half(color.f[1]); + sdc->hf[2] = _mesa_float_to_half(color.f[2]); + sdc->hf[3] = _mesa_float_to_half(color.f[3]); + + sdc->b[0] = sdc->s[0] >> 8; + sdc->b[1] = sdc->s[1] >> 8; + sdc->b[2] = sdc->s[2] >> 8; + sdc->b[3] = sdc->s[3] >> 8; + + sdc->f[0] = color.f[0]; + sdc->f[1] = color.f[1]; + sdc->f[2] = color.f[2]; + sdc->f[3] = color.f[3]; + } else { + float *sdc = brw_state_batch(brw, 4 * 4, 32, sdc_offset); + memcpy(sdc, color.f, 4 * 4); + } +} + +static uint32_t +translate_wrap_mode(struct brw_context *brw, GLenum wrap, bool using_nearest) +{ + switch (wrap) { + case GL_REPEAT: + return TCM_WRAP; + case GL_CLAMP: +#if GEN_GEN >= 8 + /* GL_CLAMP is the weird mode where coordinates are clamped to + * [0.0, 1.0], so linear filtering of coordinates outside of + * [0.0, 1.0] give you half edge texel value and half border + * color. + * + * Gen8+ supports this natively. + */ + return TCM_HALF_BORDER; +#endif + + /* On Gen4-7.5, we clamp the coordinates in the fragment shader + * and set clamp_border here, which gets the result desired. + * We just use clamp(_to_edge) for nearest, because for nearest + * clamping to 1.0 gives border color instead of the desired + * edge texels. + */ + if (using_nearest) + return TCM_CLAMP; + else + return TCM_CLAMP_BORDER; + case GL_CLAMP_TO_EDGE: + return TCM_CLAMP; + case GL_CLAMP_TO_BORDER: + return TCM_CLAMP_BORDER; + case GL_MIRRORED_REPEAT: + return TCM_MIRROR; + case GL_MIRROR_CLAMP_TO_EDGE: + return TCM_MIRROR_ONCE; + default: + return TCM_WRAP; + } +} + +/** + * Return true if the given wrap mode requires the border color to exist. + */ +static bool +wrap_mode_needs_border_color(unsigned wrap_mode) +{ +#if GEN_GEN >= 8 + return wrap_mode == TCM_CLAMP_BORDER || + wrap_mode == TCM_HALF_BORDER; +#else + return wrap_mode == TCM_CLAMP_BORDER; +#endif +} + +/** + * Sets the sampler state for a single unit based off of the sampler key + * entry. + */ +static void +genX(update_sampler_state)(struct brw_context *brw, + GLenum target, bool tex_cube_map_seamless, + GLfloat tex_unit_lod_bias, + mesa_format format, GLenum base_format, + const struct gl_texture_object *texObj, + const struct gl_sampler_object *sampler, + uint32_t *sampler_state, + uint32_t batch_offset_for_sampler_state) +{ + struct GENX(SAMPLER_STATE) samp_st = { 0 }; + + /* Select min and mip filters. */ + switch (sampler->MinFilter) { + case GL_NEAREST: + samp_st.MinModeFilter = MAPFILTER_NEAREST; + samp_st.MipModeFilter = MIPFILTER_NONE; + break; + case GL_LINEAR: + samp_st.MinModeFilter = MAPFILTER_LINEAR; + samp_st.MipModeFilter = MIPFILTER_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + samp_st.MinModeFilter = MAPFILTER_NEAREST; + samp_st.MipModeFilter = MIPFILTER_NEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + samp_st.MinModeFilter = MAPFILTER_LINEAR; + samp_st.MipModeFilter = MIPFILTER_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + samp_st.MinModeFilter = MAPFILTER_NEAREST; + samp_st.MipModeFilter = MIPFILTER_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + samp_st.MinModeFilter = MAPFILTER_LINEAR; + samp_st.MipModeFilter = MIPFILTER_LINEAR; + break; + default: + unreachable("not reached"); + } + + /* Select mag filter. */ + samp_st.MagModeFilter = sampler->MagFilter == GL_LINEAR ? + MAPFILTER_LINEAR : MAPFILTER_NEAREST; + + /* Enable anisotropic filtering if desired. */ + samp_st.MaximumAnisotropy = RATIO21; + + if (sampler->MaxAnisotropy > 1.0f) { + if (samp_st.MinModeFilter == MAPFILTER_LINEAR) + samp_st.MinModeFilter = MAPFILTER_ANISOTROPIC; + if (samp_st.MinModeFilter == MAPFILTER_LINEAR) + samp_st.MagModeFilter = MAPFILTER_ANISOTROPIC; + + if (sampler->MaxAnisotropy > 2.0f) { + samp_st.MaximumAnisotropy = + MIN2((sampler->MaxAnisotropy - 2) / 2, RATIO161); + } + } + + /* Set address rounding bits if not using nearest filtering. */ + if (samp_st.MinModeFilter != MAPFILTER_NEAREST) { + samp_st.UAddressMinFilterRoundingEnable = true; + samp_st.VAddressMinFilterRoundingEnable = true; + samp_st.RAddressMinFilterRoundingEnable = true; + } + + if (samp_st.MagModeFilter != MAPFILTER_NEAREST) { + samp_st.UAddressMagFilterRoundingEnable = true; + samp_st.VAddressMagFilterRoundingEnable = true; + samp_st.RAddressMagFilterRoundingEnable = true; + } + + bool either_nearest = + sampler->MinFilter == GL_NEAREST || sampler->MagFilter == GL_NEAREST; + unsigned wrap_s = translate_wrap_mode(brw, sampler->WrapS, either_nearest); + unsigned wrap_t = translate_wrap_mode(brw, sampler->WrapT, either_nearest); + unsigned wrap_r = translate_wrap_mode(brw, sampler->WrapR, either_nearest); + + if (target == GL_TEXTURE_CUBE_MAP || + target == GL_TEXTURE_CUBE_MAP_ARRAY) { + /* Cube maps must use the same wrap mode for all three coordinate + * dimensions. Prior to Haswell, only CUBE and CLAMP are valid. + * + * Ivybridge and Baytrail seem to have problems with CUBE mode and + * integer formats. Fall back to CLAMP for now. + */ + if ((tex_cube_map_seamless || sampler->CubeMapSeamless) && + !(GEN_GEN == 7 && !GEN_IS_HASWELL && texObj->_IsIntegerFormat)) { + wrap_s = TCM_CUBE; + wrap_t = TCM_CUBE; + wrap_r = TCM_CUBE; + } else { + wrap_s = TCM_CLAMP; + wrap_t = TCM_CLAMP; + wrap_r = TCM_CLAMP; + } + } else if (target == GL_TEXTURE_1D) { + /* There's a bug in 1D texture sampling - it actually pays + * attention to the wrap_t value, though it should not. + * Override the wrap_t value here to GL_REPEAT to keep + * any nonexistent border pixels from floating in. + */ + wrap_t = TCM_WRAP; + } + + samp_st.TCXAddressControlMode = wrap_s; + samp_st.TCYAddressControlMode = wrap_t; + samp_st.TCZAddressControlMode = wrap_r; + + samp_st.ShadowFunction = + sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB ? + intel_translate_shadow_compare_func(sampler->CompareFunc) : 0; + +#if GEN_GEN >= 7 + /* Set shadow function. */ + samp_st.AnisotropicAlgorithm = + samp_st.MinModeFilter == MAPFILTER_ANISOTROPIC ? + EWAApproximation : LEGACY; +#endif + +#if GEN_GEN >= 6 + samp_st.NonnormalizedCoordinateEnable = target == GL_TEXTURE_RECTANGLE; +#endif + + const float hw_max_lod = GEN_GEN >= 7 ? 14 : 13; + samp_st.MinLOD = CLAMP(sampler->MinLod, 0, hw_max_lod); + samp_st.MaxLOD = CLAMP(sampler->MaxLod, 0, hw_max_lod); + samp_st.TextureLODBias = + CLAMP(tex_unit_lod_bias + sampler->LodBias, -16, 15); + +#if GEN_GEN == 6 + samp_st.BaseMipLevel = + CLAMP(texObj->MinLevel + texObj->BaseLevel, 0, hw_max_lod); + samp_st.MinandMagStateNotEqual = + samp_st.MinModeFilter != samp_st.MagModeFilter; +#endif + + /* Upload the border color if necessary. If not, just point it at + * offset 0 (the start of the batch) - the color should be ignored, + * but that address won't fault in case something reads it anyway. + */ + uint32_t border_color_offset = 0; + if (wrap_mode_needs_border_color(wrap_s) || + wrap_mode_needs_border_color(wrap_t) || + wrap_mode_needs_border_color(wrap_r)) { + upload_default_color(brw, sampler, format, base_format, + texObj->_IsIntegerFormat, texObj->StencilSampling, + &border_color_offset); + } + + samp_st.BorderColorPointer = border_color_offset; + + if (GEN_GEN < 6) { + samp_st.BorderColorPointer += brw->batch.bo->offset64; /* reloc */ + brw_emit_reloc(&brw->batch, batch_offset_for_sampler_state + 8, + brw->batch.bo, border_color_offset, + I915_GEM_DOMAIN_SAMPLER, 0); + } + +#if GEN_GEN >= 8 + samp_st.LODPreClampMode = CLAMP_MODE_OGL; +#else + samp_st.LODPreClampEnable = true; +#endif + + GENX(SAMPLER_STATE_pack)(brw, sampler_state, &samp_st); +} + +static void +update_sampler_state(struct brw_context *brw, + int unit, + uint32_t *sampler_state, + uint32_t batch_offset_for_sampler_state) +{ + struct gl_context *ctx = &brw->ctx; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *texObj = texUnit->_Current; + const struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); + + /* These don't use samplers at all. */ + if (texObj->Target == GL_TEXTURE_BUFFER) + return; + + struct gl_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel]; + genX(update_sampler_state)(brw, texObj->Target, + ctx->Texture.CubeMapSeamless, + texUnit->LodBias, + firstImage->TexFormat, firstImage->_BaseFormat, + texObj, sampler, + sampler_state, batch_offset_for_sampler_state); +} + +static void +genX(upload_sampler_state_table)(struct brw_context *brw, + struct gl_program *prog, + struct brw_stage_state *stage_state) +{ + struct gl_context *ctx = &brw->ctx; + uint32_t sampler_count = stage_state->sampler_count; + + GLbitfield SamplersUsed = prog->SamplersUsed; + + if (sampler_count == 0) + return; + + /* SAMPLER_STATE is 4 DWords on all platforms. */ + const int dwords = GENX(SAMPLER_STATE_length); + const int size_in_bytes = dwords * sizeof(uint32_t); + + uint32_t *sampler_state = brw_state_batch(brw, + sampler_count * size_in_bytes, + 32, &stage_state->sampler_offset); + /* memset(sampler_state, 0, sampler_count * size_in_bytes); */ + + uint32_t batch_offset_for_sampler_state = stage_state->sampler_offset; + + for (unsigned s = 0; s < sampler_count; s++) { + if (SamplersUsed & (1 << s)) { + const unsigned unit = prog->SamplerUnits[s]; + if (ctx->Texture.Unit[unit]._Current) { + update_sampler_state(brw, unit, sampler_state, + batch_offset_for_sampler_state); + } + } + + sampler_state += dwords; + batch_offset_for_sampler_state += size_in_bytes; + } + + if (GEN_GEN >= 7 && stage_state->stage != MESA_SHADER_COMPUTE) { + /* Emit a 3DSTATE_SAMPLER_STATE_POINTERS_XS packet. */ + genX(emit_sampler_state_pointers_xs)(brw, stage_state); + } else { + /* Flag that the sampler state table pointer has changed; later atoms + * will handle it. + */ + brw->ctx.NewDriverState |= BRW_NEW_SAMPLER_STATE_TABLE; + } +} + +static void +genX(upload_fs_samplers)(struct brw_context *brw) +{ + /* BRW_NEW_FRAGMENT_PROGRAM */ + struct gl_program *fs = (struct gl_program *) brw->fragment_program; + genX(upload_sampler_state_table)(brw, fs, &brw->wm.base); +} + +static const struct brw_tracked_state genX(fs_samplers) = { + .dirty = { + .mesa = _NEW_TEXTURE, + .brw = BRW_NEW_BATCH | + BRW_NEW_BLORP | + BRW_NEW_FRAGMENT_PROGRAM, + }, + .emit = genX(upload_fs_samplers), +}; + +/* ---------------------------------------------------------------------- */ + void genX(init_atoms)(struct brw_context *brw) { @@ -4245,7 +4781,7 @@ genX(init_atoms)(struct brw_context *brw) &brw_vs_binding_table, &brw_wm_binding_table, - &brw_fs_samplers, + &genX(fs_samplers), &brw_vs_samplers, /* These set up state for brw_psp_urb_cbs */ @@ -4314,7 +4850,7 @@ genX(init_atoms)(struct brw_context *brw) &gen6_gs_binding_table, &brw_wm_binding_table, - &brw_fs_samplers, + &genX(fs_samplers), &brw_vs_samplers, &brw_gs_samplers, &gen6_sampler_state, @@ -4397,7 +4933,7 @@ genX(init_atoms)(struct brw_context *brw) &brw_gs_binding_table, &brw_wm_binding_table, - &brw_fs_samplers, + &genX(fs_samplers), &brw_vs_samplers, &brw_tcs_samplers, &brw_tes_samplers, @@ -4486,7 +5022,7 @@ genX(init_atoms)(struct brw_context *brw) &brw_gs_binding_table, &brw_wm_binding_table, - &brw_fs_samplers, + &genX(fs_samplers), &brw_vs_samplers, &brw_tcs_samplers, &brw_tes_samplers,