mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Pixel history changes
- Add config to enable pixel history - Fix several validation errors - Fix primitive ID reporting when depth test is OFF - Patch primitive ID and fixed color shader to output to the correct framebuffer location when there are multiple color attachments
This commit is contained in:
committed by
Baldur Karlsson
parent
bebc78b106
commit
bfeb66d4ce
@@ -27,6 +27,7 @@
|
||||
#include "core/core.h"
|
||||
#include "vk_common.h"
|
||||
#include "vk_core.h"
|
||||
#include "vk_shader_cache.h"
|
||||
|
||||
struct MeshDisplayPipelines
|
||||
{
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
const MeshFormat &primary,
|
||||
const MeshFormat &secondary);
|
||||
|
||||
void PatchOutputLocation(VkShaderModule &mod, BuiltinShader shaderType, uint32_t framebufferIndex);
|
||||
void PatchFixedColShader(VkShaderModule &mod, float col[4]);
|
||||
void PatchLineStripIndexBuffer(const DrawcallDescription *draw, GPUBuffer &indexBuffer,
|
||||
uint32_t &indexCount);
|
||||
|
||||
@@ -272,6 +272,55 @@ struct VulkanQuadOverdrawCallback : public VulkanDrawcallCallback
|
||||
VulkanRenderState m_PrevState;
|
||||
};
|
||||
|
||||
void VulkanDebugManager::PatchOutputLocation(VkShaderModule &mod, BuiltinShader shaderType,
|
||||
uint32_t framebufferIndex)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t *spirv;
|
||||
float *data;
|
||||
} alias;
|
||||
|
||||
rdcarray<uint32_t> spv = *m_pDriver->GetShaderCache()->GetBuiltinBlob(shaderType);
|
||||
|
||||
alias.spirv = &spv[0];
|
||||
size_t spirvLength = spv.size();
|
||||
|
||||
bool patched = false;
|
||||
|
||||
size_t it = 5;
|
||||
while(it < spirvLength)
|
||||
{
|
||||
uint16_t WordCount = alias.spirv[it] >> rdcspv::WordCountShift;
|
||||
rdcspv::Op opcode = rdcspv::Op(alias.spirv[it] & rdcspv::OpCodeMask);
|
||||
|
||||
if(opcode == rdcspv::Op::Decorate &&
|
||||
(rdcspv::Decoration(alias.spirv[it + 2]) == rdcspv::Decoration::Location))
|
||||
{
|
||||
alias.spirv[it + 3] = framebufferIndex;
|
||||
|
||||
patched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
it += WordCount;
|
||||
}
|
||||
|
||||
if(!patched)
|
||||
RDCERR("Didn't patch the output location");
|
||||
|
||||
VkShaderModuleCreateInfo modinfo = {
|
||||
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
spv.size() * sizeof(uint32_t),
|
||||
alias.spirv,
|
||||
};
|
||||
|
||||
VkResult vkr = m_pDriver->vkCreateShaderModule(m_Device, &modinfo, NULL, &mod);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::PatchFixedColShader(VkShaderModule &mod, float col[4])
|
||||
{
|
||||
union
|
||||
|
||||
@@ -126,7 +126,7 @@ struct PipelineReplacements
|
||||
// PixelHistoryShaderCache manages temporary shaders created for pixel history.
|
||||
struct PixelHistoryShaderCache
|
||||
{
|
||||
PixelHistoryShaderCache(WrappedVulkan *vk) : m_pDriver(vk), m_FixedColFS(VK_NULL_HANDLE) {}
|
||||
PixelHistoryShaderCache(WrappedVulkan *vk) : m_pDriver(vk) {}
|
||||
~PixelHistoryShaderCache()
|
||||
{
|
||||
for(auto it = m_ShaderReplacements.begin(); it != m_ShaderReplacements.end(); ++it)
|
||||
@@ -134,20 +134,38 @@ struct PixelHistoryShaderCache
|
||||
if(it->second != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderModule(m_pDriver->GetDev(), it->second, NULL);
|
||||
}
|
||||
if(m_FixedColFS != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderModule(m_pDriver->GetDev(), m_FixedColFS, NULL);
|
||||
for(auto it = m_FixedColFS.begin(); it != m_FixedColFS.end(); it++)
|
||||
m_pDriver->vkDestroyShaderModule(m_pDriver->GetDev(), it->second, NULL);
|
||||
for(auto it = m_PrimIDFS.begin(); it != m_PrimIDFS.end(); it++)
|
||||
m_pDriver->vkDestroyShaderModule(m_pDriver->GetDev(), it->second, NULL);
|
||||
}
|
||||
|
||||
// Returns a fragment shader module that outputs a fixed color.
|
||||
VkShaderModule GetFixedColShader()
|
||||
// Returns a fragment shader module that outputs a fixed color to the given
|
||||
// color attachment.
|
||||
VkShaderModule GetFixedColShader(uint32_t framebufferIndex)
|
||||
{
|
||||
// Create fixed colour shader if we haven't already.
|
||||
if(m_FixedColFS == VK_NULL_HANDLE)
|
||||
{
|
||||
float col[4] = {1.0, 0.0, 0.0, 1.0};
|
||||
m_pDriver->GetDebugManager()->PatchFixedColShader(m_FixedColFS, col);
|
||||
}
|
||||
return m_FixedColFS;
|
||||
auto it = m_FixedColFS.find(framebufferIndex);
|
||||
if(it != m_FixedColFS.end())
|
||||
return it->second;
|
||||
VkShaderModule sh;
|
||||
m_pDriver->GetDebugManager()->PatchOutputLocation(sh, BuiltinShader::FixedColFS,
|
||||
framebufferIndex);
|
||||
m_FixedColFS.insert(std::make_pair(framebufferIndex, sh));
|
||||
return sh;
|
||||
}
|
||||
|
||||
// Returns a fragment shader module that outputs primitive ID to the given
|
||||
// color attachment.
|
||||
VkShaderModule GetPrimitiveIdShader(uint32_t framebufferIndex)
|
||||
{
|
||||
auto it = m_PrimIDFS.find(framebufferIndex);
|
||||
if(it != m_PrimIDFS.end())
|
||||
return it->second;
|
||||
VkShaderModule sh;
|
||||
m_pDriver->GetDebugManager()->PatchOutputLocation(sh, BuiltinShader::PixelHistoryPrimIDFS,
|
||||
framebufferIndex);
|
||||
m_PrimIDFS.insert(std::make_pair(framebufferIndex, sh));
|
||||
return sh;
|
||||
}
|
||||
|
||||
// Returns a shader that is equivalent to the given shader, but attempts to remove
|
||||
@@ -305,7 +323,8 @@ private:
|
||||
}
|
||||
|
||||
WrappedVulkan *m_pDriver;
|
||||
VkShaderModule m_FixedColFS;
|
||||
std::map<uint32_t, VkShaderModule> m_FixedColFS;
|
||||
std::map<uint32_t, VkShaderModule> m_PrimIDFS;
|
||||
|
||||
// ShaderKey consists of original shader module ID and entry point name.
|
||||
typedef rdcpair<ResourceId, rdcstr> ShaderKey;
|
||||
@@ -712,7 +731,19 @@ struct VulkanOcclusionAndStencilCallback : public VulkanPixelHistoryCallback
|
||||
CreateRenderPass(pipestate.renderPass, pipestate.GetFramebuffer(), pipestate.subpass);
|
||||
VkFramebuffer newFb = CreateFramebuffer(pipestate.renderPass, newRp, pipestate.subpass,
|
||||
pipestate.GetFramebuffer(), m_StencilImageView);
|
||||
PipelineReplacements replacements = GetPipelineReplacements(eid, pipestate.graphics.pipeline);
|
||||
uint32_t framebufferIndex = 0;
|
||||
const rdcarray<ResourceId> &atts = pipestate.GetFramebufferAttachments();
|
||||
for(uint32_t i = 0; i < atts.size(); i++)
|
||||
{
|
||||
ResourceId img = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[i]).image;
|
||||
if(img == GetResID(m_Image))
|
||||
{
|
||||
framebufferIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PipelineReplacements replacements =
|
||||
GetPipelineReplacements(eid, pipestate.graphics.pipeline, newRp, framebufferIndex);
|
||||
|
||||
if(p.dynamicStates[VkDynamicViewport])
|
||||
for(uint32_t i = 0; i < pipestate.views.size(); i++)
|
||||
@@ -949,7 +980,8 @@ private:
|
||||
// GetPipelineReplacements creates pipeline replacements that disable all tests,
|
||||
// and use either fixed or original fragment shader, and shaders that don't
|
||||
// have side effects.
|
||||
PipelineReplacements GetPipelineReplacements(uint32_t eid, ResourceId pipeline)
|
||||
PipelineReplacements GetPipelineReplacements(uint32_t eid, ResourceId pipeline, VkRenderPass rp,
|
||||
uint32_t framebufferIndex)
|
||||
{
|
||||
// The map does not keep track of the event ID, event ID is only used to figure out
|
||||
// which shaders need to be modified. Those flags are based on the shaders bound,
|
||||
@@ -964,6 +996,7 @@ private:
|
||||
MakeAllPassIncrementStencilPipelineCI(eid, pipeline, pipeCreateInfo, stages);
|
||||
// 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.
|
||||
@@ -986,7 +1019,7 @@ private:
|
||||
{
|
||||
if(stages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
{
|
||||
stages[i].module = m_ShaderCache->GetFixedColShader();
|
||||
stages[i].module = m_ShaderCache->GetFixedColShader(framebufferIndex);
|
||||
stages[i].pName = "main";
|
||||
break;
|
||||
}
|
||||
@@ -1022,9 +1055,11 @@ private:
|
||||
// stencil test etc).
|
||||
struct TestsFailedCallback : public VulkanPixelHistoryCallback
|
||||
{
|
||||
TestsFailedCallback(WrappedVulkan *vk, PixelHistoryShaderCache *shaderCache, uint32_t x, uint32_t y,
|
||||
uint32_t sampleMask, VkQueryPool occlusionPool, rdcarray<uint32_t> events)
|
||||
TestsFailedCallback(WrappedVulkan *vk, PixelHistoryShaderCache *shaderCache, uint32_t x,
|
||||
uint32_t y, VkImage image, uint32_t sampleMask, VkQueryPool occlusionPool,
|
||||
rdcarray<uint32_t> events)
|
||||
: VulkanPixelHistoryCallback(vk, shaderCache, x, y, sampleMask, occlusionPool),
|
||||
m_Image(image),
|
||||
m_Events(events)
|
||||
{
|
||||
}
|
||||
@@ -1049,7 +1084,19 @@ struct TestsFailedCallback : public VulkanPixelHistoryCallback
|
||||
ResourceId curPipeline = pipestate.graphics.pipeline;
|
||||
VulkanRenderState m_PrevState = m_pDriver->GetCmdRenderState();
|
||||
|
||||
ReplayDrawWithTests(cmd, eid, eventFlags, curPipeline);
|
||||
uint32_t framebufferIndex = 0;
|
||||
const rdcarray<ResourceId> &atts = pipestate.GetFramebufferAttachments();
|
||||
for(uint32_t i = 0; i < atts.size(); i++)
|
||||
{
|
||||
ResourceId img = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[i]).image;
|
||||
if(img == GetResID(m_Image))
|
||||
{
|
||||
framebufferIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ReplayDrawWithTests(cmd, eid, eventFlags, curPipeline, framebufferIndex);
|
||||
|
||||
m_pDriver->GetCmdRenderState() = m_PrevState;
|
||||
m_pDriver->GetCmdRenderState().BindPipeline(m_pDriver, cmd, VulkanRenderState::BindGraphics,
|
||||
@@ -1238,7 +1285,7 @@ private:
|
||||
};
|
||||
|
||||
void ReplayDrawWithTests(VkCommandBuffer cmd, uint32_t eid, uint32_t eventFlags,
|
||||
ResourceId basePipeline)
|
||||
ResourceId basePipeline, uint32_t framebufferIndex)
|
||||
{
|
||||
// Backface culling
|
||||
if(eventFlags & TestMustFail_Culling)
|
||||
@@ -1274,7 +1321,8 @@ private:
|
||||
uint32_t pipeFlags =
|
||||
PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_DisableDepthBoundsTest |
|
||||
PipelineCreationFlags_DisableStencilTest | PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_Culling);
|
||||
}
|
||||
|
||||
@@ -1288,7 +1336,8 @@ private:
|
||||
PipelineCreationFlags_IntersectOriginalScissor | PipelineCreationFlags_DisableDepthTest |
|
||||
PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest |
|
||||
PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
// This will change the dynamic scissor state for the later tests, but since those
|
||||
// tests happen later in the pipeline, it does not matter.
|
||||
if(dynamicScissor)
|
||||
@@ -1306,7 +1355,8 @@ private:
|
||||
uint32_t pipeFlags =
|
||||
PipelineCreationFlags_DisableDepthBoundsTest | PipelineCreationFlags_DisableStencilTest |
|
||||
PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_SampleMask);
|
||||
}
|
||||
|
||||
@@ -1316,7 +1366,8 @@ private:
|
||||
uint32_t pipeFlags = PipelineCreationFlags_DisableStencilTest |
|
||||
PipelineCreationFlags_DisableDepthTest |
|
||||
PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_DepthBounds);
|
||||
}
|
||||
|
||||
@@ -1328,7 +1379,8 @@ private:
|
||||
{
|
||||
uint32_t pipeFlags =
|
||||
PipelineCreationFlags_DisableDepthTest | PipelineCreationFlags_FixedColorShader;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_StencilTesting);
|
||||
}
|
||||
|
||||
@@ -1340,7 +1392,8 @@ private:
|
||||
{
|
||||
uint32_t pipeFlags = PipelineCreationFlags_FixedColorShader;
|
||||
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_DepthTesting);
|
||||
}
|
||||
|
||||
@@ -1353,7 +1406,8 @@ private:
|
||||
uint32_t pipeFlags = PipelineCreationFlags_DisableDepthBoundsTest |
|
||||
PipelineCreationFlags_DisableStencilTest |
|
||||
PipelineCreationFlags_DisableDepthTest;
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders);
|
||||
VkPipeline pipe = CreatePipeline(basePipeline, pipeFlags, dynamicScissor, replacementShaders,
|
||||
framebufferIndex);
|
||||
ReplayDraw(cmd, pipe, eid, TestEnabled_FragmentDiscard);
|
||||
}
|
||||
}
|
||||
@@ -1362,7 +1416,8 @@ private:
|
||||
// pipeline flags. Modifies the base pipeline according to the flags, and
|
||||
// leaves the original pipeline behavior if a flag is not set.
|
||||
VkPipeline CreatePipeline(ResourceId basePipeline, uint32_t pipeCreateFlags, bool dynamicScissor,
|
||||
const rdcarray<VkShaderModule> &replacementShaders)
|
||||
const rdcarray<VkShaderModule> &replacementShaders,
|
||||
uint32_t framebufferIndex)
|
||||
{
|
||||
rdcpair<ResourceId, uint32_t> pipeKey(basePipeline, pipeCreateFlags);
|
||||
auto it = m_PipeCache.find(pipeKey);
|
||||
@@ -1404,7 +1459,7 @@ private:
|
||||
if((ci.pStages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT) &&
|
||||
(pipeCreateFlags & PipelineCreationFlags_FixedColorShader))
|
||||
{
|
||||
stages[i].module = m_ShaderCache->GetFixedColShader();
|
||||
stages[i].module = m_ShaderCache->GetFixedColShader(framebufferIndex);
|
||||
stages[i].pName = "main";
|
||||
}
|
||||
else if(replacementShaders[StageIndex(stages[i].stage)] != VK_NULL_HANDLE)
|
||||
@@ -1458,6 +1513,7 @@ private:
|
||||
ObjDisp(cmd)->CmdEndQuery(Unwrap(cmd), m_OcclusionPool, index);
|
||||
}
|
||||
|
||||
VkImage m_Image;
|
||||
rdcarray<uint32_t> m_Events;
|
||||
// Key is event ID, value is the flags for that event.
|
||||
std::map<uint32_t, uint32_t> m_EventFlags;
|
||||
@@ -1522,10 +1578,24 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
|
||||
VkRenderPass newRp = CreateRenderPass(state.renderPass, state.GetFramebuffer(), state.subpass,
|
||||
m_Image, VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||
|
||||
VkFramebuffer newFb =
|
||||
CreateFramebuffer(state.renderPass, newRp, state.subpass, state.GetFramebuffer(),
|
||||
m_StencilImageView, GetResID(m_Image), m_PerFragmentImageView);
|
||||
Pipelines pipes = CreatePipelines(curPipeline, newRp, eid, false, 0);
|
||||
|
||||
uint32_t framebufferIndex = 0;
|
||||
const rdcarray<ResourceId> &atts = prevState.GetFramebufferAttachments();
|
||||
for(uint32_t i = 0; i < atts.size(); i++)
|
||||
{
|
||||
ResourceId img = m_pDriver->GetDebugManager()->GetImageViewInfo(atts[i]).image;
|
||||
if(img == GetResID(m_Image))
|
||||
{
|
||||
framebufferIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Pipelines pipes = CreatePipelines(curPipeline, newRp, eid, false, 0, framebufferIndex);
|
||||
|
||||
state.renderPass = GetResID(newRp);
|
||||
state.SetFramebuffer(m_pDriver, GetResID(newFb));
|
||||
@@ -1554,6 +1624,20 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
{
|
||||
for(uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
Unwrap(m_StencilImage),
|
||||
{VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1}};
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
// If depth is enabled, clear out the depth value so that the test always
|
||||
// passes. Depth writes only work if depth test is enabled.
|
||||
// Regardless also need to reset the stencil back to 0.
|
||||
@@ -1567,8 +1651,14 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
range.layerCount = 1;
|
||||
range.levelCount = 1;
|
||||
ObjDisp(cmd)->CmdClearDepthStencilImage(Unwrap(cmd), Unwrap(m_StencilImage),
|
||||
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, &dsValue,
|
||||
1, &range);
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &dsValue, 1,
|
||||
&range);
|
||||
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
m_pDriver->GetCmdRenderState().graphics.pipeline = GetResID(pipesIter[i]);
|
||||
|
||||
@@ -1589,7 +1679,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
state.EndRenderPass(cmd);
|
||||
|
||||
uint32_t storeOffset = (fragsProcessed + f) * sizeof(PerFragmentInfo);
|
||||
if(i == 1 && depthEnabled)
|
||||
if(i == 1)
|
||||
{
|
||||
storeOffset += offsetof(struct PerFragmentInfo, shaderOut);
|
||||
if(depthEnabled)
|
||||
@@ -1683,7 +1773,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
void PostRedraw(uint32_t eid, VkCommandBuffer cmd) {}
|
||||
// CreatePipelines for getting per fragment information.
|
||||
Pipelines CreatePipelines(ResourceId pipe, VkRenderPass rp, uint32_t eid, bool dynamicScissor,
|
||||
uint32_t fragmentIndex)
|
||||
uint32_t fragmentIndex, uint32_t framebufferIndex)
|
||||
{
|
||||
const VulkanCreationInfo::Pipeline &p = m_pDriver->GetDebugManager()->GetPipelineInfo(pipe);
|
||||
VkGraphicsPipelineCreateInfo pipeCreateInfo = {};
|
||||
@@ -1783,6 +1873,8 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
rs->cullMode = VK_CULL_MODE_NONE;
|
||||
rs->rasterizerDiscardEnable = VK_FALSE;
|
||||
ds->depthBoundsTestEnable = VK_FALSE;
|
||||
if(ds->depthTestEnable)
|
||||
ds->depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
}
|
||||
|
||||
pipeCreateInfo.renderPass = rp;
|
||||
@@ -1792,7 +1884,18 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
VkPipelineColorBlendAttachmentState *atts =
|
||||
(VkPipelineColorBlendAttachmentState *)cbs->pAttachments;
|
||||
for(uint32_t i = 0; i < cbs->attachmentCount; i++)
|
||||
atts[i].blendEnable = VK_FALSE;
|
||||
{
|
||||
if(i == framebufferIndex)
|
||||
{
|
||||
atts[i].blendEnable = 0;
|
||||
atts[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
atts[i].colorWriteMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(), VK_NULL_HANDLE, 1,
|
||||
&pipeCreateInfo, NULL, &pipes.shaderOutPipe);
|
||||
@@ -1810,8 +1913,7 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
{
|
||||
if(stages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
{
|
||||
stages[i].module =
|
||||
m_pDriver->GetShaderCache()->GetBuiltinModule(BuiltinShader::PixelHistoryPrimIDFS);
|
||||
stages[i].module = m_ShaderCache->GetPrimitiveIdShader(framebufferIndex);
|
||||
stages[i].pName = "main";
|
||||
}
|
||||
}
|
||||
@@ -2035,7 +2137,8 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
|
||||
imgInfo.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &stencilImage);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
@@ -2337,13 +2440,11 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
ResourceId target, uint32_t x, uint32_t y,
|
||||
const Subresource &sub, CompType typeCast)
|
||||
{
|
||||
#if 1
|
||||
if(!events.empty())
|
||||
if(!GetAPIProperties().pixelHistory)
|
||||
{
|
||||
VULKANNOTIMP("PixelHistory");
|
||||
return rdcarray<PixelModification>();
|
||||
}
|
||||
#endif
|
||||
|
||||
RDCDEBUG("PixelHistory: pixel: (%u, %u) with %u events", x, y, events.size());
|
||||
rdcarray<PixelModification> history;
|
||||
@@ -2428,8 +2529,9 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
VkQueryPool tfOcclusionPool;
|
||||
CreateOcclusionPool(m_pDriver, (uint32_t)drawEvents.size() * 6, &tfOcclusionPool);
|
||||
|
||||
tfCb = new TestsFailedCallback(m_pDriver, shaderCache, x, y, sampleMask, tfOcclusionPool,
|
||||
drawEvents);
|
||||
tfCb = new TestsFailedCallback(m_pDriver, shaderCache, x, y,
|
||||
GetResourceManager()->GetCurrentHandle<VkImage>(target),
|
||||
sampleMask, tfOcclusionPool, drawEvents);
|
||||
m_pDriver->ReplayLog(0, events.back().eventId, eReplay_Full);
|
||||
m_pDriver->SubmitCmds();
|
||||
m_pDriver->FlushQ();
|
||||
@@ -2524,7 +2626,7 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
GetResourceManager()->GetCurrentHandle<VkImage>(target), imginfo.format,
|
||||
resources.dstBuffer, resources.colorImage, resources.colorImageView, resources.stencilImage,
|
||||
resources.stencilImageView);
|
||||
m_pDriver->ReplayLog(0, events.back().eventId, eReplay_Full);
|
||||
m_pDriver->ReplayLog(0, eventsWithFrags.rbegin()->first, eReplay_Full);
|
||||
m_pDriver->SubmitCmds();
|
||||
m_pDriver->FlushQ();
|
||||
|
||||
@@ -2561,7 +2663,7 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
// Replay to see which primitives were discarded.
|
||||
VulkanPixelHistoryDiscardedFragmentsCallback discardedCb(
|
||||
m_pDriver, shaderCache, x, y, sampleMask, discardedPrimsEvents, occlPool);
|
||||
m_pDriver->ReplayLog(0, events.back().eventId, eReplay_Full);
|
||||
m_pDriver->ReplayLog(0, eventsWithFrags.rbegin()->first, eReplay_Full);
|
||||
m_pDriver->SubmitCmds();
|
||||
m_pDriver->FlushQ();
|
||||
discardedCb.FetchOcclusionResults();
|
||||
@@ -2593,7 +2695,6 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
continue;
|
||||
}
|
||||
uint32_t offset = perFragmentCB.GetEventOffset(eid) + f - discardOffset;
|
||||
|
||||
FillInColor(shaderOutFormat, bp[offset].shaderOut, history[h].shaderOut);
|
||||
history[h].shaderOut.depth = bp[offset].shaderOut.depth.fdepth;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
RDOC_CONFIG(bool, Vulkan_ShaderDebugging, false,
|
||||
"BETA: Enable experimental shader debugging support.");
|
||||
RDOC_CONFIG(bool, Vulkan_PixelHistory, false, "BETA: Enable experimental pixel history support.");
|
||||
|
||||
static const char *SPIRVDisassemblyTarget = "SPIR-V (RenderDoc)";
|
||||
static const char *AMDShaderInfoTarget = "AMD_shader_info";
|
||||
@@ -191,6 +192,7 @@ APIProperties VulkanReplay::GetAPIProperties()
|
||||
ret.rgpCapture =
|
||||
m_DriverInfo.vendor == GPUVendor::AMD && m_RGP != NULL && m_RGP->DriverSupportsInterop();
|
||||
ret.shaderDebugging = Vulkan_ShaderDebugging;
|
||||
ret.pixelHistory = Vulkan_PixelHistory;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user