X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_sampler_state.c;h=b99a89893f61103f600b576190e099ab27670071;hb=0235757422d825c37ca2d2c3feb9e58a28deedd4;hp=c78e2e3cc8ed923a5d6038f9a7151f202934ebd0;hpb=47f32cb50d19145ed502e1fccd949d931c0cd392;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_sampler_state.c b/src/mesa/drivers/dri/i965/brw_sampler_state.c index c78e2e3cc8e..b99a89893f6 100644 --- a/src/mesa/drivers/dri/i965/brw_sampler_state.c +++ b/src/mesa/drivers/dri/i965/brw_sampler_state.c @@ -44,6 +44,7 @@ #include "main/macros.h" #include "main/samplerobj.h" +#include "util/half_float.h" /** * Emit a 3DSTATE_SAMPLER_STATE_POINTERS_{VS,HS,GS,DS,PS} packet. @@ -54,6 +55,8 @@ gen7_emit_sampler_state_pointers_xs(struct brw_context *brw, { static const uint16_t packet_headers[] = { [MESA_SHADER_VERTEX] = _3DSTATE_SAMPLER_STATE_POINTERS_VS, + [MESA_SHADER_TESS_CTRL] = _3DSTATE_SAMPLER_STATE_POINTERS_HS, + [MESA_SHADER_TESS_EVAL] = _3DSTATE_SAMPLER_STATE_POINTERS_DS, [MESA_SHADER_GEOMETRY] = _3DSTATE_SAMPLER_STATE_POINTERS_GS, [MESA_SHADER_FRAGMENT] = _3DSTATE_SAMPLER_STATE_POINTERS_PS, }; @@ -85,16 +88,15 @@ brw_emit_sampler_state(struct brw_context *brw, unsigned wrap_s, unsigned wrap_t, unsigned wrap_r, + unsigned base_level, unsigned min_lod, unsigned max_lod, int lod_bias, - unsigned base_level, unsigned shadow_function, bool non_normalized_coordinates, uint32_t border_color_offset) { ss[0] = BRW_SAMPLER_LOD_PRECLAMP_ENABLE | - SET_FIELD(base_level, BRW_SAMPLER_BASE_MIPLEVEL) | SET_FIELD(mip_filter, BRW_SAMPLER_MIP_FILTER) | SET_FIELD(mag_filter, BRW_SAMPLER_MAG_FILTER) | SET_FIELD(min_filter, BRW_SAMPLER_MIN_FILTER); @@ -131,6 +133,21 @@ brw_emit_sampler_state(struct brw_context *brw, ss[0] |= SET_FIELD(lod_bias & 0x7ff, GEN4_SAMPLER_LOD_BIAS) | SET_FIELD(shadow_function, GEN4_SAMPLER_SHADOW_FUNCTION); + /* This field has existed since the original i965, but is declared MBZ + * until Sandy Bridge. According to the PRM: + * + * "This was added to match OpenGL semantics" + * + * In particular, OpenGL allowed you to offset by 0.5 in certain cases + * to get slightly better filtering. On Ivy Bridge and above, it + * appears that this is added to RENDER_SURFACE_STATE::SurfaceMinLOD so + * the right value is 0.0 or 0.5 (if you want the wacky behavior). On + * Sandy Bridge, however, this sum does not seem to occur and you have + * to set it to the actual base level of the texture. + */ + if (brw->gen == 6) + ss[0] |= SET_FIELD(base_level, BRW_SAMPLER_BASE_MIPLEVEL); + if (brw->gen == 6 && min_filter != mag_filter) ss[0] |= GEN6_SAMPLER_MIN_MAG_NOT_EQUAL; @@ -148,7 +165,7 @@ brw_emit_sampler_state(struct brw_context *brw, static uint32_t translate_wrap_mode(struct brw_context *brw, GLenum wrap, bool using_nearest) { - switch( wrap ) { + switch (wrap) { case GL_REPEAT: return BRW_TEXCOORDMODE_WRAP; case GL_CLAMP: @@ -195,6 +212,16 @@ wrap_mode_needs_border_color(unsigned wrap_mode) wrap_mode == GEN8_TEXCOORDMODE_HALF_BORDER; } +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. */ @@ -202,7 +229,7 @@ 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_integer_format, bool is_stencil_sampling, uint32_t *sdc_offset) { union gl_color_union color; @@ -266,7 +293,7 @@ upload_default_color(struct brw_context *brw, uint32_t *sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR, 4 * 4, 64, sdc_offset); memcpy(sdc, color.ui, 4 * 4); - } else if (brw->is_haswell && is_integer_format) { + } 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 @@ -280,7 +307,9 @@ upload_default_color(struct brw_context *brw, memset(sdc, 0, 20 * 4); sdc = &sdc[16]; - int bits_per_channel = _mesa_get_format_bits(format, GL_RED_BITS); + 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, @@ -290,7 +319,7 @@ upload_default_color(struct brw_context *brw, */ unsigned c[4] = { 0, 0, 0, 1 }; for (int i = 0; i < 4; i++) { - if (_mesa_format_has_color_component(format, i)) + if (has_component(format, i)) c[i] = color.ui[i]; } @@ -377,19 +406,14 @@ upload_default_color(struct brw_context *brw, */ static void brw_update_sampler_state(struct brw_context *brw, - int unit, + 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 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; - unsigned min_filter, mag_filter, mip_filter; /* Select min and mip filters. */ @@ -430,11 +454,11 @@ brw_update_sampler_state(struct brw_context *brw, /* Enable anisotropic filtering if desired. */ unsigned max_anisotropy = BRW_ANISORATIO_2; - if (sampler->MaxAnisotropy > 1.0) { + if (sampler->MaxAnisotropy > 1.0f) { min_filter = BRW_MAPFILTER_ANISOTROPIC; mag_filter = BRW_MAPFILTER_ANISOTROPIC; - if (sampler->MaxAnisotropy > 2.0) { + if (sampler->MaxAnisotropy > 2.0f) { max_anisotropy = MIN2((sampler->MaxAnisotropy - 2) / 2, BRW_ANISORATIO_16); } @@ -459,14 +483,16 @@ brw_update_sampler_state(struct brw_context *brw, unsigned wrap_t = translate_wrap_mode(brw, sampler->WrapT, either_nearest); unsigned wrap_r = translate_wrap_mode(brw, sampler->WrapR, either_nearest); - if (texObj->Target == GL_TEXTURE_CUBE_MAP || - texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { + 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 ((ctx->Texture.CubeMapSeamless || sampler->CubeMapSeamless) && - (sampler->MinFilter != GL_NEAREST || - sampler->MagFilter != GL_NEAREST)) { + if ((tex_cube_map_seamless || sampler->CubeMapSeamless) && + !(brw->gen == 7 && !brw->is_haswell && texObj->_IsIntegerFormat)) { wrap_s = BRW_TEXCOORDMODE_CUBE; wrap_t = BRW_TEXCOORDMODE_CUBE; wrap_r = BRW_TEXCOORDMODE_CUBE; @@ -475,7 +501,7 @@ brw_update_sampler_state(struct brw_context *brw, wrap_t = BRW_TEXCOORDMODE_CLAMP; wrap_r = BRW_TEXCOORDMODE_CLAMP; } - } else if (texObj->Target == GL_TEXTURE_1D) { + } 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 @@ -492,11 +518,15 @@ brw_update_sampler_state(struct brw_context *brw, } const int lod_bits = brw->gen >= 7 ? 8 : 6; - const unsigned min_lod = U_FIXED(CLAMP(sampler->MinLod, 0, 13), lod_bits); - const unsigned max_lod = U_FIXED(CLAMP(sampler->MaxLod, 0, 13), lod_bits); + const float hw_max_lod = brw->gen >= 7 ? 14 : 13; + const unsigned base_level = + U_FIXED(CLAMP(texObj->MinLevel + texObj->BaseLevel, 0, hw_max_lod), 1); + const unsigned min_lod = + U_FIXED(CLAMP(sampler->MinLod, 0, hw_max_lod), lod_bits); + const unsigned max_lod = + U_FIXED(CLAMP(sampler->MaxLod, 0, hw_max_lod), lod_bits); const int lod_bias = - S_FIXED(CLAMP(texUnit->LodBias + sampler->LodBias, -16, 15), lod_bits); - const unsigned base_level = U_FIXED(0, 1); + S_FIXED(CLAMP(tex_unit_lod_bias + sampler->LodBias, -16, 15), lod_bits); /* Upload the border color if necessary. If not, just point it at * offset 0 (the start of the batch) - the color should be ignored, @@ -506,14 +536,12 @@ brw_update_sampler_state(struct brw_context *brw, if (wrap_mode_needs_border_color(wrap_s) || wrap_mode_needs_border_color(wrap_t) || wrap_mode_needs_border_color(wrap_r)) { - const struct gl_texture_image *first_image = - texObj->Image[0][texObj->BaseLevel]; - upload_default_color(brw, sampler, - first_image->TexFormat, first_image->_BaseFormat, - texObj->_IsIntegerFormat, &border_color_offset); + upload_default_color(brw, sampler, format, base_format, + texObj->_IsIntegerFormat, texObj->StencilSampling, + &border_color_offset); } - const bool non_normalized_coords = texObj->Target == GL_TEXTURE_RECTANGLE; + const bool non_normalized_coords = target == GL_TEXTURE_RECTANGLE; brw_emit_sampler_state(brw, sampler_state, @@ -522,12 +550,34 @@ brw_update_sampler_state(struct brw_context *brw, max_anisotropy, address_rounding, wrap_s, wrap_t, wrap_r, - min_lod, max_lod, lod_bias, base_level, + base_level, min_lod, max_lod, lod_bias, shadow_function, non_normalized_coords, border_color_offset); } +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]; + brw_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 brw_upload_sampler_state_table(struct brw_context *brw, @@ -557,7 +607,7 @@ brw_upload_sampler_state_table(struct brw_context *brw, if (SamplersUsed & (1 << s)) { const unsigned unit = prog->SamplerUnits[s]; if (ctx->Texture.Unit[unit]._Current) { - brw_update_sampler_state(brw, unit, sampler_state, + update_sampler_state(brw, unit, sampler_state, batch_offset_for_sampler_state); } } @@ -566,7 +616,7 @@ brw_upload_sampler_state_table(struct brw_context *brw, batch_offset_for_sampler_state += size_in_bytes; } - if (brw->gen >= 7) { + if (brw->gen >= 7 && stage_state->stage != MESA_SHADER_COMPUTE) { /* Emit a 3DSTATE_SAMPLER_STATE_POINTERS_XS packet. */ gen7_emit_sampler_state_pointers_xs(brw, stage_state); } else { @@ -589,6 +639,7 @@ 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, @@ -607,6 +658,7 @@ const struct brw_tracked_state brw_vs_samplers = { .dirty = { .mesa = _NEW_TEXTURE, .brw = BRW_NEW_BATCH | + BRW_NEW_BLORP | BRW_NEW_VERTEX_PROGRAM, }, .emit = brw_upload_vs_samplers, @@ -629,7 +681,75 @@ const struct brw_tracked_state brw_gs_samplers = { .dirty = { .mesa = _NEW_TEXTURE, .brw = BRW_NEW_BATCH | + BRW_NEW_BLORP | BRW_NEW_GEOMETRY_PROGRAM, }, .emit = brw_upload_gs_samplers, }; + + +static void +brw_upload_tcs_samplers(struct brw_context *brw) +{ + /* BRW_NEW_TESS_PROGRAMS */ + struct gl_program *tcs = (struct gl_program *) brw->tess_ctrl_program; + if (!tcs) + return; + + brw_upload_sampler_state_table(brw, tcs, &brw->tcs.base); +} + + +const struct brw_tracked_state brw_tcs_samplers = { + .dirty = { + .mesa = _NEW_TEXTURE, + .brw = BRW_NEW_BATCH | + BRW_NEW_BLORP | + BRW_NEW_TESS_PROGRAMS, + }, + .emit = brw_upload_tcs_samplers, +}; + + +static void +brw_upload_tes_samplers(struct brw_context *brw) +{ + /* BRW_NEW_TESS_PROGRAMS */ + struct gl_program *tes = (struct gl_program *) brw->tess_eval_program; + if (!tes) + return; + + brw_upload_sampler_state_table(brw, tes, &brw->tes.base); +} + + +const struct brw_tracked_state brw_tes_samplers = { + .dirty = { + .mesa = _NEW_TEXTURE, + .brw = BRW_NEW_BATCH | + BRW_NEW_BLORP | + BRW_NEW_TESS_PROGRAMS, + }, + .emit = brw_upload_tes_samplers, +}; + +static void +brw_upload_cs_samplers(struct brw_context *brw) +{ + /* BRW_NEW_COMPUTE_PROGRAM */ + struct gl_program *cs = (struct gl_program *) brw->compute_program; + if (!cs) + return; + + brw_upload_sampler_state_table(brw, cs, &brw->cs.base); +} + +const struct brw_tracked_state brw_cs_samplers = { + .dirty = { + .mesa = _NEW_TEXTURE, + .brw = BRW_NEW_BATCH | + BRW_NEW_BLORP | + BRW_NEW_COMPUTE_PROGRAM, + }, + .emit = brw_upload_cs_samplers, +};