From bf95f7c2098efc1771385b3db02c16f377e53d8f Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 29 Mar 2017 21:10:50 -0700 Subject: [PATCH] intel/isl: Add support for emitting depth/stencil/hiz Reviewed-by: Topi Pohjolainen --- src/intel/Makefile.sources | 7 + src/intel/isl/isl.c | 93 ++++++++++++ src/intel/isl/isl.h | 74 +++++++++ src/intel/isl/isl_emit_depth_stencil.c | 199 +++++++++++++++++++++++++ src/intel/isl/isl_priv.h | 28 ++++ 5 files changed, 401 insertions(+) create mode 100644 src/intel/isl/isl_emit_depth_stencil.c diff --git a/src/intel/Makefile.sources b/src/intel/Makefile.sources index aa04c078985..d7bc09ef7a8 100644 --- a/src/intel/Makefile.sources +++ b/src/intel/Makefile.sources @@ -144,32 +144,39 @@ ISL_FILES = \ ISL_GEN4_FILES = \ isl/isl_gen4.c \ isl/isl_gen4.h \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GEN5_FILES = \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GEN6_FILES = \ isl/isl_gen6.c \ isl/isl_gen6.h \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GEN7_FILES = \ isl/isl_gen7.c \ isl/isl_gen7.h \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GEN75_FILES = \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GEN8_FILES = \ isl/isl_gen8.c \ isl/isl_gen8.h \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GEN9_FILES = \ isl/isl_gen9.c \ isl/isl_gen9.h \ + isl/isl_emit_depth_stencil.c \ isl/isl_surface_state.c ISL_GENERATED_FILES = \ diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c index 4e899912260..f89f351c157 100644 --- a/src/intel/isl/isl.c +++ b/src/intel/isl/isl.c @@ -83,6 +83,32 @@ isl_device_init(struct isl_device *dev, */ dev->ss.aux_addr_offset = (RENDER_SURFACE_STATE_AuxiliarySurfaceBaseAddress_start(info) & ~31) / 8; + + dev->ds.size = + _3DSTATE_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_STENCIL_BUFFER_length(info) * 4 + + _3DSTATE_HIER_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_CLEAR_PARAMS_length(info) * 4; + + assert(_3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ds.depth_offset = + _3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; + + if (info->has_hiz_and_separate_stencil) { + assert(_3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ds.stencil_offset = + _3DSTATE_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) / 8; + + assert(_3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ds.hiz_offset = + _3DSTATE_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_STENCIL_BUFFER_length(info) * 4 + + _3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; + } else { + dev->ds.stencil_offset = 0; + dev->ds.hiz_offset = 0; + } } /** @@ -1684,6 +1710,73 @@ isl_buffer_fill_state_s(const struct isl_device *dev, void *state, } } +void +isl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info) +{ + if (info->depth_surf && info->stencil_surf) { + if (!dev->info->has_hiz_and_separate_stencil) { + assert(info->depth_surf == info->stencil_surf); + assert(info->depth_address == info->stencil_address); + } + assert(info->depth_surf->dim == info->stencil_surf->dim); + } + + if (info->depth_surf) { + assert((info->depth_surf->usage & ISL_SURF_USAGE_DEPTH_BIT)); + if (info->depth_surf->dim == ISL_SURF_DIM_3D) { + assert(info->view->base_array_layer + info->view->array_len <= + info->depth_surf->logical_level0_px.depth); + } else { + assert(info->view->base_array_layer + info->view->array_len <= + info->depth_surf->logical_level0_px.array_len); + } + } + + if (info->stencil_surf) { + assert((info->stencil_surf->usage & ISL_SURF_USAGE_STENCIL_BIT)); + if (info->stencil_surf->dim == ISL_SURF_DIM_3D) { + assert(info->view->base_array_layer + info->view->array_len <= + info->stencil_surf->logical_level0_px.depth); + } else { + assert(info->view->base_array_layer + info->view->array_len <= + info->stencil_surf->logical_level0_px.array_len); + } + } + + switch (ISL_DEV_GEN(dev)) { + case 4: + if (ISL_DEV_IS_G4X(dev)) { + /* G45 surface state is the same as gen5 */ + isl_gen5_emit_depth_stencil_hiz_s(dev, batch, info); + } else { + isl_gen4_emit_depth_stencil_hiz_s(dev, batch, info); + } + break; + case 5: + isl_gen5_emit_depth_stencil_hiz_s(dev, batch, info); + break; + case 6: + isl_gen6_emit_depth_stencil_hiz_s(dev, batch, info); + break; + case 7: + if (ISL_DEV_IS_HASWELL(dev)) { + isl_gen75_emit_depth_stencil_hiz_s(dev, batch, info); + } else { + isl_gen7_emit_depth_stencil_hiz_s(dev, batch, info); + } + break; + case 8: + isl_gen8_emit_depth_stencil_hiz_s(dev, batch, info); + break; + case 9: + isl_gen9_emit_depth_stencil_hiz_s(dev, batch, info); + break; + default: + assert(!"Cannot fill surface state for this gen"); + } +} + /** * A variant of isl_surf_get_image_offset_sa() specific to * ISL_DIM_LAYOUT_GEN4_2D. diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h index 17b52cf2f4f..1172c4e82b0 100644 --- a/src/intel/isl/isl.h +++ b/src/intel/isl/isl.h @@ -682,6 +682,17 @@ struct isl_device { uint8_t addr_offset; uint8_t aux_addr_offset; } ss; + + /** + * Describes the layout of the depth/stencil/hiz commands as emitted by + * isl_emit_depth_stencil_hiz. + */ + struct { + uint8_t size; + uint8_t depth_offset; + uint8_t stencil_offset; + uint8_t hiz_offset; + } ds; }; struct isl_extent2d { @@ -1017,6 +1028,61 @@ struct isl_buffer_fill_state_info { uint32_t stride; }; +struct isl_depth_stencil_hiz_emit_info { + /** + * The depth surface + */ + const struct isl_surf *depth_surf; + + /** + * The stencil surface + * + * If separate stencil is not available, this must point to the same + * isl_surf as depth_surf. + */ + const struct isl_surf *stencil_surf; + + /** + * The view into the depth and stencil surfaces. + * + * This view applies to both surfaces simultaneously. + */ + const struct isl_view *view; + + /** + * The address of the depth surface in GPU memory + */ + uint64_t depth_address; + + /** + * The address of the stencil surface in GPU memory + * + * If separate stencil is not available, this must have the same value as + * depth_address. + */ + uint64_t stencil_address; + + /** + * The Memory Object Control state for depth and stencil buffers + * + * Both depth and stencil will get the same MOCS value. The exact format + * of this value depends on hardware generation. + */ + uint32_t mocs; + + /** + * The HiZ surfae or NULL if HiZ is disabled. + */ + const struct isl_surf *hiz_surf; + enum isl_aux_usage hiz_usage; + uint64_t hiz_address; + + /** + * The depth clear value + */ + float depth_clear_value; +}; + extern const struct isl_format_layout isl_format_layouts[]; void @@ -1315,6 +1381,14 @@ void isl_buffer_fill_state_s(const struct isl_device *dev, void *state, const struct isl_buffer_fill_state_info *restrict info); +#define isl_emit_depth_stencil_hiz(dev, batch, ...) \ + isl_emit_depth_stencil_hiz_s((dev), (batch), \ + &(struct isl_depth_stencil_hiz_emit_info) { __VA_ARGS__ }) + +void +isl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + void isl_surf_fill_image_param(const struct isl_device *dev, struct brw_image_param *param, diff --git a/src/intel/isl/isl_emit_depth_stencil.c b/src/intel/isl/isl_emit_depth_stencil.c new file mode 100644 index 00000000000..4869659c627 --- /dev/null +++ b/src/intel/isl/isl_emit_depth_stencil.c @@ -0,0 +1,199 @@ +/* + * Copyright 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include + +#define __gen_address_type uint64_t +#define __gen_user_data void + +static inline uint64_t +__gen_combine_address(void *data, void *loc, uint64_t addr, uint32_t delta) +{ + return addr + delta; +} + +#include "genxml/gen_macros.h" +#include "genxml/genX_pack.h" + +#include "isl_priv.h" + +#define __PASTE2(x, y) x ## y +#define __PASTE(x, y) __PASTE2(x, y) +#define isl_genX(x) __PASTE(isl_, genX(x)) + +static const uint32_t isl_to_gen_ds_surftype [] = { +#if GEN_GEN >= 9 + /* From the SKL PRM, "3DSTATE_DEPTH_STENCIL::SurfaceType": + * + * "If depth/stencil is enabled with 1D render target, depth/stencil + * surface type needs to be set to 2D surface type and height set to 1. + * Depth will use (legacy) TileY and stencil will use TileW. For this + * case only, the Surface Type of the depth buffer can be 2D while the + * Surface Type of the render target(s) are 1D, representing an + * exception to a programming note above. + */ + [ISL_SURF_DIM_1D] = SURFTYPE_2D, +#else + [ISL_SURF_DIM_1D] = SURFTYPE_1D, +#endif + [ISL_SURF_DIM_2D] = SURFTYPE_2D, + [ISL_SURF_DIM_3D] = SURFTYPE_3D, +}; + +void +isl_genX(emit_depth_stencil_hiz_s)(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info) +{ + struct GENX(3DSTATE_DEPTH_BUFFER) db = { + GENX(3DSTATE_DEPTH_BUFFER_header), + }; + + if (info->depth_surf) { + db.SurfaceType = isl_to_gen_ds_surftype[info->depth_surf->dim]; + db.SurfaceFormat = isl_surf_get_depth_format(dev, info->depth_surf); + db.Width = info->depth_surf->logical_level0_px.width - 1; + db.Height = info->depth_surf->logical_level0_px.height - 1; + } else if (info->stencil_surf) { + db.SurfaceType = isl_to_gen_ds_surftype[info->stencil_surf->dim]; + db.SurfaceFormat = D32_FLOAT; + db.Width = info->stencil_surf->logical_level0_px.width - 1; + db.Height = info->stencil_surf->logical_level0_px.height - 1; + } else { + db.SurfaceType = SURFTYPE_NULL; + db.SurfaceFormat = D32_FLOAT; + } + + if (info->depth_surf || info->stencil_surf) { + /* These are based entirely on the view */ + db.Depth = db.RenderTargetViewExtent = info->view->array_len - 1; + db.LOD = info->view->base_level; + db.MinimumArrayElement = info->view->base_array_layer; + } + + if (info->depth_surf) { +#if GEN_GEN >= 7 + db.DepthWriteEnable = true; +#endif + db.SurfaceBaseAddress = info->depth_address; +#if GEN_GEN >= 6 + db.DepthBufferMOCS = info->mocs; +#endif + +#if GEN_GEN <= 6 + db.TiledSurface = info->depth_surf->tiling != ISL_TILING_LINEAR; + db.TileWalk = info->depth_surf->tiling == ISL_TILING_Y0 ? TILEWALK_YMAJOR : + TILEWALK_XMAJOR; + db.MIPMapLayoutMode = MIPLAYOUT_BELOW; +#endif + + db.SurfacePitch = info->depth_surf->row_pitch - 1; +#if GEN_GEN >= 8 + db.SurfaceQPitch = + isl_surf_get_array_pitch_el_rows(info->depth_surf) >> 2; +#endif + } + +#if GEN_GEN >= 6 + struct GENX(3DSTATE_STENCIL_BUFFER) sb = { + GENX(3DSTATE_STENCIL_BUFFER_header), + }; +#else +# define sb db +#endif + + if (info->stencil_surf) { +#if GEN_GEN >= 7 + db.StencilWriteEnable = true; +#endif +#if GEN_GEN >= 8 || GEN_IS_HASWELL + sb.StencilBufferEnable = true; +#endif + sb.SurfaceBaseAddress = info->stencil_address; +#if GEN_GEN >= 6 + sb.StencilBufferMOCS = info->mocs; +#endif + sb.SurfacePitch = info->stencil_surf->row_pitch - 1; +#if GEN_GEN >= 8 + sb.SurfaceQPitch = + isl_surf_get_array_pitch_el_rows(info->stencil_surf) >> 2; +#endif + } + +#if GEN_GEN >= 6 + struct GENX(3DSTATE_HIER_DEPTH_BUFFER) hiz = { + GENX(3DSTATE_HIER_DEPTH_BUFFER_header), + }; + struct GENX(3DSTATE_CLEAR_PARAMS) clear = { + GENX(3DSTATE_CLEAR_PARAMS_header), + }; + + assert(info->hiz_usage == ISL_AUX_USAGE_NONE || + info->hiz_usage == ISL_AUX_USAGE_HIZ); + if (info->hiz_usage == ISL_AUX_USAGE_HIZ) { + db.HierarchicalDepthBufferEnable = true; +#if GEN_GEN == 5 || GEN_GEN == 6 + db.SeparateStencilBufferEnable = true; +#endif + + hiz.SurfaceBaseAddress = info->hiz_address; + hiz.HierarchicalDepthBufferMOCS = info->mocs; + hiz.SurfacePitch = info->hiz_surf->row_pitch - 1; +#if GEN_GEN >= 8 + /* From the SKL PRM Vol2a: + * + * The interpretation of this field is dependent on Surface Type + * as follows: + * - SURFTYPE_1D: distance in pixels between array slices + * - SURFTYPE_2D/CUBE: distance in rows between array slices + * - SURFTYPE_3D: distance in rows between R - slices + * + * Unfortunately, the docs aren't 100% accurate here. They fail to + * mention that the 1-D rule only applies to linear 1-D images. + * Since depth and HiZ buffers are always tiled, they are treated as + * 2-D images. Prior to Sky Lake, this field is always in rows. + */ + hiz.SurfaceQPitch = + isl_surf_get_array_pitch_sa_rows(info->hiz_surf) >> 2; +#endif + + clear.DepthClearValueValid = true; + clear.DepthClearValue = info->depth_clear_value; + } +#endif /* GEN_GEN >= 6 */ + + /* Pack everything into the batch */ + uint32_t *dw = batch; + GENX(3DSTATE_DEPTH_BUFFER_pack)(NULL, dw, &db); + dw += GENX(3DSTATE_DEPTH_BUFFER_length); + +#if GEN_GEN >= 6 + GENX(3DSTATE_STENCIL_BUFFER_pack)(NULL, dw, &sb); + dw += GENX(3DSTATE_STENCIL_BUFFER_length); + + GENX(3DSTATE_HIER_DEPTH_BUFFER_pack)(NULL, dw, &hiz); + dw += GENX(3DSTATE_HIER_DEPTH_BUFFER_length); + + GENX(3DSTATE_CLEAR_PARAMS_pack)(NULL, dw, &clear); + dw += GENX(3DSTATE_CLEAR_PARAMS_length); +#endif +} diff --git a/src/intel/isl/isl_priv.h b/src/intel/isl/isl_priv.h index 1867d258822..3c4cc1ed95b 100644 --- a/src/intel/isl/isl_priv.h +++ b/src/intel/isl/isl_priv.h @@ -205,4 +205,32 @@ void isl_gen9_buffer_fill_state_s(void *state, const struct isl_buffer_fill_state_info *restrict info); +void +isl_gen4_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + +void +isl_gen5_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + +void +isl_gen6_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + +void +isl_gen7_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + +void +isl_gen75_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + +void +isl_gen8_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + +void +isl_gen9_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info); + #endif /* ISL_PRIV_H */ -- 2.30.2