diff --git a/renderdoc/driver/vulkan/Makefile b/renderdoc/driver/vulkan/Makefile
index 0c36536cf..f6c397264 100644
--- a/renderdoc/driver/vulkan/Makefile
+++ b/renderdoc/driver/vulkan/Makefile
@@ -19,6 +19,7 @@ vk_resources.o \
vk_debug.o \
vk_replay.o \
vk_info.o \
+vk_state.o \
vk_linux.o \
wrappers/vk_cmd_funcs.o \
wrappers/vk_dynamic_funcs.o \
diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj
index fdf1c28e1..b63c51f2c 100644
--- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj
+++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj
@@ -22,6 +22,7 @@
+
@@ -67,6 +68,7 @@
+
diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters
index a61cd932d..cbeef41e3 100644
--- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters
+++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters
@@ -76,6 +76,9 @@
Wrappers
+
+ Util
+
@@ -105,6 +108,9 @@
Core
+
+ Util
+
diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp
index 7704759f4..51790a48e 100644
--- a/renderdoc/driver/vulkan/vk_core.cpp
+++ b/renderdoc/driver/vulkan/vk_core.cpp
@@ -241,6 +241,7 @@ void VkInitParams::Set(const VkInstanceCreateInfo* pCreateInfo, ResourceId inst)
}
WrappedVulkan::WrappedVulkan(const char *logFilename)
+ : m_RenderState(m_CreationInfo)
{
#if defined(RELEASE)
const bool debugSerialiser = false;
@@ -285,8 +286,6 @@ WrappedVulkan::WrappedVulkan(const char *logFilename)
m_FirstEventID = 0;
m_LastEventID = ~0U;
- m_HackDrawIndices = ~0U;
-
m_LastCmdBufferID = ResourceId();
m_PartialReplayData.renderPassActive = false;
@@ -300,6 +299,7 @@ WrappedVulkan::WrappedVulkan(const char *logFilename)
m_ResourceManager = new VulkanResourceManager(m_State, m_pSerialiser, this);
m_pSerialiser->SetUserData(m_ResourceManager);
+ m_RenderState.m_ResourceManager = GetResourceManager();
m_HeaderChunk = NULL;
@@ -1736,7 +1736,8 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t
RDCASSERT(m_PartialReplayData.resultPartialCmdBuffer == VK_NULL_HANDLE);
m_PartialReplayData.partialParent = ResourceId();
m_PartialReplayData.baseEvent = 0;
- m_PartialReplayData.state = PartialReplayData::StateVector();
+ m_RenderState = VulkanRenderState(m_CreationInfo);
+ m_RenderState.m_ResourceManager = GetResourceManager();
}
if(replayType == eReplay_Full)
@@ -1755,124 +1756,23 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t
VkResult vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
+
+ bool rpWasActive = m_PartialReplayData.renderPassActive;
// if a render pass was active, begin it and set up the partial replay state
if(m_PartialReplayData.renderPassActive)
- {
- auto &s = m_PartialReplayData.state;
-
- RDCASSERT(s.renderPass != ResourceId());
-
- // clear values don't matter as we're using the load renderpass here, that
- // has all load ops set to load (as we're doing a partial replay - can't
- // just clear the targets that are partially written to).
-
- VkClearValue empty[16] = {0};
-
- RDCASSERT(ARRAY_COUNT(empty) >= m_CreationInfo.m_RenderPass[s.renderPass].attachments.size());
-
- VkRenderPassBeginInfo rpbegin = {
- VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL,
- Unwrap(m_CreationInfo.m_RenderPass[s.renderPass].loadRP),
- Unwrap(GetResourceManager()->GetCurrentHandle(s.framebuffer)),
- s.renderArea,
- (uint32_t)m_CreationInfo.m_RenderPass[s.renderPass].attachments.size(), empty,
- };
- ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_RENDER_PASS_CONTENTS_INLINE);
-
- for(uint32_t i=0; i < s.subpass; i++)
- ObjDisp(cmd)->CmdNextSubpass(Unwrap(cmd), VK_RENDER_PASS_CONTENTS_INLINE);
-
- if(s.graphics.pipeline != ResourceId())
- {
- ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(GetResourceManager()->GetCurrentHandle(s.graphics.pipeline)));
-
- ResourceId pipeLayoutId = m_CreationInfo.m_Pipeline[s.graphics.pipeline].layout;
- VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle(pipeLayoutId);
-
- const vector &pushRanges = m_CreationInfo.m_PipelineLayout[pipeLayoutId].pushRanges;
-
- // only set push constant ranges that the layout uses
- for(size_t i=0; i < pushRanges.size(); i++)
- ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags, pushRanges[i].start, pushRanges[i].length, s.pushconsts+pushRanges[i].start);
-
- const vector &descSetLayouts = m_CreationInfo.m_PipelineLayout[pipeLayoutId].descSetLayouts;
-
- // only iterate over the desc sets that this layout actually uses, not all that were bound
- for(size_t i=0; i < descSetLayouts.size(); i++)
- {
- const DescSetLayout &descLayout = m_CreationInfo.m_DescSetLayout[ descSetLayouts[i] ];
-
- if(i < s.graphics.descSets.size() && s.graphics.descSets[i] != ResourceId())
- {
- // if there are dynamic buffers, pass along the offsets
- ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i,
- 1, UnwrapPtr(GetResourceManager()->GetCurrentHandle(s.graphics.descSets[i])),
- descLayout.dynamicCount, descLayout.dynamicCount == 0 ? NULL : &s.graphics.offsets[i][0]);
- }
- else
- {
- RDCWARN("Descriptor set is not bound but pipeline layout expects one");
- }
- }
- }
-
- if(s.compute.pipeline != ResourceId())
- {
- ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetResourceManager()->GetCurrentHandle(s.compute.pipeline)));
-
- ResourceId pipeLayoutId = m_CreationInfo.m_Pipeline[s.compute.pipeline].layout;
- VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle(pipeLayoutId);
-
- const vector &descSetLayouts = m_CreationInfo.m_PipelineLayout[pipeLayoutId].descSetLayouts;
-
- for(size_t i=0; i < descSetLayouts.size(); i++)
- {
- const DescSetLayout &descLayout = m_CreationInfo.m_DescSetLayout[ descSetLayouts[i] ];
-
- if(s.compute.descSets[i] != ResourceId())
- {
- ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i,
- 1, UnwrapPtr(GetResourceManager()->GetCurrentHandle(s.compute.descSets[i])),
- descLayout.dynamicCount, descLayout.dynamicCount == 0 ? NULL : &s.compute.offsets[i][0]);
- }
- }
- }
-
- if(!s.views.empty())
- ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), (uint32_t)s.views.size(), &s.views[0]);
- if(!s.scissors.empty())
- ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), (uint32_t)s.scissors.size(), &s.scissors[0]);
-
- ObjDisp(cmd)->CmdSetBlendConstants(Unwrap(cmd), s.blendConst);
- ObjDisp(cmd)->CmdSetDepthBounds(Unwrap(cmd), s.mindepth, s.maxdepth);
- ObjDisp(cmd)->CmdSetLineWidth(Unwrap(cmd), s.lineWidth);
- ObjDisp(cmd)->CmdSetDepthBias(Unwrap(cmd), s.bias.depth, s.bias.biasclamp, s.bias.slope);
-
- ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, s.back.ref);
- ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, s.back.compare);
- ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, s.back.write);
-
- ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, s.front.ref);
- ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, s.front.compare);
- ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, s.front.write);
-
- if(s.ibuffer.buf != ResourceId())
- ObjDisp(cmd)->CmdBindIndexBuffer(Unwrap(cmd), Unwrap(GetResourceManager()->GetCurrentHandle(s.ibuffer.buf)), s.ibuffer.offs, s.ibuffer.bytewidth == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
-
- for(size_t i=0; i < s.vbuffers.size(); i++)
- ObjDisp(cmd)->CmdBindVertexBuffers(Unwrap(cmd), (uint32_t)i, 1, UnwrapPtr(GetResourceManager()->GetCurrentHandle(s.vbuffers[i].buf)), &s.vbuffers[i].offs);
- }
-
- bool rpWasActive = m_PartialReplayData.renderPassActive;
+ m_RenderState.BeginRenderPassAndApplyState(cmd);
ContextReplayLog(EXECUTING, endEventID, endEventID, partial);
+ // check if the render pass is active - it could have become active
+ // even if it wasn't before (if the above event was a CmdBeginRenderPass)
if(m_PartialReplayData.renderPassActive)
ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
// we might have replayed a CmdBeginRenderPass or CmdEndRenderPass,
- // but we want to keep the partial replay data state intact.
+ // but we want to keep the partial replay data state intact, so restore
+ // whether or not a render pass was active.
m_PartialReplayData.renderPassActive = rpWasActive;
ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd));
@@ -1912,13 +1812,13 @@ void WrappedVulkan::AddDrawcall(FetchDrawcall d, bool hasEvents)
draw.depthOut = ResourceId();
- ResourceId pipe = m_PartialReplayData.state.graphics.pipeline;
+ ResourceId pipe = m_RenderState.graphics.pipeline;
if(pipe != ResourceId())
draw.topology = MakePrimitiveTopology(m_CreationInfo.m_Pipeline[pipe].topology, m_CreationInfo.m_Pipeline[pipe].patchControlPoints);
else
draw.topology = eTopology_Unknown;
- draw.indexByteWidth = m_PartialReplayData.state.ibuffer.bytewidth;
+ draw.indexByteWidth = m_RenderState.ibuffer.bytewidth;
if(m_LastCmdBufferID != ResourceId())
m_BakedCmdBufferInfo[m_LastCmdBufferID].drawCount++;
diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h
index fbe4d6634..e29765d64 100644
--- a/renderdoc/driver/vulkan/vk_core.h
+++ b/renderdoc/driver/vulkan/vk_core.h
@@ -33,6 +33,7 @@
#include "vk_common.h"
#include "vk_info.h"
+#include "vk_state.h"
#include "vk_manager.h"
#include "vk_replay.h"
@@ -304,75 +305,12 @@ private:
// reach the vkEndCommandBuffer that we also need to end a render
// pass.
bool renderPassActive;
-
- // There is only a state while currently partially replaying, it's
- // undefined/empty otherwise.
- // All IDs are original IDs, not live.
- struct StateVector
- {
- StateVector()
- {
- compute.pipeline = graphics.pipeline = renderPass = framebuffer = ResourceId();
- compute.descSets.clear();
- graphics.descSets.clear();
- compute.offsets.clear();
- graphics.offsets.clear();
-
- lineWidth = 1.0f;
- RDCEraseEl(bias);
- RDCEraseEl(blendConst);
- mindepth = 0.0f; maxdepth = 1.0f;
- RDCEraseEl(front);
- RDCEraseEl(back);
-
- RDCEraseEl(renderArea);
-
- RDCEraseEl(ibuffer);
- vbuffers.clear();
- }
-
- // dynamic state
- vector views;
- vector scissors;
- float lineWidth;
- struct { float depth, biasclamp, slope; } bias;
- float blendConst[4];
- float mindepth, maxdepth;
- struct { uint32_t compare, write, ref; } front, back;
-
- // this should be big enough for any implementation
- byte pushconsts[1024];
-
- ResourceId renderPass;
- uint32_t subpass;
-
- ResourceId framebuffer;
- VkRect2D renderArea;
-
- struct Pipeline
- {
- ResourceId pipeline;
- vector descSets;
- vector< vector > offsets;
- } compute, graphics;
-
- struct IdxBuffer
- {
- ResourceId buf;
- VkDeviceSize offs;
- int bytewidth;
- } ibuffer;
-
- struct VertBuffer
- {
- ResourceId buf;
- VkDeviceSize offs;
- };
- vector vbuffers;
- } state;
} m_PartialReplayData;
- uint32_t m_HackDrawIndices;
+ // There is only a state while currently partially replaying, it's
+ // undefined/empty otherwise.
+ // All IDs are original IDs, not live.
+ VulkanRenderState m_RenderState;
bool IsPartialCmd(ResourceId cmdid)
{
diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp
index 381294891..2b848aef0 100644
--- a/renderdoc/driver/vulkan/vk_debug.cpp
+++ b/renderdoc/driver/vulkan/vk_debug.cpp
@@ -2178,7 +2178,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
highlightCol[3] = 1.0f;
// backup state
- WrappedVulkan::PartialReplayData::StateVector prevstate = m_pDriver->m_PartialReplayData.state;
+ VulkanRenderState prevstate = m_pDriver->m_RenderState;
// make patched shader
VkShaderModule mod = VK_NULL_HANDLE;
@@ -2266,23 +2266,23 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
RDCASSERT(vkr == VK_SUCCESS);
// modify state
- m_pDriver->m_PartialReplayData.state.renderPass = GetResID(m_OverlayNoDepthRP);
- m_pDriver->m_PartialReplayData.state.subpass = 0;
- m_pDriver->m_PartialReplayData.state.framebuffer = GetResID(m_OverlayNoDepthFB);
+ m_pDriver->m_RenderState.renderPass = GetResID(m_OverlayNoDepthRP);
+ m_pDriver->m_RenderState.subpass = 0;
+ m_pDriver->m_RenderState.framebuffer = GetResID(m_OverlayNoDepthFB);
- m_pDriver->m_PartialReplayData.state.graphics.pipeline = GetResID(pipe);
+ m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe);
// set dynamic scissors in case pipeline was using them
- for(size_t i=0; i < m_pDriver->m_PartialReplayData.state.scissors.size(); i++)
+ for(size_t i=0; i < m_pDriver->m_RenderState.scissors.size(); i++)
{
- m_pDriver->m_PartialReplayData.state.scissors[i].offset.x = 0;
- m_pDriver->m_PartialReplayData.state.scissors[i].offset.x = 0;
- m_pDriver->m_PartialReplayData.state.scissors[i].extent.width = 4096;
- m_pDriver->m_PartialReplayData.state.scissors[i].extent.height = 4096;
+ m_pDriver->m_RenderState.scissors[i].offset.x = 0;
+ m_pDriver->m_RenderState.scissors[i].offset.x = 0;
+ m_pDriver->m_RenderState.scissors[i].extent.width = 4096;
+ m_pDriver->m_RenderState.scissors[i].extent.height = 4096;
}
if(overlay == eTexOverlay_Wireframe)
- m_pDriver->m_PartialReplayData.state.lineWidth = 1.0f;
+ m_pDriver->m_RenderState.lineWidth = 1.0f;
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
@@ -2296,7 +2296,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
RDCASSERT(vkr == VK_SUCCESS);
// restore state
- m_pDriver->m_PartialReplayData.state = prevstate;
+ m_pDriver->m_RenderState = prevstate;
m_pDriver->vkDestroyPipeline(m_Device, pipe);
m_pDriver->vkDestroyShaderModule(m_Device, mod);
@@ -2316,26 +2316,26 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
VkRenderPassBeginInfo rpbegin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL,
Unwrap(m_OverlayNoDepthRP), Unwrap(m_OverlayNoDepthFB),
- m_pDriver->m_PartialReplayData.state.renderArea,
+ m_pDriver->m_RenderState.renderArea,
1, &clearval,
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_RENDER_PASS_CONTENTS_INLINE);
VkRect3D rect = {
{
- m_pDriver->m_PartialReplayData.state.renderArea.offset.x,
- m_pDriver->m_PartialReplayData.state.renderArea.offset.y,
+ m_pDriver->m_RenderState.renderArea.offset.x,
+ m_pDriver->m_RenderState.renderArea.offset.y,
0,
},
{
- m_pDriver->m_PartialReplayData.state.renderArea.extent.width,
- m_pDriver->m_PartialReplayData.state.renderArea.extent.height,
+ m_pDriver->m_RenderState.renderArea.extent.width,
+ m_pDriver->m_RenderState.renderArea.extent.height,
1,
},
};
vt->CmdClearColorAttachment(Unwrap(cmd), 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, (VkClearColorValue *)black, 1, &rect);
- VkViewport viewport = m_pDriver->m_PartialReplayData.state.views[0];
+ VkViewport viewport = m_pDriver->m_RenderState.views[0];
vt->CmdSetViewport(Unwrap(cmd), 1, &viewport);
uint32_t uboOffs = 0;
@@ -2355,12 +2355,12 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
vt->CmdDraw(Unwrap(cmd), 4, 1, 0, 0);
- if(!m_pDriver->m_PartialReplayData.state.scissors.empty())
+ if(!m_pDriver->m_RenderState.scissors.empty())
{
- Vec4f scissor((float)m_pDriver->m_PartialReplayData.state.scissors[0].offset.x,
- (float)m_pDriver->m_PartialReplayData.state.scissors[0].offset.y,
- (float)m_pDriver->m_PartialReplayData.state.scissors[0].extent.width,
- (float)m_pDriver->m_PartialReplayData.state.scissors[0].extent.height);
+ Vec4f scissor((float)m_pDriver->m_RenderState.scissors[0].offset.x,
+ (float)m_pDriver->m_RenderState.scissors[0].offset.y,
+ (float)m_pDriver->m_RenderState.scissors[0].extent.width,
+ (float)m_pDriver->m_RenderState.scissors[0].extent.height);
outlineuniforms *ubo = (outlineuniforms *)m_OutlineUBO.Map(vt, m_Device, &uboOffs);
@@ -2397,7 +2397,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
highlightCol[3] = 1.0f;
// backup state
- WrappedVulkan::PartialReplayData::StateVector prevstate = m_pDriver->m_PartialReplayData.state;
+ VulkanRenderState prevstate = m_pDriver->m_RenderState;
// make patched shader
VkShaderModule mod[2] = {0};
@@ -2495,24 +2495,24 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
RDCASSERT(vkr == VK_SUCCESS);
// modify state
- m_pDriver->m_PartialReplayData.state.renderPass = GetResID(m_OverlayNoDepthRP);
- m_pDriver->m_PartialReplayData.state.subpass = 0;
- m_pDriver->m_PartialReplayData.state.framebuffer = GetResID(m_OverlayNoDepthFB);
+ m_pDriver->m_RenderState.renderPass = GetResID(m_OverlayNoDepthRP);
+ m_pDriver->m_RenderState.subpass = 0;
+ m_pDriver->m_RenderState.framebuffer = GetResID(m_OverlayNoDepthFB);
- m_pDriver->m_PartialReplayData.state.graphics.pipeline = GetResID(pipe[0]);
+ m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[0]);
// set dynamic scissors in case pipeline was using them
- for(size_t i=0; i < m_pDriver->m_PartialReplayData.state.scissors.size(); i++)
+ for(size_t i=0; i < m_pDriver->m_RenderState.scissors.size(); i++)
{
- m_pDriver->m_PartialReplayData.state.scissors[i].offset.x = 0;
- m_pDriver->m_PartialReplayData.state.scissors[i].offset.x = 0;
- m_pDriver->m_PartialReplayData.state.scissors[i].extent.width = 4096;
- m_pDriver->m_PartialReplayData.state.scissors[i].extent.height = 4096;
+ m_pDriver->m_RenderState.scissors[i].offset.x = 0;
+ m_pDriver->m_RenderState.scissors[i].offset.x = 0;
+ m_pDriver->m_RenderState.scissors[i].extent.width = 4096;
+ m_pDriver->m_RenderState.scissors[i].extent.height = 4096;
}
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
- m_pDriver->m_PartialReplayData.state.graphics.pipeline = GetResID(pipe[1]);
+ m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[1]);
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
@@ -2526,7 +2526,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
RDCASSERT(vkr == VK_SUCCESS);
// restore state
- m_pDriver->m_PartialReplayData.state = prevstate;
+ m_pDriver->m_RenderState = prevstate;
for(int i=0; i < 2; i++)
{
@@ -2544,7 +2544,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
VkFramebuffer depthFB;
VkRenderPass depthRP;
- const WrappedVulkan::PartialReplayData::StateVector &state = m_pDriver->m_PartialReplayData.state;
+ const VulkanRenderState &state = m_pDriver->m_RenderState;
VulkanCreationInfo &createinfo = m_pDriver->m_CreationInfo;
RDCASSERT(state.subpass < createinfo.m_RenderPass[state.renderPass].subpasses.size());
@@ -2623,7 +2623,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
highlightCol[3] = 1.0f;
// backup state
- WrappedVulkan::PartialReplayData::StateVector prevstate = m_pDriver->m_PartialReplayData.state;
+ VulkanRenderState prevstate = m_pDriver->m_RenderState;
// make patched shader
VkShaderModule mod[2] = {0};
@@ -2730,28 +2730,28 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
RDCASSERT(vkr == VK_SUCCESS);
// modify state
- m_pDriver->m_PartialReplayData.state.renderPass = GetResID(m_OverlayNoDepthRP);
- m_pDriver->m_PartialReplayData.state.subpass = 0;
- m_pDriver->m_PartialReplayData.state.framebuffer = GetResID(m_OverlayNoDepthFB);
+ m_pDriver->m_RenderState.renderPass = GetResID(m_OverlayNoDepthRP);
+ m_pDriver->m_RenderState.subpass = 0;
+ m_pDriver->m_RenderState.framebuffer = GetResID(m_OverlayNoDepthFB);
- m_pDriver->m_PartialReplayData.state.graphics.pipeline = GetResID(pipe[0]);
+ m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[0]);
// set dynamic scissors in case pipeline was using them
- for(size_t i=0; i < m_pDriver->m_PartialReplayData.state.scissors.size(); i++)
+ for(size_t i=0; i < m_pDriver->m_RenderState.scissors.size(); i++)
{
- m_pDriver->m_PartialReplayData.state.scissors[i].offset.x = 0;
- m_pDriver->m_PartialReplayData.state.scissors[i].offset.x = 0;
- m_pDriver->m_PartialReplayData.state.scissors[i].extent.width = 4096;
- m_pDriver->m_PartialReplayData.state.scissors[i].extent.height = 4096;
+ m_pDriver->m_RenderState.scissors[i].offset.x = 0;
+ m_pDriver->m_RenderState.scissors[i].offset.x = 0;
+ m_pDriver->m_RenderState.scissors[i].extent.width = 4096;
+ m_pDriver->m_RenderState.scissors[i].extent.height = 4096;
}
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
- m_pDriver->m_PartialReplayData.state.graphics.pipeline = GetResID(pipe[1]);
+ m_pDriver->m_RenderState.graphics.pipeline = GetResID(pipe[1]);
if(depthRP != VK_NULL_HANDLE)
{
- m_pDriver->m_PartialReplayData.state.renderPass = GetResID(depthRP);
- m_pDriver->m_PartialReplayData.state.framebuffer = GetResID(depthFB);
+ m_pDriver->m_RenderState.renderPass = GetResID(depthRP);
+ m_pDriver->m_RenderState.framebuffer = GetResID(depthFB);
}
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
@@ -2766,7 +2766,7 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
RDCASSERT(vkr == VK_SUCCESS);
// restore state
- m_pDriver->m_PartialReplayData.state = prevstate;
+ m_pDriver->m_RenderState = prevstate;
for(int i=0; i < 2; i++)
{
@@ -3806,7 +3806,7 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
if(!m_pDriver->GetDeviceFeatures().vertexSideEffects)
return;
- WrappedVulkan::PartialReplayData::StateVector &state = m_pDriver->m_PartialReplayData.state;
+ const VulkanRenderState &state = m_pDriver->m_RenderState;
VulkanCreationInfo &c = m_pDriver->m_CreationInfo;
if(state.graphics.pipeline == ResourceId())
@@ -4079,14 +4079,14 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, &pipe);
RDCASSERT(vkr == VK_SUCCESS);
- // backup state
- WrappedVulkan::PartialReplayData::StateVector prevstate = state;
+ // make copy of state to draw from
+ VulkanRenderState modifiedstate = state;
// bind created pipeline to partial replay state
- state.graphics.pipeline = GetResID(pipe);
+ modifiedstate.graphics.pipeline = GetResID(pipe);
// push back extra descriptor set to partial replay state
- state.graphics.descSets.push_back( GetResID(m_MeshFetchDescSet) );
+ modifiedstate.graphics.descSets.push_back( GetResID(m_MeshFetchDescSet) );
if((drawcall->flags & eDraw_UseIBuffer) == 0)
{
@@ -4151,9 +4151,6 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
};
m_pDriver->vkUpdateDescriptorSets(dev, 1, &write, 0, NULL);
- // do single draw
- m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
-
VkCmdBuffer cmd = m_pDriver->GetNextCmd();
VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT };
@@ -4161,6 +4158,11 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
+ // do single draw
+ modifiedstate.BeginRenderPassAndApplyState(cmd);
+ ObjDisp(cmd)->CmdDraw(Unwrap(cmd), drawcall->numIndices, drawcall->numInstances, drawcall->vertexOffset, drawcall->instanceOffset);
+ ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
+
VkBufferMemoryBarrier meshbufbarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, NULL,
VK_MEMORY_OUTPUT_SHADER_WRITE_BIT, VK_MEMORY_INPUT_TRANSFER_BIT|VK_MEMORY_INPUT_VERTEX_ATTRIBUTE_FETCH_BIT,
@@ -4280,9 +4282,9 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
bufSize = numVerts*RDCMAX(1U, drawcall->numInstances)*bufStride;
// bind unique'd ibuffer
- state.ibuffer.bytewidth = 4;
- state.ibuffer.offs = 0;
- state.ibuffer.buf = GetResID(uniqIdxBuf);
+ modifiedstate.ibuffer.bytewidth = 4;
+ modifiedstate.ibuffer.offs = 0;
+ modifiedstate.ibuffer.buf = GetResID(uniqIdxBuf);
// vkUpdateDescriptorSet desc set to point to buffer
VkDescriptorInfo fetchdesc = { 0 };
@@ -4299,21 +4301,19 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
RDCASSERT(vkr == VK_SUCCESS);
- // a bit of a hack to ensure we have the right number of indices for rendering.
- // we want to have a nicer 'apply current state' function so we can reuse that
- // then do our own draw.
- m_pDriver->m_HackDrawIndices = (uint32_t)indices.size();
-
// do single draw
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
-
- m_pDriver->m_HackDrawIndices = ~0U;
cmd = m_pDriver->GetNextCmd();
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
+ // do single draw
+ modifiedstate.BeginRenderPassAndApplyState(cmd);
+ ObjDisp(cmd)->CmdDrawIndexed(Unwrap(cmd), (uint32_t)indices.size(), drawcall->numInstances, 0, drawcall->vertexOffset, drawcall->instanceOffset);
+ ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
+
// rebase existing index buffer to point to the right elements in our stream-out'd
// vertex buffer
@@ -4447,9 +4447,6 @@ void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
m_pDriver->vkDestroyBuffer(m_Device, uniqIdxBuf);
m_pDriver->vkFreeMemory(m_Device, uniqIdxBufMem);
}
-
- // reset pipeline state back to normal
- state = prevstate;
// fill out m_PostVSData
m_PostVSData[idx].vsin.topo = topo;
diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp
index 319b1a2a9..76bf319d7 100644
--- a/renderdoc/driver/vulkan/vk_replay.cpp
+++ b/renderdoc/driver/vulkan/vk_replay.cpp
@@ -2584,7 +2584,7 @@ void VulkanReplay::FileChanged()
void VulkanReplay::SavePipelineState()
{
{
- const WrappedVulkan::PartialReplayData::StateVector &state = m_pDriver->m_PartialReplayData.state;
+ const VulkanRenderState &state = m_pDriver->m_RenderState;
VulkanCreationInfo &c = m_pDriver->m_CreationInfo;
VulkanResourceManager *rm = m_pDriver->GetResourceManager();
@@ -3245,8 +3245,8 @@ void VulkanReplay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, ve
else
{
vector pushdata;
- pushdata.resize(sizeof(m_pDriver->m_PartialReplayData.state.pushconsts));
- memcpy(&pushdata[0], m_pDriver->m_PartialReplayData.state.pushconsts, pushdata.size());
+ pushdata.resize(sizeof(m_pDriver->m_RenderState.pushconsts));
+ memcpy(&pushdata[0], m_pDriver->m_RenderState.pushconsts, pushdata.size());
FillCBufferVariables(c.variables, outvars, pushdata, zero);
}
diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp
new file mode 100644
index 000000000..53af1ff73
--- /dev/null
+++ b/renderdoc/driver/vulkan/vk_state.cpp
@@ -0,0 +1,191 @@
+/******************************************************************************
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#include "vk_state.h"
+#include "vk_info.h"
+#include "vk_resources.h"
+
+VulkanRenderState::VulkanRenderState(VulkanCreationInfo &createInfo)
+ : m_CreationInfo(createInfo)
+{
+ compute.pipeline = graphics.pipeline = renderPass = framebuffer = ResourceId();
+ compute.descSets.clear();
+ graphics.descSets.clear();
+ compute.offsets.clear();
+ graphics.offsets.clear();
+
+ views.clear();
+ scissors.clear();
+ lineWidth = 1.0f;
+ RDCEraseEl(bias);
+ RDCEraseEl(blendConst);
+ mindepth = 0.0f; maxdepth = 1.0f;
+ RDCEraseEl(front);
+ RDCEraseEl(back);
+ RDCEraseEl(pushconsts);
+
+ renderPass = ResourceId();
+ subpass = 0;
+
+ RDCEraseEl(renderArea);
+
+ RDCEraseEl(ibuffer);
+ vbuffers.clear();
+}
+
+VulkanRenderState & VulkanRenderState::operator =(const VulkanRenderState &o)
+{
+ views = o.views;
+ scissors = o.scissors;
+ lineWidth = o.lineWidth;
+ bias = o.bias;
+ memcpy(blendConst, o.blendConst, sizeof(blendConst));
+ mindepth = o.mindepth;
+ maxdepth = o.maxdepth;
+ front = o.front;
+ back = o.back;
+ memcpy(pushconsts, o.pushconsts, sizeof(pushconsts));
+ renderPass = o.renderPass;
+ subpass = o.subpass;
+ framebuffer = o.framebuffer;
+ renderArea = o.renderArea;
+
+ compute.pipeline = o.compute.pipeline;
+ compute.descSets = o.compute.descSets;
+ compute.offsets = o.compute.offsets;
+
+ graphics.pipeline = o.graphics.pipeline;
+ graphics.descSets = o.graphics.descSets;
+ graphics.offsets = o.graphics.offsets;
+
+ ibuffer = o.ibuffer;
+ vbuffers = o.vbuffers;
+
+ return *this;
+}
+
+void VulkanRenderState::BeginRenderPassAndApplyState(VkCmdBuffer cmd)
+{
+ RDCASSERT(renderPass != ResourceId());
+
+ // clear values don't matter as we're using the load renderpass here, that
+ // has all load ops set to load (as we're doing a partial replay - can't
+ // just clear the targets that are partially written to).
+
+ VkClearValue empty[16] = {0};
+
+ RDCASSERT(ARRAY_COUNT(empty) >= m_CreationInfo.m_RenderPass[renderPass].attachments.size());
+
+ VkRenderPassBeginInfo rpbegin = {
+ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL,
+ Unwrap(m_CreationInfo.m_RenderPass[renderPass].loadRP),
+ Unwrap(GetResourceManager()->GetCurrentHandle(framebuffer)),
+ renderArea,
+ (uint32_t)m_CreationInfo.m_RenderPass[renderPass].attachments.size(), empty,
+ };
+ ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_RENDER_PASS_CONTENTS_INLINE);
+
+ for(uint32_t i=0; i < subpass; i++)
+ ObjDisp(cmd)->CmdNextSubpass(Unwrap(cmd), VK_RENDER_PASS_CONTENTS_INLINE);
+
+ if(graphics.pipeline != ResourceId())
+ {
+ ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(GetResourceManager()->GetCurrentHandle(graphics.pipeline)));
+
+ ResourceId pipeLayoutId = m_CreationInfo.m_Pipeline[graphics.pipeline].layout;
+ VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle(pipeLayoutId);
+
+ const vector &pushRanges = m_CreationInfo.m_PipelineLayout[pipeLayoutId].pushRanges;
+
+ // only set push constant ranges that the layout uses
+ for(size_t i=0; i < pushRanges.size(); i++)
+ ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags, pushRanges[i].start, pushRanges[i].length, pushconsts+pushRanges[i].start);
+
+ const vector &descSetLayouts = m_CreationInfo.m_PipelineLayout[pipeLayoutId].descSetLayouts;
+
+ // only iterate over the desc sets that this layout actually uses, not all that were bound
+ for(size_t i=0; i < descSetLayouts.size(); i++)
+ {
+ const DescSetLayout &descLayout = m_CreationInfo.m_DescSetLayout[ descSetLayouts[i] ];
+
+ if(i < graphics.descSets.size() && graphics.descSets[i] != ResourceId())
+ {
+ // if there are dynamic buffers, pass along the offsets
+ ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i,
+ 1, UnwrapPtr(GetResourceManager()->GetCurrentHandle(graphics.descSets[i])),
+ descLayout.dynamicCount, descLayout.dynamicCount == 0 ? NULL : &graphics.offsets[i][0]);
+ }
+ else
+ {
+ RDCWARN("Descriptor set is not bound but pipeline layout expects one");
+ }
+ }
+ }
+
+ if(compute.pipeline != ResourceId())
+ {
+ ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetResourceManager()->GetCurrentHandle(compute.pipeline)));
+
+ ResourceId pipeLayoutId = m_CreationInfo.m_Pipeline[compute.pipeline].layout;
+ VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle(pipeLayoutId);
+
+ const vector &descSetLayouts = m_CreationInfo.m_PipelineLayout[pipeLayoutId].descSetLayouts;
+
+ for(size_t i=0; i < descSetLayouts.size(); i++)
+ {
+ const DescSetLayout &descLayout = m_CreationInfo.m_DescSetLayout[ descSetLayouts[i] ];
+
+ if(compute.descSets[i] != ResourceId())
+ {
+ ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i,
+ 1, UnwrapPtr(GetResourceManager()->GetCurrentHandle(compute.descSets[i])),
+ descLayout.dynamicCount, descLayout.dynamicCount == 0 ? NULL : &compute.offsets[i][0]);
+ }
+ }
+ }
+
+ if(!views.empty())
+ ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), (uint32_t)views.size(), &views[0]);
+ if(!scissors.empty())
+ ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), (uint32_t)scissors.size(), &scissors[0]);
+
+ ObjDisp(cmd)->CmdSetBlendConstants(Unwrap(cmd), blendConst);
+ ObjDisp(cmd)->CmdSetDepthBounds(Unwrap(cmd), mindepth, maxdepth);
+ ObjDisp(cmd)->CmdSetLineWidth(Unwrap(cmd), lineWidth);
+ ObjDisp(cmd)->CmdSetDepthBias(Unwrap(cmd), bias.depth, bias.biasclamp, bias.slope);
+
+ ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.ref);
+ ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.compare);
+ ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.write);
+
+ ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.ref);
+ ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.compare);
+ ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.write);
+
+ if(ibuffer.buf != ResourceId())
+ ObjDisp(cmd)->CmdBindIndexBuffer(Unwrap(cmd), Unwrap(GetResourceManager()->GetCurrentHandle(ibuffer.buf)), ibuffer.offs, ibuffer.bytewidth == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
+
+ for(size_t i=0; i < vbuffers.size(); i++)
+ ObjDisp(cmd)->CmdBindVertexBuffers(Unwrap(cmd), (uint32_t)i, 1, UnwrapPtr(GetResourceManager()->GetCurrentHandle(vbuffers[i].buf)), &vbuffers[i].offs);
+}
diff --git a/renderdoc/driver/vulkan/vk_state.h b/renderdoc/driver/vulkan/vk_state.h
new file mode 100644
index 000000000..96a77f846
--- /dev/null
+++ b/renderdoc/driver/vulkan/vk_state.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#pragma once
+
+#include
+
+#include "vk_common.h"
+
+struct VulkanCreationInfo;
+class VulkanResourceManager;
+
+struct VulkanRenderState
+{
+ VulkanRenderState(VulkanCreationInfo &createInfo);
+ VulkanRenderState &operator =(const VulkanRenderState &o);
+ void BeginRenderPassAndApplyState(VkCmdBuffer cmd);
+
+ // dynamic state
+ vector views;
+ vector scissors;
+ float lineWidth;
+ struct { float depth, biasclamp, slope; } bias;
+ float blendConst[4];
+ float mindepth, maxdepth;
+ struct { uint32_t compare, write, ref; } front, back;
+
+ // this should be big enough for any implementation
+ byte pushconsts[1024];
+
+ ResourceId renderPass;
+ uint32_t subpass;
+
+ ResourceId framebuffer;
+ VkRect2D renderArea;
+
+ struct Pipeline
+ {
+ ResourceId pipeline;
+ vector descSets;
+ vector< vector > offsets;
+ } compute, graphics;
+
+ struct IdxBuffer
+ {
+ ResourceId buf;
+ VkDeviceSize offs;
+ int bytewidth;
+ } ibuffer;
+
+ struct VertBuffer
+ {
+ ResourceId buf;
+ VkDeviceSize offs;
+ };
+ vector vbuffers;
+
+ VulkanResourceManager *GetResourceManager() { return m_ResourceManager; }
+
+ VulkanResourceManager *m_ResourceManager;
+ VulkanCreationInfo &m_CreationInfo;
+};
+
+
diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp
index 7c7715abd..dd0841fdc 100644
--- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp
+++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp
@@ -28,8 +28,8 @@ string WrappedVulkan::MakeRenderPassOpString(bool store)
{
string opDesc = "";
- const VulkanCreationInfo::RenderPass &info = m_CreationInfo.m_RenderPass[m_PartialReplayData.state.renderPass];
- const VulkanCreationInfo::Framebuffer &fbinfo = m_CreationInfo.m_Framebuffer[m_PartialReplayData.state.framebuffer];
+ const VulkanCreationInfo::RenderPass &info = m_CreationInfo.m_RenderPass[m_RenderState.renderPass];
+ const VulkanCreationInfo::Framebuffer &fbinfo = m_CreationInfo.m_Framebuffer[m_RenderState.framebuffer];
const vector &atts = info.attachments;
@@ -42,7 +42,7 @@ string WrappedVulkan::MakeRenderPassOpString(bool store)
bool colsame = true;
// find which attachment is the depth-stencil one
- int32_t dsAttach = info.subpasses[m_PartialReplayData.state.subpass].depthstencilAttachment;
+ int32_t dsAttach = info.subpasses[m_RenderState.subpass].depthstencilAttachment;
bool hasStencil = false;
bool depthonly = false;
@@ -51,7 +51,7 @@ string WrappedVulkan::MakeRenderPassOpString(bool store)
if(dsAttach >= 0)
{
hasStencil = !IsDepthOnlyFormat(fbinfo.attachments[dsAttach].format);
- depthonly = info.subpasses[m_PartialReplayData.state.subpass].colorAttachments.size() == 0;
+ depthonly = info.subpasses[m_RenderState.subpass].colorAttachments.size() == 0;
}
// first colour attachment, if there is one
@@ -585,11 +585,11 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(
m_PartialReplayData.renderPassActive = true;
ObjDisp(cmdBuffer)->CmdBeginRenderPass(Unwrap(cmdBuffer), &beginInfo, cont);
- m_PartialReplayData.state.subpass = 0;
+ m_RenderState.subpass = 0;
- m_PartialReplayData.state.renderPass = GetResourceManager()->GetNonDispWrapper(beginInfo.renderPass)->id;
- m_PartialReplayData.state.framebuffer = GetResourceManager()->GetNonDispWrapper(beginInfo.framebuffer)->id;
- m_PartialReplayData.state.renderArea = beginInfo.renderArea;
+ m_RenderState.renderPass = GetResourceManager()->GetNonDispWrapper(beginInfo.renderPass)->id;
+ m_RenderState.framebuffer = GetResourceManager()->GetNonDispWrapper(beginInfo.framebuffer)->id;
+ m_RenderState.renderArea = beginInfo.renderArea;
}
}
else if(m_State == READING)
@@ -599,9 +599,9 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(
ObjDisp(cmdBuffer)->CmdBeginRenderPass(Unwrap(cmdBuffer), &beginInfo, cont);
// track during reading
- m_PartialReplayData.state.subpass = 0;
- m_PartialReplayData.state.renderPass = GetResourceManager()->GetNonDispWrapper(beginInfo.renderPass)->id;
- m_PartialReplayData.state.framebuffer = GetResourceManager()->GetNonDispWrapper(beginInfo.framebuffer)->id;
+ m_RenderState.subpass = 0;
+ m_RenderState.renderPass = GetResourceManager()->GetNonDispWrapper(beginInfo.renderPass)->id;
+ m_RenderState.framebuffer = GetResourceManager()->GetNonDispWrapper(beginInfo.framebuffer)->id;
const string desc = localSerialiser->GetDebugStr();
@@ -674,7 +674,7 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass(
{
cmdBuffer = PartialCmdBuf();
- m_PartialReplayData.state.subpass++;
+ m_RenderState.subpass++;
ObjDisp(cmdBuffer)->CmdNextSubpass(Unwrap(cmdBuffer), cont);
}
@@ -686,13 +686,13 @@ bool WrappedVulkan::Serialise_vkCmdNextSubpass(
ObjDisp(cmdBuffer)->CmdNextSubpass(Unwrap(cmdBuffer), cont);
// track during reading
- m_PartialReplayData.state.subpass++;
+ m_RenderState.subpass++;
const string desc = localSerialiser->GetDebugStr();
AddEvent(NEXT_SUBPASS, desc);
FetchDrawcall draw;
- draw.name = StringFormat::Fmt("vkCmdNextSubpass() => %u", m_PartialReplayData.state.subpass);
+ draw.name = StringFormat::Fmt("vkCmdNextSubpass() => %u", m_RenderState.subpass);
draw.flags |= eDraw_Clear;
AddDrawcall(draw, true);
@@ -893,51 +893,51 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(
ResourceId liveid = GetResID(pipeline);
if(bind == VK_PIPELINE_BIND_POINT_GRAPHICS)
- m_PartialReplayData.state.graphics.pipeline = liveid;
+ m_RenderState.graphics.pipeline = liveid;
else
- m_PartialReplayData.state.compute.pipeline = liveid;
+ m_RenderState.compute.pipeline = liveid;
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_VIEWPORT])
{
- m_PartialReplayData.state.views = m_CreationInfo.m_Pipeline[liveid].viewports;
+ m_RenderState.views = m_CreationInfo.m_Pipeline[liveid].viewports;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_SCISSOR])
{
- m_PartialReplayData.state.scissors = m_CreationInfo.m_Pipeline[liveid].scissors;
+ m_RenderState.scissors = m_CreationInfo.m_Pipeline[liveid].scissors;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH])
{
- m_PartialReplayData.state.lineWidth = m_CreationInfo.m_Pipeline[liveid].lineWidth;
+ m_RenderState.lineWidth = m_CreationInfo.m_Pipeline[liveid].lineWidth;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS])
{
- m_PartialReplayData.state.bias.depth = m_CreationInfo.m_Pipeline[liveid].depthBias;
- m_PartialReplayData.state.bias.biasclamp = m_CreationInfo.m_Pipeline[liveid].depthBiasClamp;
- m_PartialReplayData.state.bias.slope = m_CreationInfo.m_Pipeline[liveid].slopeScaledDepthBias;
+ m_RenderState.bias.depth = m_CreationInfo.m_Pipeline[liveid].depthBias;
+ m_RenderState.bias.biasclamp = m_CreationInfo.m_Pipeline[liveid].depthBiasClamp;
+ m_RenderState.bias.slope = m_CreationInfo.m_Pipeline[liveid].slopeScaledDepthBias;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS])
{
- memcpy(m_PartialReplayData.state.blendConst, m_CreationInfo.m_Pipeline[liveid].blendConst, sizeof(float)*4);
+ memcpy(m_RenderState.blendConst, m_CreationInfo.m_Pipeline[liveid].blendConst, sizeof(float)*4);
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS])
{
- m_PartialReplayData.state.mindepth = m_CreationInfo.m_Pipeline[liveid].minDepthBounds;
- m_PartialReplayData.state.maxdepth = m_CreationInfo.m_Pipeline[liveid].maxDepthBounds;
+ m_RenderState.mindepth = m_CreationInfo.m_Pipeline[liveid].minDepthBounds;
+ m_RenderState.maxdepth = m_CreationInfo.m_Pipeline[liveid].maxDepthBounds;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK])
{
- m_PartialReplayData.state.front.compare = m_CreationInfo.m_Pipeline[liveid].front.stencilCompareMask;
- m_PartialReplayData.state.back.compare = m_CreationInfo.m_Pipeline[liveid].back.stencilCompareMask;
+ m_RenderState.front.compare = m_CreationInfo.m_Pipeline[liveid].front.stencilCompareMask;
+ m_RenderState.back.compare = m_CreationInfo.m_Pipeline[liveid].back.stencilCompareMask;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK])
{
- m_PartialReplayData.state.front.write = m_CreationInfo.m_Pipeline[liveid].front.stencilWriteMask;
- m_PartialReplayData.state.back.write = m_CreationInfo.m_Pipeline[liveid].back.stencilWriteMask;
+ m_RenderState.front.write = m_CreationInfo.m_Pipeline[liveid].front.stencilWriteMask;
+ m_RenderState.back.write = m_CreationInfo.m_Pipeline[liveid].back.stencilWriteMask;
}
if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE])
{
- m_PartialReplayData.state.front.ref = m_CreationInfo.m_Pipeline[liveid].front.stencilReference;
- m_PartialReplayData.state.back.ref = m_CreationInfo.m_Pipeline[liveid].back.stencilReference;
+ m_RenderState.front.ref = m_CreationInfo.m_Pipeline[liveid].front.stencilReference;
+ m_RenderState.back.ref = m_CreationInfo.m_Pipeline[liveid].back.stencilReference;
}
}
}
@@ -948,9 +948,9 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(
// track this while reading, as we need to bind current topology & index byte width to draws
if(bind == VK_PIPELINE_BIND_POINT_GRAPHICS)
- m_PartialReplayData.state.graphics.pipeline = GetResID(pipeline);
+ m_RenderState.graphics.pipeline = GetResID(pipeline);
else
- m_PartialReplayData.state.compute.pipeline = GetResID(pipeline);
+ m_RenderState.compute.pipeline = GetResID(pipeline);
ObjDisp(cmdBuffer)->CmdBindPipeline(Unwrap(cmdBuffer), bind, Unwrap(pipeline));
}
@@ -1036,13 +1036,13 @@ bool WrappedVulkan::Serialise_vkCmdBindDescriptorSets(
vector &descsets =
(bind == VK_PIPELINE_BIND_POINT_GRAPHICS)
- ? m_PartialReplayData.state.graphics.descSets
- : m_PartialReplayData.state.compute.descSets;
+ ? m_RenderState.graphics.descSets
+ : m_RenderState.compute.descSets;
vector< vector > &offsets =
(bind == VK_PIPELINE_BIND_POINT_GRAPHICS)
- ? m_PartialReplayData.state.graphics.offsets
- : m_PartialReplayData.state.compute.offsets;
+ ? m_RenderState.graphics.offsets
+ : m_RenderState.compute.offsets;
// expand as necessary
if(descsets.size() < first + numSets)
@@ -1195,13 +1195,13 @@ bool WrappedVulkan::Serialise_vkCmdBindVertexBuffers(
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdBindVertexBuffers(Unwrap(cmdBuffer), start, count, &bufs[0], &offs[0]);
- if(m_PartialReplayData.state.vbuffers.size() < start + count)
- m_PartialReplayData.state.vbuffers.resize(start + count);
+ if(m_RenderState.vbuffers.size() < start + count)
+ m_RenderState.vbuffers.resize(start + count);
for(uint32_t i=0; i < count; i++)
{
- m_PartialReplayData.state.vbuffers[start + i].buf = bufids[i];
- m_PartialReplayData.state.vbuffers[start + i].offs = offs[i];
+ m_RenderState.vbuffers[start + i].buf = bufids[i];
+ m_RenderState.vbuffers[start + i].offs = offs[i];
}
}
}
@@ -1272,9 +1272,9 @@ bool WrappedVulkan::Serialise_vkCmdBindIndexBuffer(
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdBindIndexBuffer(Unwrap(cmdBuffer), Unwrap(buffer), offs, idxType);
- m_PartialReplayData.state.ibuffer.buf = GetResID(buffer);
- m_PartialReplayData.state.ibuffer.offs = offs;
- m_PartialReplayData.state.ibuffer.bytewidth = idxType == VK_INDEX_TYPE_UINT32 ? 4 : 2;
+ m_RenderState.ibuffer.buf = GetResID(buffer);
+ m_RenderState.ibuffer.offs = offs;
+ m_RenderState.ibuffer.bytewidth = idxType == VK_INDEX_TYPE_UINT32 ? 4 : 2;
}
}
else if(m_State == READING)
@@ -1283,7 +1283,7 @@ bool WrappedVulkan::Serialise_vkCmdBindIndexBuffer(
buffer = GetResourceManager()->GetLiveHandle(bufid);
// track this while reading, as we need to bind current topology & index byte width to draws
- m_PartialReplayData.state.ibuffer.bytewidth = idxType == VK_INDEX_TYPE_UINT32 ? 4 : 2;
+ m_RenderState.ibuffer.bytewidth = idxType == VK_INDEX_TYPE_UINT32 ? 4 : 2;
ObjDisp(cmdBuffer)->CmdBindIndexBuffer(Unwrap(cmdBuffer), Unwrap(buffer), offs, idxType);
}
@@ -1486,9 +1486,9 @@ bool WrappedVulkan::Serialise_vkCmdPushConstants(
layout = GetResourceManager()->GetLiveHandle(layid);
ObjDisp(cmdBuffer)->CmdPushConstants(Unwrap(cmdBuffer), Unwrap(layout), flags, s, len, vals);
- RDCASSERT(s+len < (uint32_t)ARRAY_COUNT(m_PartialReplayData.state.pushconsts));
+ RDCASSERT(s+len < (uint32_t)ARRAY_COUNT(m_RenderState.pushconsts));
- memcpy(m_PartialReplayData.state.pushconsts + s, vals, len);
+ memcpy(m_RenderState.pushconsts + s, vals, len);
}
}
else if(m_State == READING)
diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp
index caefeb941..5c42b6e1c 100644
--- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp
+++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp
@@ -1048,13 +1048,6 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexed(
if(IsPartialCmd(cmdid) && InPartialRange())
{
cmdBuffer = PartialCmdBuf();
-
- if(m_HackDrawIndices != ~0U)
- {
- firstIdx = 0;
- idxCount = m_HackDrawIndices;
- }
-
ObjDisp(cmdBuffer)->CmdDrawIndexed(Unwrap(cmdBuffer), idxCount, instCount, firstIdx, vtxOffs, firstInst);
}
}
diff --git a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp
index bb194a169..7c269f9c1 100644
--- a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp
+++ b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp
@@ -43,7 +43,7 @@ bool WrappedVulkan::Serialise_vkCmdSetViewport(
{
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdSetViewport(Unwrap(cmdBuffer), count, views);
- m_PartialReplayData.state.views.assign(views, views + count);
+ m_RenderState.views.assign(views, views + count);
}
}
else if(m_State == READING)
@@ -97,7 +97,7 @@ bool WrappedVulkan::Serialise_vkCmdSetScissor(
{
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdSetScissor(Unwrap(cmdBuffer), count, scissors);
- m_PartialReplayData.state.scissors.assign(scissors, scissors + count);
+ m_RenderState.scissors.assign(scissors, scissors + count);
}
}
else if(m_State == READING)
@@ -149,7 +149,7 @@ bool WrappedVulkan::Serialise_vkCmdSetLineWidth(
{
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdSetLineWidth(Unwrap(cmdBuffer), width);
- m_PartialReplayData.state.lineWidth = width;
+ m_RenderState.lineWidth = width;
}
}
else if(m_State == READING)
@@ -202,9 +202,9 @@ bool WrappedVulkan::Serialise_vkCmdSetDepthBias(
{
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdSetDepthBias(Unwrap(cmdBuffer), bias, biasclamp, slope);
- m_PartialReplayData.state.bias.depth = bias;
- m_PartialReplayData.state.bias.biasclamp = biasclamp;
- m_PartialReplayData.state.bias.slope = slope;
+ m_RenderState.bias.depth = bias;
+ m_RenderState.bias.biasclamp = biasclamp;
+ m_RenderState.bias.slope = slope;
}
}
else if(m_State == READING)
@@ -263,7 +263,7 @@ bool WrappedVulkan::Serialise_vkCmdSetBlendConstants(
{
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdSetBlendConstants(Unwrap(cmdBuffer), blendFactor);
- memcpy(m_PartialReplayData.state.blendConst, blendFactor, sizeof(blendFactor));
+ memcpy(m_RenderState.blendConst, blendFactor, sizeof(blendFactor));
}
}
else if(m_State == READING)
@@ -314,8 +314,8 @@ bool WrappedVulkan::Serialise_vkCmdSetDepthBounds(
{
cmdBuffer = PartialCmdBuf();
ObjDisp(cmdBuffer)->CmdSetDepthBounds(Unwrap(cmdBuffer), mind, maxd);
- m_PartialReplayData.state.mindepth = mind;
- m_PartialReplayData.state.maxdepth = maxd;
+ m_RenderState.mindepth = mind;
+ m_RenderState.maxdepth = maxd;
}
}
else if(m_State == READING)
@@ -369,9 +369,9 @@ bool WrappedVulkan::Serialise_vkCmdSetStencilCompareMask(
ObjDisp(cmdBuffer)->CmdSetStencilCompareMask(Unwrap(cmdBuffer), face, mask);
if(face & VK_STENCIL_FACE_FRONT_BIT)
- m_PartialReplayData.state.front.compare = mask;
+ m_RenderState.front.compare = mask;
if(face & VK_STENCIL_FACE_BACK_BIT)
- m_PartialReplayData.state.back.compare = mask;
+ m_RenderState.back.compare = mask;
}
}
else if(m_State == READING)
@@ -425,9 +425,9 @@ bool WrappedVulkan::Serialise_vkCmdSetStencilWriteMask(
ObjDisp(cmdBuffer)->CmdSetStencilWriteMask(Unwrap(cmdBuffer), face, mask);
if(face & VK_STENCIL_FACE_FRONT_BIT)
- m_PartialReplayData.state.front.write = mask;
+ m_RenderState.front.write = mask;
if(face & VK_STENCIL_FACE_BACK_BIT)
- m_PartialReplayData.state.back.write = mask;
+ m_RenderState.back.write = mask;
}
}
else if(m_State == READING)
@@ -481,9 +481,9 @@ bool WrappedVulkan::Serialise_vkCmdSetStencilReference(
ObjDisp(cmdBuffer)->CmdSetStencilReference(Unwrap(cmdBuffer), face, mask);
if(face & VK_STENCIL_FACE_FRONT_BIT)
- m_PartialReplayData.state.front.ref = mask;
+ m_RenderState.front.ref = mask;
if(face & VK_STENCIL_FACE_BACK_BIT)
- m_PartialReplayData.state.back.ref = mask;
+ m_RenderState.back.ref = mask;
}
}
else if(m_State == READING)