Implement quad overdraw display modes (not quite 100% yet)

This commit is contained in:
baldurk
2015-12-21 23:34:24 +01:00
parent d8f8a97c9e
commit db22eb64fb
15 changed files with 769 additions and 58 deletions
-1
View File
@@ -31,7 +31,6 @@ Known Issues
* Memory/image barriers are as yet unverified, potentially could lead to bad capture or replay.
* Sparse images with mips or array slices will not properly replay
* 'Quad overdraw' debug overlays aren't implemented.
Future work, post 1.0
========
+2
View File
@@ -62,5 +62,7 @@ DECLARE_EMBED(spv_histogram_comp);
DECLARE_EMBED(spv_outline_frag);
DECLARE_EMBED(spv_debuguniforms_h);
DECLARE_EMBED(spv_texsample_h);
DECLARE_EMBED(spv_quadresolve_frag);
DECLARE_EMBED(spv_quadwrite_frag);
#undef DECLARE_EMBED
+2
View File
@@ -146,6 +146,8 @@ RESOURCE_spv_histogram_comp TYPE_EMBED "spv/histogram.comp"
RESOURCE_spv_outline_frag TYPE_EMBED "spv/outline.frag"
RESOURCE_spv_debuguniforms_h TYPE_EMBED "spv/debuguniforms.h"
RESOURCE_spv_texsample_h TYPE_EMBED "spv/texsample.h"
RESOURCE_spv_quadresolve_frag TYPE_EMBED "spv/quadresolve.frag"
RESOURCE_spv_quadwrite_frag TYPE_EMBED "spv/quadwrite.frag"
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
+2
View File
@@ -48,6 +48,8 @@
#define RESOURCE_spv_outline_frag 415
#define RESOURCE_spv_debuguniforms_h 416
#define RESOURCE_spv_texsample_h 417
#define RESOURCE_spv_quadresolve_frag 418
#define RESOURCE_spv_quadwrite_frag 419
#if !defined(STRINGIZE)
#define STRINGIZE2(a) #a
+64
View File
@@ -0,0 +1,64 @@
/******************************************************************************
* 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.
******************************************************************************/
////////////////////////////////////////////////////////////////////////////////////////////
// Below shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
// http://blog.selfshadow.com/2012/11/12/counting-quads/
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
layout(binding = 0, r32ui) uniform coherent uimage2DArray overdrawImage;
#define NUM_RAMP_COLOURS 128
layout(binding = 1) uniform OverdrawRampColors
{
vec4 colors[NUM_RAMP_COLOURS];
} ramp;
vec4 ToColour(uint v)
{
return ramp.colors[min(v, uint(NUM_RAMP_COLOURS-1))];
}
layout (location = 0) out vec4 color_out;
void main()
{
ivec2 quad = ivec2(gl_FragCoord.xy*0.5f);
uint overdraw = 0;
for(uint i = 0; i < 4; i++)
overdraw += imageLoad(overdrawImage, ivec3(quad, i)).x/(i + 1);
color_out = ToColour(overdraw);
}
////////////////////////////////////////////////////////////////////////////////////////////
// Above shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
// http://blog.selfshadow.com/2012/11/12/counting-quads/
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
+64
View File
@@ -0,0 +1,64 @@
/******************************************************************************
* 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.
******************************************************************************/
// outer code will hoist this up to just after the #version
//#extension GL_ARB_derivative_control : require
////////////////////////////////////////////////////////////////////////////////////////////
// Below shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
// http://blog.selfshadow.com/2012/11/12/counting-quads/
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
// descriptor set will be patched from 0 to whichever descriptor set we're using in code
layout(set = 0, binding = 0, r32ui) uniform coherent uimage2DArray overdrawImage;
layout(early_fragment_tests) in;
void main()
{
uint c0 = uint(gl_SampleMaskIn[0]);
// Obtain coverage for all pixels in the quad, via 'message passing'*.
// (* For more details, see:
// "Shader Amortization using Pixel Quad Message Passing", Eric Penner, GPU Pro 2.)
uvec2 p = uvec2(uint(gl_FragCoord.x) & 1u, uint(gl_FragCoord.y) & 1u);
ivec2 sign = ivec2(p.x > 0u ? -1 : 1, p.y > 0u ? -1 : 1);
uint c1 = c0 + sign.x*int(dFdxFine(c0));
uint c2 = c0 + sign.y*int(dFdyFine(c0));
uint c3 = c2 + sign.x*int(dFdxFine(c2));
// Count the live pixels, minus 1 (zero indexing)
uint pixelCount = c0 + c1 + c2 + c3 - 1;
ivec3 quad = ivec3(gl_FragCoord.xy*0.5, pixelCount);
imageAtomicAdd(overdrawImage, quad, 1);
}
////////////////////////////////////////////////////////////////////////////////////////////
// Above shaders courtesy of Stephen Hill (@self_shadow), converted to glsl trivially
//
// http://blog.selfshadow.com/2012/11/12/counting-quads/
// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx
////////////////////////////////////////////////////////////////////////////////////////////
+33 -13
View File
@@ -98,8 +98,24 @@ struct DrawcallTreeNode
struct DrawcallCallback
{
virtual void PreDraw(uint32_t eid) = 0;
virtual void PostDraw(uint32_t eid) = 0;
// the three callbacks are used to allow the callback implementor to either
// do a modified draw before or after the real thing.
//
// PreDraw()
// do draw call as specified by the log
// PostDraw()
// if PostDraw() returns true:
// do draw call again
// PostRedraw()
//
// So either the modification happens in PreDraw, the modified draw happens,
// then in PostDraw() the implementation can elect to undo the modifications
// and do the real draw by returning true. OR they can do nothing in PreDraw,
// do the real draw, then in PostDraw return true to apply the modifications
// which are then undone in PostRedraw.
virtual void PreDraw(uint32_t eid, VkCommandBuffer cmd) = 0;
virtual bool PostDraw(uint32_t eid, VkCommandBuffer cmd) = 0;
virtual void PostRedraw(uint32_t eid, VkCommandBuffer cmd) = 0;
};
class WrappedVulkan : public IFrameCapturer
@@ -241,17 +257,6 @@ private:
vector<VkDeviceMemory> m_CleanupMems;
vector<VkEvent> m_CleanupEvents;
// return the pre-selected device and queue
VkDevice GetDev() { RDCASSERT(m_Device != VK_NULL_HANDLE); return m_Device; }
VkQueue GetQ() { RDCASSERT(m_Device != VK_NULL_HANDLE); return m_Queue; }
VkInstance GetInstance() { RDCASSERT(m_Instance != VK_NULL_HANDLE); return m_Instance; }
VkPhysicalDevice GetPhysDev() { RDCASSERT(m_PhysicalDevice != VK_NULL_HANDLE); return m_PhysicalDevice; }
VkCommandBuffer GetNextCmd();
void SubmitCmds();
VkSemaphore GetNextSemaphore();
void SubmitSemaphores();
void FlushQ();
const VkPhysicalDeviceFeatures &GetDeviceFeatures()
{ return m_PhysicalDeviceData.features; }
const VkPhysicalDeviceProperties &GetDeviceProps()
@@ -483,6 +488,8 @@ public:
VulkanResourceManager *GetResourceManager() { return m_ResourceManager; }
VulkanDebugManager *GetDebugManager() { return m_DebugManager; }
LogState GetState() { return m_State; }
VulkanReplay *GetReplay() { return &m_Replay; }
@@ -503,6 +510,19 @@ public:
FetchAPIEvent GetEvent(uint32_t eventID);
const FetchDrawcall *GetDrawcall(uint32_t frameID, uint32_t eventID);
// return the pre-selected device and queue
VkDevice GetDev() { RDCASSERT(m_Device != VK_NULL_HANDLE); return m_Device; }
VkQueue GetQ() { RDCASSERT(m_Device != VK_NULL_HANDLE); return m_Queue; }
VkInstance GetInstance() { RDCASSERT(m_Instance != VK_NULL_HANDLE); return m_Instance; }
VkPhysicalDevice GetPhysDev() { RDCASSERT(m_PhysicalDevice != VK_NULL_HANDLE); return m_PhysicalDevice; }
VkCommandBuffer GetNextCmd();
void SubmitCmds();
VkSemaphore GetNextSemaphore();
void SubmitSemaphores();
void FlushQ();
VulkanRenderState &GetRenderState() { return m_RenderState; }
void SetDrawcallCB(DrawcallCallback *cb) { m_DrawcallCallback = cb; }
// Device initialization
+518 -9
View File
@@ -240,6 +240,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
{
// VKTODOLOW needs tidy up - isn't scalable. Needs more classes like UBO above.
m_pDriver = driver;
m_State = m_pDriver->GetState();
m_ResourceManager = m_pDriver->GetResourceManager();
@@ -281,6 +282,11 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
m_OverlayNoDepthRP = VK_NULL_HANDLE;
RDCEraseEl(m_OverlayDim);
m_OverlayMemSize = 0;
m_QuadDescSetLayout = VK_NULL_HANDLE;
m_QuadResolvePipeLayout = VK_NULL_HANDLE;
m_QuadDescSet = VK_NULL_HANDLE;
m_QuadResolvePipeline = VK_NULL_HANDLE;
m_MeshDescSetLayout = VK_NULL_HANDLE;
m_MeshPipeLayout = VK_NULL_HANDLE;
@@ -299,6 +305,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
m_OutlineDescSet = VK_NULL_HANDLE;
m_OutlinePipeline = VK_NULL_HANDLE;
m_MeshFetchDescSetLayout = VK_NULL_HANDLE;
m_MeshFetchDescSet = VK_NULL_HANDLE;
m_Device = dev;
bool success = LoadShaderCache("vkshaders.cache", m_ShaderCacheMagic, m_ShaderCacheVersion, m_ShaderCache, ShaderCacheCallbacks);
@@ -367,6 +376,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_OutlineDescSetLayout);
}
if(m_State < WRITING)
{
VkDescriptorSetLayoutBinding layoutBinding[] = {
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, }
@@ -432,6 +442,24 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_TextDescSetLayout);
}
if(m_State < WRITING)
{
VkDescriptorSetLayoutBinding layoutBinding[] = {
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_ALL, NULL, },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, },
};
VkDescriptorSetLayoutCreateInfo descsetLayoutInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0,
ARRAY_COUNT(layoutBinding), &layoutBinding[0],
};
// because this will go through partial replay, needs proper creation info etc so we go through our wrapped
// function
vkr = m_pDriver->vkCreateDescriptorSetLayout(dev, &descsetLayoutInfo, NULL, &m_QuadDescSetLayout);
RDCASSERT(vkr == VK_SUCCESS);
}
{
VkDescriptorSetLayoutBinding layoutBinding[] = {
@@ -477,6 +505,14 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_TextPipeLayout);
pipeLayoutInfo.pSetLayouts = &m_QuadDescSetLayout;
if(m_State < WRITING)
{
vkr = m_pDriver->vkCreatePipelineLayout(dev, &pipeLayoutInfo, NULL, &m_QuadResolvePipeLayout);
RDCASSERT(vkr == VK_SUCCESS);
}
pipeLayoutInfo.pSetLayouts = UnwrapPtr(m_OutlineDescSetLayout);
vkr = vt->CreatePipelineLayout(Unwrap(dev), &pipeLayoutInfo, NULL, &m_OutlinePipeLayout);
@@ -507,7 +543,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
VkDescriptorPoolCreateInfo descpoolInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, NULL,
0, 8+ARRAY_COUNT(m_TexDisplayDescSet),
0, 9+ARRAY_COUNT(m_TexDisplayDescSet),
ARRAY_COUNT(descPoolTypes), &descPoolTypes[0],
};
@@ -542,6 +578,15 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_TextDescSet);
if(m_State < WRITING)
{
descAllocInfo.pSetLayouts = UnwrapPtr(m_QuadDescSetLayout);
vkr = vt->AllocateDescriptorSets(Unwrap(dev), &descAllocInfo, &m_QuadDescSet);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_QuadDescSet);
}
descAllocInfo.pSetLayouts = UnwrapPtr(m_OutlineDescSetLayout);
vkr = vt->AllocateDescriptorSets(Unwrap(dev), &descAllocInfo, &m_OutlineDescSet);
RDCASSERT(vkr == VK_SUCCESS);
@@ -565,11 +610,14 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramDescSet[1]);
descAllocInfo.pSetLayouts = UnwrapPtr(m_MeshFetchDescSetLayout);
vkr = vt->AllocateDescriptorSets(Unwrap(dev), &descAllocInfo, &m_MeshFetchDescSet);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MeshFetchDescSet);
if(m_State < WRITING)
{
descAllocInfo.pSetLayouts = UnwrapPtr(m_MeshFetchDescSetLayout);
vkr = vt->AllocateDescriptorSets(Unwrap(dev), &descAllocInfo, &m_MeshFetchDescSet);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MeshFetchDescSet);
}
m_ReadbackWindow.Create(driver, dev, STAGE_BUFFER_BYTE_SIZE, 1, GPUBuffer::eGPUBufferReadback);
@@ -600,6 +648,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetEmbeddedResource(spv_minmaxresult_comp),
GetEmbeddedResource(spv_histogram_comp),
GetEmbeddedResource(spv_outline_frag),
GetEmbeddedResource(spv_quadresolve_frag),
GetEmbeddedResource(spv_quadwrite_frag),
};
SPIRVShaderStage shaderStages[] = {
@@ -615,6 +665,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
eSPIRVCompute,
eSPIRVCompute,
eSPIRVFragment,
eSPIRVFragment,
eSPIRVFragment,
};
enum shaderIdx
@@ -631,6 +683,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
MINMAXRESULTCS,
HISTOGRAMCS,
OUTLINEFS,
QUADRESOLVEFS,
QUADWRITEFS,
NUM_SHADERS,
};
@@ -656,12 +710,28 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
for(size_t i=0; i < ARRAY_COUNT(module); i++)
{
sources[0] = "#version 430 core\n";
sources[2] = "";
sources[3] = shaderSources[i];
if(sources[3].find("#include \"texsample.h\"") != string::npos)
sources[2] = GetEmbeddedResource(spv_texsample_h);
// hoist up any #extension directives
size_t extsearch = 0;
do
{
extsearch = sources[3].find("#extension", extsearch);
if(extsearch == string::npos)
break;
size_t begin = extsearch;
extsearch = sources[3].find('\n', extsearch);
sources[0] += sources[3].substr(begin, extsearch-begin+1);
} while(extsearch != string::npos);
string err = GetSPIRVBlob(shaderStages[i], sources, &shaderSPIRV[i]);
RDCASSERT(err.empty() && shaderSPIRV[i]);
@@ -669,6 +739,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, NULL, 0,
shaderSPIRV[i]->size()*sizeof(uint32_t), &(*shaderSPIRV[i])[0],
};
if(i == QUADWRITEFS)
m_QuadSPIRV = shaderSPIRV[i];
vkr = vt->CreateShaderModule(Unwrap(dev), &modinfo, NULL, &module[i]);
RDCASSERT(vkr == VK_SUCCESS);
@@ -679,6 +752,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
m_CacheShaders = false;
VkRenderPass RGBA32RP, RGBA8RP, RGBA16RP, RGBA8MSRP; // compatible render passes for creating pipelines
VkRenderPass wrappedRGBA8RP;
{
VkAttachmentDescription attDesc = {
@@ -707,6 +781,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
};
vt->CreateRenderPass(Unwrap(dev), &rpinfo, NULL, &RGBA8RP);
if(m_State < WRITING)
m_pDriver->vkCreateRenderPass(dev, &rpinfo, NULL, &wrappedRGBA8RP);
attDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT;
@@ -873,6 +950,20 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_OutlinePipeline);
attState.blendEnable = false;
stages[0].module = module[BLITVS];
stages[1].module = module[QUADRESOLVEFS];
pipeInfo.layout = m_QuadResolvePipeLayout;
pipeInfo.renderPass = wrappedRGBA8RP;
if(m_State < WRITING)
{
vkr = m_pDriver->vkCreateGraphicsPipelines(dev, VK_NULL_HANDLE, 1, &pipeInfo, NULL, &m_QuadResolvePipeline);
RDCASSERT(vkr == VK_SUCCESS);
}
VkComputePipelineCreateInfo compPipeInfo = {
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, NULL, 0,
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 0, VK_SHADER_STAGE_COMPUTE_BIT, VK_NULL_HANDLE, "main", NULL },
@@ -905,6 +996,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
vt->DestroyRenderPass(Unwrap(dev), RGBA32RP, NULL);
vt->DestroyRenderPass(Unwrap(dev), RGBA8RP, NULL);
vt->DestroyRenderPass(Unwrap(dev), RGBA8MSRP, NULL);
if(m_State < WRITING)
m_pDriver->vkDestroyRenderPass(dev, wrappedRGBA8RP, NULL);
for(size_t i=0; i < ARRAY_COUNT(module); i++)
{
@@ -1070,6 +1163,13 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
m_TextGlyphUBO.Unmap(vt, dev);
}
m_OverdrawRampUBO.Create(driver, dev, 2048, 1, 0); // no ring needed, fixed data
RDCCOMPILE_ASSERT(sizeof(overdrawRamp) <= 2048, "overdraw ramp uniforms size");
void *ramp = m_OverdrawRampUBO.Map(vt, dev, (uint32_t *)NULL);
memcpy(ramp, overdrawRamp, sizeof(overdrawRamp));
m_OverdrawRampUBO.Unmap(vt, dev);
// pick pixel data
{
@@ -1251,7 +1351,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
// don't need to ring this, as we hard-sync for readback anyway
m_HistogramUBO.Create(driver, dev, sizeof(HistogramUBOData), 1, 0);
VkDescriptorBufferInfo bufInfo[6];
VkDescriptorBufferInfo bufInfo[7];
RDCEraseEl(bufInfo);
// tex display is updated right before rendering
@@ -1262,6 +1362,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
m_TextStringUBO.FillDescriptor(bufInfo[3]);
m_MeshUBO.FillDescriptor(bufInfo[4]);
m_OutlineUBO.FillDescriptor(bufInfo[5]);
m_OverdrawRampUBO.FillDescriptor(bufInfo[6]);
VkDescriptorImageInfo atlasImInfo;
atlasImInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -1304,9 +1405,16 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
Unwrap(m_OutlineDescSet), 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
NULL, &bufInfo[5], NULL
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(m_QuadDescSet), 1, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
NULL, &bufInfo[6], NULL
},
};
vt->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL);
uint32_t writeCount = ARRAY_COUNT(writeSet);
if(m_State >= WRITING) writeCount--; // don't write to m_QuadDescSet when it's not allocated
vt->UpdateDescriptorSets(Unwrap(dev), writeCount, writeSet, 0, NULL);
vt->EndCommandBuffer(Unwrap(cmd));
}
@@ -1367,7 +1475,11 @@ VulkanDebugManager::~VulkanDebugManager()
GetResourceManager()->ReleaseWrappedResource(m_TextDescSet);
GetResourceManager()->ReleaseWrappedResource(m_MeshDescSet);
GetResourceManager()->ReleaseWrappedResource(m_OutlineDescSet);
GetResourceManager()->ReleaseWrappedResource(m_MeshFetchDescSet);
if(m_QuadDescSet)
{
GetResourceManager()->ReleaseWrappedResource(m_MeshFetchDescSet);
GetResourceManager()->ReleaseWrappedResource(m_QuadDescSet);
}
for(size_t i=0; i < ARRAY_COUNT(m_HistogramDescSet); i++)
GetResourceManager()->ReleaseWrappedResource(m_HistogramDescSet[i]);
@@ -1597,6 +1709,8 @@ VulkanDebugManager::~VulkanDebugManager()
m_HistogramReadback.Destroy(vt, dev);
m_HistogramUBO.Destroy(vt, dev);
m_OverdrawRampUBO.Destroy(vt, dev);
// overlay & postvs resources are allocated through driver
if(m_MeshFetchDescSetLayout != VK_NULL_HANDLE)
m_pDriver->vkDestroyDescriptorSetLayout(dev, m_MeshFetchDescSetLayout, NULL);
@@ -1615,6 +1729,15 @@ VulkanDebugManager::~VulkanDebugManager()
if(m_OverlayImageMem != VK_NULL_HANDLE)
m_pDriver->vkFreeMemory(dev, m_OverlayImageMem, NULL);
if(m_QuadDescSetLayout != VK_NULL_HANDLE)
m_pDriver->vkDestroyDescriptorSetLayout(dev, m_QuadDescSetLayout, NULL);
if(m_QuadResolvePipeLayout != VK_NULL_HANDLE)
m_pDriver->vkDestroyPipelineLayout(dev, m_QuadResolvePipeLayout, NULL);
if(m_QuadResolvePipeline != VK_NULL_HANDLE)
m_pDriver->vkDestroyPipeline(dev, m_QuadResolvePipeline, NULL);
}
void VulkanDebugManager::BeginText(const TextPrintState &textstate)
@@ -2003,6 +2126,203 @@ void VulkanDebugManager::PatchFixedColShader(VkShaderModule &mod, float col[4])
RDCASSERT(vkr == VK_SUCCESS);
}
struct QuadOverdrawCallback : public DrawcallCallback
{
QuadOverdrawCallback(WrappedVulkan *vk, uint32_t frameID, const vector<uint32_t> &events)
: m_pDriver(vk)
, m_pDebug(vk->GetDebugManager())
, m_FrameID(frameID)
, m_Events(events)
, m_PrevState(VulkanCreationInfo())
{ m_pDriver->SetDrawcallCB(this); }
~QuadOverdrawCallback()
{ m_pDriver->SetDrawcallCB(NULL); }
void PreDraw(uint32_t eid, VkCommandBuffer cmd)
{
if(std::find(m_Events.begin(), m_Events.end(), eid) == m_Events.end())
return;
// we customise the pipeline to disable framebuffer writes, but perform normal testing
// and substitute our quad calculation fragment shader that writes to a storage image
// that is bound in a new descriptor set.
VkResult vkr = VK_SUCCESS;
m_PrevState = m_pDriver->GetRenderState();
VulkanRenderState &pipestate = m_pDriver->GetRenderState();
// check cache first
VkPipeline pipe = m_PipelineCache[pipestate.graphics.pipeline];
// if we don't get a hit, create a modified pipeline
if(pipe == VK_NULL_HANDLE)
{
VulkanCreationInfo &c = pipestate.m_CreationInfo;
VulkanCreationInfo::Pipeline &p = c.m_Pipeline[pipestate.graphics.pipeline];
VkDescriptorSetLayout *descSetLayouts;
// descSet will be the index of our new descriptor set
uint32_t descSet = (uint32_t)c.m_PipelineLayout[p.layout].descSetLayouts.size();
descSetLayouts = new VkDescriptorSetLayout[descSet+1];
for(uint32_t i=0; i < descSet; i++)
descSetLayouts[i] = m_pDriver->GetResourceManager()->GetCurrentHandle<VkDescriptorSetLayout>(c.m_PipelineLayout[p.layout].descSetLayouts[i]);
// this layout has storage image and
descSetLayouts[descSet] = m_pDebug->m_QuadDescSetLayout;
const vector<VkPushConstantRange> &push = c.m_PipelineLayout[p.layout].pushRanges;
VkPipelineLayoutCreateInfo pipeLayoutInfo = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, NULL, 0,
descSet+1, descSetLayouts,
(uint32_t)push.size(), push.empty() ? NULL : &push[0],
};
// create pipeline layout with same descriptor set layouts, plus our mesh output set
VkPipelineLayout pipeLayout;
vkr = m_pDriver->vkCreatePipelineLayout(m_pDriver->GetDev(), &pipeLayoutInfo, NULL, &pipeLayout);
RDCASSERT(vkr == VK_SUCCESS);
SAFE_DELETE_ARRAY(descSetLayouts);
VkGraphicsPipelineCreateInfo pipeCreateInfo;
m_pDebug->MakeGraphicsPipelineInfo(pipeCreateInfo, pipestate.graphics.pipeline);
// repoint pipeline layout
pipeCreateInfo.layout = pipeLayout;
// disable colour writes/blends
VkPipelineColorBlendStateCreateInfo *cb = (VkPipelineColorBlendStateCreateInfo *)pipeCreateInfo.pColorBlendState;
for(uint32_t i=0; i < cb->attachmentCount; i++)
{
VkPipelineColorBlendAttachmentState *att = (VkPipelineColorBlendAttachmentState *)&cb->pAttachments[i];
att->blendEnable = false;
att->colorWriteMask = 0x0;
}
// disable tests and depth/stencil writes
VkPipelineDepthStencilStateCreateInfo *ds = (VkPipelineDepthStencilStateCreateInfo *)pipeCreateInfo.pDepthStencilState;
ds->depthTestEnable = false;
ds->depthWriteEnable = false;
ds->stencilTestEnable = false;
ds->depthBoundsTestEnable = false;
ds->front.passOp = ds->front.failOp = ds->front.depthFailOp = VK_STENCIL_OP_KEEP;
ds->back.passOp = ds->back.failOp = ds->back.depthFailOp = VK_STENCIL_OP_KEEP;
// don't discard
VkPipelineRasterizationStateCreateInfo *rs = (VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState;
rs->rasterizerDiscardEnable = false;
vector<uint32_t> spirv = *m_pDebug->m_QuadSPIRV;
// patch spirv, change descriptor set to descSet value
size_t it = 5;
while(it < spirv.size())
{
uint16_t WordCount = spirv[it]>>spv::WordCountShift;
spv::Op opcode = spv::Op(spirv[it]&spv::OpCodeMask);
if(opcode == spv::OpDecorate && spirv[it+2] == spv::DecorationDescriptorSet)
{
spirv[it+3] = descSet;
break;
}
it += WordCount;
}
VkShaderModuleCreateInfo modinfo = {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, NULL, 0,
spirv.size()*sizeof(uint32_t), &spirv[0],
};
VkShaderModule module;
VkDevice dev = m_pDriver->GetDev();
vkr = ObjDisp(dev)->CreateShaderModule(Unwrap(dev), &modinfo, NULL, &module);
RDCASSERT(vkr == VK_SUCCESS);
m_pDriver->GetResourceManager()->WrapResource(Unwrap(dev), module);
bool found = false;
for(uint32_t i=0; i < pipeCreateInfo.stageCount; i++)
{
VkPipelineShaderStageCreateInfo &sh = (VkPipelineShaderStageCreateInfo &)pipeCreateInfo.pStages[i];
if(sh.stage == VK_SHADER_STAGE_FRAGMENT_BIT)
{
sh.module = module;
sh.pName = "main";
found = true;
break;
}
}
if(!found)
{
// we know this is safe because it's pointing to a static array that's
// big enough for all shaders
VkPipelineShaderStageCreateInfo &sh = (VkPipelineShaderStageCreateInfo &)pipeCreateInfo.pStages[pipeCreateInfo.stageCount++];
sh.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
sh.pNext = NULL;
sh.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
sh.module = module;
sh.pName = "main";
sh.pSpecializationInfo = NULL;
}
vkr = m_pDriver->vkCreateGraphicsPipelines(dev, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL, &pipe);
RDCASSERT(vkr == VK_SUCCESS);
ObjDisp(dev)->DestroyShaderModule(Unwrap(dev), Unwrap(module), NULL);
m_pDriver->GetResourceManager()->ReleaseWrappedResource(module);
m_PipelineCache[pipestate.graphics.pipeline] = pipe;
}
// modify state for first draw call
pipestate.graphics.pipeline = GetResID(pipe);
pipestate.graphics.descSets.push_back(GetResID(m_pDebug->m_QuadDescSet));
if(cmd)
pipestate.BindPipeline(cmd);
}
bool PostDraw(uint32_t eid, VkCommandBuffer cmd)
{
if(std::find(m_Events.begin(), m_Events.end(), eid) == m_Events.end())
return false;
// restore the render state and go ahead with the real draw
m_pDriver->GetRenderState() = m_PrevState;
RDCASSERT(cmd);
m_pDriver->GetRenderState().BindPipeline(cmd);
return true;
}
void PostRedraw(uint32_t eid, VkCommandBuffer cmd)
{
// nothing to do
}
uint32_t m_FrameID;
WrappedVulkan *m_pDriver;
VulkanDebugManager *m_pDebug;
const vector<uint32_t> &m_Events;
// cache modified pipelines
map<ResourceId, VkPipeline> m_PipelineCache;
VulkanRenderState m_PrevState;
};
ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents)
{
const VkLayerDispatchTable *vt = ObjDisp(m_Device);
@@ -2788,6 +3108,195 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve
m_pDriver->vkDestroyFramebuffer(m_Device, depthFB, NULL);
}
}
else if(overlay == eTexOverlay_QuadOverdrawPass || overlay == eTexOverlay_QuadOverdrawDraw)
{
VulkanRenderState prevstate = m_pDriver->m_RenderState;
{
SCOPED_TIMER("Quad Overdraw");
float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
vt->CmdClearColorImage(Unwrap(cmd), Unwrap(m_OverlayImage), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, (VkClearColorValue *)black, 1, &subresourceRange);
vector<uint32_t> events = passEvents;
if(overlay == eTexOverlay_QuadOverdrawDraw)
events.clear();
events.push_back(eventID);
VkImage quadImg;
VkDeviceMemory quadImgMem;
VkImageView quadImgView;
VkImageCreateInfo imInfo = {
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, NULL, 0,
VK_IMAGE_TYPE_2D, VK_FORMAT_R32_UINT,
{ RDCMAX(1, m_OverlayDim.width>>1), RDCMAX(1, m_OverlayDim.height>>1), 1 },
1, 4, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_STORAGE_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
VK_SHARING_MODE_EXCLUSIVE, 0, NULL,
VK_IMAGE_LAYOUT_UNDEFINED,
};
VkResult vkr = m_pDriver->vkCreateImage(m_Device, &imInfo, NULL, &quadImg);
RDCASSERT(vkr == VK_SUCCESS);
VkMemoryRequirements mrq = {0};
m_pDriver->vkGetImageMemoryRequirements(m_Device, quadImg, &mrq);
VkMemoryAllocateInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL,
mrq.size, m_pDriver->GetGPULocalMemoryIndex(mrq.memoryTypeBits),
};
vkr = m_pDriver->vkAllocateMemory(m_Device, &allocInfo, NULL, &quadImgMem);
RDCASSERT(vkr == VK_SUCCESS);
vkr = m_pDriver->vkBindImageMemory(m_Device, quadImg, quadImgMem, 0);
RDCASSERT(vkr == VK_SUCCESS);
VkImageViewCreateInfo viewinfo = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, NULL,
0, quadImg, VK_IMAGE_VIEW_TYPE_2D_ARRAY,
VK_FORMAT_R32_UINT,
{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE },
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 4 },
};
vkr = m_pDriver->vkCreateImageView(m_Device, &viewinfo, NULL, &quadImgView);
RDCASSERT(vkr == VK_SUCCESS);
// update descriptor to point to our R32 result image
VkDescriptorImageInfo imdesc = { 0 };
imdesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
imdesc.sampler = VK_NULL_HANDLE;
imdesc.imageView = Unwrap(quadImgView);
VkWriteDescriptorSet write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(m_QuadDescSet), 0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
&imdesc, NULL, NULL
};
vt->UpdateDescriptorSets(Unwrap(m_Device), 1, &write, 0, NULL);
VkImageMemoryBarrier quadImBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL,
0, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
Unwrap(quadImg),
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 4 }
};
void *barrier = &quadImBarrier;
// clear all to black
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
vt->CmdClearColorImage(Unwrap(cmd), Unwrap(quadImg), VK_IMAGE_LAYOUT_GENERAL, (VkClearColorValue *)&black, 1, &quadImBarrier.subresourceRange);
quadImBarrier.srcAccessMask = quadImBarrier.dstAccessMask;
quadImBarrier.oldLayout = quadImBarrier.newLayout;
quadImBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
// set to general layout, for load/store operations
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
// end this cmd buffer so the image is in the right state for the next part
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERT(vkr == VK_SUCCESS);
if(overlay == eTexOverlay_QuadOverdrawPass)
m_pDriver->ReplayLog(frameID, 0, events[0], eReplay_WithoutDraw);
// declare callback struct here
QuadOverdrawCallback cb(m_pDriver, frameID, events);
if(overlay == eTexOverlay_QuadOverdrawPass)
{
m_pDriver->ReplayLog(frameID, events.front(), events.back(), eReplay_Full);
}
else
{
// don't have the driver call the callback
m_pDriver->SetDrawcallCB(NULL);
// call PreDraw to set up per-draw changed state without binding anything
cb.PreDraw(events.back(), NULL);
// do the single drawcall, which will bind the pipeline above
m_pDriver->ReplayLog(frameID, events.front(), events.back(), eReplay_OnlyDraw);
}
// resolve pass
{
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
quadImBarrier.srcAccessMask = quadImBarrier.dstAccessMask;
quadImBarrier.oldLayout = quadImBarrier.newLayout;
quadImBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
// wait for writing to finish
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
VkClearValue clearval = {0};
VkRenderPassBeginInfo rpbegin = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL,
Unwrap(m_OverlayNoDepthRP), Unwrap(m_OverlayNoDepthFB),
m_pDriver->m_RenderState.renderArea,
1, &clearval,
};
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(m_QuadResolvePipeline));
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(m_QuadResolvePipeLayout), 0, 1, UnwrapPtr(m_QuadDescSet), 0, NULL);
VkViewport viewport = {
0.0f, 0.0f,
(float)m_OverlayDim.width,
(float)m_OverlayDim.height,
0.0f, 1.0f
};
vt->CmdSetViewport(Unwrap(cmd), 1, &viewport);
vt->CmdDraw(Unwrap(cmd), 4, 1, 0, 0);
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERT(vkr == VK_SUCCESS);
}
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
m_pDriver->vkDestroyImageView(m_Device, quadImgView, NULL);
m_pDriver->vkDestroyImage(m_Device, quadImg, NULL);
m_pDriver->vkFreeMemory(m_Device, quadImgMem, NULL);
for(auto it=cb.m_PipelineCache.begin(); it != cb.m_PipelineCache.end(); ++it)
{
m_pDriver->vkDestroyPipeline(m_Device, it->second, NULL);
}
}
// restore back to normal
if(overlay == eTexOverlay_QuadOverdrawPass)
m_pDriver->ReplayLog(frameID, 0, eventID, eReplay_WithoutDraw);
else
m_pDriver->m_RenderState = prevstate;
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
}
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERT(vkr == VK_SUCCESS);
+10 -2
View File
@@ -197,6 +197,13 @@ class VulkanDebugManager
VkRenderPass m_OverlayNoDepthRP;
VkExtent2D m_OverlayDim;
VkDeviceSize m_OverlayMemSize;
GPUBuffer m_OverdrawRampUBO;
VkDescriptorSetLayout m_QuadDescSetLayout;
VkDescriptorSet m_QuadDescSet;
VkPipelineLayout m_QuadResolvePipeLayout;
VkPipeline m_QuadResolvePipeline;
vector<uint32_t> *m_QuadSPIRV;
VkDescriptorSetLayout m_MeshDescSetLayout;
VkPipelineLayout m_MeshPipeLayout;
@@ -227,7 +234,7 @@ class VulkanDebugManager
VkDescriptorSet m_MeshFetchDescSet;
MeshDisplayPipelines CacheMeshDisplayPipelines(const MeshFormat &primary, const MeshFormat &secondary);
void MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &pipeCreateInfo, ResourceId pipeline);
private:
void InitDebugData();
void ShutdownDebugData();
@@ -245,10 +252,11 @@ class VulkanDebugManager
void PatchFixedColShader(VkShaderModule &mod, float col[4]);
void RenderTextInternal(const TextPrintState &textstate, float x, float y, const char *text);
void MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &pipeCreateInfo, ResourceId pipeline);
static const int FONT_TEX_WIDTH = 256;
static const int FONT_TEX_HEIGHT = 128;
LogState m_State;
float m_FontCharAspect;
float m_FontCharSize;
+7 -2
View File
@@ -3787,13 +3787,18 @@ struct InitPostVSCallback : public DrawcallCallback
~InitPostVSCallback()
{ m_pDriver->SetDrawcallCB(NULL); }
void PreDraw(uint32_t eid)
void PreDraw(uint32_t eid, VkCommandBuffer cmd)
{
if(std::find(m_Events.begin(), m_Events.end(), eid) != m_Events.end())
m_pReplay->InitPostVSBuffers(m_FrameID, eid);
}
void PostDraw(uint32_t eid)
bool PostDraw(uint32_t eid, VkCommandBuffer cmd)
{
return false;
}
void PostRedraw(uint32_t eid, VkCommandBuffer cmd)
{
}
+36 -25
View File
@@ -109,6 +109,35 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd)
for(uint32_t i=0; i < subpass; i++)
ObjDisp(cmd)->CmdNextSubpass(Unwrap(cmd), VK_SUBPASS_CONTENTS_INLINE);
BindPipeline(cmd);
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<VkBuffer>(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<VkBuffer>(vbuffers[i].buf)), &vbuffers[i].offs);
}
void VulkanRenderState::BindPipeline(VkCommandBuffer cmd)
{
if(graphics.pipeline != ResourceId())
{
ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(GetResourceManager()->GetCurrentHandle<VkPipeline>(graphics.pipeline)));
@@ -150,6 +179,12 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd)
ResourceId pipeLayoutId = m_CreationInfo.m_Pipeline[compute.pipeline].layout;
VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle<VkPipelineLayout>(pipeLayoutId);
const vector<VkPushConstantRange> &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].offset, pushRanges[i].size, pushconsts+pushRanges[i].offset);
const vector<ResourceId> &descSetLayouts = m_CreationInfo.m_PipelineLayout[pipeLayoutId].descSetLayouts;
for(size_t i=0; i < descSetLayouts.size(); i++)
@@ -158,34 +193,10 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd)
if(compute.descSets[i] != ResourceId())
{
ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i,
ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(layout), (uint32_t)i,
1, UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(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<VkBuffer>(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<VkBuffer>(vbuffers[i].buf)), &vbuffers[i].offs);
}
+1
View File
@@ -36,6 +36,7 @@ struct VulkanRenderState
VulkanRenderState(VulkanCreationInfo &createInfo);
VulkanRenderState &operator =(const VulkanRenderState &o);
void BeginRenderPassAndApplyState(VkCommandBuffer cmd);
void BindPipeline(VkCommandBuffer cmd);
// dynamic state
vector<VkViewport> views;
@@ -45,12 +45,20 @@ bool WrappedVulkan::Serialise_vkCmdDraw(
{
if(IsPartialCmd(cmdid) && InPartialRange())
{
if(m_DrawcallCallback) m_DrawcallCallback->PreDraw(m_RootEventID);
commandBuffer = PartialCmdBuf();
if(m_DrawcallCallback) m_DrawcallCallback->PreDraw(m_RootEventID, commandBuffer);
ObjDisp(commandBuffer)->CmdDraw(Unwrap(commandBuffer), vtxCount, instCount, firstVtx, firstInst);
if(m_DrawcallCallback) m_DrawcallCallback->PostDraw(m_RootEventID);
if(m_DrawcallCallback)
{
if(m_DrawcallCallback->PostDraw(m_RootEventID, commandBuffer))
{
ObjDisp(commandBuffer)->CmdDraw(Unwrap(commandBuffer), vtxCount, instCount, firstVtx, firstInst);
m_DrawcallCallback->PostRedraw(m_RootEventID, commandBuffer);
}
}
}
}
else if(m_State == READING)
@@ -979,12 +987,20 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexed(
{
if(IsPartialCmd(cmdid) && InPartialRange())
{
if(m_DrawcallCallback) m_DrawcallCallback->PreDraw(m_RootEventID);
commandBuffer = PartialCmdBuf();
if(m_DrawcallCallback) m_DrawcallCallback->PreDraw(m_RootEventID, commandBuffer);
ObjDisp(commandBuffer)->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs, firstInst);
if(m_DrawcallCallback) m_DrawcallCallback->PostDraw(m_RootEventID);
if(m_DrawcallCallback)
{
if(m_DrawcallCallback->PostDraw(m_RootEventID, commandBuffer))
{
ObjDisp(commandBuffer)->CmdDrawIndexed(Unwrap(commandBuffer), idxCount, instCount, firstIdx, vtxOffs, firstInst);
m_DrawcallCallback->PostRedraw(m_RootEventID, commandBuffer);
}
}
}
}
else if(m_State == READING)
+2
View File
@@ -370,6 +370,8 @@
<None Include="data\spv\minmaxresult.comp" />
<None Include="data\spv\minmaxtile.comp" />
<None Include="data\spv\outline.frag" />
<None Include="data\spv\quadresolve.frag" />
<None Include="data\spv\quadwrite.frag" />
<None Include="data\spv\texdisplay.frag" />
<None Include="data\spv\text.frag" />
<None Include="data\spv\text.vert" />
+6
View File
@@ -478,6 +478,12 @@
<None Include="data\spv\outline.frag">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\quadwrite.frag">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\quadresolve.frag">
<Filter>Resources\spv</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="data\renderdoc.rc">