mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Vk Pixel history: Add occlusion query test
Create a pipeline for doing occlusion queries
This commit is contained in:
committed by
Baldur Karlsson
parent
fa18367109
commit
97c3186e34
@@ -1,7 +1,7 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2019 Baldur Karlsson
|
||||
* Copyright (c) 2019 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,6 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <float.h>
|
||||
#include <vector>
|
||||
#include "driver/vulkan/vk_debug.h"
|
||||
#include "driver/vulkan/vk_replay.h"
|
||||
@@ -67,14 +68,20 @@ struct PixelHistoryResources
|
||||
struct PixelHistoryValue
|
||||
{
|
||||
uint8_t color[16];
|
||||
uint8_t depth[8];
|
||||
union
|
||||
{
|
||||
uint32_t udepth;
|
||||
float fdepth;
|
||||
} depth;
|
||||
int8_t stencil;
|
||||
uint8_t padding[3];
|
||||
};
|
||||
|
||||
struct EventInfo
|
||||
{
|
||||
PixelHistoryValue premod;
|
||||
PixelHistoryValue postmod;
|
||||
uint8_t shadout[16];
|
||||
PixelHistoryValue shadout;
|
||||
uint8_t fixed_stencil[8];
|
||||
uint8_t original_stencil[8];
|
||||
};
|
||||
@@ -92,18 +99,26 @@ std::vector<PixelModification> VulkanReplay::PixelHistory(std::vector<EventUsage
|
||||
|
||||
#else
|
||||
|
||||
struct PipelineReplacements
|
||||
{
|
||||
VkPipeline occlusion;
|
||||
VkPipeline fixedShaderStencil;
|
||||
VkPipeline originalShaderStencil;
|
||||
};
|
||||
|
||||
struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
{
|
||||
VulkanPixelHistoryCallback(WrappedVulkan *vk, uint32_t x, uint32_t y, VkImage image,
|
||||
VkFormat format, uint32_t sampleMask, VkQueryPool occlusionPool,
|
||||
VkImageView colorImageView, VkImageView stencilImageView,
|
||||
VkImage colorImage, VkImage stencilImage, VkBuffer dstBuffer,
|
||||
const std::vector<EventUsage> &events)
|
||||
VkFormat format, VkExtent3D extent, uint32_t sampleMask,
|
||||
VkQueryPool occlusionPool, VkImageView colorImageView,
|
||||
VkImageView stencilImageView, VkImage colorImage, VkImage stencilImage,
|
||||
VkBuffer dstBuffer, const std::vector<EventUsage> &events)
|
||||
: m_pDriver(vk),
|
||||
m_X(x),
|
||||
m_Y(y),
|
||||
m_Image(image),
|
||||
m_Format(format),
|
||||
m_Extent(extent),
|
||||
m_DstBuffer(dstBuffer),
|
||||
m_SampleMask(sampleMask),
|
||||
m_OcclusionPool(occlusionPool),
|
||||
@@ -118,14 +133,74 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
m_Events.insert(std::make_pair(events[i].eventId, events[i]));
|
||||
}
|
||||
~VulkanPixelHistoryCallback() { m_pDriver->SetDrawcallCB(NULL); }
|
||||
void CopyPixel(uint32_t eid, VkCommandBuffer cmd, size_t offset)
|
||||
// CreateResources creates fixed colour shader, offscreen framebuffer and
|
||||
// a renderpass for occlusion and stencil tests.
|
||||
void CreateResources()
|
||||
{
|
||||
// Create fixed colour shader
|
||||
float col[4] = {1.0, 0.0, 0.0, 1.0};
|
||||
m_pDriver->GetDebugManager()->PatchFixedColShader(m_FixedColFS, col);
|
||||
|
||||
VkResult vkr;
|
||||
|
||||
// TODO: add depth/stencil attachment
|
||||
VkAttachmentReference colRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||
VkSubpassDescription sub = {};
|
||||
sub.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
sub.colorAttachmentCount = 1;
|
||||
sub.pColorAttachments = &colRef;
|
||||
|
||||
VkAttachmentDescription colDesc = {};
|
||||
colDesc.format = m_Format;
|
||||
colDesc.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
colDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
colDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
colDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
colDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
colDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
colDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkRenderPassCreateInfo rpinfo = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
rpinfo.attachmentCount = 1;
|
||||
rpinfo.pAttachments = &colDesc;
|
||||
rpinfo.subpassCount = 1;
|
||||
rpinfo.pSubpasses = ⊂
|
||||
vkr = m_pDriver->vkCreateRenderPass(m_pDriver->GetDev(), &rpinfo, NULL, &m_RenderPass);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
fbinfo.renderPass = m_RenderPass;
|
||||
fbinfo.attachmentCount = 1;
|
||||
fbinfo.pAttachments = &m_ColorImageView;
|
||||
fbinfo.width = m_Extent.width;
|
||||
fbinfo.height = m_Extent.height;
|
||||
fbinfo.layers = 1;
|
||||
|
||||
vkr = m_pDriver->vkCreateFramebuffer(m_pDriver->GetDev(), &fbinfo, NULL, &m_OffscreenFB);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
void DestroyResources()
|
||||
{
|
||||
m_pDriver->vkDestroyShaderModule(m_pDriver->GetDev(), m_FixedColFS, NULL);
|
||||
m_pDriver->vkDestroyFramebuffer(m_pDriver->GetDev(), m_OffscreenFB, NULL);
|
||||
m_pDriver->vkDestroyRenderPass(m_pDriver->GetDev(), m_RenderPass, NULL);
|
||||
|
||||
for(auto it = m_PipelineCache.begin(); it != m_PipelineCache.end(); ++it)
|
||||
{
|
||||
m_pDriver->vkDestroyPipeline(m_pDriver->GetDev(), it->second.occlusion, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyPixel(VkImage srcImage, VkFormat srcFormat, VkImage depthImage, VkFormat depthFormat,
|
||||
VkCommandBuffer cmd, size_t offset)
|
||||
{
|
||||
CopyPixelParams colourCopyParams = {};
|
||||
colourCopyParams.multisampled = false; // TODO: multisampled
|
||||
colourCopyParams.srcImage = m_Image;
|
||||
colourCopyParams.srcImage = srcImage;
|
||||
colourCopyParams.srcImageLayout =
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: image layout
|
||||
colourCopyParams.srcImageFormat = m_Format;
|
||||
colourCopyParams.srcImageFormat = srcFormat;
|
||||
colourCopyParams.imageOffset.x = int32_t(m_X);
|
||||
colourCopyParams.imageOffset.y = int32_t(m_Y);
|
||||
colourCopyParams.imageOffset.z = 0;
|
||||
@@ -133,24 +208,139 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(cmd, colourCopyParams, offset);
|
||||
|
||||
const DrawcallDescription *draw = m_pDriver->GetDrawcall(eid);
|
||||
if(draw && draw->depthOut != ResourceId())
|
||||
if(depthImage != VK_NULL_HANDLE)
|
||||
{
|
||||
// The draw call had a depth image attachment.
|
||||
ResourceId depthImage = m_pDriver->GetResourceManager()->GetLiveID(draw->depthOut);
|
||||
const VulkanCreationInfo::Image &imginfo =
|
||||
m_pDriver->GetDebugManager()->GetImageInfo(depthImage);
|
||||
CopyPixelParams depthCopyParams = colourCopyParams;
|
||||
depthCopyParams.depthcopy = true;
|
||||
depthCopyParams.srcImage =
|
||||
m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(depthImage);
|
||||
depthCopyParams.srcImage = depthImage;
|
||||
depthCopyParams.srcImageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthCopyParams.srcImageFormat = imginfo.format;
|
||||
depthCopyParams.srcImageFormat = depthFormat;
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, depthCopyParams, offset + offsetof(struct PixelHistoryValue, depth));
|
||||
}
|
||||
}
|
||||
|
||||
// ReplayDraw begins renderpass, executes a single draw defined by the eventId and
|
||||
// ends the renderpass.
|
||||
void ReplayDraw(VkCommandBuffer cmd, size_t eventIndex, int eventId, bool doQuery)
|
||||
{
|
||||
VulkanRenderState &state = m_pDriver->GetRenderState();
|
||||
const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eventId);
|
||||
state.BeginRenderPassAndApplyState(cmd, VulkanRenderState::BindGraphics);
|
||||
|
||||
if(doQuery)
|
||||
ObjDisp(cmd)->CmdBeginQuery(Unwrap(cmd), m_OcclusionPool, (uint32_t)eventIndex,
|
||||
VK_QUERY_CONTROL_PRECISE_BIT);
|
||||
|
||||
if(drawcall->flags & DrawFlags::Indexed)
|
||||
ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
|
||||
drawcall->indexOffset, drawcall->baseVertex,
|
||||
drawcall->instanceOffset);
|
||||
else
|
||||
ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances,
|
||||
drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
|
||||
if(doQuery)
|
||||
ObjDisp(cmd)->CmdEndQuery(Unwrap(cmd), m_OcclusionPool, (uint32_t)eventIndex);
|
||||
|
||||
state.EndRenderPass(cmd);
|
||||
}
|
||||
|
||||
void UpdateScissor(const VkViewport &view, VkRect2D &scissor)
|
||||
{
|
||||
float fx = (float)m_X;
|
||||
float fy = (float)m_Y;
|
||||
float y_start = view.y;
|
||||
float y_end = view.y + view.height;
|
||||
if(view.height < 0)
|
||||
{
|
||||
y_start = view.y + view.height;
|
||||
y_end = view.y;
|
||||
}
|
||||
|
||||
if(fx < view.x || fy < y_start || fx >= view.x + view.width || fy >= y_end)
|
||||
{
|
||||
scissor.offset.x = scissor.offset.y = scissor.extent.width = scissor.extent.height = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scissor.offset.x = m_X;
|
||||
scissor.offset.y = m_Y;
|
||||
scissor.extent.width = scissor.extent.height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePipelineForOcclusion creates a graphics VkPipeline to use for occlusion
|
||||
// queries. The pipeline uses a fixed colour shader, disables all tests, and
|
||||
// scissors to just the pixel we are interested in.
|
||||
VkPipeline CreatePipelineForOcclusion(ResourceId pipeline)
|
||||
{
|
||||
VkGraphicsPipelineCreateInfo pipeCreateInfo = {};
|
||||
m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, pipeline);
|
||||
VkPipelineRasterizationStateCreateInfo *rs =
|
||||
(VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState;
|
||||
VkPipelineDepthStencilStateCreateInfo *ds =
|
||||
(VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState;
|
||||
VkPipelineViewportStateCreateInfo *vs =
|
||||
(VkPipelineViewportStateCreateInfo *)pipeCreateInfo.pViewportState;
|
||||
const VulkanCreationInfo::Pipeline &p =
|
||||
m_pDriver->GetRenderState().m_CreationInfo->m_Pipeline[pipeline];
|
||||
|
||||
std::vector<VkPipelineShaderStageCreateInfo> prevStages;
|
||||
prevStages.resize(pipeCreateInfo.stageCount);
|
||||
memcpy(prevStages.data(), pipeCreateInfo.pStages,
|
||||
sizeof(VkPipelineShaderStageCreateInfo) * pipeCreateInfo.stageCount);
|
||||
|
||||
std::vector<VkPipelineShaderStageCreateInfo> stages;
|
||||
stages.resize(pipeCreateInfo.stageCount);
|
||||
memcpy(stages.data(), pipeCreateInfo.pStages,
|
||||
sizeof(VkPipelineShaderStageCreateInfo) * pipeCreateInfo.stageCount);
|
||||
|
||||
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
|
||||
{
|
||||
if(stages[i].stage == VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
{
|
||||
stages[i].module = m_FixedColFS;
|
||||
stages[i].pName = "main";
|
||||
}
|
||||
}
|
||||
pipeCreateInfo.pStages = stages.data();
|
||||
|
||||
VkRect2D newScissors[16];
|
||||
memset(newScissors, 0, sizeof(newScissors));
|
||||
{
|
||||
// Disable all tests
|
||||
rs->cullMode = VK_CULL_MODE_NONE;
|
||||
rs->rasterizerDiscardEnable = VK_FALSE;
|
||||
ds->depthTestEnable = VK_FALSE;
|
||||
ds->depthWriteEnable = VK_FALSE;
|
||||
ds->stencilTestEnable = VK_FALSE;
|
||||
ds->depthBoundsTestEnable = VK_FALSE;
|
||||
|
||||
if(m_pDriver->GetDeviceFeatures().depthClamp)
|
||||
rs->depthClampEnable = true;
|
||||
|
||||
// Change scissors unless they are set dynamically.
|
||||
if(!p.dynamicStates[VkDynamicViewport])
|
||||
{
|
||||
for(uint32_t i = 0; i < vs->viewportCount; i++)
|
||||
{
|
||||
UpdateScissor(vs->pViewports[i], newScissors[i]);
|
||||
}
|
||||
vs->pScissors = newScissors;
|
||||
}
|
||||
}
|
||||
// TODO: Disable discard rectangles from VK_EXT_discard_rectangles.
|
||||
|
||||
pipeCreateInfo.renderPass = m_RenderPass;
|
||||
|
||||
VkPipeline pipe;
|
||||
VkResult vkr = m_pDriver->vkCreateGraphicsPipelines(m_pDriver->GetDev(), VK_NULL_HANDLE, 1,
|
||||
&pipeCreateInfo, NULL, &pipe);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
return pipe;
|
||||
}
|
||||
|
||||
void PreDraw(uint32_t eid, VkCommandBuffer cmd)
|
||||
{
|
||||
auto it = m_Events.find(eid);
|
||||
@@ -163,9 +353,66 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
m_pDriver->GetRenderState().EndRenderPass(cmd);
|
||||
// Get pre-modification values
|
||||
size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo);
|
||||
CopyPixel(eid, cmd, storeOffset);
|
||||
VkImage depthImage = VK_NULL_HANDLE;
|
||||
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
|
||||
const DrawcallDescription *draw = m_pDriver->GetDrawcall(eid);
|
||||
if(draw && draw->depthOut != ResourceId())
|
||||
{
|
||||
ResourceId resId = m_pDriver->GetResourceManager()->GetLiveID(draw->depthOut);
|
||||
depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(resId);
|
||||
const VulkanCreationInfo::Image &imginfo = m_pDriver->GetDebugManager()->GetImageInfo(resId);
|
||||
depthFormat = imginfo.format;
|
||||
}
|
||||
|
||||
CopyPixel(m_Image, m_Format, depthImage, depthFormat, cmd, storeOffset);
|
||||
|
||||
// TODO: add all logic for draw calls.
|
||||
VulkanRenderState &pipestate = m_pDriver->GetRenderState();
|
||||
ResourceId prevState = pipestate.graphics.pipeline;
|
||||
ResourceId prevRenderpass = pipestate.renderPass;
|
||||
ResourceId prevFramebuffer = pipestate.framebuffer;
|
||||
uint32_t prevSubpass = pipestate.subpass;
|
||||
|
||||
{
|
||||
auto pipeIt = m_PipelineCache.find(pipestate.graphics.pipeline);
|
||||
PipelineReplacements replacements;
|
||||
|
||||
if(pipeIt != m_PipelineCache.end())
|
||||
{
|
||||
replacements = pipeIt->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Create other pipeline replacements
|
||||
replacements.occlusion = CreatePipelineForOcclusion(pipestate.graphics.pipeline);
|
||||
|
||||
m_PipelineCache.insert(std::make_pair(pipestate.graphics.pipeline, replacements));
|
||||
}
|
||||
|
||||
const VulkanCreationInfo::Pipeline &p =
|
||||
pipestate.m_CreationInfo->m_Pipeline[pipestate.graphics.pipeline];
|
||||
if(p.dynamicStates[VkDynamicViewport])
|
||||
for(uint32_t i = 0; i < pipestate.views.size(); i++)
|
||||
UpdateScissor(pipestate.views[i], pipestate.scissors[i]);
|
||||
|
||||
pipestate.framebuffer = GetResID(m_OffscreenFB);
|
||||
pipestate.renderPass = GetResID(m_RenderPass);
|
||||
pipestate.subpass = 0;
|
||||
pipestate.graphics.pipeline = GetResID(replacements.occlusion);
|
||||
// TODO: Draws might have side-effects (writing to storage images/buffers).
|
||||
// Consider re-writing SPIR-V for all shaders except fragment shader
|
||||
// to remove all stores.s
|
||||
ReplayDraw(cmd, (uint32_t)m_OcclusionQueries.size(), eid, true);
|
||||
|
||||
m_OcclusionQueries.insert(
|
||||
std::pair<uint32_t, uint32_t>(eid, (uint32_t)m_OcclusionQueries.size()));
|
||||
}
|
||||
|
||||
// Restore the state.
|
||||
m_pDriver->GetRenderState() = m_PrevState;
|
||||
pipestate.framebuffer = prevFramebuffer;
|
||||
pipestate.renderPass = prevRenderpass;
|
||||
pipestate.subpass = prevSubpass;
|
||||
|
||||
if(m_PrevState.graphics.pipeline != ResourceId())
|
||||
m_pDriver->GetRenderState().BeginRenderPassAndApplyState(cmd, VulkanRenderState::BindGraphics);
|
||||
@@ -179,7 +426,19 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
m_pDriver->GetRenderState().EndRenderPass(cmd);
|
||||
|
||||
size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo);
|
||||
CopyPixel(eid, cmd, storeOffset + offsetof(struct EventInfo, postmod));
|
||||
VkImage depthImage = VK_NULL_HANDLE;
|
||||
VkFormat depthFormat = VK_FORMAT_UNDEFINED;
|
||||
const DrawcallDescription *draw = m_pDriver->GetDrawcall(eid);
|
||||
if(draw && draw->depthOut != ResourceId())
|
||||
{
|
||||
ResourceId resId = m_pDriver->GetResourceManager()->GetLiveID(draw->depthOut);
|
||||
depthImage = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(resId);
|
||||
const VulkanCreationInfo::Image &imginfo = m_pDriver->GetDebugManager()->GetImageInfo(resId);
|
||||
depthFormat = imginfo.format;
|
||||
}
|
||||
|
||||
CopyPixel(m_Image, m_Format, depthImage, depthFormat, cmd,
|
||||
storeOffset + offsetof(struct EventInfo, postmod));
|
||||
|
||||
m_pDriver->GetRenderState().BeginRenderPassAndApplyState(cmd, VulkanRenderState::BindGraphics);
|
||||
|
||||
@@ -199,7 +458,7 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
return;
|
||||
|
||||
size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo);
|
||||
CopyPixel(eid, cmd, storeOffset);
|
||||
CopyPixel(m_Image, m_Format, VK_NULL_HANDLE, VK_FORMAT_UNDEFINED, cmd, storeOffset);
|
||||
}
|
||||
bool PostDispatch(uint32_t eid, VkCommandBuffer cmd)
|
||||
{
|
||||
@@ -207,7 +466,8 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
return false;
|
||||
|
||||
size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo);
|
||||
CopyPixel(eid, cmd, storeOffset + offsetof(struct EventInfo, postmod));
|
||||
CopyPixel(m_Image, m_Format, VK_NULL_HANDLE, VK_FORMAT_UNDEFINED, cmd,
|
||||
storeOffset + offsetof(struct EventInfo, postmod));
|
||||
m_EventIndices.insert(std::make_pair(eid, m_EventIndices.size()));
|
||||
return false;
|
||||
}
|
||||
@@ -218,7 +478,7 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
return;
|
||||
|
||||
size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo);
|
||||
CopyPixel(eid, cmd, storeOffset);
|
||||
CopyPixel(m_Image, m_Format, VK_NULL_HANDLE, VK_FORMAT_UNDEFINED, cmd, storeOffset);
|
||||
}
|
||||
bool PostMisc(uint32_t eid, DrawFlags flags, VkCommandBuffer cmd)
|
||||
{
|
||||
@@ -226,7 +486,8 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
return false;
|
||||
|
||||
size_t storeOffset = m_EventIndices.size() * sizeof(EventInfo);
|
||||
CopyPixel(eid, cmd, storeOffset + offsetof(struct EventInfo, postmod));
|
||||
CopyPixel(m_Image, m_Format, VK_NULL_HANDLE, VK_FORMAT_UNDEFINED, cmd,
|
||||
storeOffset + offsetof(struct EventInfo, postmod));
|
||||
m_EventIndices.insert(std::make_pair(eid, m_EventIndices.size()));
|
||||
return false;
|
||||
}
|
||||
@@ -241,8 +502,10 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
WrappedVulkan *m_pDriver;
|
||||
VkImage m_Image;
|
||||
VkFormat m_Format;
|
||||
VkExtent3D m_Extent;
|
||||
std::map<uint32_t, EventUsage> m_Events;
|
||||
std::map<uint32_t, size_t> m_EventIndices;
|
||||
std::map<uint32_t, uint32_t> m_OcclusionQueries;
|
||||
VkBuffer m_DstBuffer;
|
||||
uint32_t m_X, m_Y;
|
||||
|
||||
@@ -253,6 +516,11 @@ struct VulkanPixelHistoryCallback : public VulkanDrawcallCallback
|
||||
VkImage m_ColorImage;
|
||||
VkImage m_StencilImage;
|
||||
|
||||
VkShaderModule m_FixedColFS;
|
||||
VkRenderPass m_RenderPass;
|
||||
VkFramebuffer m_OffscreenFB;
|
||||
std::map<ResourceId, PipelineReplacements> m_PipelineCache;
|
||||
|
||||
VulkanRenderState m_PrevState;
|
||||
};
|
||||
|
||||
@@ -283,7 +551,9 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
|
||||
// Device local resources:
|
||||
imgInfo.format = format;
|
||||
imgInfo.extent = {extent.width, extent.height, 1};
|
||||
imgInfo.extent.width = extent.width;
|
||||
imgInfo.extent.height = extent.height;
|
||||
imgInfo.extent.depth = 1;
|
||||
imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
@@ -328,7 +598,7 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
|
||||
viewInfo.image = stencilImage;
|
||||
viewInfo.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
viewInfo.subresourceRange = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1};
|
||||
viewInfo.subresourceRange = {VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1};
|
||||
|
||||
vkr = m_pDriver->vkCreateImageView(m_Device, &viewInfo, NULL, &stencilImageView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
@@ -521,6 +791,7 @@ std::vector<PixelModification> VulkanReplay::PixelHistory(std::vector<EventUsage
|
||||
uint32_t slice, uint32_t mip,
|
||||
uint32_t sampleIdx, CompType typeHint)
|
||||
{
|
||||
RDCDEBUG("PixelHistory: pixel: (%u, %u) with %u events", x, y, events.size());
|
||||
std::vector<PixelModification> history;
|
||||
VkResult vkr;
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
@@ -564,11 +835,24 @@ std::vector<PixelModification> VulkanReplay::PixelHistory(std::vector<EventUsage
|
||||
|
||||
VulkanPixelHistoryCallback cb(
|
||||
m_pDriver, x, y, GetResourceManager()->GetCurrentHandle<VkImage>(target), imginfo.format,
|
||||
sampleMask, occlusionPool, resources.colorImageView, resources.stencilImageView,
|
||||
imginfo.extent, sampleMask, occlusionPool, resources.colorImageView, resources.stencilImageView,
|
||||
resources.colorImage, resources.stencilImage, resources.dstBuffer, events);
|
||||
cb.CreateResources();
|
||||
m_pDriver->ReplayLog(0, events.back().eventId, eReplay_Full);
|
||||
m_pDriver->SubmitCmds();
|
||||
m_pDriver->FlushQ();
|
||||
cb.DestroyResources();
|
||||
|
||||
std::vector<uint64_t> occlusionResults;
|
||||
if(cb.m_OcclusionQueries.size() > 0)
|
||||
{
|
||||
occlusionResults.resize(cb.m_OcclusionQueries.size());
|
||||
vkr = ObjDisp(dev)->GetQueryPoolResults(
|
||||
Unwrap(dev), occlusionPool, 0, (uint32_t)occlusionResults.size(),
|
||||
occlusionResults.size() * sizeof(occlusionResults[0]), occlusionResults.data(),
|
||||
sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
for(size_t ev = 0; ev < events.size(); ev++)
|
||||
{
|
||||
@@ -576,7 +860,19 @@ std::vector<PixelModification> VulkanReplay::PixelHistory(std::vector<EventUsage
|
||||
bool clear = bool(draw->flags & DrawFlags::Clear);
|
||||
bool directWrite = isDirectWrite(events[ev].usage);
|
||||
// TODO: actually do occlusion query.
|
||||
uint64_t occlData = 1;
|
||||
uint64_t occlData = 0;
|
||||
if(!directWrite)
|
||||
{
|
||||
auto it = cb.m_OcclusionQueries.find((uint32_t)events[ev].eventId);
|
||||
if(it == cb.m_OcclusionQueries.end() || it->second > occlusionResults.size())
|
||||
{
|
||||
RDCERR("Failed to find occlusion query result for event id %u", events[ev].eventId);
|
||||
}
|
||||
occlData = occlusionResults[it->second];
|
||||
}
|
||||
|
||||
RDCDEBUG("PixelHistory event id: %u, clear = %u, directWrite = %u, occlData = %u",
|
||||
events[ev].eventId, clear, directWrite, occlData);
|
||||
|
||||
if(events[ev].view != ResourceId())
|
||||
{
|
||||
@@ -621,15 +917,14 @@ std::vector<PixelModification> VulkanReplay::PixelHistory(std::vector<EventUsage
|
||||
postMod.col.floatValue[0] = (float)(ei.postmod.color[2] / 255.0);
|
||||
postMod.col.floatValue[1] = (float)(ei.postmod.color[1] / 255.0);
|
||||
postMod.col.floatValue[2] = (float)(ei.postmod.color[0] / 255.0);
|
||||
postMod.col.floatValue[3] = (float)(ei.shadout[3] / 255.0);
|
||||
shadout.col.floatValue[0] = (float)(ei.shadout[2] / 255.0);
|
||||
shadout.col.floatValue[1] = (float)(ei.shadout[1] / 255.0);
|
||||
shadout.col.floatValue[2] = (float)(ei.shadout[0] / 255.0);
|
||||
shadout.col.floatValue[3] = (float)(ei.shadout[3] / 255.0);
|
||||
preMod.depth = *((float *)ei.premod.depth);
|
||||
preMod.stencil = ei.premod.depth[4];
|
||||
postMod.depth = *((float *)ei.postmod.depth);
|
||||
postMod.stencil = ei.postmod.depth[4];
|
||||
postMod.col.floatValue[3] = (float)(ei.shadout.color[3] / 255.0);
|
||||
shadout.col.floatValue[0] = (float)(ei.shadout.color[2] / 255.0);
|
||||
shadout.col.floatValue[1] = (float)(ei.shadout.color[1] / 255.0);
|
||||
shadout.col.floatValue[2] = (float)(ei.shadout.color[0] / 255.0);
|
||||
preMod.depth = ei.premod.depth.fdepth;
|
||||
preMod.stencil = ei.premod.stencil;
|
||||
postMod.depth = ei.postmod.depth.fdepth;
|
||||
postMod.stencil = ei.postmod.stencil;
|
||||
|
||||
mod.preMod = preMod;
|
||||
mod.shaderOut = shadout;
|
||||
@@ -643,4 +938,4 @@ std::vector<PixelModification> VulkanReplay::PixelHistory(std::vector<EventUsage
|
||||
return history;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user