X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fintel%2Fisl%2Fisl_surface_state.c;h=b7354781cf0f79ec539e15f13e83fd314291c7a6;hb=ff0dd67d2f9fc7cc240da732153ac4fac4e8d04d;hp=4a7e921a798ab7aba869ae0dc79d33a13f6c9f04;hpb=dc880c99b656988eadf012000a01869e40be8f57;p=mesa.git diff --git a/src/intel/isl/isl_surface_state.c b/src/intel/isl/isl_surface_state.c index 4a7e921a798..b7354781cf0 100644 --- a/src/intel/isl/isl_surface_state.c +++ b/src/intel/isl/isl_surface_state.c @@ -113,12 +113,14 @@ get_surftype(enum isl_surf_dim dim, isl_surf_usage_flags_t usage) assert(!(usage & ISL_SURF_USAGE_CUBE_BIT)); return SURFTYPE_1D; case ISL_SURF_DIM_2D: - if (usage & ISL_SURF_USAGE_STORAGE_BIT) { - /* Storage images are always plain 2-D, not cube */ - return SURFTYPE_2D; - } else if (usage & ISL_SURF_USAGE_CUBE_BIT) { + if ((usage & ISL_SURF_USAGE_CUBE_BIT) && + (usage & ISL_SURF_USAGE_TEXTURE_BIT)) { + /* We need SURFTYPE_CUBE to make cube sampling work */ return SURFTYPE_CUBE; } else { + /* Everything else (render and storage) treat cubes as plain + * 2D array textures + */ return SURFTYPE_2D; } case ISL_SURF_DIM_3D: @@ -172,9 +174,21 @@ get_qpitch(const struct isl_surf *surf) default: unreachable("Bad isl_surf_dim"); case ISL_DIM_LAYOUT_GEN4_2D: - case ISL_DIM_LAYOUT_GEN4_3D: if (GEN_GEN >= 9) { - return isl_surf_get_array_pitch_el_rows(surf); + if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) { + /* This is rather annoying and completely undocumented. It + * appears that the hardware has a bug (or undocumented feature) + * regarding stencil buffers most likely related to the way + * W-tiling is handled as modified Y-tiling. If you bind a 3-D + * stencil buffer normally, and use texelFetch on it, the z or + * array index will get implicitly multiplied by 2 for no obvious + * reason. The fix appears to be to divide qpitch by 2 for + * W-tiled surfaces. + */ + return isl_surf_get_array_pitch_el_rows(surf) / 2; + } else { + return isl_surf_get_array_pitch_el_rows(surf); + } } else { /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch * @@ -199,6 +213,22 @@ get_qpitch(const struct isl_surf *surf) * slices. */ return isl_surf_get_array_pitch_el(surf); + case ISL_DIM_LAYOUT_GEN4_3D: + /* QPitch doesn't make sense for ISL_DIM_LAYOUT_GEN4_3D since it uses a + * different pitch at each LOD. Also, the QPitch field is ignored for + * these surfaces. From the Broadwell PRM documentation for QPitch: + * + * This field specifies the distance in rows between array slices. It + * is used only in the following cases: + * - Surface Array is enabled OR + * - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled + * Surface Storage Format set to MSFMT_MSS OR + * - Surface Type is SURFTYPE_CUBE + * + * None of the three conditions above can possibly apply to a 3D surface + * so it is safe to just set QPitch to 0. + */ + return 0; } } #endif /* GEN_GEN >= 8 */ @@ -210,12 +240,29 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state, struct GENX(RENDER_SURFACE_STATE) s = { 0 }; s.SurfaceType = get_surftype(info->surf->dim, info->view->usage); + + if (info->view->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) + assert(isl_format_supports_rendering(dev->info, info->view->format)); + else if (info->view->usage & ISL_SURF_USAGE_TEXTURE_BIT) + assert(isl_format_supports_sampling(dev->info, info->view->format)); + + /* From the Sky Lake PRM Vol. 2d, RENDER_SURFACE_STATE::SurfaceFormat + * + * This field cannot be a compressed (BC*, DXT*, FXT*, ETC*, EAC*) + * format if the Surface Type is SURFTYPE_1D + */ + if (info->surf->dim == ISL_SURF_DIM_1D) + assert(!isl_format_is_compressed(info->view->format)); + s.SurfaceFormat = info->view->format; #if GEN_IS_HASWELL s.IntegerSurfaceFormat = isl_format_has_int_channel(s.SurfaceFormat); #endif + assert(info->surf->logical_level0_px.width > 0 && + info->surf->logical_level0_px.height > 0); + s.Width = info->surf->logical_level0_px.width - 1; s.Height = info->surf->logical_level0_px.height - 1; @@ -283,8 +330,6 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state, s.RenderTargetViewExtent = s.Depth; break; case SURFTYPE_3D: - s.MinimumArrayElement = info->view->base_array_layer; - /* From the Broadwell PRM >> RENDER_SURFACE_STATE::Depth: * * If the volume texture is MIP-mapped, this field specifies the @@ -304,11 +349,16 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state, * textures with more levels than we can render to. In order to prevent * assert-failures in the packing function below, we only set the field * when it's actually going to be used by the hardware. + * + * Similaraly, the MinimumArrayElement field is ignored by all hardware + * prior to Sky Lake when texturing and we want it set to 0 anyway. + * Since it's already initialized to 0, we can just leave it alone for + * texture surfaces. */ if (info->view->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT | ISL_SURF_USAGE_STORAGE_BIT)) { - s.RenderTargetViewExtent = isl_minify(info->surf->logical_level0_px.depth, - info->view->base_level) - 1; + s.MinimumArrayElement = info->view->base_array_layer; + s.RenderTargetViewExtent = info->view->array_len - 1; } break; default: @@ -403,10 +453,10 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state, #endif #if (GEN_GEN >= 8 || GEN_IS_HASWELL) - s.ShaderChannelSelectRed = info->view->channel_select[0]; - s.ShaderChannelSelectGreen = info->view->channel_select[1]; - s.ShaderChannelSelectBlue = info->view->channel_select[2]; - s.ShaderChannelSelectAlpha = info->view->channel_select[3]; + s.ShaderChannelSelectRed = info->view->swizzle.r; + s.ShaderChannelSelectGreen = info->view->swizzle.g; + s.ShaderChannelSelectBlue = info->view->swizzle.b; + s.ShaderChannelSelectAlpha = info->view->swizzle.a; #endif s.SurfaceBaseAddress = info->address; @@ -470,6 +520,26 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state, s.AuxiliarySurfaceQPitch = isl_surf_get_array_pitch_sa_rows(info->aux_surf) >> 2; s.AuxiliarySurfaceBaseAddress = info->aux_address; + + if (info->aux_usage == ISL_AUX_USAGE_HIZ) { + /* The number of samples must be 1 */ + assert(info->surf->samples == 1); + + /* The dimension must not be 3D */ + assert(info->surf->dim != ISL_SURF_DIM_3D); + + /* The format must be one of the following: */ + switch (info->view->format) { + case ISL_FORMAT_R32_FLOAT: + case ISL_FORMAT_R24_UNORM_X8_TYPELESS: + case ISL_FORMAT_R16_UNORM: + break; + default: + assert(!"Incompatible HiZ Sampling format"); + break; + } + } + s.AuxiliarySurfaceMode = isl_to_gen_aux_mode[info->aux_usage]; #else assert(info->aux_usage == ISL_AUX_USAGE_MCS || @@ -498,6 +568,15 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state, s.SamplerL2BypassModeDisable = true; break; default: + /* From the SKL PRM, Programming Note under Sampler Output Channel + * Mapping: + * + * If a surface has an associated HiZ Auxilliary surface, the + * Sampler L2 Bypass Mode Disable field in the RENDER_SURFACE_STATE + * must be set. + */ + if (GEN_GEN >= 9 && info->aux_usage == ISL_AUX_USAGE_HIZ) + s.SamplerL2BypassModeDisable = true; break; } }