#include "genxml/gen_macros.h"
#include "genxml/genX_pack.h"
+#include "common/gen_guardband.h"
#if GEN_GEN == 8
void
gen8_cmd_buffer_emit_viewport(struct anv_cmd_buffer *cmd_buffer)
{
- uint32_t count = cmd_buffer->state.dynamic.viewport.count;
- const VkViewport *viewports = cmd_buffer->state.dynamic.viewport.viewports;
+ struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
+ uint32_t count = cmd_buffer->state.gfx.dynamic.viewport.count;
+ const VkViewport *viewports =
+ cmd_buffer->state.gfx.dynamic.viewport.viewports;
struct anv_state sf_clip_state =
anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, count * 64, 64);
/* The gen7 state struct has just the matrix and guardband fields, the
* gen8 struct adds the min/max viewport fields. */
- struct GENX(SF_CLIP_VIEWPORT) sf_clip_viewport = {
+ struct GENX(SF_CLIP_VIEWPORT) sfv = {
.ViewportMatrixElementm00 = vp->width / 2,
.ViewportMatrixElementm11 = vp->height / 2,
- .ViewportMatrixElementm22 = 1.0,
+ .ViewportMatrixElementm22 = vp->maxDepth - vp->minDepth,
.ViewportMatrixElementm30 = vp->x + vp->width / 2,
.ViewportMatrixElementm31 = vp->y + vp->height / 2,
- .ViewportMatrixElementm32 = 0.0,
+ .ViewportMatrixElementm32 = vp->minDepth,
.XMinClipGuardband = -1.0f,
.XMaxClipGuardband = 1.0f,
.YMinClipGuardband = -1.0f,
.YMaxClipGuardband = 1.0f,
.XMinViewPort = vp->x,
.XMaxViewPort = vp->x + vp->width - 1,
- .YMinViewPort = vp->y,
- .YMaxViewPort = vp->y + vp->height - 1,
+ .YMinViewPort = MIN2(vp->y, vp->y + vp->height),
+ .YMaxViewPort = MAX2(vp->y, vp->y + vp->height) - 1,
};
- GENX(SF_CLIP_VIEWPORT_pack)(NULL, sf_clip_state.map + i * 64,
- &sf_clip_viewport);
- }
+ if (fb) {
+ /* We can only calculate a "real" guardband clip if we know the
+ * framebuffer at the time we emit the packet. Otherwise, we have
+ * fall back to a worst-case guardband of [-1, 1].
+ */
+ gen_calculate_guardband_size(fb->width, fb->height,
+ sfv.ViewportMatrixElementm00,
+ sfv.ViewportMatrixElementm11,
+ sfv.ViewportMatrixElementm30,
+ sfv.ViewportMatrixElementm31,
+ &sfv.XMinClipGuardband,
+ &sfv.XMaxClipGuardband,
+ &sfv.YMinClipGuardband,
+ &sfv.YMaxClipGuardband);
+ }
- if (!cmd_buffer->device->info.has_llc)
- anv_state_clflush(sf_clip_state);
+ GENX(SF_CLIP_VIEWPORT_pack)(NULL, sf_clip_state.map + i * 64, &sfv);
+ }
anv_batch_emit(&cmd_buffer->batch,
GENX(3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP), clip) {
gen8_cmd_buffer_emit_depth_viewport(struct anv_cmd_buffer *cmd_buffer,
bool depth_clamp_enable)
{
- uint32_t count = cmd_buffer->state.dynamic.viewport.count;
- const VkViewport *viewports = cmd_buffer->state.dynamic.viewport.viewports;
+ uint32_t count = cmd_buffer->state.gfx.dynamic.viewport.count;
+ const VkViewport *viewports =
+ cmd_buffer->state.gfx.dynamic.viewport.viewports;
struct anv_state cc_state =
anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, count * 8, 32);
for (uint32_t i = 0; i < count; i++) {
const VkViewport *vp = &viewports[i];
+ /* From the Vulkan spec:
+ *
+ * "It is valid for minDepth to be greater than or equal to
+ * maxDepth."
+ */
+ float min_depth = MIN2(vp->minDepth, vp->maxDepth);
+ float max_depth = MAX2(vp->minDepth, vp->maxDepth);
+
struct GENX(CC_VIEWPORT) cc_viewport = {
- .MinimumDepth = depth_clamp_enable ? vp->minDepth : 0.0f,
- .MaximumDepth = depth_clamp_enable ? vp->maxDepth : 1.0f,
+ .MinimumDepth = depth_clamp_enable ? min_depth : 0.0f,
+ .MaximumDepth = depth_clamp_enable ? max_depth : 1.0f,
};
GENX(CC_VIEWPORT_pack)(NULL, cc_state.map + i * 8, &cc_viewport);
}
- if (!cmd_buffer->device->info.has_llc)
- anv_state_clflush(cc_state);
-
anv_batch_emit(&cmd_buffer->batch,
GENX(3DSTATE_VIEWPORT_STATE_POINTERS_CC), cc) {
cc.CCViewportPointer = cc_state.offset;
}
#endif
-static void
-__emit_genx_sf_state(struct anv_cmd_buffer *cmd_buffer)
+void
+genX(cmd_buffer_enable_pma_fix)(struct anv_cmd_buffer *cmd_buffer, bool enable)
{
- uint32_t sf_dw[GENX(3DSTATE_SF_length)];
- struct GENX(3DSTATE_SF) sf = {
- GENX(3DSTATE_SF_header),
- .LineWidth = cmd_buffer->state.dynamic.line_width,
- };
- GENX(3DSTATE_SF_pack)(NULL, sf_dw, &sf);
- /* FIXME: gen9.fs */
- anv_batch_emit_merge(&cmd_buffer->batch, sf_dw,
- cmd_buffer->state.pipeline->gen8.sf);
+ if (cmd_buffer->state.pma_fix_enabled == enable)
+ return;
+
+ cmd_buffer->state.pma_fix_enabled = enable;
+
+ /* According to the Broadwell PIPE_CONTROL documentation, software should
+ * emit a PIPE_CONTROL with the CS Stall and Depth Cache Flush bits set
+ * prior to the LRI. If stencil buffer writes are enabled, then a Render
+ * Cache Flush is also necessary.
+ *
+ * The Skylake docs say to use a depth stall rather than a command
+ * streamer stall. However, the hardware seems to violently disagree.
+ * A full command streamer stall seems to be needed in both cases.
+ */
+ anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
+ pc.DepthCacheFlushEnable = true;
+ pc.CommandStreamerStallEnable = true;
+ pc.RenderTargetCacheFlushEnable = true;
+#if GEN_GEN >= 12
+ pc.TileCacheFlushEnable = true;
+
+ /* GEN:BUG:1409600907: "PIPE_CONTROL with Depth Stall Enable bit must
+ * be set with any PIPE_CONTROL with Depth Flush Enable bit set.
+ */
+ pc.DepthStallEnable = true;
+#endif
+ }
+
+#if GEN_GEN == 9
+
+ uint32_t cache_mode;
+ anv_pack_struct(&cache_mode, GENX(CACHE_MODE_0),
+ .STCPMAOptimizationEnable = enable,
+ .STCPMAOptimizationEnableMask = true);
+ anv_batch_emit(&cmd_buffer->batch, GENX(MI_LOAD_REGISTER_IMM), lri) {
+ lri.RegisterOffset = GENX(CACHE_MODE_0_num);
+ lri.DataDWord = cache_mode;
+ }
+
+#elif GEN_GEN == 8
+
+ uint32_t cache_mode;
+ anv_pack_struct(&cache_mode, GENX(CACHE_MODE_1),
+ .NPPMAFixEnable = enable,
+ .NPEarlyZFailsDisable = enable,
+ .NPPMAFixEnableMask = true,
+ .NPEarlyZFailsDisableMask = true);
+ anv_batch_emit(&cmd_buffer->batch, GENX(MI_LOAD_REGISTER_IMM), lri) {
+ lri.RegisterOffset = GENX(CACHE_MODE_1_num);
+ lri.DataDWord = cache_mode;
+ }
+
+#endif /* GEN_GEN == 8 */
+
+ /* After the LRI, a PIPE_CONTROL with both the Depth Stall and Depth Cache
+ * Flush bits is often necessary. We do it regardless because it's easier.
+ * The render cache flush is also necessary if stencil writes are enabled.
+ *
+ * Again, the Skylake docs give a different set of flushes but the BDW
+ * flushes seem to work just as well.
+ */
+ anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
+ pc.DepthStallEnable = true;
+ pc.DepthCacheFlushEnable = true;
+ pc.RenderTargetCacheFlushEnable = true;
+#if GEN_GEN >= 12
+ pc.TileCacheFlushEnable = true;
+#endif
+ }
}
-#include "genxml/gen9_pack.h"
-static void
-__emit_gen9_sf_state(struct anv_cmd_buffer *cmd_buffer)
+UNUSED static bool
+want_depth_pma_fix(struct anv_cmd_buffer *cmd_buffer)
{
- uint32_t sf_dw[GENX(3DSTATE_SF_length)];
- struct GEN9_3DSTATE_SF sf = {
- GEN9_3DSTATE_SF_header,
- .LineWidth = cmd_buffer->state.dynamic.line_width,
- };
- GEN9_3DSTATE_SF_pack(NULL, sf_dw, &sf);
- /* FIXME: gen9.fs */
- anv_batch_emit_merge(&cmd_buffer->batch, sf_dw,
- cmd_buffer->state.pipeline->gen8.sf);
+ assert(GEN_GEN == 8);
+
+ /* From the Broadwell PRM Vol. 2c CACHE_MODE_1::NP_PMA_FIX_ENABLE:
+ *
+ * SW must set this bit in order to enable this fix when following
+ * expression is TRUE.
+ *
+ * 3DSTATE_WM::ForceThreadDispatch != 1 &&
+ * !(3DSTATE_RASTER::ForceSampleCount != NUMRASTSAMPLES_0) &&
+ * (3DSTATE_DEPTH_BUFFER::SURFACE_TYPE != NULL) &&
+ * (3DSTATE_DEPTH_BUFFER::HIZ Enable) &&
+ * !(3DSTATE_WM::EDSC_Mode == EDSC_PREPS) &&
+ * (3DSTATE_PS_EXTRA::PixelShaderValid) &&
+ * !(3DSTATE_WM_HZ_OP::DepthBufferClear ||
+ * 3DSTATE_WM_HZ_OP::DepthBufferResolve ||
+ * 3DSTATE_WM_HZ_OP::Hierarchical Depth Buffer Resolve Enable ||
+ * 3DSTATE_WM_HZ_OP::StencilBufferClear) &&
+ * (3DSTATE_WM_DEPTH_STENCIL::DepthTestEnable) &&
+ * (((3DSTATE_PS_EXTRA::PixelShaderKillsPixels ||
+ * 3DSTATE_PS_EXTRA::oMask Present to RenderTarget ||
+ * 3DSTATE_PS_BLEND::AlphaToCoverageEnable ||
+ * 3DSTATE_PS_BLEND::AlphaTestEnable ||
+ * 3DSTATE_WM_CHROMAKEY::ChromaKeyKillEnable) &&
+ * 3DSTATE_WM::ForceKillPix != ForceOff &&
+ * ((3DSTATE_WM_DEPTH_STENCIL::DepthWriteEnable &&
+ * 3DSTATE_DEPTH_BUFFER::DEPTH_WRITE_ENABLE) ||
+ * (3DSTATE_WM_DEPTH_STENCIL::Stencil Buffer Write Enable &&
+ * 3DSTATE_DEPTH_BUFFER::STENCIL_WRITE_ENABLE &&
+ * 3DSTATE_STENCIL_BUFFER::STENCIL_BUFFER_ENABLE))) ||
+ * (3DSTATE_PS_EXTRA:: Pixel Shader Computed Depth mode != PSCDEPTH_OFF))
+ */
+
+ /* These are always true:
+ * 3DSTATE_WM::ForceThreadDispatch != 1 &&
+ * !(3DSTATE_RASTER::ForceSampleCount != NUMRASTSAMPLES_0)
+ */
+
+ /* We only enable the PMA fix if we know for certain that HiZ is enabled.
+ * If we don't know whether HiZ is enabled or not, we disable the PMA fix
+ * and there is no harm.
+ *
+ * (3DSTATE_DEPTH_BUFFER::SURFACE_TYPE != NULL) &&
+ * 3DSTATE_DEPTH_BUFFER::HIZ Enable
+ */
+ if (!cmd_buffer->state.hiz_enabled)
+ return false;
+
+ /* 3DSTATE_PS_EXTRA::PixelShaderValid */
+ struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
+ if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT))
+ return false;
+
+ /* !(3DSTATE_WM::EDSC_Mode == EDSC_PREPS) */
+ const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
+ if (wm_prog_data->early_fragment_tests)
+ return false;
+
+ /* We never use anv_pipeline for HiZ ops so this is trivially true:
+ * !(3DSTATE_WM_HZ_OP::DepthBufferClear ||
+ * 3DSTATE_WM_HZ_OP::DepthBufferResolve ||
+ * 3DSTATE_WM_HZ_OP::Hierarchical Depth Buffer Resolve Enable ||
+ * 3DSTATE_WM_HZ_OP::StencilBufferClear)
+ */
+
+ /* 3DSTATE_WM_DEPTH_STENCIL::DepthTestEnable */
+ if (!pipeline->depth_test_enable)
+ return false;
+
+ /* (((3DSTATE_PS_EXTRA::PixelShaderKillsPixels ||
+ * 3DSTATE_PS_EXTRA::oMask Present to RenderTarget ||
+ * 3DSTATE_PS_BLEND::AlphaToCoverageEnable ||
+ * 3DSTATE_PS_BLEND::AlphaTestEnable ||
+ * 3DSTATE_WM_CHROMAKEY::ChromaKeyKillEnable) &&
+ * 3DSTATE_WM::ForceKillPix != ForceOff &&
+ * ((3DSTATE_WM_DEPTH_STENCIL::DepthWriteEnable &&
+ * 3DSTATE_DEPTH_BUFFER::DEPTH_WRITE_ENABLE) ||
+ * (3DSTATE_WM_DEPTH_STENCIL::Stencil Buffer Write Enable &&
+ * 3DSTATE_DEPTH_BUFFER::STENCIL_WRITE_ENABLE &&
+ * 3DSTATE_STENCIL_BUFFER::STENCIL_BUFFER_ENABLE))) ||
+ * (3DSTATE_PS_EXTRA:: Pixel Shader Computed Depth mode != PSCDEPTH_OFF))
+ */
+ return (pipeline->kill_pixel && (pipeline->writes_depth ||
+ pipeline->writes_stencil)) ||
+ wm_prog_data->computed_depth_mode != PSCDEPTH_OFF;
}
-static void
-__emit_sf_state(struct anv_cmd_buffer *cmd_buffer)
+UNUSED static bool
+want_stencil_pma_fix(struct anv_cmd_buffer *cmd_buffer)
{
- if (cmd_buffer->device->info.is_cherryview)
- __emit_gen9_sf_state(cmd_buffer);
- else
- __emit_genx_sf_state(cmd_buffer);
+ if (GEN_GEN > 9)
+ return false;
+ assert(GEN_GEN == 9);
+
+ /* From the Skylake PRM Vol. 2c CACHE_MODE_1::STC PMA Optimization Enable:
+ *
+ * Clearing this bit will force the STC cache to wait for pending
+ * retirement of pixels at the HZ-read stage and do the STC-test for
+ * Non-promoted, R-computed and Computed depth modes instead of
+ * postponing the STC-test to RCPFE.
+ *
+ * STC_TEST_EN = 3DSTATE_STENCIL_BUFFER::STENCIL_BUFFER_ENABLE &&
+ * 3DSTATE_WM_DEPTH_STENCIL::StencilTestEnable
+ *
+ * STC_WRITE_EN = 3DSTATE_STENCIL_BUFFER::STENCIL_BUFFER_ENABLE &&
+ * (3DSTATE_WM_DEPTH_STENCIL::Stencil Buffer Write Enable &&
+ * 3DSTATE_DEPTH_BUFFER::STENCIL_WRITE_ENABLE)
+ *
+ * COMP_STC_EN = STC_TEST_EN &&
+ * 3DSTATE_PS_EXTRA::PixelShaderComputesStencil
+ *
+ * SW parses the pipeline states to generate the following logical
+ * signal indicating if PMA FIX can be enabled.
+ *
+ * STC_PMA_OPT =
+ * 3DSTATE_WM::ForceThreadDispatch != 1 &&
+ * !(3DSTATE_RASTER::ForceSampleCount != NUMRASTSAMPLES_0) &&
+ * 3DSTATE_DEPTH_BUFFER::SURFACE_TYPE != NULL &&
+ * 3DSTATE_DEPTH_BUFFER::HIZ Enable &&
+ * !(3DSTATE_WM::EDSC_Mode == 2) &&
+ * 3DSTATE_PS_EXTRA::PixelShaderValid &&
+ * !(3DSTATE_WM_HZ_OP::DepthBufferClear ||
+ * 3DSTATE_WM_HZ_OP::DepthBufferResolve ||
+ * 3DSTATE_WM_HZ_OP::Hierarchical Depth Buffer Resolve Enable ||
+ * 3DSTATE_WM_HZ_OP::StencilBufferClear) &&
+ * (COMP_STC_EN || STC_WRITE_EN) &&
+ * ((3DSTATE_PS_EXTRA::PixelShaderKillsPixels ||
+ * 3DSTATE_WM::ForceKillPix == ON ||
+ * 3DSTATE_PS_EXTRA::oMask Present to RenderTarget ||
+ * 3DSTATE_PS_BLEND::AlphaToCoverageEnable ||
+ * 3DSTATE_PS_BLEND::AlphaTestEnable ||
+ * 3DSTATE_WM_CHROMAKEY::ChromaKeyKillEnable) ||
+ * (3DSTATE_PS_EXTRA::Pixel Shader Computed Depth mode != PSCDEPTH_OFF))
+ */
+
+ /* These are always true:
+ * 3DSTATE_WM::ForceThreadDispatch != 1 &&
+ * !(3DSTATE_RASTER::ForceSampleCount != NUMRASTSAMPLES_0)
+ */
+
+ /* We only enable the PMA fix if we know for certain that HiZ is enabled.
+ * If we don't know whether HiZ is enabled or not, we disable the PMA fix
+ * and there is no harm.
+ *
+ * (3DSTATE_DEPTH_BUFFER::SURFACE_TYPE != NULL) &&
+ * 3DSTATE_DEPTH_BUFFER::HIZ Enable
+ */
+ if (!cmd_buffer->state.hiz_enabled)
+ return false;
+
+ /* We can't possibly know if HiZ is enabled without the framebuffer */
+ assert(cmd_buffer->state.framebuffer);
+
+ /* HiZ is enabled so we had better have a depth buffer with HiZ */
+ const struct anv_image_view *ds_iview =
+ anv_cmd_buffer_get_depth_stencil_view(cmd_buffer);
+ assert(ds_iview && ds_iview->image->planes[0].aux_usage == ISL_AUX_USAGE_HIZ);
+
+ /* 3DSTATE_PS_EXTRA::PixelShaderValid */
+ struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
+ if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT))
+ return false;
+
+ /* !(3DSTATE_WM::EDSC_Mode == 2) */
+ const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
+ if (wm_prog_data->early_fragment_tests)
+ return false;
+
+ /* We never use anv_pipeline for HiZ ops so this is trivially true:
+ * !(3DSTATE_WM_HZ_OP::DepthBufferClear ||
+ * 3DSTATE_WM_HZ_OP::DepthBufferResolve ||
+ * 3DSTATE_WM_HZ_OP::Hierarchical Depth Buffer Resolve Enable ||
+ * 3DSTATE_WM_HZ_OP::StencilBufferClear)
+ */
+
+ /* 3DSTATE_STENCIL_BUFFER::STENCIL_BUFFER_ENABLE &&
+ * 3DSTATE_WM_DEPTH_STENCIL::StencilTestEnable
+ */
+ const bool stc_test_en =
+ (ds_iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
+ pipeline->stencil_test_enable;
+
+ /* 3DSTATE_STENCIL_BUFFER::STENCIL_BUFFER_ENABLE &&
+ * (3DSTATE_WM_DEPTH_STENCIL::Stencil Buffer Write Enable &&
+ * 3DSTATE_DEPTH_BUFFER::STENCIL_WRITE_ENABLE)
+ */
+ const bool stc_write_en =
+ (ds_iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
+ (cmd_buffer->state.gfx.dynamic.stencil_write_mask.front ||
+ cmd_buffer->state.gfx.dynamic.stencil_write_mask.back) &&
+ pipeline->writes_stencil;
+
+ /* STC_TEST_EN && 3DSTATE_PS_EXTRA::PixelShaderComputesStencil */
+ const bool comp_stc_en = stc_test_en && wm_prog_data->computed_stencil;
+
+ /* COMP_STC_EN || STC_WRITE_EN */
+ if (!(comp_stc_en || stc_write_en))
+ return false;
+
+ /* (3DSTATE_PS_EXTRA::PixelShaderKillsPixels ||
+ * 3DSTATE_WM::ForceKillPix == ON ||
+ * 3DSTATE_PS_EXTRA::oMask Present to RenderTarget ||
+ * 3DSTATE_PS_BLEND::AlphaToCoverageEnable ||
+ * 3DSTATE_PS_BLEND::AlphaTestEnable ||
+ * 3DSTATE_WM_CHROMAKEY::ChromaKeyKillEnable) ||
+ * (3DSTATE_PS_EXTRA::Pixel Shader Computed Depth mode != PSCDEPTH_OFF)
+ */
+ return pipeline->kill_pixel ||
+ wm_prog_data->computed_depth_mode != PSCDEPTH_OFF;
}
void
genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
{
- struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
+ struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
+ struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic;
- if (cmd_buffer->state.dirty & (ANV_CMD_DIRTY_PIPELINE |
- ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH)) {
- __emit_sf_state(cmd_buffer);
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH)) {
+ uint32_t sf_dw[GENX(3DSTATE_SF_length)];
+ struct GENX(3DSTATE_SF) sf = {
+ GENX(3DSTATE_SF_header),
+ };
+#if GEN_GEN == 8
+ if (cmd_buffer->device->info.is_cherryview) {
+ sf.CHVLineWidth = d->line_width;
+ } else {
+ sf.LineWidth = d->line_width;
+ }
+#else
+ sf.LineWidth = d->line_width,
+#endif
+ GENX(3DSTATE_SF_pack)(NULL, sf_dw, &sf);
+ anv_batch_emit_merge(&cmd_buffer->batch, sf_dw, pipeline->gen8.sf);
}
- if (cmd_buffer->state.dirty & (ANV_CMD_DIRTY_PIPELINE |
- ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS)){
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS |
+ ANV_CMD_DIRTY_DYNAMIC_CULL_MODE |
+ ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE)) {
uint32_t raster_dw[GENX(3DSTATE_RASTER_length)];
struct GENX(3DSTATE_RASTER) raster = {
GENX(3DSTATE_RASTER_header),
- .GlobalDepthOffsetConstant = cmd_buffer->state.dynamic.depth_bias.bias,
- .GlobalDepthOffsetScale = cmd_buffer->state.dynamic.depth_bias.slope,
- .GlobalDepthOffsetClamp = cmd_buffer->state.dynamic.depth_bias.clamp
+ .GlobalDepthOffsetConstant = d->depth_bias.bias,
+ .GlobalDepthOffsetScale = d->depth_bias.slope,
+ .GlobalDepthOffsetClamp = d->depth_bias.clamp,
+ .CullMode = genX(vk_to_gen_cullmode)[d->cull_mode],
+ .FrontWinding = genX(vk_to_gen_front_face)[d->front_face],
};
GENX(3DSTATE_RASTER_pack)(NULL, raster_dw, &raster);
anv_batch_emit_merge(&cmd_buffer->batch, raster_dw,
* using a big old #if switch here.
*/
#if GEN_GEN == 8
- if (cmd_buffer->state.dirty & (ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS |
- ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE)) {
- struct anv_dynamic_state *d = &cmd_buffer->state.dynamic;
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE)) {
struct anv_state cc_state =
anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
GENX(COLOR_CALC_STATE_length) * 4,
64);
struct GENX(COLOR_CALC_STATE) cc = {
- .BlendConstantColorRed = cmd_buffer->state.dynamic.blend_constants[0],
- .BlendConstantColorGreen = cmd_buffer->state.dynamic.blend_constants[1],
- .BlendConstantColorBlue = cmd_buffer->state.dynamic.blend_constants[2],
- .BlendConstantColorAlpha = cmd_buffer->state.dynamic.blend_constants[3],
+ .BlendConstantColorRed = d->blend_constants[0],
+ .BlendConstantColorGreen = d->blend_constants[1],
+ .BlendConstantColorBlue = d->blend_constants[2],
+ .BlendConstantColorAlpha = d->blend_constants[3],
.StencilReferenceValue = d->stencil_reference.front & 0xff,
- .BackFaceStencilReferenceValue = d->stencil_reference.back & 0xff,
+ .BackfaceStencilReferenceValue = d->stencil_reference.back & 0xff,
};
GENX(COLOR_CALC_STATE_pack)(NULL, cc_state.map, &cc);
- if (!cmd_buffer->device->info.has_llc)
- anv_state_clflush(cc_state);
-
anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CC_STATE_POINTERS), ccp) {
ccp.ColorCalcStatePointer = cc_state.offset;
ccp.ColorCalcStatePointerValid = true;
}
}
- if (cmd_buffer->state.dirty & (ANV_CMD_DIRTY_PIPELINE |
- ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK |
- ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK)) {
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_RENDER_TARGETS |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP)) {
uint32_t wm_depth_stencil_dw[GENX(3DSTATE_WM_DEPTH_STENCIL_length)];
- struct anv_dynamic_state *d = &cmd_buffer->state.dynamic;
struct GENX(3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil) = {
GENX(3DSTATE_WM_DEPTH_STENCIL_header),
.BackfaceStencilTestMask = d->stencil_compare_mask.back & 0xff,
.BackfaceStencilWriteMask = d->stencil_write_mask.back & 0xff,
+
+ .StencilBufferWriteEnable =
+ (d->stencil_write_mask.front || d->stencil_write_mask.back) &&
+ d->stencil_test_enable,
+
+ .DepthTestEnable = d->depth_test_enable,
+ .DepthBufferWriteEnable = d->depth_test_enable && d->depth_write_enable,
+ .DepthTestFunction = genX(vk_to_gen_compare_op)[d->depth_compare_op],
+ .StencilTestEnable = d->stencil_test_enable,
+ .StencilFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.front.fail_op],
+ .StencilPassDepthPassOp = genX(vk_to_gen_stencil_op)[d->stencil_op.front.pass_op],
+ .StencilPassDepthFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.front.depth_fail_op],
+ .StencilTestFunction = genX(vk_to_gen_compare_op)[d->stencil_op.front.compare_op],
+ .BackfaceStencilFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.back.fail_op],
+ .BackfaceStencilPassDepthPassOp = genX(vk_to_gen_stencil_op)[d->stencil_op.back.pass_op],
+ .BackfaceStencilPassDepthFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.back.depth_fail_op],
+ .BackfaceStencilTestFunction = genX(vk_to_gen_compare_op)[d->stencil_op.back.compare_op],
};
GENX(3DSTATE_WM_DEPTH_STENCIL_pack)(NULL, wm_depth_stencil_dw,
&wm_depth_stencil);
anv_batch_emit_merge(&cmd_buffer->batch, wm_depth_stencil_dw,
pipeline->gen8.wm_depth_stencil);
+
+ genX(cmd_buffer_enable_pma_fix)(cmd_buffer,
+ want_depth_pma_fix(cmd_buffer));
}
#else
- if (cmd_buffer->state.dirty & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS) {
+ if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS) {
struct anv_state cc_state =
anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
- GEN9_COLOR_CALC_STATE_length * 4,
+ GENX(COLOR_CALC_STATE_length) * 4,
64);
- struct GEN9_COLOR_CALC_STATE cc = {
- .BlendConstantColorRed = cmd_buffer->state.dynamic.blend_constants[0],
- .BlendConstantColorGreen = cmd_buffer->state.dynamic.blend_constants[1],
- .BlendConstantColorBlue = cmd_buffer->state.dynamic.blend_constants[2],
- .BlendConstantColorAlpha = cmd_buffer->state.dynamic.blend_constants[3],
+ struct GENX(COLOR_CALC_STATE) cc = {
+ .BlendConstantColorRed = d->blend_constants[0],
+ .BlendConstantColorGreen = d->blend_constants[1],
+ .BlendConstantColorBlue = d->blend_constants[2],
+ .BlendConstantColorAlpha = d->blend_constants[3],
};
- GEN9_COLOR_CALC_STATE_pack(NULL, cc_state.map, &cc);
-
- if (!cmd_buffer->device->info.has_llc)
- anv_state_clflush(cc_state);
+ GENX(COLOR_CALC_STATE_pack)(NULL, cc_state.map, &cc);
- anv_batch_emit(&cmd_buffer->batch, GEN9_3DSTATE_CC_STATE_POINTERS, ccp) {
+ anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_CC_STATE_POINTERS), ccp) {
ccp.ColorCalcStatePointer = cc_state.offset;
ccp.ColorCalcStatePointerValid = true;
}
}
- if (cmd_buffer->state.dirty & (ANV_CMD_DIRTY_PIPELINE |
- ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK |
- ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK |
- ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE)) {
- uint32_t dwords[GEN9_3DSTATE_WM_DEPTH_STENCIL_length];
- struct anv_dynamic_state *d = &cmd_buffer->state.dynamic;
- struct GEN9_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
- GEN9_3DSTATE_WM_DEPTH_STENCIL_header,
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_RENDER_TARGETS |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE |
+ ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP)) {
+ uint32_t dwords[GENX(3DSTATE_WM_DEPTH_STENCIL_length)];
+ struct GENX(3DSTATE_WM_DEPTH_STENCIL) wm_depth_stencil = {
+ GENX(3DSTATE_WM_DEPTH_STENCIL_header),
.StencilTestMask = d->stencil_compare_mask.front & 0xff,
.StencilWriteMask = d->stencil_write_mask.front & 0xff,
.StencilReferenceValue = d->stencil_reference.front & 0xff,
.BackfaceStencilReferenceValue = d->stencil_reference.back & 0xff,
+
+ .StencilBufferWriteEnable =
+ (d->stencil_write_mask.front || d->stencil_write_mask.back) &&
+ d->stencil_test_enable,
+
+ .DepthTestEnable = d->depth_test_enable,
+ .DepthBufferWriteEnable = d->depth_test_enable && d->depth_write_enable,
+ .DepthTestFunction = genX(vk_to_gen_compare_op)[d->depth_compare_op],
+ .StencilTestEnable = d->stencil_test_enable,
+ .StencilFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.front.fail_op],
+ .StencilPassDepthPassOp = genX(vk_to_gen_stencil_op)[d->stencil_op.front.pass_op],
+ .StencilPassDepthFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.front.depth_fail_op],
+ .StencilTestFunction = genX(vk_to_gen_compare_op)[d->stencil_op.front.compare_op],
+ .BackfaceStencilFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.back.fail_op],
+ .BackfaceStencilPassDepthPassOp = genX(vk_to_gen_stencil_op)[d->stencil_op.back.pass_op],
+ .BackfaceStencilPassDepthFailOp = genX(vk_to_gen_stencil_op)[d->stencil_op.back.depth_fail_op],
+ .BackfaceStencilTestFunction = genX(vk_to_gen_compare_op)[d->stencil_op.back.compare_op],
+
};
- GEN9_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, dwords, &wm_depth_stencil);
+ GENX(3DSTATE_WM_DEPTH_STENCIL_pack)(NULL, dwords, &wm_depth_stencil);
anv_batch_emit_merge(&cmd_buffer->batch, dwords,
pipeline->gen9.wm_depth_stencil);
+
+ genX(cmd_buffer_enable_pma_fix)(cmd_buffer,
+ want_stencil_pma_fix(cmd_buffer));
}
#endif
- if (cmd_buffer->state.dirty & (ANV_CMD_DIRTY_PIPELINE |
- ANV_CMD_DIRTY_INDEX_BUFFER)) {
- anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF), vf) {
- vf.IndexedDrawCutIndexEnable = pipeline->primitive_restart;
- vf.CutIndex = cmd_buffer->state.restart_index;
+#if GEN_GEN >= 12
+ if(cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS |
+ ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE)) {
+ anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_DEPTH_BOUNDS), db) {
+ db.DepthBoundsTestValueModifyDisable = false;
+ db.DepthBoundsTestEnableModifyDisable = false;
+ db.DepthBoundsTestEnable = d->depth_bounds_test_enable;
+ db.DepthBoundsTestMinValue = d->depth_bounds.min;
+ db.DepthBoundsTestMaxValue = d->depth_bounds.max;
}
}
-
- cmd_buffer->state.dirty = 0;
-}
-
-void genX(CmdBindIndexBuffer)(
- VkCommandBuffer commandBuffer,
- VkBuffer _buffer,
- VkDeviceSize offset,
- VkIndexType indexType)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
-
- static const uint32_t vk_to_gen_index_type[] = {
- [VK_INDEX_TYPE_UINT16] = INDEX_WORD,
- [VK_INDEX_TYPE_UINT32] = INDEX_DWORD,
- };
-
- static const uint32_t restart_index_for_type[] = {
- [VK_INDEX_TYPE_UINT16] = UINT16_MAX,
- [VK_INDEX_TYPE_UINT32] = UINT32_MAX,
- };
-
- cmd_buffer->state.restart_index = restart_index_for_type[indexType];
-
- anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_INDEX_BUFFER), ib) {
- ib.IndexFormat = vk_to_gen_index_type[indexType];
- ib.MemoryObjectControlState = GENX(MOCS);
- ib.BufferStartingAddress =
- (struct anv_address) { buffer->bo, buffer->offset + offset };
- ib.BufferSize = buffer->size - offset;
- }
-
- cmd_buffer->state.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER;
-}
-
-
-/**
- * Emit the HZ_OP packet in the sequence specified by the BDW PRM section
- * entitled: "Optimized Depth Buffer Clear and/or Stencil Buffer Clear."
- *
- * \todo Enable Stencil Buffer-only clears
- */
-void
-genX(cmd_buffer_emit_hz_op)(struct anv_cmd_buffer *cmd_buffer,
- enum blorp_hiz_op op)
-{
- struct anv_cmd_state *cmd_state = &cmd_buffer->state;
- const struct anv_image_view *iview =
- anv_cmd_buffer_get_depth_stencil_view(cmd_buffer);
-
- if (iview == NULL || !anv_image_has_hiz(iview->image))
- return;
-
- /* FINISHME: Implement multi-subpass HiZ */
- if (cmd_buffer->state.pass->subpass_count > 1)
- return;
-
- const uint32_t ds = cmd_state->subpass->depth_stencil_attachment;
-
- /* Section 7.4. of the Vulkan 1.0.27 spec states:
- *
- * "The render area must be contained within the framebuffer dimensions."
- *
- * Therefore, the only way the extent of the render area can match that of
- * the image view is if the render area offset equals (0, 0).
- */
- const bool full_surface_op =
- cmd_state->render_area.extent.width == iview->extent.width &&
- cmd_state->render_area.extent.height == iview->extent.height;
- if (full_surface_op)
- assert(cmd_state->render_area.offset.x == 0 &&
- cmd_state->render_area.offset.y == 0);
-
- /* This variable corresponds to the Pixel Dim column in the table below */
- struct isl_extent2d px_dim;
-
- /* Validate that we can perform the HZ operation and that it's necessary. */
- switch (op) {
- case BLORP_HIZ_OP_DEPTH_CLEAR:
- if (cmd_buffer->state.pass->attachments[ds].load_op !=
- VK_ATTACHMENT_LOAD_OP_CLEAR)
- return;
-
- /* Apply alignment restrictions. Despite the BDW PRM mentioning this is
- * only needed for a depth buffer surface type of D16_UNORM, testing
- * showed it to be necessary for other depth formats as well
- * (e.g., D32_FLOAT).
- */
-#if GEN_GEN == 8
- /* Pre-SKL, HiZ has an 8x4 sample block. As the number of samples
- * increases, the number of pixels representable by this block
- * decreases by a factor of the sample dimensions. Sample dimensions
- * scale following the MSAA interleaved pattern.
- *
- * Sample|Sample|Pixel
- * Count |Dim |Dim
- * ===================
- * 1 | 1x1 | 8x4
- * 2 | 2x1 | 4x4
- * 4 | 2x2 | 4x2
- * 8 | 4x2 | 2x2
- * 16 | 4x4 | 2x1
- *
- * Table: Pixel Dimensions in a HiZ Sample Block Pre-SKL
- */
- /* This variable corresponds to the Sample Dim column in the table
- * above.
- */
- const struct isl_extent2d sa_dim =
- isl_get_interleaved_msaa_px_size_sa(iview->image->samples);
- px_dim.w = 8 / sa_dim.w;
- px_dim.h = 4 / sa_dim.h;
-#elif GEN_GEN >= 9
- /* SKL+, the sample block becomes a "pixel block" so the expected
- * pixel dimension is a constant 8x4 px for all sample counts.
- */
- px_dim = (struct isl_extent2d) { .w = 8, .h = 4};
#endif
- if (!full_surface_op) {
- /* Fast depth clears clear an entire sample block at a time. As a
- * result, the rectangle must be aligned to the pixel dimensions of
- * a sample block for a successful operation.
- *
- * Fast clears can still work if the offset is aligned and the render
- * area offset + extent touches the edge of a depth buffer whose extent
- * is unaligned. This is because each physical HiZ miplevel is padded
- * by the px_dim. In this case, the size of the clear rectangle will be
- * padded later on in this function.
- */
- if (cmd_state->render_area.offset.x % px_dim.w ||
- cmd_state->render_area.offset.y % px_dim.h)
- return;
- if (cmd_state->render_area.offset.x +
- cmd_state->render_area.extent.width != iview->extent.width &&
- cmd_state->render_area.extent.width % px_dim.w)
- return;
- if (cmd_state->render_area.offset.y +
- cmd_state->render_area.extent.height != iview->extent.height &&
- cmd_state->render_area.extent.height % px_dim.h)
- return;
+ if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) {
+ anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_LINE_STIPPLE), ls) {
+ ls.LineStipplePattern = d->line_stipple.pattern;
+ ls.LineStippleInverseRepeatCount =
+ 1.0f / MAX2(1, d->line_stipple.factor);
+ ls.LineStippleRepeatCount = d->line_stipple.factor;
}
- break;
- case BLORP_HIZ_OP_DEPTH_RESOLVE:
- if (cmd_buffer->state.pass->attachments[ds].store_op !=
- VK_ATTACHMENT_STORE_OP_STORE)
- return;
- break;
- case BLORP_HIZ_OP_HIZ_RESOLVE:
- /* If the render area covers the entire surface *and* load_op is either
- * CLEAR or DONT_CARE then the previous contents of the depth buffer
- * will be entirely discarded. In this case, we can skip the HiZ
- * resolve.
- *
- * If the render area is not the full surface, we need to do
- * the resolve because otherwise data outside the render area may get
- * garbled by the resolve at the end of the render pass.
- */
- if (full_surface_op &&
- cmd_buffer->state.pass->attachments[ds].load_op !=
- VK_ATTACHMENT_LOAD_OP_LOAD)
- return;
- break;
- case BLORP_HIZ_OP_NONE:
- unreachable("Invalid HiZ OP");
- break;
}
- anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_WM_HZ_OP), hzp) {
- switch (op) {
- case BLORP_HIZ_OP_DEPTH_CLEAR:
- hzp.StencilBufferClearEnable = VK_IMAGE_ASPECT_STENCIL_BIT &
- cmd_state->attachments[ds].pending_clear_aspects;
- hzp.DepthBufferClearEnable = VK_IMAGE_ASPECT_DEPTH_BIT &
- cmd_state->attachments[ds].pending_clear_aspects;
- hzp.FullSurfaceDepthandStencilClear = full_surface_op;
- hzp.StencilClearValue =
- cmd_state->attachments[ds].clear_value.depthStencil.stencil & 0xff;
-
- /* Mark aspects as cleared */
- cmd_state->attachments[ds].pending_clear_aspects = 0;
- break;
- case BLORP_HIZ_OP_DEPTH_RESOLVE:
- hzp.DepthBufferResolveEnable = true;
- break;
- case BLORP_HIZ_OP_HIZ_RESOLVE:
- hzp.HierarchicalDepthBufferResolveEnable = true;
- break;
- case BLORP_HIZ_OP_NONE:
- unreachable("Invalid HiZ OP");
- break;
- }
-
- if (op != BLORP_HIZ_OP_DEPTH_CLEAR) {
- /* The Optimized HiZ resolve rectangle must be the size of the full RT
- * and aligned to 8x4. The non-optimized Depth resolve rectangle must
- * be the size of the full RT. The same alignment is assumed to be
- * required.
- */
- hzp.ClearRectangleXMin = 0;
- hzp.ClearRectangleYMin = 0;
- hzp.ClearRectangleXMax = align_u32(iview->extent.width, 8);
- hzp.ClearRectangleYMax = align_u32(iview->extent.height, 4);
- } else {
- /* This clear rectangle is aligned */
- hzp.ClearRectangleXMin = cmd_state->render_area.offset.x;
- hzp.ClearRectangleYMin = cmd_state->render_area.offset.y;
- hzp.ClearRectangleXMax = cmd_state->render_area.offset.x +
- align_u32(cmd_state->render_area.extent.width, px_dim.width);
- hzp.ClearRectangleYMax = cmd_state->render_area.offset.y +
- align_u32(cmd_state->render_area.extent.height, px_dim.height);
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_INDEX_BUFFER)) {
+ anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF), vf) {
+ vf.IndexedDrawCutIndexEnable = pipeline->primitive_restart;
+ vf.CutIndex = cmd_buffer->state.restart_index;
}
-
-
- /* Due to a hardware issue, this bit MBZ */
- hzp.ScissorRectangleEnable = false;
- hzp.NumberofMultisamples = ffs(iview->image->samples) - 1;
- hzp.SampleMask = 0xFFFF;
}
- anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
- pc.PostSyncOperation = WriteImmediateData;
- pc.Address =
- (struct anv_address){ &cmd_buffer->device->workaround_bo, 0 };
- }
+ if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
+ ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) {
+ uint32_t topology;
+ if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
+ topology = d->primitive_topology;
+ else
+ topology = genX(vk_to_gen_primitive_type)[d->primitive_topology];
- anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_WM_HZ_OP), hzp);
+ cmd_buffer->state.gfx.primitive_topology = topology;
- if (!full_surface_op && op == BLORP_HIZ_OP_DEPTH_CLEAR) {
- anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
- pc.DepthStallEnable = true;
- pc.DepthCacheFlushEnable = true;
+ anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) {
+ vft.PrimitiveTopologyType = topology;
}
}
+
+ cmd_buffer->state.gfx.dirty = 0;
}
-/* Set of stage bits for which are pipelined, i.e. they get queued by the
- * command streamer for later execution.
- */
-#define ANV_PIPELINE_STAGE_PIPELINED_BITS \
- (VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | \
- VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | \
- VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | \
- VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | \
- VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | \
- VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | \
- VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | \
- VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | \
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | \
- VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | \
- VK_PIPELINE_STAGE_TRANSFER_BIT | \
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | \
- VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | \
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)
-
-void genX(CmdSetEvent)(
- VkCommandBuffer commandBuffer,
- VkEvent _event,
- VkPipelineStageFlags stageMask)
+static uint32_t vk_to_gen_index_type(VkIndexType type)
{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
- ANV_FROM_HANDLE(anv_event, event, _event);
-
- anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
- if (stageMask & ANV_PIPELINE_STAGE_PIPELINED_BITS) {
- pc.StallAtPixelScoreboard = true;
- pc.CommandStreamerStallEnable = true;
- }
-
- pc.DestinationAddressType = DAT_PPGTT,
- pc.PostSyncOperation = WriteImmediateData,
- pc.Address = (struct anv_address) {
- &cmd_buffer->device->dynamic_state_block_pool.bo,
- event->state.offset
- };
- pc.ImmediateData = VK_EVENT_SET;
+ switch (type) {
+ case VK_INDEX_TYPE_UINT8_EXT:
+ return INDEX_BYTE;
+ case VK_INDEX_TYPE_UINT16:
+ return INDEX_WORD;
+ case VK_INDEX_TYPE_UINT32:
+ return INDEX_DWORD;
+ default:
+ unreachable("invalid index type");
}
}
-void genX(CmdResetEvent)(
- VkCommandBuffer commandBuffer,
- VkEvent _event,
- VkPipelineStageFlags stageMask)
+static uint32_t restart_index_for_type(VkIndexType type)
{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
- ANV_FROM_HANDLE(anv_event, event, _event);
-
- anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
- if (stageMask & ANV_PIPELINE_STAGE_PIPELINED_BITS) {
- pc.StallAtPixelScoreboard = true;
- pc.CommandStreamerStallEnable = true;
- }
-
- pc.DestinationAddressType = DAT_PPGTT;
- pc.PostSyncOperation = WriteImmediateData;
- pc.Address = (struct anv_address) {
- &cmd_buffer->device->dynamic_state_block_pool.bo,
- event->state.offset
- };
- pc.ImmediateData = VK_EVENT_RESET;
+ switch (type) {
+ case VK_INDEX_TYPE_UINT8_EXT:
+ return UINT8_MAX;
+ case VK_INDEX_TYPE_UINT16:
+ return UINT16_MAX;
+ case VK_INDEX_TYPE_UINT32:
+ return UINT32_MAX;
+ default:
+ unreachable("invalid index type");
}
}
-void genX(CmdWaitEvents)(
+void genX(CmdBindIndexBuffer)(
VkCommandBuffer commandBuffer,
- uint32_t eventCount,
- const VkEvent* pEvents,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags destStageMask,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier* pMemoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier* pBufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier* pImageMemoryBarriers)
+ VkBuffer _buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
- for (uint32_t i = 0; i < eventCount; i++) {
- ANV_FROM_HANDLE(anv_event, event, pEvents[i]);
-
- anv_batch_emit(&cmd_buffer->batch, GENX(MI_SEMAPHORE_WAIT), sem) {
- sem.WaitMode = PollingMode,
- sem.CompareOperation = COMPARE_SAD_EQUAL_SDD,
- sem.SemaphoreDataDword = VK_EVENT_SET,
- sem.SemaphoreAddress = (struct anv_address) {
- &cmd_buffer->device->dynamic_state_block_pool.bo,
- event->state.offset
- };
- }
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+
+ cmd_buffer->state.restart_index = restart_index_for_type(indexType);
+
+ anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_INDEX_BUFFER), ib) {
+ ib.IndexFormat = vk_to_gen_index_type(indexType);
+ ib.MOCS = anv_mocs_for_bo(cmd_buffer->device,
+ buffer->address.bo);
+ ib.BufferStartingAddress = anv_address_add(buffer->address, offset);
+ ib.BufferSize = buffer->size - offset;
}
- genX(CmdPipelineBarrier)(commandBuffer, srcStageMask, destStageMask,
- false, /* byRegion */
- memoryBarrierCount, pMemoryBarriers,
- bufferMemoryBarrierCount, pBufferMemoryBarriers,
- imageMemoryBarrierCount, pImageMemoryBarriers);
+ cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_INDEX_BUFFER;
}