From c70929d40a553f53ee611ff801d082bc51324d36 Mon Sep 17 00:00:00 2001 From: Aliya Pazylbekova Date: Mon, 4 May 2020 12:20:18 -0400 Subject: [PATCH] Vk Pixel History: misc fixes incl. fragment count - Filter events that don't match image view range - Leave some tests in the original state. Disable depth test and write, this causes the individual fragments that failed the depth test to show up, but the post modification value for them will be accurate. - Fix a couple of things: delete TestsFailedCallback, and fix the padding --- renderdoc/driver/vulkan/vk_pixelhistory.cpp | 124 +++++++++----------- 1 file changed, 57 insertions(+), 67 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_pixelhistory.cpp b/renderdoc/driver/vulkan/vk_pixelhistory.cpp index 1d6ce01b8..40ce891b3 100644 --- a/renderdoc/driver/vulkan/vk_pixelhistory.cpp +++ b/renderdoc/driver/vulkan/vk_pixelhistory.cpp @@ -137,9 +137,9 @@ struct EventInfo PixelHistoryValue premod; PixelHistoryValue postmod; uint8_t dsWithoutShaderDiscard[8]; - uint32_t padding[4]; + uint8_t padding[8]; uint8_t dsWithShaderDiscard[8]; - uint32_t padding1[4]; + uint8_t padding1[8]; }; struct PerFragmentInfo @@ -379,7 +379,7 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback m_pDriver->SetDrawcallCB(this); } - ~VulkanPixelHistoryCallback() + virtual ~VulkanPixelHistoryCallback() { m_pDriver->SetDrawcallCB(NULL); for(const VkRenderPass &rp : m_RpsToDestroy) @@ -433,15 +433,17 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback } protected: - // MakeAllPassIncrementStencilPipelineCI fills in the provided pipeCreateInfo + // MakeIncrementStencilPipelineCI fills in the provided pipeCreateInfo // to create a graphics pipeline that is based on the original. The modifications - // to the original pipeline: disables all tests except stencil, stencil is set + // to the original pipeline: disables depth test and write, stencil is set // to always pass and increment, scissor is set to scissor around target pixel, // all shaders are replaced with their "clean" versions (attempts to remove side - // effects). - void MakeAllPassIncrementStencilPipelineCI(uint32_t eid, ResourceId pipe, - VkGraphicsPipelineCreateInfo &pipeCreateInfo, - rdcarray &stages) + // effects), all color modifications are disabled. + // Optionally disables other tests like culling, depth bounds. + void MakeIncrementStencilPipelineCI(uint32_t eid, ResourceId pipe, + VkGraphicsPipelineCreateInfo &pipeCreateInfo, + rdcarray &stages, + bool disableTests) { const VulkanCreationInfo::Pipeline &p = m_pDriver->GetDebugManager()->GetPipelineInfo(pipe); m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, pipe); @@ -457,17 +459,22 @@ protected: VkRect2D newScissors[16]; memset(newScissors, 0, sizeof(newScissors)); - // Turn off all tests, except stencil which is set to always pass - // and increment. + + // TODO: should leave in the original state. + ds->depthTestEnable = VK_FALSE; + ds->depthWriteEnable = VK_FALSE; + + if(disableTests) { rs->cullMode = VK_CULL_MODE_NONE; rs->rasterizerDiscardEnable = VK_FALSE; - ds->depthTestEnable = VK_FALSE; - ds->depthWriteEnable = VK_FALSE; ds->depthBoundsTestEnable = VK_FALSE; if(m_pDriver->GetDeviceFeatures().depthClamp) rs->depthClampEnable = true; + } + // Set up the stencil state. + { ds->stencilTestEnable = VK_TRUE; ds->front.compareOp = VK_COMPARE_OP_ALWAYS; ds->front.failOp = VK_STENCIL_OP_INCREMENT_AND_CLAMP; @@ -477,7 +484,10 @@ protected: ds->front.writeMask = 0xff; ds->front.reference = 0; ds->back = ds->front; + } + // Narrow on the specific pixel and sample. + { ms->pSampleMask = &m_CallbackInfo.sampleMask; // Change scissors unless they are set dynamically. @@ -497,6 +507,16 @@ protected: } } + // Turn off all color modifications. + { + VkPipelineColorBlendStateCreateInfo *cbs = + (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState; + VkPipelineColorBlendAttachmentState *atts = + (VkPipelineColorBlendAttachmentState *)cbs->pAttachments; + for(uint32_t i = 0; i < cbs->attachmentCount; i++) + atts[i].colorWriteMask = 0; + } + // TODO: this is wrong, should take into account subpass. pipeCreateInfo.subpass = 0; @@ -982,17 +1002,8 @@ private: VkGraphicsPipelineCreateInfo pipeCreateInfo = {}; rdcarray stages; - MakeAllPassIncrementStencilPipelineCI(eid, pipeline, pipeCreateInfo, stages); - { - // We just need to determine if something attempted to write to pixel. - // Disable actual color modifications. - VkPipelineColorBlendStateCreateInfo *cbs = - (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState; - VkPipelineColorBlendAttachmentState *atts = - (VkPipelineColorBlendAttachmentState *)cbs->pAttachments; - for(uint32_t i = 0; i < cbs->attachmentCount; i++) - atts[i].colorWriteMask = 0; - } + MakeIncrementStencilPipelineCI(eid, pipeline, pipeCreateInfo, stages, true); + for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++) { if(stages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT) @@ -1094,6 +1105,8 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback for(uint32_t i = 0; i < pipestate.views.size(); i++) ScissorToPixel(pipestate.views[i], pipestate.scissors[i]); + // TODO: should fill depth value from the original DS attachment. + // Replay the draw with a fixed color shader that never discards, and stencil // increment to count number of fragments. We will get the number of fragments // not accounting for shader discard. @@ -1112,6 +1125,8 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback // shader discard. CopyImagePixel(cmd, params, storeOffset + offsetof(struct EventInfo, dsWithoutShaderDiscard)); + // TODO: in between reset the depth value. + // Replay the draw with the original fragment shader to get the actual number // of fragments, accounting for potential shader discard. pipestate.graphics.pipeline = GetResID(replacements.originalShaderStencil); @@ -1364,22 +1379,11 @@ private: VkGraphicsPipelineCreateInfo pipeCreateInfo = {}; rdcarray stages; - MakeAllPassIncrementStencilPipelineCI(eid, pipeline, pipeCreateInfo, stages); + MakeIncrementStencilPipelineCI(eid, pipeline, pipeCreateInfo, stages, false); // No need to change depth stencil state, it is already // set to always pass, and increment. pipeCreateInfo.renderPass = rp; - { - // We just need to determine if something attempted to write to pixel. - // Disable actual color modifications. - VkPipelineColorBlendStateCreateInfo *cbs = - (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState; - VkPipelineColorBlendAttachmentState *atts = - (VkPipelineColorBlendAttachmentState *)cbs->pAttachments; - for(uint32_t i = 0; i < cbs->attachmentCount; i++) - atts[i].colorWriteMask = 0; - } - PipelineReplacements replacements = {}; VkResult vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(), VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL, @@ -2241,23 +2245,6 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback RDCASSERTEQUAL(vkr, VK_SUCCESS); m_PipesToDestroy.push_back(pipes.postModPipe); - VkPipelineRasterizationStateCreateInfo *rs = - (VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState; - // Disable some tests, leave depthTest and depthWriteEnable as is. - // If we disable depth test, depth information would not be written. - { - // TODO: this causes post-modification values to be incorrectly mapped to events - // if some fragments failed due to culling. We are disabling culling for reporting - // shader output values and events, but if some events failed culling when we - // replay to get post-modification values the stencil count will not reach the - // expected stencil count, since stencil is not updated if culling failed. - rs->cullMode = VK_CULL_MODE_NONE; - rs->rasterizerDiscardEnable = VK_FALSE; - ds->depthBoundsTestEnable = VK_FALSE; - if(ds->depthTestEnable) - ds->depthCompareOp = VK_COMPARE_OP_ALWAYS; - } - VkPipelineColorBlendStateCreateInfo *cbs = (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState; // Turn off blending so that we can get shader output values. @@ -2425,21 +2412,12 @@ struct VulkanPixelHistoryDiscardedFragmentsCallback : VulkanPixelHistoryCallback { rdcarray stages; VkGraphicsPipelineCreateInfo pipeCreateInfo = {}; - MakeAllPassIncrementStencilPipelineCI(eid, pipe, pipeCreateInfo, stages); - - VkPipelineDepthStencilStateCreateInfo *ds = - (VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState; - VkPipelineColorBlendStateCreateInfo *cbs = - (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState; + MakeIncrementStencilPipelineCI(eid, pipe, pipeCreateInfo, stages, false); { - // Disable all tests, but stencil. + VkPipelineDepthStencilStateCreateInfo *ds = + (VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState; ds->stencilTestEnable = VK_FALSE; - - VkPipelineColorBlendAttachmentState *atts = - (VkPipelineColorBlendAttachmentState *)cbs->pAttachments; - for(uint32_t i = 0; i < cbs->attachmentCount; i++) - atts[i].colorWriteMask = 0; } VkPipeline newPipe; @@ -2505,6 +2483,7 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou VkMarkerRegion region(StringFormat::Fmt("PixelHistorySetupResources %ux%ux%u %s %ux MSAA", extent.width, extent.height, extent.depth, ToStr(format).c_str(), samples)); + VulkanCreationInfo::Image targetImageInfo = GetImageInfo(GetResID(targetImage)); VkImage colorImage; VkImageView colorImageView; @@ -2530,8 +2509,8 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou // Create Images VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; imgInfo.imageType = VK_IMAGE_TYPE_2D; - imgInfo.mipLevels = 1; - imgInfo.arrayLayers = 1; + imgInfo.mipLevels = targetImageInfo.mipLevels; + imgInfo.arrayLayers = targetImageInfo.arrayLayers; imgInfo.samples = samples; imgInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imgInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -2993,6 +2972,15 @@ rdcarray VulkanReplay::PixelHistory(rdcarray even if(events[ev].view != ResourceId()) { // TODO: Check that the slice and mip matches. + VulkanCreationInfo::ImageView viewInfo = + m_pDriver->GetDebugManager()->GetImageViewInfo(events[ev].view); + uint32_t layerEnd = viewInfo.range.baseArrayLayer + viewInfo.range.layerCount; + if(sub.slice < viewInfo.range.baseArrayLayer || sub.slice >= layerEnd) + { + RDCDEBUG("Usage %d at %u didn't refer to the matching mip/slice (%u/%u)", events[ev].usage, + events[ev].eventId, sub.mip, sub.slice); + continue; + } } if(directWrite || clear) @@ -3072,6 +3060,8 @@ rdcarray VulkanReplay::PixelHistory(rdcarray even } } + SAFE_DELETE(tfCb); + // Try to read memory back EventInfo *eventsInfo;