<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Feb 9, 2017 at 5:32 PM, Nanley Chery <span dir="ltr"><<a href="mailto:nanleychery@gmail.com" target="_blank">nanleychery@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">On Wed, Feb 01, 2017 at 05:43:55PM -0800, Jason Ekstrand wrote:<br>
> This seemed to help Dota 2 by a percent or two.<br>
<br>
</span>I wasn't able to reproduce this on SKL, could you qualify this with "on<br>
BDW"?<span class="gmail-"><br></span></blockquote><div><br></div><div>I've changed it to:<br><br> It's a bit hard to measure because it almost gets lost in the noise,<br> but this seemed to help Dota 2 by a percent or two on my Broadwell<br> GT3e desktop.<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
> ---<br>
> src/intel/vulkan/genX_<wbr>pipeline.c | 133 +++++++++++++++++++++++++++++-<wbr>---------<br>
> 1 file changed, 99 insertions(+), 34 deletions(-)<br>
><br>
> diff --git a/src/intel/vulkan/genX_<wbr>pipeline.c b/src/intel/vulkan/genX_<wbr>pipeline.c<br>
> index f6940d2..1961874 100644<br>
> --- a/src/intel/vulkan/genX_<wbr>pipeline.c<br>
> +++ b/src/intel/vulkan/genX_<wbr>pipeline.c<br>
> @@ -634,6 +634,95 @@ static const uint32_t vk_to_gen_stencil_op[] = {<br>
> [VK_STENCIL_OP_DECREMENT_AND_<wbr>WRAP] = STENCILOP_DECR,<br>
> };<br>
><br>
> +static bool<br>
> +may_write_stencil_face(const VkStencilOpState *face,<br>
> + VkCompareOp depthCompareOp)<br>
> +{<br>
> + return (face->compareOp != VK_COMPARE_OP_ALWAYS &&<br>
> + face->failOp != VK_STENCIL_OP_KEEP) ||<br>
> + (face->compareOp != VK_COMPARE_OP_NEVER &&<br>
> + ((depthCompareOp != VK_COMPARE_OP_NEVER &&<br>
> + face->passOp != VK_STENCIL_OP_KEEP) ||<br>
> + (depthCompareOp != VK_COMPARE_OP_ALWAYS &&<br>
> + face->depthFailOp != VK_STENCIL_OP_KEEP)));<br>
<br>
</span>This is quite confusing to me. Could you split out each<br>
part of this condition? Comments may also help.<span class="gmail-"><br></span></blockquote><div><br></div><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
> +}<br>
> +<br>
> +/* Intel hardware is fairly sensitive to whether or not depth/stencil writes<br>
> + * are enabled. In the presence of discards, disabling writes means that the<br>
> + * depth/stencil testing can get moved earlier in the pipeline which allows it<br>
<br>
</span>Could you cite the source for this statement? This doesn't match my<br>
understanding of what the following sections of the hardware docs say:<br>
* ILK PRM: 8.4.3.2 Early Depth Test Cases [Pre-DevSNB]<br>
* IVB PRM: 11.5.2 Early Depth Test/Stencil Test/Write<br>
<br>
According to these docs, on IVB+, depth/stencil testing is always<br>
performed early when the PS doesn't write out depth. In the presence of<br>
discards, disabling writes makes a depth pixel promoted instead of<br>
non-promoted, meaning that the writes aren't performed at the end of the<br>
PS.<span class="gmail-"><br></span></blockquote><div><br></div><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
> + * to avoid executing the fragment shader of the depth or stencil test fails.<br>
> + *<br>
> + * Unfortunately, the way depth and stencil testing is specified, there are<br>
> + * many case where, regardless of depth/stencil writes being enabled, nothing<br>
> + * actually gets written due to some other bit of state being set. This<br>
> + * function attempts to "sanitize" the depth stencil state and disable writes<br>
> + * and sometimes even testing whenever possible.<br>
> + */<br>
<br>
</span>This is a great idea!<br>
<div><div class="gmail-h5"><br>
> +static void<br>
> +sanitize_ds_state(<wbr>VkPipelineDepthStencilStateCre<wbr>ateInfo *state,<br>
> + bool *stencilWriteEnable,<br>
> + VkImageAspectFlags ds_aspects)<br>
> +{<br>
> + *stencilWriteEnable = state->stencilTestEnable;<br>
> +<br>
> + /* If the depth test is disabled, we won't be writing anything. */<br>
> + if (!state->depthTestEnable)<br>
> + state->depthWriteEnable = false;<br>
> +<br>
> + /* The Vulkan spec requires that if either depth or stencil is not present,<br>
> + * the pipeline is to act as if the test silently passes.<br>
> + */<br>
> + if (!(ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {<br>
> + state->depthWriteEnable = false;<br>
> + state->depthCompareOp = VK_COMPARE_OP_ALWAYS;<br>
> + }<br>
> +<br>
> + if (!(ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {<br>
> + *stencilWriteEnable = false;<br>
> + state->front.compareOp = VK_COMPARE_OP_ALWAYS;<br>
> + state->back.compareOp = VK_COMPARE_OP_ALWAYS;<br>
> + }<br>
> +<br>
> + /* If the stencil test is enabled and always fails, then we will never get<br>
> + * to the depth test so we can just disable the depth test entirely.<br>
> + */<br>
> + if (state->stencilTestEnable &&<br>
<br>
</div></div>This also needs:<br>
<br>
ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT &&<br>
<br>
If a stencil aspect isn't there, the stencil test always passes. You<br>
could mention this nuance in the comment above.<span class="gmail-"><br></span></blockquote><div><br></div><div>If we don't have stencil, we set the compare ops to ALWAYS above so the two cases below will fail.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
> + state->front.compareOp == VK_COMPARE_OP_NEVER &&<br>
> + state->back.compareOp == VK_COMPARE_OP_NEVER) {<br>
> + state->depthTestEnable = false;<br>
> + state->depthWriteEnable = false;<br>
> + }<br>
<br>
</span>We may want to handle the following cases eventually:<br>
<br>
1. state->maxDepthBounds < state->minDepthBounds<br>
2. compareMask && compareOp combinations<br>
<span class="gmail-"><br>
> +<br>
> + /* If depthCompareOp is EQUAL then the value we would be writing to the<br>
> + * depth buffer is the same as the value that's already there so there's no<br>
> + * point in writing it.<br>
> + */<br>
> + if (state->depthCompareOp == VK_COMPARE_OP_EQUAL)<br>
> + state->depthWriteEnable = false;<br>
> +<br>
> + /* If the stencil ops are such that we don't actually ever modify the<br>
> + * stencil buffer, we should disable writes.<br>
> + */<br>
> + if (!may_write_stencil_face(&<wbr>state->front, state->depthCompareOp) &&<br>
> + !may_write_stencil_face(&<wbr>state->back, state->depthCompareOp))<br>
<br>
</span>This is not enough to disable writes. Even if the user sets<br>
VK_STENCIL_OP_KEEP and VK_COMPARE_OP_ALWAYS in the appropriate fields, a<br>
non-0xFF writemask would require us to write new values into the<br>
stencil buffer.<br></blockquote><div><br></div><div>I believe you misunderstand stencil write masks. From the spec:<br><br>The least significant <span class="eq">s</span> bits of <code>writeMask</code>, where <span class="eq">s</span> is the
number of bits in the stencil framebuffer attachment, specify an integer
mask.
Where a <span class="eq">1</span> appears in this mask, the corresponding bit in the stencil
value in the depth/stencil attachment is written; where a <span class="eq">0</span> appears,
the bit is not written.
The <code>writeMask</code> value uses either the front-facing or back-facing state
based on the facing-ness of the fragment.<br><br></div><div>In other words, the mask simply controls which bits get updated. It does not automatically cause any bits not in the mask to get zeroed out.<br><br></div><div>--Jason<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
-Nanley<br>
<div><div class="gmail-h5"><br>
> + *stencilWriteEnable = false;<br>
> +<br>
> + /* If the depth test always passes and we never write out depth, that's the<br>
> + * same as if the depth test is disabled entirely.<br>
> + */<br>
> + if (state->depthCompareOp == VK_COMPARE_OP_ALWAYS &&<br>
> + !state->depthWriteEnable)<br>
> + state->depthTestEnable = false;<br>
> +<br>
> + /* If the stencil test always passes and we never write out stencil, that's<br>
> + * the same as if the stencil test is disabled entirely.<br>
> + */<br>
> + if (state->front.compareOp == VK_COMPARE_OP_ALWAYS &&<br>
> + state->back.compareOp == VK_COMPARE_OP_ALWAYS &&<br>
> + !*stencilWriteEnable)<br>
> + state->stencilTestEnable = false;<br>
> +}<br>
> +<br>
> static void<br>
> emit_ds_state(struct anv_pipeline *pipeline,<br>
> const VkPipelineDepthStencilStateCre<wbr>ateInfo *pCreateInfo,<br>
> @@ -656,12 +745,20 @@ emit_ds_state(struct anv_pipeline *pipeline,<br>
> return;<br>
> }<br>
><br>
> + VkImageAspectFlags ds_aspects = 0;<br>
> + if (subpass->depth_stencil_<wbr>attachment != VK_ATTACHMENT_UNUSED) {<br>
> + VkFormat depth_stencil_format =<br>
> + pass->attachments[subpass-><wbr>depth_stencil_attachment].<wbr>format;<br>
> + ds_aspects = vk_format_aspects(depth_<wbr>stencil_format);<br>
> + }<br>
> +<br>
> VkPipelineDepthStencilStateCre<wbr>ateInfo info = *pCreateInfo;<br>
> + sanitize_ds_state(&info, &pipeline->writes_stencil, ds_aspects);<br>
> + pipeline->writes_depth = info.depthWriteEnable;<br>
> + pipeline->depth_test_enable = info.depthTestEnable;<br>
><br>
> /* VkBool32 depthBoundsTestEnable; // optional (depth_bounds_test) */<br>
><br>
> - pipeline->writes_stencil = info.stencilTestEnable;<br>
> -<br>
> #if GEN_GEN <= 7<br>
> struct GENX(DEPTH_STENCIL_STATE) depth_stencil = {<br>
> #else<br>
> @@ -683,38 +780,6 @@ emit_ds_state(struct anv_pipeline *pipeline,<br>
> .BackfaceStencilTestFunction = vk_to_gen_compare_op[info.<wbr>back.compareOp],<br>
> };<br>
><br>
> - VkImageAspectFlags aspects = 0;<br>
> - if (subpass->depth_stencil_<wbr>attachment != VK_ATTACHMENT_UNUSED) {<br>
> - VkFormat depth_stencil_format =<br>
> - pass->attachments[subpass-><wbr>depth_stencil_attachment].<wbr>format;<br>
> - aspects = vk_format_aspects(depth_<wbr>stencil_format);<br>
> - }<br>
> -<br>
> - /* The Vulkan spec requires that if either depth or stencil is not present,<br>
> - * the pipeline is to act as if the test silently passes.<br>
> - */<br>
> - if (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {<br>
> - depth_stencil.<wbr>DepthBufferWriteEnable = false;<br>
> - depth_stencil.<wbr>DepthTestFunction = PREFILTEROPALWAYS;<br>
> - }<br>
> -<br>
> - if (!(aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {<br>
> - depth_stencil.<wbr>StencilBufferWriteEnable = false;<br>
> - depth_stencil.<wbr>StencilTestFunction = PREFILTEROPALWAYS;<br>
> - depth_stencil.<wbr>BackfaceStencilTestFunction = PREFILTEROPALWAYS;<br>
> - }<br>
> -<br>
> - /* From the Broadwell PRM:<br>
> - *<br>
> - * "If Depth_Test_Enable = 1 AND Depth_Test_func = EQUAL, the<br>
> - * Depth_Write_Enable must be set to 0."<br>
> - */<br>
> - if (info.depthTestEnable && info.depthCompareOp == VK_COMPARE_OP_EQUAL)<br>
> - depth_stencil.<wbr>DepthBufferWriteEnable = false;<br>
> -<br>
> - pipeline->writes_depth = depth_stencil.<wbr>DepthBufferWriteEnable;<br>
> - pipeline->depth_test_enable = depth_stencil.DepthTestEnable;<br>
> -<br>
> #if GEN_GEN <= 7<br>
> GENX(DEPTH_STENCIL_STATE_pack)<wbr>(NULL, depth_stencil_dw, &depth_stencil);<br>
> #else<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div>> ______________________________<wbr>_________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</blockquote></div><br></div></div>