Add post-vertex mesh data fetching. Not complete, but proof-of-concept

This commit is contained in:
baldurk
2016-02-07 18:47:19 +01:00
parent cf13662804
commit a5be2b4f48
3 changed files with 479 additions and 19 deletions
+429 -13
View File
@@ -394,6 +394,22 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_OutlineDescSetLayout);
}
{
VkDescriptorSetLayoutBinding layoutBinding[] = {
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, }
};
VkDescriptorSetLayoutCreateInfo descsetLayoutInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL,
ARRAY_COUNT(layoutBinding), &layoutBinding[0],
};
vkr = vt->CreateDescriptorSetLayout(Unwrap(dev), &descsetLayoutInfo, &m_MeshFetchDescSetLayout);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MeshFetchDescSetLayout);
}
{
VkDescriptorSetLayoutBinding layoutBinding[] = {
@@ -512,7 +528,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
VkDescriptorPoolCreateInfo descpoolInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, NULL,
VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 7+ARRAY_COUNT(m_TexDisplayDescSet),
VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 8+ARRAY_COUNT(m_TexDisplayDescSet),
ARRAY_COUNT(descPoolTypes), &descPoolTypes[0],
};
@@ -571,6 +587,12 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramDescSet[1]);
vkr = vt->AllocDescriptorSets(Unwrap(dev), Unwrap(m_DescriptorPool), VK_DESCRIPTOR_SET_USAGE_STATIC, 1,
UnwrapPtr(m_MeshFetchDescSetLayout), &m_MeshFetchDescSet);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MeshFetchDescSet);
m_GenericUBO.Create(driver, dev, 128, 10, 0);
RDCCOMPILE_ASSERT(sizeof(genericuniforms) <= 128, "generic UBO size");
@@ -1409,8 +1431,8 @@ VulkanDebugManager::~VulkanDebugManager()
GetResourceManager()->ReleaseWrappedResource(m_TextDescSet);
GetResourceManager()->ReleaseWrappedResource(m_MeshDescSet);
GetResourceManager()->ReleaseWrappedResource(m_OutlineDescSet);
GetResourceManager()->ReleaseWrappedResource(m_MeshFetchDescSet);
for(size_t i=0; i < ARRAY_COUNT(m_HistogramDescSet); i++)
GetResourceManager()->ReleaseWrappedResource(m_HistogramDescSet[i]);
@@ -1621,6 +1643,12 @@ VulkanDebugManager::~VulkanDebugManager()
m_OutlineUBO.Destroy(vt, dev);
if(m_MeshFetchDescSetLayout != VK_NULL_HANDLE)
{
vt->DestroyDescriptorSetLayout(Unwrap(dev), Unwrap(m_MeshFetchDescSetLayout));
GetResourceManager()->ReleaseWrappedResource(m_MeshFetchDescSetLayout);
}
if(m_HistogramDescSetLayout != VK_NULL_HANDLE)
{
vt->DestroyDescriptorSetLayout(Unwrap(dev), Unwrap(m_HistogramDescSetLayout));
@@ -3072,7 +3100,7 @@ inline bool ShouldSkipOutput(SystemAttribute val)
val == eAttr_ClipDistance);
}
void AddOutputDumping(ShaderReflection refl, const char *entryName, vector<uint32_t> &modSpirv)
void AddOutputDumping(ShaderReflection refl, const char *entryName, uint32_t descSet, vector<uint32_t> &modSpirv, uint32_t &bufStride)
{
uint32_t *spirv = &modSpirv[0];
size_t spirvLength = modSpirv.size();
@@ -3128,8 +3156,6 @@ void AddOutputDumping(ShaderReflection refl, const char *entryName, vector<uint3
RDCASSERT(numOutputs < 100);
uint32_t maxDescSetBind = 0;
size_t decorateOffset = 0;
size_t typeVarOffset = 0;
@@ -3242,9 +3268,6 @@ void AddOutputDumping(ShaderReflection refl, const char *entryName, vector<uint3
}
}
if(opcode == spv::OpDecorate && spirv[it+2] == spv::DecorationDescriptorSet)
maxDescSetBind = RDCMAX(maxDescSetBind, spirv[it+3]);
// when we reach the types, decorations are over
if(decorateOffset == 0 && opcode >= spv::OpTypeVoid && opcode <= spv::OpTypeForwardPointer)
decorateOffset = it;
@@ -3579,6 +3602,8 @@ void AddOutputDumping(ShaderReflection refl, const char *entryName, vector<uint3
decorations.push_back(spv::DecorationArrayStride);
decorations.push_back(memberOffset);
bufStride = memberOffset;
// set object type
decorations.push_back(MakeSPIRVOp(spv::OpDecorate, 3));
decorations.push_back(outputStructID);
@@ -3588,7 +3613,7 @@ void AddOutputDumping(ShaderReflection refl, const char *entryName, vector<uint3
decorations.push_back(MakeSPIRVOp(spv::OpDecorate, 4));
decorations.push_back(outBufferVarID);
decorations.push_back(spv::DecorationDescriptorSet);
decorations.push_back(maxDescSetBind+1);
decorations.push_back(descSet);
decorations.push_back(MakeSPIRVOp(spv::OpDecorate, 4));
decorations.push_back(outBufferVarID);
@@ -3720,14 +3745,405 @@ void AddOutputDumping(ShaderReflection refl, const char *entryName, vector<uint3
void VulkanDebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
{
const WrappedVulkan::PartialReplayData::StateVector &state = m_pDriver->m_PartialReplayData.state;
auto idx = std::make_pair(frameID, eventID);
if(m_PostVSData.find(idx) != m_PostVSData.end())
return;
if(!m_pDriver->GetDeviceFeatures().vertexSideEffects)
return;
WrappedVulkan::PartialReplayData::StateVector &state = m_pDriver->m_PartialReplayData.state;
VulkanCreationInfo &c = m_pDriver->m_CreationInfo;
if(state.graphics.pipeline == ResourceId())
return;
const VulkanCreationInfo::Pipeline &p = c.m_Pipeline[state.graphics.pipeline];
if(p.shaders[VK_SHADER_STAGE_VERTEX] == ResourceId())
return;
const VulkanCreationInfo::Shader &s = c.m_Shader[p.shaders[VK_SHADER_STAGE_VERTEX]];
const VulkanCreationInfo::ShaderModule &m = c.m_ShaderModule[s.module];
vector<uint32_t> modSpirv = m.spirv.spirv;
AddOutputDumping(s.refl, s.entry.c_str(), modSpirv);
const FetchDrawcall *drawcall = m_pDriver->GetDrawcall(frameID, eventID);
if(drawcall->numIndices == 0)
return;
RDCBREAK();
uint32_t descSet = (uint32_t)c.m_PipelineLayout[p.layout].descSetLayouts.size();
uint32_t bufStride = 0;
vector<uint32_t> modSpirv = m.spirv.spirv;
AddOutputDumping(s.refl, s.entry.c_str(), descSet, modSpirv, bufStride);
// we go through the driver for all these creations since they need to be properly
// registered in order to be put in the partial replay state
VkResult vkr = VK_SUCCESS;
VkDevice dev = m_Device;
VkDescriptorSetLayout *descSetLayouts;
// descSet will be the index of our new descriptor set
descSetLayouts = new VkDescriptorSetLayout[descSet+1];
for(uint32_t i=0; i < descSet; i++)
descSetLayouts[i] = GetResourceManager()->GetCurrentHandle<VkDescriptorSetLayout>(c.m_PipelineLayout[p.layout].descSetLayouts[i]);
// this layout just says it has one storage buffer
descSetLayouts[descSet] = m_MeshFetchDescSetLayout;
const vector<VkPushConstantRange> &push = c.m_PipelineLayout[p.layout].pushRanges;
VkPipelineLayoutCreateInfo pipeLayoutInfo = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, NULL,
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(dev, &pipeLayoutInfo, &pipeLayout);
RDCASSERT(vkr == VK_SUCCESS);
SAFE_DELETE_ARRAY(descSetLayouts);
VkGraphicsPipelineCreateInfo pipeCreateInfo;
// get pipeline create info
MakeGraphicsPipelineInfo(pipeCreateInfo, state.graphics.pipeline);
// repoint pipeline layout
pipeCreateInfo.layout = pipeLayout;
// enable rasterizer discard
VkPipelineRasterStateCreateInfo *rs = (VkPipelineRasterStateCreateInfo *)pipeCreateInfo.pRasterState;
rs->rasterizerDiscardEnable = true;
// create vertex shader with modified code
VkShaderModuleCreateInfo moduleInfo = {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, NULL,
modSpirv.size()*sizeof(uint32_t), (void *)&modSpirv[0], 0,
};
VkShaderModule module;
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleInfo, &module);
RDCASSERT(vkr == VK_SUCCESS);
VkShaderCreateInfo shadinfo = {
VK_STRUCTURE_TYPE_SHADER_CREATE_INFO, NULL,
module, s.entry.c_str(), 0,
VK_SHADER_STAGE_VERTEX,
};
VkShader shad;
vkr = m_pDriver->vkCreateShader(m_Device, &shadinfo, &shad);
RDCASSERT(vkr == VK_SUCCESS);
// change vertex shader to use our modified code
for(uint32_t i=0; i < pipeCreateInfo.stageCount; i++)
{
VkPipelineShaderStageCreateInfo &sh = (VkPipelineShaderStageCreateInfo &)pipeCreateInfo.pStages[i];
if(sh.stage == VK_SHADER_STAGE_VERTEX)
{
sh.shader = shad;
break;
}
}
// create new pipeline
VkPipeline pipe;
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, &pipe);
RDCASSERT(vkr == VK_SUCCESS);
// backup state
WrappedVulkan::PartialReplayData::StateVector prevstate = state;
// bind created pipeline to partial replay state
state.graphics.pipeline = GetResID(pipe);
// push back extra descriptor set to partial replay state
state.graphics.descSets.push_back( GetResID(m_MeshFetchDescSet) );
VkBuffer meshBuffer = VK_NULL_HANDLE, readbackBuffer = VK_NULL_HANDLE;
VkDeviceMemory meshMem = VK_NULL_HANDLE, readbackMem = VK_NULL_HANDLE;
VkBuffer idxBuf = VK_NULL_HANDLE;
VkDeviceMemory idxBufMem = VK_NULL_HANDLE;
uint32_t numVerts = drawcall->numIndices;
VkDeviceSize bufSize = 0;
if((drawcall->flags & eDraw_UseIBuffer) == 0)
{
// create buffer of sufficient size (num indices * bufStride)
VkBufferCreateInfo bufInfo = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL,
drawcall->numIndices*bufStride, 0, 0,
VK_SHARING_MODE_EXCLUSIVE, 0, NULL,
};
bufSize = bufInfo.size;
bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT;
bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT;
bufInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
bufInfo.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
vkr = m_pDriver->vkCreateBuffer(dev, &bufInfo, &meshBuffer);
RDCASSERT(vkr == VK_SUCCESS);
bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT;
vkr = m_pDriver->vkCreateBuffer(dev, &bufInfo, &readbackBuffer);
RDCASSERT(vkr == VK_SUCCESS);
VkMemoryRequirements mrq;
vkr = m_pDriver->vkGetBufferMemoryRequirements(dev, meshBuffer, &mrq);
RDCASSERT(vkr == VK_SUCCESS);
VkMemoryAllocInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL,
mrq.size,
m_pDriver->GetGPULocalMemoryIndex(mrq.memoryTypeBits),
};
vkr = m_pDriver->vkAllocMemory(dev, &allocInfo, &meshMem);
RDCASSERT(vkr == VK_SUCCESS);
vkr = m_pDriver->vkBindBufferMemory(dev, meshBuffer, meshMem, 0);
RDCASSERT(vkr == VK_SUCCESS);
vkr = m_pDriver->vkGetBufferMemoryRequirements(dev, readbackBuffer, &mrq);
RDCASSERT(vkr == VK_SUCCESS);
allocInfo.memoryTypeIndex = m_pDriver->GetReadbackMemoryIndex(mrq.memoryTypeBits);
vkr = m_pDriver->vkAllocMemory(dev, &allocInfo, &readbackMem);
RDCASSERT(vkr == VK_SUCCESS);
vkr = m_pDriver->vkBindBufferMemory(dev, readbackBuffer, readbackMem, 0);
RDCASSERT(vkr == VK_SUCCESS);
// vkUpdateDescriptorSet desc set to point to buffer
VkDescriptorInfo fetchdesc = { 0 };
fetchdesc.bufferInfo.buffer = meshBuffer;
fetchdesc.bufferInfo.offset = 0;
fetchdesc.bufferInfo.range = bufInfo.size;
VkWriteDescriptorSet write = {
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
m_MeshFetchDescSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &fetchdesc
};
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 };
vkr = ObjDisp(dev)->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERT(vkr == VK_SUCCESS);
VkBufferMemoryBarrier meshbufbarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, NULL,
VK_MEMORY_OUTPUT_SHADER_WRITE_BIT, VK_MEMORY_INPUT_TRANSFER_BIT,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
Unwrap(meshBuffer),
0, bufInfo.size,
};
void *barrierptr = (void *)&meshbufbarrier;
// wait for writing to finish
ObjDisp(dev)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrierptr);
VkBufferCopy bufcopy = {
0, 0, bufInfo.size,
};
// copy to readback buffer
ObjDisp(dev)->CmdCopyBuffer(Unwrap(cmd), Unwrap(meshBuffer), Unwrap(readbackBuffer), 1, &bufcopy);
meshbufbarrier.outputMask = VK_MEMORY_OUTPUT_TRANSFER_BIT;
meshbufbarrier.inputMask = VK_MEMORY_INPUT_HOST_READ_BIT;
meshbufbarrier.buffer = Unwrap(readbackBuffer);
// wait for copy to finish
ObjDisp(dev)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrierptr);
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
RDCASSERT(vkr == VK_SUCCESS);
// submit & flush so that we don't have to keep pipeline around for a while
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
}
else
{
VULKANNOTIMP("Fetching post-transform data for indexed draws");
// fetch ibuffer
// do ibuffer rebasing/remapping
// create buffer of sufficient size (num unique indices * bufStride)
// set numVerts and bufSize
// bind unique'd ibuffer
// create remapped ibuffer
}
// readback mesh data
byte *byteData = NULL;
vkr = m_pDriver->vkMapMemory(m_Device, readbackMem, 0, 0, 0, (void **)&byteData);
// do near/far calculations
float nearp = 0.1f;
float farp = 100.0f;
Vec4f *pos0 = (Vec4f *)byteData;
for(uint32_t i=1; i < numVerts; i++)
{
//////////////////////////////////////////////////////////////////////////////////
// derive near/far, assuming a standard perspective matrix
//
// the transformation from from pre-projection {Z,W} to post-projection {Z,W}
// is linear. So we can say Zpost = Zpre*m + c . Here we assume Wpre = 1
// and we know Wpost = Zpre from the perspective matrix.
// we can then see from the perspective matrix that
// m = F/(F-N)
// c = -(F*N)/(F-N)
//
// with re-arranging and substitution, we then get:
// N = -c/m
// F = c/(1-m)
//
// so if we can derive m and c then we can determine N and F. We can do this with
// two points, and we pick them reasonably distinct on z to reduce floating-point
// error
Vec4f *pos = (Vec4f *)(byteData + i*bufStride);
if(fabs(pos->w - pos0->w) > 0.01f)
{
Vec2f A(pos0->w, pos0->z);
Vec2f B(pos->w, pos->z);
float m = (B.y-A.y)/(B.x-A.x);
float c = B.y - B.x*m;
if(m == 1.0f) continue;
nearp = -c/m;
farp = c/(1-m);
break;
}
}
// expect position at the start of the buffer
RDCASSERT(s.refl.OutputSig[0].systemValue == eAttr_Position);
m_pDriver->vkUnmapMemory(m_Device, readbackMem);
m_pDriver->vkDestroyBuffer(m_Device, readbackBuffer);
m_pDriver->vkFreeMemory(m_Device, readbackMem);
// reset pipeline state back to normal
state = prevstate;
// fill out m_PostVSData
m_PostVSData[idx].vsin.topo = pipeCreateInfo.pInputAssemblyState->topology;
m_PostVSData[idx].vsout.topo = pipeCreateInfo.pInputAssemblyState->topology;
m_PostVSData[idx].vsout.buf = meshBuffer;
m_PostVSData[idx].vsout.bufmem = meshMem;
m_PostVSData[idx].vsout.vertStride = bufStride;
m_PostVSData[idx].vsout.nearPlane = nearp;
m_PostVSData[idx].vsout.farPlane = farp;
m_PostVSData[idx].vsout.useIndices = (drawcall->flags & eDraw_UseIBuffer) > 0;
m_PostVSData[idx].vsout.numVerts = drawcall->numIndices;
m_PostVSData[idx].vsout.instStride = 0;
if(drawcall->flags & eDraw_Instanced)
m_PostVSData[idx].vsout.instStride = uint32_t(bufSize / RDCMAX(1U, drawcall->numInstances));
m_PostVSData[idx].vsout.idxBuf = VK_NULL_HANDLE;
if(m_PostVSData[idx].vsout.useIndices && idxBuf != VK_NULL_HANDLE)
{
m_PostVSData[idx].vsout.idxBuf = idxBuf;
m_PostVSData[idx].vsout.idxBufMem = idxBufMem;
m_PostVSData[idx].vsout.idxFmt = state.ibuffer.bytewidth == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
}
// VKTODOMED set this properly
m_PostVSData[idx].vsout.hasPosOut = true;
// delete pipeline layout
m_pDriver->vkDestroyPipelineLayout(dev, pipeLayout);
// delete pipeline
m_pDriver->vkDestroyPipeline(dev, pipe);
// delete shader/shader module
m_pDriver->vkDestroyShader(dev, shad);
m_pDriver->vkDestroyShaderModule(dev, module);
}
MeshFormat VulkanDebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage)
{
VulkanPostVSData postvs;
RDCEraseEl(postvs);
auto idx = std::make_pair(frameID, eventID);
if(m_PostVSData.find(idx) != m_PostVSData.end())
postvs = m_PostVSData[idx];
VulkanPostVSData::StageData s = postvs.GetStage(stage);
MeshFormat ret;
if(s.useIndices && s.idxBuf != VK_NULL_HANDLE)
{
ret.idxbuf = GetResID(s.idxBuf);
ret.idxByteWidth = s.idxFmt == VK_INDEX_TYPE_UINT16 ? 2 : 4;
}
else
{
ret.idxbuf = ResourceId();
ret.idxByteWidth = 0;
}
ret.idxoffs = 0;
if(s.buf != VK_NULL_HANDLE)
ret.buf = GetResID(s.buf);
else
ret.buf = ResourceId();
ret.offset = s.instStride*instID;
ret.stride = s.vertStride;
ret.compCount = 4;
ret.compByteWidth = 4;
ret.compType = eCompType_Float;
ret.specialFormat = eSpecial_Unknown;
ret.showAlpha = false;
ret.topo = MakePrimitiveTopology(s.topo, 1);
ret.numVerts = s.numVerts;
ret.unproject = s.hasPosOut;
ret.nearPlane = s.nearPlane;
ret.farPlane = s.farPlane;
return ret;
}
+49
View File
@@ -54,6 +54,49 @@ struct MeshDisplayPipelines
VkPipeline pipes[ePipe_Count];
};
struct VulkanPostVSData
{
struct StageData
{
VkBuffer buf;
VkDeviceMemory bufmem;
VkPrimitiveTopology topo;
uint32_t numVerts;
uint32_t vertStride;
uint32_t instStride;
bool useIndices;
VkBuffer idxBuf;
VkDeviceMemory idxBufMem;
VkIndexType idxFmt;
bool hasPosOut;
float nearPlane;
float farPlane;
} vsin, vsout, gsout;
VulkanPostVSData()
{
RDCEraseEl(vsin);
RDCEraseEl(vsout);
RDCEraseEl(gsout);
}
const StageData &GetStage(MeshDataStage type)
{
if(type == eMeshDataStage_VSOut)
return vsout;
else if(type == eMeshDataStage_GSOut)
return gsout;
else
RDCERR("Unexpected mesh data stage!");
return vsin;
}
};
class VulkanResourceManager;
class VulkanDebugManager
@@ -69,6 +112,7 @@ class VulkanDebugManager
ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents);
void InitPostVSBuffers(uint32_t frameID, uint32_t eventID);
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage);
struct GPUBuffer
{
@@ -183,6 +227,9 @@ class VulkanDebugManager
VkDescriptorSet m_OutlineDescSet;
VkPipeline m_OutlinePipeline;
GPUBuffer m_OutlineUBO;
VkDescriptorSetLayout m_MeshFetchDescSetLayout;
VkDescriptorSet m_MeshFetchDescSet;
MeshDisplayPipelines CacheMeshDisplayPipelines(const MeshFormat &primary, const MeshFormat &secondary);
@@ -203,6 +250,8 @@ class VulkanDebugManager
float m_FontCharSize;
map<uint64_t, MeshDisplayPipelines> m_CachedMeshPipelines;
map<pair<uint32_t,uint32_t>, VulkanPostVSData> m_PostVSData;
WrappedVulkan *m_pDriver;
VulkanResourceManager *m_ResourceManager;
+1 -6
View File
@@ -3737,12 +3737,7 @@ void VulkanReplay::FreeCustomShader(ResourceId id)
MeshFormat VulkanReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage)
{
MeshFormat ret;
RDCEraseEl(ret);
VULKANNOTIMP("VulkanReplay::GetPostVSBuffers");
return ret;
return GetDebugManager()->GetPostVSBuffers(frameID, eventID, instID, stage);
}
byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize)