diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_builder_3d_top.h | 106 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_state_3d.h | 25 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_state_3d_top.c | 459 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_render_dynamic.c | 60 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_state.c | 183 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_state.h | 15 |
6 files changed, 258 insertions, 590 deletions
diff --git a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h index cec1043b204..d5a4c778a87 100644 --- a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h +++ b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h @@ -36,6 +36,7 @@ #include "ilo_core.h" #include "ilo_dev.h" #include "ilo_state_3d.h" +#include "ilo_state_sampler.h" #include "ilo_builder.h" static inline void @@ -1728,13 +1729,12 @@ gen6_so_SURFACE_STATE(struct ilo_builder *builder, static inline uint32_t gen6_SAMPLER_STATE(struct ilo_builder *builder, - const struct ilo_sampler_cso * const *samplers, - const struct pipe_sampler_view * const *views, + const struct ilo_state_sampler *samplers, const uint32_t *sampler_border_colors, - int num_samplers) + int sampler_count) { const int state_align = 32; - const int state_len = 4 * num_samplers; + const int state_len = 4 * sampler_count; uint32_t state_offset, *dw; int i; @@ -1745,9 +1745,9 @@ gen6_SAMPLER_STATE(struct ilo_builder *builder, * * "The sampler state is stored as an array of up to 16 elements..." */ - assert(num_samplers <= 16); + assert(sampler_count <= 16); - if (!num_samplers) + if (!sampler_count) return 0; /* @@ -1759,86 +1759,19 @@ gen6_SAMPLER_STATE(struct ilo_builder *builder, * * It also applies to other shader stages. */ - ilo_builder_dynamic_pad_top(builder, 4 * (4 - (num_samplers % 4))); + ilo_builder_dynamic_pad_top(builder, 4 * (4 - (sampler_count % 4))); state_offset = ilo_builder_dynamic_pointer(builder, ILO_BUILDER_ITEM_SAMPLER, state_align, state_len, &dw); - for (i = 0; i < num_samplers; i++) { - const struct ilo_sampler_cso *sampler = samplers[i]; - const struct pipe_sampler_view *view = views[i]; - const uint32_t border_color = sampler_border_colors[i]; - uint32_t dw_filter, dw_wrap; + for (i = 0; i < sampler_count; i++) { + /* see sampler_set_gen6_SAMPLER_STATE() */ + dw[0] = samplers[i].sampler[0]; + dw[1] = samplers[i].sampler[1]; + dw[3] = samplers[i].sampler[2]; - /* there may be holes */ - if (!sampler || !view) { - /* disabled sampler */ - dw[0] = 1 << 31; - dw[1] = 0; - dw[2] = 0; - dw[3] = 0; - dw += 4; - - continue; - } - - /* determine filter and wrap modes */ - switch (view->texture->target) { - case PIPE_TEXTURE_1D: - dw_filter = (sampler->anisotropic) ? - sampler->dw_filter_aniso : sampler->dw_filter; - dw_wrap = sampler->dw_wrap_1d; - break; - case PIPE_TEXTURE_3D: - /* - * From the Sandy Bridge PRM, volume 4 part 1, page 103: - * - * "Only MAPFILTER_NEAREST and MAPFILTER_LINEAR are supported for - * surfaces of type SURFTYPE_3D." - */ - dw_filter = sampler->dw_filter; - dw_wrap = sampler->dw_wrap; - break; - case PIPE_TEXTURE_CUBE: - dw_filter = (sampler->anisotropic) ? - sampler->dw_filter_aniso : sampler->dw_filter; - dw_wrap = sampler->dw_wrap_cube; - break; - default: - dw_filter = (sampler->anisotropic) ? - sampler->dw_filter_aniso : sampler->dw_filter; - dw_wrap = sampler->dw_wrap; - break; - } - - dw[0] = sampler->payload[0]; - dw[1] = sampler->payload[1]; - assert(!(border_color & 0x1f)); - dw[2] = border_color; - dw[3] = sampler->payload[2]; - - dw[0] |= dw_filter; - - if (ilo_dev_gen(builder->dev) >= ILO_GEN(7)) { - dw[3] |= dw_wrap; - } - else { - /* - * From the Sandy Bridge PRM, volume 4 part 1, page 21: - * - * "[DevSNB] Errata: Incorrect behavior is observed in cases - * where the min and mag mode filters are different and - * SurfMinLOD is nonzero. The determination of MagMode uses the - * following equation instead of the one in the above - * pseudocode: MagMode = (LOD + SurfMinLOD - Base <= 0)" - * - * As a way to work around that, we set Base to - * view->u.tex.first_level. - */ - dw[0] |= view->u.tex.first_level << 22; - - dw[1] |= dw_wrap; - } + assert(!(sampler_border_colors[i] & 0x1f)); + dw[2] = sampler_border_colors[i]; dw += 4; } @@ -1848,7 +1781,7 @@ gen6_SAMPLER_STATE(struct ilo_builder *builder, static inline uint32_t gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_builder *builder, - const struct ilo_sampler_cso *sampler) + const struct ilo_state_sampler_border *border) { const int state_align = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 64 : 32; @@ -1856,11 +1789,12 @@ gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_builder *builder, ILO_DEV_ASSERT(builder->dev, 6, 8); - assert(Elements(sampler->payload) >= 3 + state_len); - - /* see ilo_gpe_init_sampler_cso() */ + /* + * see border_set_gen6_SAMPLER_BORDER_COLOR_STATE() and + * border_set_gen7_SAMPLER_BORDER_COLOR_STATE() + */ return ilo_builder_dynamic_write(builder, ILO_BUILDER_ITEM_BLOB, - state_align, state_len, &sampler->payload[3]); + state_align, state_len, border->color); } static inline uint32_t diff --git a/src/gallium/drivers/ilo/core/ilo_state_3d.h b/src/gallium/drivers/ilo/core/ilo_state_3d.h index 6518c442249..260f94bf766 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_3d.h +++ b/src/gallium/drivers/ilo/core/ilo_state_3d.h @@ -195,26 +195,6 @@ struct ilo_blend_state { uint32_t dw_ps_blend_dst_alpha_forced_one; }; -struct ilo_sampler_cso { - /* SAMPLER_STATE and SAMPLER_BORDER_COLOR_STATE */ - uint32_t payload[15]; - - uint32_t dw_filter; - uint32_t dw_filter_aniso; - uint32_t dw_wrap; - uint32_t dw_wrap_1d; - uint32_t dw_wrap_cube; - - bool anisotropic; - bool saturate_r; - bool saturate_s; - bool saturate_t; -}; - -struct ilo_sampler_state { - const struct ilo_sampler_cso *cso[ILO_MAX_SAMPLERS]; -}; - struct ilo_surface_cso { struct pipe_surface base; @@ -291,11 +271,6 @@ ilo_gpe_init_blend(const struct ilo_dev *dev, struct ilo_blend_state *blend); void -ilo_gpe_init_sampler_cso(const struct ilo_dev *dev, - const struct pipe_sampler_state *state, - struct ilo_sampler_cso *sampler); - -void ilo_gpe_init_vs_cso(const struct ilo_dev *dev, const struct ilo_shader_state *vs, struct ilo_shader_cso *cso); diff --git a/src/gallium/drivers/ilo/core/ilo_state_3d_top.c b/src/gallium/drivers/ilo/core/ilo_state_3d_top.c index 8f3133e1345..ca58f73783e 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_3d_top.c +++ b/src/gallium/drivers/ilo/core/ilo_state_3d_top.c @@ -408,462 +408,3 @@ ilo_gpe_init_gs_cso(const struct ilo_dev *dev, else gs_init_cso_gen6(dev, gs, cso); } - -static void -sampler_init_border_color_gen6(const struct ilo_dev *dev, - const union pipe_color_union *color, - uint32_t *dw, int num_dwords) -{ - float rgba[4] = { - color->f[0], color->f[1], color->f[2], color->f[3], - }; - - ILO_DEV_ASSERT(dev, 6, 6); - - assert(num_dwords >= 12); - - /* - * This state is not documented in the Sandy Bridge PRM, but in the - * Ironlake PRM. SNORM8 seems to be in DW11 instead of DW1. - */ - - /* IEEE_FP */ - dw[1] = fui(rgba[0]); - dw[2] = fui(rgba[1]); - dw[3] = fui(rgba[2]); - dw[4] = fui(rgba[3]); - - /* FLOAT_16 */ - dw[5] = util_float_to_half(rgba[0]) | - util_float_to_half(rgba[1]) << 16; - dw[6] = util_float_to_half(rgba[2]) | - util_float_to_half(rgba[3]) << 16; - - /* clamp to [-1.0f, 1.0f] */ - rgba[0] = CLAMP(rgba[0], -1.0f, 1.0f); - rgba[1] = CLAMP(rgba[1], -1.0f, 1.0f); - rgba[2] = CLAMP(rgba[2], -1.0f, 1.0f); - rgba[3] = CLAMP(rgba[3], -1.0f, 1.0f); - - /* SNORM16 */ - dw[9] = (int16_t) util_iround(rgba[0] * 32767.0f) | - (int16_t) util_iround(rgba[1] * 32767.0f) << 16; - dw[10] = (int16_t) util_iround(rgba[2] * 32767.0f) | - (int16_t) util_iround(rgba[3] * 32767.0f) << 16; - - /* SNORM8 */ - dw[11] = (int8_t) util_iround(rgba[0] * 127.0f) | - (int8_t) util_iround(rgba[1] * 127.0f) << 8 | - (int8_t) util_iround(rgba[2] * 127.0f) << 16 | - (int8_t) util_iround(rgba[3] * 127.0f) << 24; - - /* clamp to [0.0f, 1.0f] */ - rgba[0] = CLAMP(rgba[0], 0.0f, 1.0f); - rgba[1] = CLAMP(rgba[1], 0.0f, 1.0f); - rgba[2] = CLAMP(rgba[2], 0.0f, 1.0f); - rgba[3] = CLAMP(rgba[3], 0.0f, 1.0f); - - /* UNORM8 */ - dw[0] = (uint8_t) util_iround(rgba[0] * 255.0f) | - (uint8_t) util_iround(rgba[1] * 255.0f) << 8 | - (uint8_t) util_iround(rgba[2] * 255.0f) << 16 | - (uint8_t) util_iround(rgba[3] * 255.0f) << 24; - - /* UNORM16 */ - dw[7] = (uint16_t) util_iround(rgba[0] * 65535.0f) | - (uint16_t) util_iround(rgba[1] * 65535.0f) << 16; - dw[8] = (uint16_t) util_iround(rgba[2] * 65535.0f) | - (uint16_t) util_iround(rgba[3] * 65535.0f) << 16; -} - -/** - * Translate a pipe texture mipfilter to the matching hardware mipfilter. - */ -static int -gen6_translate_tex_mipfilter(unsigned filter) -{ - switch (filter) { - case PIPE_TEX_MIPFILTER_NEAREST: return GEN6_MIPFILTER_NEAREST; - case PIPE_TEX_MIPFILTER_LINEAR: return GEN6_MIPFILTER_LINEAR; - case PIPE_TEX_MIPFILTER_NONE: return GEN6_MIPFILTER_NONE; - default: - assert(!"unknown mipfilter"); - return GEN6_MIPFILTER_NONE; - } -} - -/** - * Translate a pipe texture filter to the matching hardware mapfilter. - */ -static int -gen6_translate_tex_filter(unsigned filter) -{ - switch (filter) { - case PIPE_TEX_FILTER_NEAREST: return GEN6_MAPFILTER_NEAREST; - case PIPE_TEX_FILTER_LINEAR: return GEN6_MAPFILTER_LINEAR; - default: - assert(!"unknown sampler filter"); - return GEN6_MAPFILTER_NEAREST; - } -} - -/** - * Translate a pipe texture coordinate wrapping mode to the matching hardware - * wrapping mode. - */ -static int -gen6_translate_tex_wrap(unsigned wrap) -{ - switch (wrap) { - case PIPE_TEX_WRAP_CLAMP: return GEN8_TEXCOORDMODE_HALF_BORDER; - case PIPE_TEX_WRAP_REPEAT: return GEN6_TEXCOORDMODE_WRAP; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return GEN6_TEXCOORDMODE_CLAMP; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return GEN6_TEXCOORDMODE_CLAMP_BORDER; - case PIPE_TEX_WRAP_MIRROR_REPEAT: return GEN6_TEXCOORDMODE_MIRROR; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - default: - assert(!"unknown sampler wrap mode"); - return GEN6_TEXCOORDMODE_WRAP; - } -} - -/** - * Translate a pipe shadow compare function to the matching hardware shadow - * function. - */ -static int -gen6_translate_shadow_func(unsigned func) -{ - /* - * For PIPE_FUNC_x, the reference value is on the left-hand side of the - * comparison, and 1.0 is returned when the comparison is true. - * - * For GEN6_COMPAREFUNCTION_x, the reference value is on the right-hand side of - * the comparison, and 0.0 is returned when the comparison is true. - */ - switch (func) { - case PIPE_FUNC_NEVER: return GEN6_COMPAREFUNCTION_ALWAYS; - case PIPE_FUNC_LESS: return GEN6_COMPAREFUNCTION_LEQUAL; - case PIPE_FUNC_EQUAL: return GEN6_COMPAREFUNCTION_NOTEQUAL; - case PIPE_FUNC_LEQUAL: return GEN6_COMPAREFUNCTION_LESS; - case PIPE_FUNC_GREATER: return GEN6_COMPAREFUNCTION_GEQUAL; - case PIPE_FUNC_NOTEQUAL: return GEN6_COMPAREFUNCTION_EQUAL; - case PIPE_FUNC_GEQUAL: return GEN6_COMPAREFUNCTION_GREATER; - case PIPE_FUNC_ALWAYS: return GEN6_COMPAREFUNCTION_NEVER; - default: - assert(!"unknown shadow compare function"); - return GEN6_COMPAREFUNCTION_NEVER; - } -} - -void -ilo_gpe_init_sampler_cso(const struct ilo_dev *dev, - const struct pipe_sampler_state *state, - struct ilo_sampler_cso *sampler) -{ - int mip_filter, min_filter, mag_filter, max_aniso; - int lod_bias, max_lod, min_lod; - int wrap_s, wrap_t, wrap_r, wrap_cube; - uint32_t dw0, dw1, dw3; - - ILO_DEV_ASSERT(dev, 6, 8); - - memset(sampler, 0, sizeof(*sampler)); - - mip_filter = gen6_translate_tex_mipfilter(state->min_mip_filter); - min_filter = gen6_translate_tex_filter(state->min_img_filter); - mag_filter = gen6_translate_tex_filter(state->mag_img_filter); - - sampler->anisotropic = state->max_anisotropy; - - if (state->max_anisotropy >= 2 && state->max_anisotropy <= 16) - max_aniso = state->max_anisotropy / 2 - 1; - else if (state->max_anisotropy > 16) - max_aniso = GEN6_ANISORATIO_16; - else - max_aniso = GEN6_ANISORATIO_2; - - /* - * - * Here is how the hardware calculate per-pixel LOD, from my reading of the - * PRMs: - * - * 1) LOD is set to log2(ratio of texels to pixels) if not specified in - * other ways. The number of texels is measured using level - * SurfMinLod. - * 2) Bias is added to LOD. - * 3) LOD is clamped to [MinLod, MaxLod], and the clamped value is - * compared with Base to determine whether magnification or - * minification is needed. (if preclamp is disabled, LOD is compared - * with Base before clamping) - * 4) If magnification is needed, or no mipmapping is requested, LOD is - * set to floor(MinLod). - * 5) LOD is clamped to [0, MIPCnt], and SurfMinLod is added to LOD. - * - * With Gallium interface, Base is always zero and - * pipe_sampler_view::u.tex.first_level specifies SurfMinLod. - */ - if (ilo_dev_gen(dev) >= ILO_GEN(7)) { - const float scale = 256.0f; - - /* [-16.0, 16.0) in S4.8 */ - lod_bias = (int) - (CLAMP(state->lod_bias, -16.0f, 15.9f) * scale); - lod_bias &= 0x1fff; - - /* [0.0, 14.0] in U4.8 */ - max_lod = (int) (CLAMP(state->max_lod, 0.0f, 14.0f) * scale); - min_lod = (int) (CLAMP(state->min_lod, 0.0f, 14.0f) * scale); - } - else { - const float scale = 64.0f; - - /* [-16.0, 16.0) in S4.6 */ - lod_bias = (int) - (CLAMP(state->lod_bias, -16.0f, 15.9f) * scale); - lod_bias &= 0x7ff; - - /* [0.0, 13.0] in U4.6 */ - max_lod = (int) (CLAMP(state->max_lod, 0.0f, 13.0f) * scale); - min_lod = (int) (CLAMP(state->min_lod, 0.0f, 13.0f) * scale); - } - - /* - * We want LOD to be clamped to determine magnification/minification, and - * get set to zero when it is magnification or when mipmapping is disabled. - * The hardware would set LOD to floor(MinLod) and that is a problem when - * MinLod is greater than or equal to 1.0f. - * - * With Base being zero, it is always minification when MinLod is non-zero. - * To achieve our goal, we just need to set MinLod to zero and set - * MagFilter to MinFilter when mipmapping is disabled. - */ - if (state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE && min_lod) { - min_lod = 0; - mag_filter = min_filter; - } - - /* determine wrap s/t/r */ - wrap_s = gen6_translate_tex_wrap(state->wrap_s); - wrap_t = gen6_translate_tex_wrap(state->wrap_t); - wrap_r = gen6_translate_tex_wrap(state->wrap_r); - if (ilo_dev_gen(dev) < ILO_GEN(8)) { - /* - * For nearest filtering, PIPE_TEX_WRAP_CLAMP means - * PIPE_TEX_WRAP_CLAMP_TO_EDGE; for linear filtering, - * PIPE_TEX_WRAP_CLAMP means PIPE_TEX_WRAP_CLAMP_TO_BORDER while - * additionally clamping the texture coordinates to [0.0, 1.0]. - * - * PIPE_TEX_WRAP_CLAMP is not supported natively until Gen8. The - * clamping has to be taken care of in the shaders. There are two - * filters here, but let the minification one has a say. - */ - const bool clamp_is_to_edge = - (state->min_img_filter == PIPE_TEX_FILTER_NEAREST); - - if (clamp_is_to_edge) { - if (wrap_s == GEN8_TEXCOORDMODE_HALF_BORDER) - wrap_s = GEN6_TEXCOORDMODE_CLAMP; - if (wrap_t == GEN8_TEXCOORDMODE_HALF_BORDER) - wrap_t = GEN6_TEXCOORDMODE_CLAMP; - if (wrap_r == GEN8_TEXCOORDMODE_HALF_BORDER) - wrap_r = GEN6_TEXCOORDMODE_CLAMP; - } else { - if (wrap_s == GEN8_TEXCOORDMODE_HALF_BORDER) { - wrap_s = GEN6_TEXCOORDMODE_CLAMP_BORDER; - sampler->saturate_s = true; - } - if (wrap_t == GEN8_TEXCOORDMODE_HALF_BORDER) { - wrap_t = GEN6_TEXCOORDMODE_CLAMP_BORDER; - sampler->saturate_t = true; - } - if (wrap_r == GEN8_TEXCOORDMODE_HALF_BORDER) { - wrap_r = GEN6_TEXCOORDMODE_CLAMP_BORDER; - sampler->saturate_r = true; - } - } - } - - /* - * From the Sandy Bridge PRM, volume 4 part 1, page 107: - * - * "When using cube map texture coordinates, only TEXCOORDMODE_CLAMP - * and TEXCOORDMODE_CUBE settings are valid, and each TC component - * must have the same Address Control mode." - * - * From the Ivy Bridge PRM, volume 4 part 1, page 96: - * - * "This field (Cube Surface Control Mode) must be set to - * CUBECTRLMODE_PROGRAMMED" - * - * Therefore, we cannot use "Cube Surface Control Mode" for semless cube - * map filtering. - */ - if (state->seamless_cube_map && - (state->min_img_filter != PIPE_TEX_FILTER_NEAREST || - state->mag_img_filter != PIPE_TEX_FILTER_NEAREST)) { - wrap_cube = GEN6_TEXCOORDMODE_CUBE; - } - else { - wrap_cube = GEN6_TEXCOORDMODE_CLAMP; - } - - if (!state->normalized_coords) { - /* - * From the Ivy Bridge PRM, volume 4 part 1, page 98: - * - * "The following state must be set as indicated if this field - * (Non-normalized Coordinate Enable) is enabled: - * - * - TCX/Y/Z Address Control Mode must be TEXCOORDMODE_CLAMP, - * TEXCOORDMODE_HALF_BORDER, or TEXCOORDMODE_CLAMP_BORDER. - * - Surface Type must be SURFTYPE_2D or SURFTYPE_3D. - * - Mag Mode Filter must be MAPFILTER_NEAREST or - * MAPFILTER_LINEAR. - * - Min Mode Filter must be MAPFILTER_NEAREST or - * MAPFILTER_LINEAR. - * - Mip Mode Filter must be MIPFILTER_NONE. - * - Min LOD must be 0. - * - Max LOD must be 0. - * - MIP Count must be 0. - * - Surface Min LOD must be 0. - * - Texture LOD Bias must be 0." - */ - assert(wrap_s == GEN6_TEXCOORDMODE_CLAMP || - wrap_s == GEN6_TEXCOORDMODE_CLAMP_BORDER); - assert(wrap_t == GEN6_TEXCOORDMODE_CLAMP || - wrap_t == GEN6_TEXCOORDMODE_CLAMP_BORDER); - assert(wrap_r == GEN6_TEXCOORDMODE_CLAMP || - wrap_r == GEN6_TEXCOORDMODE_CLAMP_BORDER); - - assert(mag_filter == GEN6_MAPFILTER_NEAREST || - mag_filter == GEN6_MAPFILTER_LINEAR); - assert(min_filter == GEN6_MAPFILTER_NEAREST || - min_filter == GEN6_MAPFILTER_LINEAR); - - /* work around a bug in util_blitter */ - mip_filter = GEN6_MIPFILTER_NONE; - - assert(mip_filter == GEN6_MIPFILTER_NONE); - } - - if (ilo_dev_gen(dev) >= ILO_GEN(7)) { - dw0 = 1 << 28 | - mip_filter << 20 | - lod_bias << 1; - - sampler->dw_filter = mag_filter << 17 | - min_filter << 14; - - sampler->dw_filter_aniso = GEN6_MAPFILTER_ANISOTROPIC << 17 | - GEN6_MAPFILTER_ANISOTROPIC << 14 | - 1; - - dw1 = min_lod << 20 | - max_lod << 8; - - if (state->compare_mode != PIPE_TEX_COMPARE_NONE) - dw1 |= gen6_translate_shadow_func(state->compare_func) << 1; - - dw3 = max_aniso << 19; - - /* round the coordinates for linear filtering */ - if (min_filter != GEN6_MAPFILTER_NEAREST) { - dw3 |= (GEN6_SAMPLER_DW3_U_MIN_ROUND | - GEN6_SAMPLER_DW3_V_MIN_ROUND | - GEN6_SAMPLER_DW3_R_MIN_ROUND); - } - if (mag_filter != GEN6_MAPFILTER_NEAREST) { - dw3 |= (GEN6_SAMPLER_DW3_U_MAG_ROUND | - GEN6_SAMPLER_DW3_V_MAG_ROUND | - GEN6_SAMPLER_DW3_R_MAG_ROUND); - } - - if (!state->normalized_coords) - dw3 |= 1 << 10; - - sampler->dw_wrap = wrap_s << 6 | - wrap_t << 3 | - wrap_r; - - /* - * As noted in the classic i965 driver, the HW may still reference - * wrap_t and wrap_r for 1D textures. We need to set them to a safe - * mode - */ - sampler->dw_wrap_1d = wrap_s << 6 | - GEN6_TEXCOORDMODE_WRAP << 3 | - GEN6_TEXCOORDMODE_WRAP; - - sampler->dw_wrap_cube = wrap_cube << 6 | - wrap_cube << 3 | - wrap_cube; - - STATIC_ASSERT(Elements(sampler->payload) >= 7); - - sampler->payload[0] = dw0; - sampler->payload[1] = dw1; - sampler->payload[2] = dw3; - - memcpy(&sampler->payload[3], - state->border_color.ui, sizeof(state->border_color.ui)); - } - else { - dw0 = 1 << 28 | - mip_filter << 20 | - lod_bias << 3; - - if (state->compare_mode != PIPE_TEX_COMPARE_NONE) - dw0 |= gen6_translate_shadow_func(state->compare_func); - - sampler->dw_filter = (min_filter != mag_filter) << 27 | - mag_filter << 17 | - min_filter << 14; - - sampler->dw_filter_aniso = GEN6_MAPFILTER_ANISOTROPIC << 17 | - GEN6_MAPFILTER_ANISOTROPIC << 14; - - dw1 = min_lod << 22 | - max_lod << 12; - - sampler->dw_wrap = wrap_s << 6 | - wrap_t << 3 | - wrap_r; - - sampler->dw_wrap_1d = wrap_s << 6 | - GEN6_TEXCOORDMODE_WRAP << 3 | - GEN6_TEXCOORDMODE_WRAP; - - sampler->dw_wrap_cube = wrap_cube << 6 | - wrap_cube << 3 | - wrap_cube; - - dw3 = max_aniso << 19; - - /* round the coordinates for linear filtering */ - if (min_filter != GEN6_MAPFILTER_NEAREST) { - dw3 |= (GEN6_SAMPLER_DW3_U_MIN_ROUND | - GEN6_SAMPLER_DW3_V_MIN_ROUND | - GEN6_SAMPLER_DW3_R_MIN_ROUND); - } - if (mag_filter != GEN6_MAPFILTER_NEAREST) { - dw3 |= (GEN6_SAMPLER_DW3_U_MAG_ROUND | - GEN6_SAMPLER_DW3_V_MAG_ROUND | - GEN6_SAMPLER_DW3_R_MAG_ROUND); - } - - if (!state->normalized_coords) - dw3 |= 1; - - STATIC_ASSERT(Elements(sampler->payload) >= 15); - - sampler->payload[0] = dw0; - sampler->payload[1] = dw1; - sampler->payload[2] = dw3; - - sampler_init_border_color_gen6(dev, - &state->border_color, &sampler->payload[3], 12); - } -} diff --git a/src/gallium/drivers/ilo/ilo_render_dynamic.c b/src/gallium/drivers/ilo/ilo_render_dynamic.c index a346ebb3201..d7822281611 100644 --- a/src/gallium/drivers/ilo/ilo_render_dynamic.c +++ b/src/gallium/drivers/ilo/ilo_render_dynamic.c @@ -137,12 +137,11 @@ gen6_emit_draw_dynamic_samplers(struct ilo_render *r, int shader_type, struct ilo_render_draw_session *session) { - const struct ilo_sampler_cso * const *samplers = - vec->sampler[shader_type].cso; - const struct pipe_sampler_view * const *views = - (const struct pipe_sampler_view **) vec->view[shader_type].states; + const struct ilo_view_cso * const *views = + (const struct ilo_view_cso **) vec->view[shader_type].states; + struct ilo_state_sampler samplers[ILO_MAX_SAMPLERS]; uint32_t *sampler_state, *border_color_state; - int sampler_count; + int sampler_count, i; bool emit_border_color = false; bool skip = false; @@ -194,16 +193,28 @@ gen6_emit_draw_dynamic_samplers(struct ilo_render *r, sampler_count <= Elements(vec->sampler[shader_type].cso)); if (emit_border_color) { - int i; - for (i = 0; i < sampler_count; i++) { - border_color_state[i] = (samplers[i]) ? - gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0; + const struct ilo_sampler_cso *cso = vec->sampler[shader_type].cso[i]; + + border_color_state[i] = (cso) ? + gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, &cso->border) : 0; + } + } + + for (i = 0; i < sampler_count; i++) { + const struct ilo_sampler_cso *cso = vec->sampler[shader_type].cso[i]; + + if (cso && views[i]) { + samplers[i] = cso->sampler; + ilo_state_sampler_set_surface(&samplers[i], + r->dev, &views[i]->surface); + } else { + samplers[i] = vec->disabled_sampler; } } - *sampler_state = gen6_SAMPLER_STATE(r->builder, - samplers, views, border_color_state, sampler_count); + *sampler_state = gen6_SAMPLER_STATE(r->builder, samplers, + border_color_state, sampler_count); } static void @@ -466,10 +477,9 @@ gen6_emit_launch_grid_dynamic_samplers(struct ilo_render *r, { const unsigned shader_type = PIPE_SHADER_COMPUTE; const struct ilo_shader_state *cs = vec->cs; - const struct ilo_sampler_cso * const *samplers = - vec->sampler[shader_type].cso; - const struct pipe_sampler_view * const *views = - (const struct pipe_sampler_view **) vec->view[shader_type].states; + const struct ilo_view_cso * const *views = + (const struct ilo_view_cso **) vec->view[shader_type].states; + struct ilo_state_sampler samplers[ILO_MAX_SAMPLERS]; int sampler_count, i; ILO_DEV_ASSERT(r->dev, 7, 7.5); @@ -480,11 +490,25 @@ gen6_emit_launch_grid_dynamic_samplers(struct ilo_render *r, sampler_count <= Elements(vec->sampler[shader_type].cso)); for (i = 0; i < sampler_count; i++) { - r->state.cs.SAMPLER_BORDER_COLOR_STATE[i] = (samplers[i]) ? - gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0; + const struct ilo_sampler_cso *cso = vec->sampler[shader_type].cso[i]; + + r->state.cs.SAMPLER_BORDER_COLOR_STATE[i] = (cso) ? + gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, &cso->border) : 0; + } + + for (i = 0; i < sampler_count; i++) { + const struct ilo_sampler_cso *cso = vec->sampler[shader_type].cso[i]; + + if (cso && views[i]) { + samplers[i] = cso->sampler; + ilo_state_sampler_set_surface(&samplers[i], + r->dev, &views[i]->surface); + } else { + samplers[i] = vec->disabled_sampler; + } } - r->state.cs.SAMPLER_STATE = gen6_SAMPLER_STATE(r->builder, samplers, views, + r->state.cs.SAMPLER_STATE = gen6_SAMPLER_STATE(r->builder, samplers, r->state.cs.SAMPLER_BORDER_COLOR_STATE, sampler_count); } diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index 060f8ae4453..82fa6696e90 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -37,6 +37,89 @@ #include "ilo_shader.h" #include "ilo_state.h" +static enum gen_mip_filter +ilo_translate_mip_filter(unsigned filter) +{ + switch (filter) { + case PIPE_TEX_MIPFILTER_NEAREST: return GEN6_MIPFILTER_NEAREST; + case PIPE_TEX_MIPFILTER_LINEAR: return GEN6_MIPFILTER_LINEAR; + case PIPE_TEX_MIPFILTER_NONE: return GEN6_MIPFILTER_NONE; + default: + assert(!"unknown mipfilter"); + return GEN6_MIPFILTER_NONE; + } +} + +static int +ilo_translate_img_filter(unsigned filter) +{ + switch (filter) { + case PIPE_TEX_FILTER_NEAREST: return GEN6_MAPFILTER_NEAREST; + case PIPE_TEX_FILTER_LINEAR: return GEN6_MAPFILTER_LINEAR; + default: + assert(!"unknown sampler filter"); + return GEN6_MAPFILTER_NEAREST; + } +} + +static enum gen_texcoord_mode +ilo_translate_address_wrap(unsigned wrap) +{ + switch (wrap) { + case PIPE_TEX_WRAP_CLAMP: return GEN8_TEXCOORDMODE_HALF_BORDER; + case PIPE_TEX_WRAP_REPEAT: return GEN6_TEXCOORDMODE_WRAP; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return GEN6_TEXCOORDMODE_CLAMP; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return GEN6_TEXCOORDMODE_CLAMP_BORDER; + case PIPE_TEX_WRAP_MIRROR_REPEAT: return GEN6_TEXCOORDMODE_MIRROR; + case PIPE_TEX_WRAP_MIRROR_CLAMP: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + default: + assert(!"unknown sampler wrap mode"); + return GEN6_TEXCOORDMODE_WRAP; + } +} + +static enum gen_aniso_ratio +ilo_translate_max_anisotropy(unsigned max_anisotropy) +{ + switch (max_anisotropy) { + case 0: case 1: case 2: return GEN6_ANISORATIO_2; + case 3: case 4: return GEN6_ANISORATIO_4; + case 5: case 6: return GEN6_ANISORATIO_6; + case 7: case 8: return GEN6_ANISORATIO_8; + case 9: case 10: return GEN6_ANISORATIO_10; + case 11: case 12: return GEN6_ANISORATIO_12; + case 13: case 14: return GEN6_ANISORATIO_14; + default: return GEN6_ANISORATIO_16; + } +} + +static enum gen_prefilter_op +ilo_translate_shadow_func(unsigned func) +{ + /* + * For PIPE_FUNC_x, the reference value is on the left-hand side of the + * comparison, and 1.0 is returned when the comparison is true. + * + * For GEN6_PREFILTEROP_x, the reference value is on the right-hand side of + * the comparison, and 0.0 is returned when the comparison is true. + */ + switch (func) { + case PIPE_FUNC_NEVER: return GEN6_PREFILTEROP_ALWAYS; + case PIPE_FUNC_LESS: return GEN6_PREFILTEROP_LEQUAL; + case PIPE_FUNC_EQUAL: return GEN6_PREFILTEROP_NOTEQUAL; + case PIPE_FUNC_LEQUAL: return GEN6_PREFILTEROP_LESS; + case PIPE_FUNC_GREATER: return GEN6_PREFILTEROP_GEQUAL; + case PIPE_FUNC_NOTEQUAL: return GEN6_PREFILTEROP_EQUAL; + case PIPE_FUNC_GEQUAL: return GEN6_PREFILTEROP_GREATER; + case PIPE_FUNC_ALWAYS: return GEN6_PREFILTEROP_NEVER; + default: + assert(!"unknown shadow compare function"); + return GEN6_PREFILTEROP_NEVER; + } +} + static void finalize_shader_states(struct ilo_state_vector *vec) { @@ -336,11 +419,105 @@ ilo_create_sampler_state(struct pipe_context *pipe, { const struct ilo_dev *dev = ilo_context(pipe)->dev; struct ilo_sampler_cso *sampler; + struct ilo_state_sampler_info info; + struct ilo_state_sampler_border_info border; - sampler = MALLOC_STRUCT(ilo_sampler_cso); + sampler = CALLOC_STRUCT(ilo_sampler_cso); assert(sampler); - ilo_gpe_init_sampler_cso(dev, state, sampler); + memset(&info, 0, sizeof(info)); + + info.non_normalized = !state->normalized_coords; + if (state->normalized_coords) { + info.lod_bias = state->lod_bias; + info.min_lod = state->min_lod; + info.max_lod = state->max_lod; + + info.mip_filter = ilo_translate_mip_filter(state->min_mip_filter); + } else { + /* work around a bug in util_blitter */ + info.mip_filter = GEN6_MIPFILTER_NONE; + } + + if (state->max_anisotropy) { + info.min_filter = GEN6_MAPFILTER_ANISOTROPIC; + info.mag_filter = GEN6_MAPFILTER_ANISOTROPIC; + } else { + info.min_filter = ilo_translate_img_filter(state->min_img_filter); + info.mag_filter = ilo_translate_img_filter(state->mag_img_filter); + } + + info.max_anisotropy = ilo_translate_max_anisotropy(state->max_anisotropy); + + /* use LOD 0 when no mipmapping (see sampler_set_gen6_SAMPLER_STATE()) */ + if (info.mip_filter == GEN6_MIPFILTER_NONE && info.min_lod > 0.0f) { + info.min_lod = 0.0f; + info.mag_filter = info.min_filter; + } + + if (state->seamless_cube_map) { + if (state->min_img_filter == PIPE_TEX_FILTER_NEAREST || + state->mag_img_filter == PIPE_TEX_FILTER_NEAREST) { + info.tcx_ctrl = GEN6_TEXCOORDMODE_CLAMP; + info.tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP; + info.tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP; + } else { + info.tcx_ctrl = GEN6_TEXCOORDMODE_CUBE; + info.tcy_ctrl = GEN6_TEXCOORDMODE_CUBE; + info.tcz_ctrl = GEN6_TEXCOORDMODE_CUBE; + } + } else { + info.tcx_ctrl = ilo_translate_address_wrap(state->wrap_s); + info.tcy_ctrl = ilo_translate_address_wrap(state->wrap_t); + info.tcz_ctrl = ilo_translate_address_wrap(state->wrap_r); + + if (ilo_dev_gen(dev) < ILO_GEN(8)) { + /* + * For nearest filtering, PIPE_TEX_WRAP_CLAMP means + * PIPE_TEX_WRAP_CLAMP_TO_EDGE; for linear filtering, + * PIPE_TEX_WRAP_CLAMP means PIPE_TEX_WRAP_CLAMP_TO_BORDER while + * additionally clamping the texture coordinates to [0.0, 1.0]. + * + * PIPE_TEX_WRAP_CLAMP is not supported natively until Gen8. The + * clamping has to be taken care of in the shaders. There are two + * filters here, but let the minification one has a say. + */ + const bool clamp_is_to_edge = + (state->min_img_filter == PIPE_TEX_FILTER_NEAREST); + + if (clamp_is_to_edge) { + if (info.tcx_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) + info.tcx_ctrl = GEN6_TEXCOORDMODE_CLAMP; + if (info.tcy_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) + info.tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP; + if (info.tcz_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) + info.tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP; + } else { + if (info.tcx_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) { + info.tcx_ctrl = GEN6_TEXCOORDMODE_CLAMP_BORDER; + sampler->saturate_s = true; + } + if (info.tcy_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) { + info.tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP_BORDER; + sampler->saturate_t = true; + } + if (info.tcz_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) { + info.tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP_BORDER; + sampler->saturate_r = true; + } + } + } + } + + if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) + info.shadow_func = ilo_translate_shadow_func(state->compare_func); + + ilo_state_sampler_init(&sampler->sampler, dev, &info); + + memset(&border, 0, sizeof(border)); + memcpy(border.rgba.f, state->border_color.f, sizeof(border.rgba.f)); + + ilo_state_sampler_border_init(&sampler->border, dev, &border); return sampler; } @@ -1358,6 +1535,8 @@ ilo_state_vector_init(const struct ilo_dev *dev, ilo_state_surface_init_for_null(&vec->fb.null_rt, dev); ilo_state_zs_init_for_null(&vec->fb.null_zs, dev); + ilo_state_sampler_init_disabled(&vec->disabled_sampler, dev); + util_dynarray_init(&vec->global_binding.bindings); vec->dirty = ILO_DIRTY_ALL; diff --git a/src/gallium/drivers/ilo/ilo_state.h b/src/gallium/drivers/ilo/ilo_state.h index 9a7d196a2a6..95dbe73bfdc 100644 --- a/src/gallium/drivers/ilo/ilo_state.h +++ b/src/gallium/drivers/ilo/ilo_state.h @@ -29,6 +29,7 @@ #define ILO_STATE_H #include "core/ilo_state_3d.h" +#include "core/ilo_state_sampler.h" #include "core/ilo_state_surface.h" #include "core/ilo_state_zs.h" #include "pipe/p_state.h" @@ -135,6 +136,18 @@ struct ilo_cbuf_cso { const void *user_buffer; }; +struct ilo_sampler_cso { + struct ilo_state_sampler sampler; + struct ilo_state_sampler_border border; + bool saturate_s; + bool saturate_t; + bool saturate_r; +}; + +struct ilo_sampler_state { + const struct ilo_sampler_cso *cso[ILO_MAX_SAMPLERS]; +}; + struct ilo_cbuf_state { struct ilo_cbuf_cso cso[ILO_MAX_CONST_BUFFERS]; uint32_t enabled_mask; @@ -216,6 +229,8 @@ struct ilo_state_vector { struct ilo_cbuf_state cbuf[PIPE_SHADER_TYPES]; struct ilo_resource_state resource; + struct ilo_state_sampler disabled_sampler; + /* GPGPU */ struct ilo_shader_state *cs; struct ilo_resource_state cs_resource; |