mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Update postvs and overlay helpers for shader object
This commit is contained in:
committed by
Baldur Karlsson
parent
205b627dd4
commit
71b8a7d600
@@ -92,6 +92,7 @@ public:
|
||||
const MeshFormat &secondary);
|
||||
|
||||
void PatchFixedColShader(VkShaderModule &mod, float col[4]);
|
||||
void PatchFixedColShaderObject(VkShaderEXT &shad, float col[4]);
|
||||
void PatchLineStripIndexBuffer(const ActionDescription *action, GPUBuffer &indexBuffer,
|
||||
uint32_t &indexCount);
|
||||
|
||||
|
||||
@@ -351,6 +351,69 @@ void VulkanDebugManager::PatchFixedColShader(VkShaderModule &mod, float col[4])
|
||||
CheckVkResult(vkr);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::PatchFixedColShaderObject(VkShaderEXT &shad, float col[4])
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t *spirv;
|
||||
float *data;
|
||||
} alias;
|
||||
|
||||
rdcarray<uint32_t> spv = *m_pDriver->GetShaderCache()->GetBuiltinBlob(BuiltinShader::FixedColFS);
|
||||
|
||||
alias.spirv = &spv[0];
|
||||
size_t spirvLength = spv.size();
|
||||
|
||||
int patched = 0;
|
||||
|
||||
size_t it = 5;
|
||||
while(it < spirvLength)
|
||||
{
|
||||
uint16_t WordCount = alias.spirv[it] >> rdcspv::WordCountShift;
|
||||
rdcspv::Op opcode = rdcspv::Op(alias.spirv[it] & rdcspv::OpCodeMask);
|
||||
|
||||
if(opcode == rdcspv::Op::Constant)
|
||||
{
|
||||
if(alias.data[it + 3] >= 1.0f && alias.data[it + 3] <= 1.5f)
|
||||
alias.data[it + 3] = col[0];
|
||||
else if(alias.data[it + 3] >= 2.0f && alias.data[it + 3] <= 2.5f)
|
||||
alias.data[it + 3] = col[1];
|
||||
else if(alias.data[it + 3] >= 3.0f && alias.data[it + 3] <= 3.5f)
|
||||
alias.data[it + 3] = col[2];
|
||||
else if(alias.data[it + 3] >= 4.0f && alias.data[it + 3] <= 4.5f)
|
||||
alias.data[it + 3] = col[3];
|
||||
else
|
||||
RDCERR("Unexpected constant value");
|
||||
|
||||
patched++;
|
||||
}
|
||||
|
||||
it += WordCount;
|
||||
}
|
||||
|
||||
if(patched != 4)
|
||||
RDCERR("Didn't patch all constants");
|
||||
|
||||
VkShaderCreateInfoEXT shadInfo = {VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
|
||||
NULL,
|
||||
0,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0,
|
||||
VK_SHADER_CODE_TYPE_SPIRV_EXT,
|
||||
spv.size() * sizeof(uint32_t),
|
||||
alias.spirv,
|
||||
"main",
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL};
|
||||
|
||||
VkResult vkr = m_pDriver->vkCreateShadersEXT(m_Device, 1, &shadInfo, NULL, &shad);
|
||||
|
||||
CheckVkResult(vkr);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::PatchLineStripIndexBuffer(const ActionDescription *action,
|
||||
GPUBuffer &indexBuffer, uint32_t &indexCount)
|
||||
{
|
||||
|
||||
@@ -2865,7 +2865,12 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
|
||||
const VulkanCreationInfo::Pipeline &pipeInfo = creationInfo.m_Pipeline[state.graphics.pipeline];
|
||||
|
||||
const VulkanCreationInfo::ShaderEntry &meshShad = pipeInfo.shaders[7];
|
||||
const VulkanCreationInfo::ShaderObject &meshShadObjInfo =
|
||||
creationInfo.m_ShaderObject[state.shaderObjects[(size_t)ShaderStage::Mesh]];
|
||||
|
||||
const VulkanCreationInfo::ShaderEntry &meshShad =
|
||||
state.graphics.shaderObject ? meshShadObjInfo.shad
|
||||
: pipeInfo.shaders[(size_t)ShaderStage::Mesh];
|
||||
|
||||
const VulkanCreationInfo::ShaderModule &meshInfo = creationInfo.m_ShaderModule[meshShad.module];
|
||||
ShaderReflection *meshrefl = meshShad.refl;
|
||||
@@ -2931,6 +2936,16 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// get pipeline create info
|
||||
m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, state.graphics.pipeline);
|
||||
|
||||
// get shader object create info for task/mesh
|
||||
VkShaderCreateInfoEXT taskCreateInfo = {}, meshCreateInfo = {};
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
m_pDriver->GetShaderCache()->MakeShaderObjectInfo(
|
||||
taskCreateInfo, state.shaderObjects[(size_t)ShaderStage::Task]);
|
||||
m_pDriver->GetShaderCache()->MakeShaderObjectInfo(
|
||||
meshCreateInfo, state.shaderObjects[(size_t)ShaderStage::Mesh]);
|
||||
}
|
||||
|
||||
uint32_t bufSpecConstant = 0;
|
||||
|
||||
bytebuf meshSpecData;
|
||||
@@ -2959,6 +2974,25 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
}
|
||||
}
|
||||
|
||||
// copy over specialization info for shader objects
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
if(meshCreateInfo.pSpecializationInfo)
|
||||
{
|
||||
meshSpecData.append((const byte *)meshCreateInfo.pSpecializationInfo->pData,
|
||||
meshCreateInfo.pSpecializationInfo->dataSize);
|
||||
meshSpecEntries.append(meshCreateInfo.pSpecializationInfo->pMapEntries,
|
||||
meshCreateInfo.pSpecializationInfo->mapEntryCount);
|
||||
}
|
||||
if(taskCreateInfo.pSpecializationInfo)
|
||||
{
|
||||
taskSpecData.append((const byte *)taskCreateInfo.pSpecializationInfo->pData,
|
||||
taskCreateInfo.pSpecializationInfo->dataSize);
|
||||
taskSpecEntries.append(taskCreateInfo.pSpecializationInfo->pMapEntries,
|
||||
taskCreateInfo.pSpecializationInfo->mapEntryCount);
|
||||
}
|
||||
}
|
||||
|
||||
// don't overlap with existing pipeline constants
|
||||
for(const VkSpecializationMapEntry &specConst : meshSpecEntries)
|
||||
bufSpecConstant = RDCMAX(bufSpecConstant, specConst.constantID + 1);
|
||||
@@ -2998,6 +3032,9 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
rdcarray<VulkanPostVSData::InstData> taskDispatchSizes;
|
||||
const uint32_t totalNumTaskGroups = totalNumMeshlets;
|
||||
|
||||
const VulkanCreationInfo::ShaderObject &taskShadObjInfo =
|
||||
creationInfo.m_ShaderObject[state.shaderObjects[(size_t)ShaderStage::Task]];
|
||||
|
||||
// if we have a task shader, we fetch both outputs together as a necessary component.
|
||||
// In order to properly pre-allocate the mesh output buffer we need to run the task shader, cache
|
||||
// all of its payloads and mesh dispatches per-group, then run a dispatch for each task group that
|
||||
@@ -3005,9 +3042,12 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// behaviour or ordering will remain consistent between both passes and still allow for the
|
||||
// allocation after we know the average case. This is necessary because with task expansion the
|
||||
// worst case buffer size could be massive
|
||||
if(pipeInfo.shaders[(size_t)ShaderStage::Task].refl)
|
||||
if(state.graphics.shaderObject ? taskShadObjInfo.shad.refl
|
||||
: pipeInfo.shaders[(size_t)ShaderStage::Task].refl)
|
||||
{
|
||||
const VulkanCreationInfo::ShaderEntry &taskShad = pipeInfo.shaders[(size_t)ShaderStage::Task];
|
||||
const VulkanCreationInfo::ShaderEntry &taskShad =
|
||||
state.graphics.shaderObject ? taskShadObjInfo.shad
|
||||
: pipeInfo.shaders[(size_t)ShaderStage::Task];
|
||||
|
||||
if(taskShad.patchData->invalidTaskPayload)
|
||||
{
|
||||
@@ -3132,7 +3172,7 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
taskSpecInfo.mapEntryCount = (uint32_t)taskSpecEntries.size();
|
||||
taskSpecInfo.pMapEntries = taskSpecEntries.data();
|
||||
|
||||
// create mesh shader with modified code
|
||||
// create task shader with modified code
|
||||
VkShaderModuleCreateInfo moduleCreateInfo = {
|
||||
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
NULL,
|
||||
@@ -3141,9 +3181,12 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
taskSpirv.data(),
|
||||
};
|
||||
|
||||
VkShaderModule taskModule;
|
||||
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleCreateInfo, NULL, &taskModule);
|
||||
CheckVkResult(vkr);
|
||||
VkShaderModule taskModule = VK_NULL_HANDLE;
|
||||
if(!state.graphics.shaderObject)
|
||||
{
|
||||
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleCreateInfo, NULL, &taskModule);
|
||||
CheckVkResult(vkr);
|
||||
}
|
||||
|
||||
for(uint32_t s = 0; s < pipeCreateInfo.stageCount; s++)
|
||||
{
|
||||
@@ -3157,9 +3200,10 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
}
|
||||
|
||||
// create new pipeline
|
||||
VkPipeline taskPipe;
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
|
||||
&taskPipe);
|
||||
VkPipeline taskPipe = VK_NULL_HANDLE;
|
||||
if(!state.graphics.shaderObject)
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
|
||||
&taskPipe);
|
||||
|
||||
// delete shader/shader module
|
||||
m_pDriver->vkDestroyShaderModule(dev, taskModule, NULL);
|
||||
@@ -3177,11 +3221,44 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
return;
|
||||
}
|
||||
|
||||
// create task shader object with modified code
|
||||
VkShaderEXT taskShader = VK_NULL_HANDLE;
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
VkShaderCreateInfoEXT shaderCreateInfo = taskCreateInfo;
|
||||
shaderCreateInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT;
|
||||
shaderCreateInfo.codeSize = taskSpirv.size() * sizeof(uint32_t);
|
||||
shaderCreateInfo.pCode = taskSpirv.data();
|
||||
|
||||
vkr = m_pDriver->vkCreateShadersEXT(m_Device, 1, &shaderCreateInfo, NULL, &taskShader);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
m_pDriver->vkFreeMemory(m_Device, taskMem, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, readbackTaskMem, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, taskBuffer, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, readbackTaskBuffer, NULL);
|
||||
|
||||
ret.meshout.status = ret.taskout.status =
|
||||
StringFormat::Fmt("Failed to create patched task shader object: %s", ToStr(vkr).c_str());
|
||||
RDCERR("%s", ret.meshout.status.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// make copy of state to draw from
|
||||
VulkanRenderState modifiedstate = state;
|
||||
|
||||
// bind created pipeline to partial replay state
|
||||
modifiedstate.graphics.pipeline = GetResID(taskPipe);
|
||||
// bind created shader object or pipeline to partial replay state
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
modifiedstate.graphics.pipeline = ResourceId();
|
||||
modifiedstate.shaderObjects[(size_t)ShaderStage::Task] = GetResID(taskShader);
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiedstate.graphics.pipeline = GetResID(taskPipe);
|
||||
}
|
||||
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
|
||||
@@ -3193,6 +3270,8 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
m_pDriver->vkDestroyBuffer(m_Device, readbackTaskBuffer, NULL);
|
||||
|
||||
m_pDriver->vkDestroyPipeline(dev, taskPipe, NULL);
|
||||
if(taskShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, taskShader, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3257,13 +3336,17 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
vkr = ObjDisp(dev)->EndCommandBuffer(Unwrap(cmd));
|
||||
CheckVkResult(vkr);
|
||||
|
||||
// submit & flush so that we don't have to keep pipeline around for a while
|
||||
// submit & flush so that we don't have to keep pipeline or shader object around for a while
|
||||
m_pDriver->SubmitCmds();
|
||||
m_pDriver->FlushQ();
|
||||
|
||||
// delete pipeline
|
||||
m_pDriver->vkDestroyPipeline(dev, taskPipe, NULL);
|
||||
|
||||
// delete task shader object
|
||||
if(taskShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, taskShader, NULL);
|
||||
|
||||
// readback task data
|
||||
const byte *taskData = NULL;
|
||||
vkr = m_pDriver->vkMapMemory(m_Device, readbackTaskMem, 0, VK_WHOLE_SIZE, 0, (void **)&taskData);
|
||||
@@ -3503,13 +3586,48 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
modSpirv.size() * sizeof(uint32_t), &modSpirv[0],
|
||||
};
|
||||
|
||||
VkShaderModule module, taskFeedModule = VK_NULL_HANDLE;
|
||||
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleCreateInfo, NULL, &module);
|
||||
CheckVkResult(vkr);
|
||||
VkShaderModule module = VK_NULL_HANDLE, taskFeedModule = VK_NULL_HANDLE;
|
||||
if(!state.graphics.shaderObject)
|
||||
{
|
||||
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleCreateInfo, NULL, &module);
|
||||
CheckVkResult(vkr);
|
||||
}
|
||||
|
||||
// create mesh shader object with modified code
|
||||
VkShaderCreateInfoEXT shaderCreateInfo = meshCreateInfo;
|
||||
VkShaderEXT taskShader = VK_NULL_HANDLE, meshShader = VK_NULL_HANDLE;
|
||||
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
shaderCreateInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT;
|
||||
shaderCreateInfo.codeSize = modSpirv.byteSize();
|
||||
shaderCreateInfo.pCode = modSpirv.data();
|
||||
shaderCreateInfo.pSpecializationInfo = &meshSpecInfo;
|
||||
|
||||
vkr = m_pDriver->vkCreateShadersEXT(dev, 1, &shaderCreateInfo, NULL, &meshShader);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
m_pDriver->vkFreeMemory(m_Device, taskMem, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, taskBuffer, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, meshBuffer, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, meshMem, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, readbackBuffer, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, readbackMem, NULL);
|
||||
|
||||
ret.meshout.status =
|
||||
StringFormat::Fmt("Failed to create patched mesh shader object: %s", ToStr(vkr).c_str());
|
||||
RDCERR("%s", ret.meshout.status.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(taskDataAddress != 0)
|
||||
{
|
||||
const VulkanCreationInfo::ShaderEntry &taskShad = pipeInfo.shaders[(size_t)ShaderStage::Task];
|
||||
// use the shader object or shader module, as applicable
|
||||
const VulkanCreationInfo::ShaderEntry &taskShad =
|
||||
state.graphics.shaderObject ? taskShadObjInfo.shad
|
||||
: pipeInfo.shaders[(size_t)ShaderStage::Task];
|
||||
|
||||
const VulkanCreationInfo::ShaderModule &taskInfo = creationInfo.m_ShaderModule[taskShad.module];
|
||||
|
||||
@@ -3521,11 +3639,41 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
if(!Vulkan_Debug_PostVSDumpDirPath().empty())
|
||||
FileIO::WriteAll(Vulkan_Debug_PostVSDumpDirPath() + "/debug_postts_feeder.spv", modSpirv);
|
||||
|
||||
moduleCreateInfo.pCode = modSpirv.data();
|
||||
moduleCreateInfo.codeSize = modSpirv.byteSize();
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
shaderCreateInfo = taskCreateInfo;
|
||||
shaderCreateInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT;
|
||||
shaderCreateInfo.codeSize = modSpirv.byteSize();
|
||||
shaderCreateInfo.pCode = modSpirv.data();
|
||||
shaderCreateInfo.pSpecializationInfo = &taskSpecInfo;
|
||||
|
||||
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleCreateInfo, NULL, &taskFeedModule);
|
||||
CheckVkResult(vkr);
|
||||
vkr = m_pDriver->vkCreateShadersEXT(dev, 1, &shaderCreateInfo, NULL, &taskShader);
|
||||
|
||||
if(vkr != VK_SUCCESS)
|
||||
{
|
||||
if(meshShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, meshShader, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, taskMem, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, taskBuffer, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, meshBuffer, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, meshMem, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, readbackBuffer, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, readbackMem, NULL);
|
||||
|
||||
ret.meshout.status =
|
||||
StringFormat::Fmt("Failed to create patched task shader object: %s", ToStr(vkr).c_str());
|
||||
RDCERR("%s", ret.meshout.status.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
moduleCreateInfo.pCode = modSpirv.data();
|
||||
moduleCreateInfo.codeSize = modSpirv.byteSize();
|
||||
|
||||
vkr = m_pDriver->vkCreateShaderModule(dev, &moduleCreateInfo, NULL, &taskFeedModule);
|
||||
CheckVkResult(vkr);
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t s = 0; s < pipeCreateInfo.stageCount; s++)
|
||||
@@ -3547,9 +3695,10 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
}
|
||||
|
||||
// create new pipeline
|
||||
VkPipeline pipe;
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
|
||||
&pipe);
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
if(!state.graphics.shaderObject)
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
|
||||
&pipe);
|
||||
|
||||
// delete shader/shader module
|
||||
m_pDriver->vkDestroyShaderModule(dev, module, NULL);
|
||||
@@ -3578,12 +3727,24 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// bind created pipeline to partial replay state
|
||||
modifiedstate.graphics.pipeline = GetResID(pipe);
|
||||
|
||||
// bind task/mesh to partial replay state if using shader objects
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
modifiedstate.graphics.pipeline = ResourceId();
|
||||
modifiedstate.shaderObjects[(size_t)ShaderStage::Task] = GetResID(taskShader);
|
||||
modifiedstate.shaderObjects[(size_t)ShaderStage::Mesh] = GetResID(meshShader);
|
||||
}
|
||||
|
||||
if(totalNumMeshlets > 0)
|
||||
{
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
|
||||
if(cmd == VK_NULL_HANDLE)
|
||||
{
|
||||
if(taskShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, taskShader, NULL);
|
||||
if(meshShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, meshShader, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, pipe, NULL);
|
||||
m_pDriver->vkFreeMemory(m_Device, taskMem, NULL);
|
||||
m_pDriver->vkDestroyBuffer(m_Device, taskBuffer, NULL);
|
||||
@@ -3663,6 +3824,12 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// delete pipeline
|
||||
m_pDriver->vkDestroyPipeline(dev, pipe, NULL);
|
||||
|
||||
// delete task/mesh shader objects
|
||||
if(taskShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, taskShader, NULL);
|
||||
if(meshShader != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, meshShader, NULL);
|
||||
|
||||
rdcarray<VulkanPostVSData::InstData> meshletOffsets;
|
||||
|
||||
uint32_t baseIndex = 0;
|
||||
@@ -4001,7 +4168,8 @@ void VulkanReplay::FetchMeshOut(uint32_t eventId, VulkanRenderState &state)
|
||||
ret.taskout.buf = taskBuffer;
|
||||
ret.taskout.bufmem = taskMem;
|
||||
|
||||
if(!pipeInfo.shaders[6].refl)
|
||||
if(state.graphics.shaderObject ? !taskShadObjInfo.shad.refl
|
||||
: !pipeInfo.shaders[(size_t)ShaderStage::Task].refl)
|
||||
ret.taskout.status = "No task shader bound";
|
||||
|
||||
ret.taskout.baseVertex = 0;
|
||||
@@ -4072,10 +4240,15 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
|
||||
const ActionDescription *action = m_pDriver->GetAction(eventId);
|
||||
|
||||
const VulkanCreationInfo::ShaderModule &moduleInfo =
|
||||
creationInfo.m_ShaderModule[pipeInfo.shaders[0].module];
|
||||
const VulkanCreationInfo::ShaderObject &shadObjInfo =
|
||||
creationInfo.m_ShaderObject[state.shaderObjects[(size_t)ShaderStage::Vertex]];
|
||||
|
||||
ShaderReflection *refl = pipeInfo.shaders[0].refl;
|
||||
const VulkanCreationInfo::ShaderEntry &vertShad =
|
||||
state.graphics.shaderObject ? shadObjInfo.shad : pipeInfo.shaders[(size_t)ShaderStage::Vertex];
|
||||
|
||||
const VulkanCreationInfo::ShaderModule &moduleInfo = creationInfo.m_ShaderModule[vertShad.module];
|
||||
|
||||
ShaderReflection *refl = vertShad.refl;
|
||||
|
||||
VulkanPostVSData &ret = m_PostVS.Data[eventId];
|
||||
|
||||
@@ -4198,7 +4371,8 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
VkPushConstantRange push;
|
||||
uint32_t numPush = 0;
|
||||
rdcarray<VkPushConstantRange> oldPush =
|
||||
creationInfo.m_PipelineLayout[pipeInfo.vertLayout].pushRanges;
|
||||
state.graphics.shaderObject ? shadObjInfo.pushRanges
|
||||
: creationInfo.m_PipelineLayout[pipeInfo.vertLayout].pushRanges;
|
||||
|
||||
// ensure the push range is visible to the compute shader
|
||||
for(const VkPushConstantRange &range : oldPush)
|
||||
@@ -4250,7 +4424,9 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// present wherever VERTEX_BIT was, so we can use the application's descriptor sets and layouts
|
||||
|
||||
const rdcarray<ResourceId> &sets =
|
||||
creationInfo.m_PipelineLayout[pipeInfo.vertLayout].descSetLayouts;
|
||||
state.graphics.shaderObject
|
||||
? shadObjInfo.descSetLayouts
|
||||
: creationInfo.m_PipelineLayout[pipeInfo.vertLayout].descSetLayouts;
|
||||
|
||||
setLayouts.reserve(sets.size());
|
||||
|
||||
@@ -4617,22 +4793,37 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// get pipeline create info
|
||||
m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, state.graphics.pipeline);
|
||||
|
||||
VkShaderCreateInfoEXT shaderCreateInfo;
|
||||
|
||||
// get shader object create info
|
||||
m_pDriver->GetShaderCache()->MakeShaderObjectInfo(
|
||||
shaderCreateInfo, state.shaderObjects[(size_t)ShaderStage::Vertex]);
|
||||
|
||||
// copy over specialization info
|
||||
for(uint32_t s = 0; s < pipeCreateInfo.stageCount; s++)
|
||||
const VkSpecializationInfo *prevSpecInfo = NULL;
|
||||
|
||||
if(state.graphics.shaderObject)
|
||||
{
|
||||
if(pipeCreateInfo.pStages[s].stage == VK_SHADER_STAGE_VERTEX_BIT)
|
||||
prevSpecInfo = shaderCreateInfo.pSpecializationInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t s = 0; s < pipeCreateInfo.stageCount; s++)
|
||||
{
|
||||
if(pipeCreateInfo.pStages[s].pSpecializationInfo)
|
||||
if(pipeCreateInfo.pStages[s].stage == VK_SHADER_STAGE_VERTEX_BIT)
|
||||
{
|
||||
specData.assign((const byte *)pipeCreateInfo.pStages[s].pSpecializationInfo->pData,
|
||||
pipeCreateInfo.pStages[s].pSpecializationInfo->dataSize);
|
||||
specEntries.assign(pipeCreateInfo.pStages[s].pSpecializationInfo->pMapEntries,
|
||||
pipeCreateInfo.pStages[s].pSpecializationInfo->mapEntryCount);
|
||||
prevSpecInfo = pipeCreateInfo.pStages[s].pSpecializationInfo;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(prevSpecInfo)
|
||||
{
|
||||
specData.assign((const byte *)prevSpecInfo->pData, prevSpecInfo->dataSize);
|
||||
specEntries.assign(prevSpecInfo->pMapEntries, prevSpecInfo->mapEntryCount);
|
||||
}
|
||||
|
||||
// don't overlap with existing pipeline constants
|
||||
for(const VkSpecializationMapEntry &specConst : specEntries)
|
||||
baseSpecConstant = RDCMAX(baseSpecConstant, specConst.constantID + 1);
|
||||
@@ -5032,9 +5223,9 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
if(!Vulkan_Debug_PostVSDumpDirPath().empty())
|
||||
FileIO::WriteAll(Vulkan_Debug_PostVSDumpDirPath() + "/debug_postvs_vert.spv", modSpirv);
|
||||
|
||||
ConvertToMeshOutputCompute(*refl, *pipeInfo.shaders[0].patchData, pipeInfo.shaders[0].entryPoint,
|
||||
storageMode, attrInstDivisor, action, numVerts, numViews,
|
||||
baseSpecConstant, modSpirv, bufStride);
|
||||
ConvertToMeshOutputCompute(*refl, *vertShad.patchData, vertShad.entryPoint, storageMode,
|
||||
attrInstDivisor, action, numVerts, numViews, baseSpecConstant,
|
||||
modSpirv, bufStride);
|
||||
|
||||
if(!Vulkan_Debug_PostVSDumpDirPath().empty())
|
||||
FileIO::WriteAll(Vulkan_Debug_PostVSDumpDirPath() + "/debug_postvs_comp.spv", modSpirv);
|
||||
@@ -5513,14 +5704,22 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
int stageIndex = 3;
|
||||
|
||||
// if there is no such shader bound, try tessellation
|
||||
if(!pipeInfo.shaders[stageIndex].refl)
|
||||
if(state.graphics.shaderObject
|
||||
? !creationInfo.m_ShaderObject[state.shaderObjects[stageIndex]].shad.refl
|
||||
: !pipeInfo.shaders[stageIndex].refl)
|
||||
stageIndex = 2;
|
||||
|
||||
// if still nothing, do vertex
|
||||
if(!pipeInfo.shaders[stageIndex].refl)
|
||||
if(state.graphics.shaderObject
|
||||
? !creationInfo.m_ShaderObject[state.shaderObjects[stageIndex]].shad.refl
|
||||
: !pipeInfo.shaders[stageIndex].refl)
|
||||
stageIndex = 0;
|
||||
|
||||
ShaderReflection *lastRefl = pipeInfo.shaders[stageIndex].refl;
|
||||
const VulkanCreationInfo::ShaderEntry &shader =
|
||||
state.graphics.shaderObject ? creationInfo.m_ShaderObject[state.shaderObjects[stageIndex]].shad
|
||||
: pipeInfo.shaders[stageIndex];
|
||||
|
||||
ShaderReflection *lastRefl = shader.refl;
|
||||
|
||||
RDCASSERT(lastRefl);
|
||||
|
||||
@@ -5571,8 +5770,7 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
return;
|
||||
}
|
||||
|
||||
const VulkanCreationInfo::ShaderModule &moduleInfo =
|
||||
creationInfo.m_ShaderModule[pipeInfo.shaders[stageIndex].module];
|
||||
const VulkanCreationInfo::ShaderModule &moduleInfo = creationInfo.m_ShaderModule[shader.module];
|
||||
|
||||
rdcarray<uint32_t> modSpirv = moduleInfo.spirv.GetSPIRV();
|
||||
|
||||
@@ -5582,8 +5780,8 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
FileIO::WriteAll(Vulkan_Debug_PostVSDumpDirPath() + "/debug_postgs_before.spv", modSpirv);
|
||||
|
||||
// adds XFB annotations in order of the output signature (with the position first)
|
||||
AddXFBAnnotations(*lastRefl, *pipeInfo.shaders[stageIndex].patchData, pipeInfo.rasterizationStream,
|
||||
pipeInfo.shaders[stageIndex].entryPoint.c_str(), modSpirv, xfbStride);
|
||||
AddXFBAnnotations(*lastRefl, *shader.patchData, pipeInfo.rasterizationStream,
|
||||
shader.entryPoint.c_str(), modSpirv, xfbStride);
|
||||
|
||||
if(!Vulkan_Debug_PostVSDumpDirPath().empty())
|
||||
FileIO::WriteAll(Vulkan_Debug_PostVSDumpDirPath() + "/debug_postgs_after.spv", modSpirv);
|
||||
@@ -5606,9 +5804,19 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
// get pipeline create info
|
||||
m_pDriver->GetShaderCache()->MakeGraphicsPipelineInfo(pipeCreateInfo, state.graphics.pipeline);
|
||||
|
||||
VkShaderCreateInfoEXT shaderObjectCreateInfo;
|
||||
|
||||
// get shader object create info
|
||||
m_pDriver->GetShaderCache()->MakeShaderObjectInfo(shaderObjectCreateInfo,
|
||||
state.shaderObjects[stageIndex]);
|
||||
|
||||
shaderObjectCreateInfo.codeSize = modSpirv.size() * sizeof(uint32_t);
|
||||
shaderObjectCreateInfo.pCode = &modSpirv[0];
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo *rs =
|
||||
(VkPipelineRasterizationStateCreateInfo *)pipeCreateInfo.pRasterizationState;
|
||||
rs->rasterizerDiscardEnable = true;
|
||||
if(rs)
|
||||
rs->rasterizerDiscardEnable = true;
|
||||
|
||||
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
|
||||
{
|
||||
@@ -5648,11 +5856,22 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
RemoveNextStruct(&pipeCreateInfo, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO);
|
||||
|
||||
VkPipeline pipe = VK_NULL_HANDLE;
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
|
||||
&pipe);
|
||||
VkShaderEXT shad = VK_NULL_HANDLE;
|
||||
|
||||
if(state.graphics.shaderObject)
|
||||
vkr = m_pDriver->vkCreateShadersEXT(m_Device, 1, &shaderObjectCreateInfo, NULL, &shad);
|
||||
else
|
||||
vkr = m_pDriver->vkCreateGraphicsPipelines(m_Device, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL,
|
||||
&pipe);
|
||||
|
||||
CheckVkResult(vkr);
|
||||
|
||||
state.graphics.pipeline = GetResID(pipe);
|
||||
if(state.graphics.shaderObject)
|
||||
state.shaderObjects[stageIndex] = GetResID(shad);
|
||||
else
|
||||
state.graphics.pipeline = GetResID(pipe);
|
||||
|
||||
state.rastDiscardEnable = true;
|
||||
state.SetFramebuffer(m_pDriver, GetResID(fb));
|
||||
state.SetRenderPass(GetResID(rp));
|
||||
state.dynamicRendering = VulkanRenderState::DynamicRendering();
|
||||
@@ -5997,6 +6216,10 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state)
|
||||
m_pDriver->vkDestroyFramebuffer(dev, fb, NULL);
|
||||
m_pDriver->vkDestroyRenderPass(dev, rp, NULL);
|
||||
|
||||
// delete shader object
|
||||
if(shad != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyShaderEXT(dev, shad, NULL);
|
||||
|
||||
// delete pipeline
|
||||
m_pDriver->vkDestroyPipeline(dev, pipe, NULL);
|
||||
|
||||
@@ -6020,7 +6243,7 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId, VulkanRenderState state)
|
||||
|
||||
VulkanPostVSData &ret = m_PostVS.Data[eventId];
|
||||
|
||||
if(state.graphics.pipeline == ResourceId() ||
|
||||
if((state.graphics.pipeline == ResourceId() && !state.graphics.shaderObject) ||
|
||||
(state.GetRenderPass() == ResourceId() && !state.dynamicRendering.active))
|
||||
{
|
||||
ret.gsout.status = ret.vsout.status = "Draw outside of renderpass";
|
||||
@@ -6029,7 +6252,15 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId, VulkanRenderState state)
|
||||
|
||||
const VulkanCreationInfo::Pipeline &pipeInfo = creationInfo.m_Pipeline[state.graphics.pipeline];
|
||||
|
||||
if(pipeInfo.shaders[size_t(ShaderStage::Vertex)].module == ResourceId() &&
|
||||
if(state.graphics.shaderObject && state.shaderObjects[size_t(ShaderStage::Vertex)] == ResourceId() &&
|
||||
state.shaderObjects[size_t(ShaderStage::Mesh)] == ResourceId())
|
||||
{
|
||||
ret.gsout.status = ret.vsout.status = "No vertex or mesh shader object";
|
||||
return;
|
||||
}
|
||||
|
||||
if(!state.graphics.shaderObject &&
|
||||
pipeInfo.shaders[size_t(ShaderStage::Vertex)].module == ResourceId() &&
|
||||
pipeInfo.shaders[size_t(ShaderStage::Mesh)].module == ResourceId())
|
||||
{
|
||||
ret.gsout.status = ret.vsout.status = "No vertex or mesh shader in pipeline";
|
||||
@@ -6068,8 +6299,17 @@ void VulkanReplay::InitPostVSBuffers(uint32_t eventId, VulkanRenderState state)
|
||||
|
||||
VkMarkerRegion::End();
|
||||
|
||||
bool noTessGS = false;
|
||||
|
||||
if(state.graphics.shaderObject)
|
||||
noTessGS = state.shaderObjects[size_t(ShaderStage::Tess_Eval)] == ResourceId() &&
|
||||
state.shaderObjects[size_t(ShaderStage::Geometry)] == ResourceId();
|
||||
else
|
||||
noTessGS = pipeInfo.shaders[size_t(ShaderStage::Tess_Eval)].module == ResourceId() &&
|
||||
pipeInfo.shaders[size_t(ShaderStage::Geometry)].module == ResourceId();
|
||||
|
||||
// if there's no tessellation or geometry shader active, bail out now
|
||||
if(pipeInfo.shaders[2].module == ResourceId() && pipeInfo.shaders[3].module == ResourceId())
|
||||
if(noTessGS)
|
||||
{
|
||||
ret.gsout.status = "No geometry and no tessellation shader bound.";
|
||||
return;
|
||||
|
||||
@@ -544,6 +544,13 @@ void VulkanShaderCache::SetPipeCacheBlob(bytebuf &blob)
|
||||
void VulkanShaderCache::MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &pipeCreateInfo,
|
||||
ResourceId pipeline)
|
||||
{
|
||||
// skip if invalid pipeline
|
||||
if(pipeline == ResourceId())
|
||||
{
|
||||
RDCEraseEl(pipeCreateInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
const VulkanCreationInfo::Pipeline &pipeInfo = m_pDriver->m_CreationInfo.m_Pipeline[pipeline];
|
||||
|
||||
VulkanResourceManager *rm = m_pDriver->GetResourceManager();
|
||||
@@ -1105,3 +1112,84 @@ void VulkanShaderCache::MakeComputePipelineInfo(VkComputePipelineCreateInfo &pip
|
||||
|
||||
pipeCreateInfo = ret;
|
||||
}
|
||||
|
||||
void VulkanShaderCache::MakeShaderObjectInfo(VkShaderCreateInfoEXT &shadCreateInfo,
|
||||
ResourceId shaderObj)
|
||||
{
|
||||
// skip if invalid shader object
|
||||
if(shaderObj == ResourceId())
|
||||
{
|
||||
RDCEraseEl(shadCreateInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
const VulkanCreationInfo::ShaderObject &shadInfo =
|
||||
m_pDriver->m_CreationInfo.m_ShaderObject[shaderObj];
|
||||
|
||||
const VulkanCreationInfo::ShaderModule &moduleInfo =
|
||||
m_pDriver->m_CreationInfo.m_ShaderModule[shadInfo.shad.module];
|
||||
const rdcarray<uint32_t> &modSpirv = moduleInfo.spirv.GetSPIRV();
|
||||
|
||||
VulkanResourceManager *rm = m_pDriver->GetResourceManager();
|
||||
|
||||
static VkSpecializationInfo specInfo;
|
||||
static rdcarray<VkSpecializationMapEntry> specMapEntries;
|
||||
|
||||
// the specialization constants can't use more than a uint64_t, so we just over-allocate
|
||||
static rdcarray<uint64_t> specdata;
|
||||
|
||||
size_t specEntries = shadInfo.shad.specialization.size();
|
||||
|
||||
specdata.resize(specEntries);
|
||||
specMapEntries.resize(specEntries);
|
||||
VkSpecializationMapEntry *entry = specMapEntries.data();
|
||||
|
||||
uint32_t stage = (uint32_t)shadInfo.shad.stage;
|
||||
|
||||
static rdcarray<VkDescriptorSetLayout> descSetLayouts;
|
||||
descSetLayouts = {};
|
||||
|
||||
for(ResourceId setLayout : shadInfo.descSetLayouts)
|
||||
descSetLayouts.push_back(rm->GetCurrentHandle<VkDescriptorSetLayout>(setLayout));
|
||||
|
||||
VkShaderCreateInfoEXT ret = {VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
|
||||
NULL,
|
||||
shadInfo.flags,
|
||||
(VkShaderStageFlagBits)(1 << stage),
|
||||
shadInfo.nextStage,
|
||||
VK_SHADER_CODE_TYPE_SPIRV_EXT,
|
||||
modSpirv.size() * sizeof(uint32_t),
|
||||
modSpirv.data(),
|
||||
shadInfo.shad.entryPoint.c_str(),
|
||||
(uint32_t)descSetLayouts.size(),
|
||||
descSetLayouts.data(),
|
||||
(uint32_t)shadInfo.pushRanges.size(),
|
||||
shadInfo.pushRanges.data(),
|
||||
NULL};
|
||||
|
||||
// specialization info
|
||||
uint32_t dataOffset = 0;
|
||||
|
||||
if(!shadInfo.shad.specialization.empty())
|
||||
{
|
||||
ret.pSpecializationInfo = &specInfo;
|
||||
specInfo.pMapEntries = entry;
|
||||
specInfo.mapEntryCount = (uint32_t)shadInfo.shad.specialization.size();
|
||||
|
||||
for(size_t s = 0; s < shadInfo.shad.specialization.size(); s++)
|
||||
{
|
||||
entry[s].constantID = shadInfo.shad.specialization[s].specID;
|
||||
entry[s].size = shadInfo.shad.specialization[s].dataSize;
|
||||
entry[s].offset = dataOffset * sizeof(uint64_t);
|
||||
|
||||
specdata[dataOffset] = shadInfo.shad.specialization[s].value;
|
||||
|
||||
dataOffset++;
|
||||
}
|
||||
|
||||
specInfo.dataSize = specdata.size() * sizeof(uint64_t);
|
||||
specInfo.pData = specdata.data();
|
||||
}
|
||||
|
||||
shadCreateInfo = ret;
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ public:
|
||||
VkPipelineCache GetPipeCache() { return m_PipelineCache; }
|
||||
void MakeGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo &pipeCreateInfo, ResourceId pipeline);
|
||||
void MakeComputePipelineInfo(VkComputePipelineCreateInfo &pipeCreateInfo, ResourceId pipeline);
|
||||
void MakeShaderObjectInfo(VkShaderCreateInfoEXT &shadCreateInfo, ResourceId shader);
|
||||
|
||||
bool IsBuffer2MSSupported() { return m_Buffer2MSSupported; }
|
||||
void SetCaching(bool enabled) { m_CacheShaders = enabled; }
|
||||
|
||||
Reference in New Issue
Block a user