diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index b22f3c1c8..56f22ce8c 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -951,6 +951,7 @@ struct DrawcallDescription baseVertex = 0; vertexOffset = 0; instanceOffset = 0; + drawIndex = 0; dispatchDimension[0] = dispatchDimension[1] = dispatchDimension[2] = 0; dispatchThreadsDimension[0] = dispatchThreadsDimension[1] = dispatchThreadsDimension[2] = 0; @@ -1010,6 +1011,12 @@ struct DrawcallDescription "For instanced drawcalls, the offset applied before looking up instanced vertex inputs."); uint32_t instanceOffset; + DOCUMENT(R"(The index of this draw in an call with multiple draws, e.g. an indirect draw. + +0 if not part of a multi-draw. +)"); + uint32_t drawIndex; + DOCUMENT("The 3D number of workgroups to dispatch in a dispatch call."); uint32_t dispatchDimension[3]; diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 17d8d664a..7288ff81f 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -702,6 +702,20 @@ to apply to multiple related things - see :data:`ClipDistance`, :data:`CullDista be less than or equal to the original depth produced by the rasterizer. Related to :data:`DepthOutputGreaterEqual` and :data:`DepthOutput`. + +.. data:: BaseVertex + + The first vertex processed in this draw, as specified by the ``firstVertex`` / ``baseVertex`` + parameter to the draw call. + +.. data:: BaseInstance + + The first instance processed in this draw call, as specified by the ``firstInstance`` parameter. + +.. data:: DrawIndex + + For indirect or multi-draw commands, the index of this draw call within the overall draw command. + )"); enum class ShaderBuiltin : uint32_t { @@ -735,6 +749,9 @@ enum class ShaderBuiltin : uint32_t DepthOutput, DepthOutputGreaterEqual, DepthOutputLessEqual, + BaseVertex, + BaseInstance, + DrawIndex, Count, }; diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index 27baded10..9b102d1b0 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -3423,6 +3423,7 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in D3D12_DRAW_ARGUMENTS *args = (D3D12_DRAW_ARGUMENTS *)data; data += sizeof(D3D12_DRAW_ARGUMENTS); + curDraw.drawIndex = a; curDraw.numIndices = args->VertexCountPerInstance; curDraw.numInstances = args->InstanceCount; curDraw.vertexOffset = args->StartVertexLocation; @@ -3463,6 +3464,7 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in D3D12_DRAW_INDEXED_ARGUMENTS *args = (D3D12_DRAW_INDEXED_ARGUMENTS *)data; data += sizeof(D3D12_DRAW_INDEXED_ARGUMENTS); + curDraw.drawIndex = a; curDraw.numIndices = args->IndexCountPerInstance; curDraw.numInstances = args->InstanceCount; curDraw.baseVertex = args->BaseVertexLocation; diff --git a/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp index 3de5f0e0c..bd7c9d00a 100644 --- a/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp @@ -1933,6 +1933,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArrays(SerialiserType &ser, GLenum mode m_CurEventID++; DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = count[i]; multidraw.vertexOffset = first[i]; @@ -2080,6 +2081,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawElements(SerialiserType &ser, GLenum mo m_CurEventID++; DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = count[i]; multidraw.indexOffset = (uint32_t)(indices[i] & 0xFFFFFFFF); multidraw.indexByteWidth = IdxSize; @@ -2232,6 +2234,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsBaseVertex(SerialiserType &ser, m_CurEventID++; DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = count[i]; multidraw.indexOffset = (uint32_t)(indices[i] & 0xFFFFFFFF); multidraw.baseVertex = basevertex[i]; @@ -2389,6 +2392,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirect(SerialiserType &ser, GLe offs += sizeof(params); DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = params.count; multidraw.numInstances = params.instanceCount; multidraw.vertexOffset = params.first; @@ -2582,6 +2586,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirect(SerialiserType &ser, G offs += sizeof(params); DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = params.count; multidraw.numInstances = params.instanceCount; multidraw.indexOffset = params.firstIndex; @@ -2783,6 +2788,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirectCountARB(SerialiserType & offs += sizeof(params); DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = params.count; multidraw.numInstances = params.instanceCount; multidraw.vertexOffset = params.first; @@ -2986,6 +2992,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirectCountARB(SerialiserType offs += sizeof(params); DrawcallDescription multidraw; + multidraw.drawIndex = i; multidraw.numIndices = params.count; multidraw.numInstances = params.instanceCount; multidraw.indexOffset = params.firstIndex; diff --git a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp index b67e6d545..325e10d5f 100644 --- a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp @@ -3678,6 +3678,9 @@ ShaderBuiltin BuiltInToSystemAttribute(ShaderStage stage, const spv::BuiltIn el) case spv::BuiltInFragDepth: return ShaderBuiltin::DepthOutput; case spv::BuiltInVertexIndex: return ShaderBuiltin::VertexIndex; case spv::BuiltInInstanceIndex: return ShaderBuiltin::InstanceIndex; + case spv::BuiltInBaseVertex: return ShaderBuiltin::BaseVertex; + case spv::BuiltInBaseInstance: return ShaderBuiltin::BaseInstance; + case spv::BuiltInDrawIndex: return ShaderBuiltin::DrawIndex; default: break; } @@ -4432,6 +4435,37 @@ void SPVModule::MakeReflection(ShaderStage stage, const string &entryPoint, cblocks.push_back(cblockpair(bindmap, cblock)); } + // look for execution modes that affect the reflection and apply them + for(SPVInstruction *inst : entries) + { + if(inst->entry && inst->entry->name == entryPoint) + { + for(const SPVExecutionMode &mode : inst->entry->modes) + { + if(mode.mode == spv::ExecutionModeDepthGreater) + { + for(SigParameter &sig : outputs) + { + if(sig.systemValue == ShaderBuiltin::DepthOutput) + sig.systemValue = ShaderBuiltin::DepthOutputGreaterEqual; + } + break; + } + if(mode.mode == spv::ExecutionModeDepthLess) + { + for(SigParameter &sig : outputs) + { + if(sig.systemValue == ShaderBuiltin::DepthOutput) + sig.systemValue = ShaderBuiltin::DepthOutputLessEqual; + } + break; + } + } + + break; + } + } + // sort system value semantics to the start of the list struct sig_param_sort { diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 4b67e9629..00f368b2c 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -818,6 +818,29 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, instIndex})); } + else if(builtin == ShaderBuiltin::BaseVertex) + { + if(draw->flags & DrawFlags::UseIBuffer) + ops.push_back(SPIRVOperation( + spv::OpStore, {ins[i].variableID, editor.AddConstantImmediate( + int32_t(draw->vertexOffset & 0x7fffffff))})); + else + ops.push_back(SPIRVOperation( + spv::OpStore, {ins[i].variableID, + editor.AddConstantImmediate(int32_t(draw->baseVertex & 0x7fffffff))})); + } + else if(builtin == ShaderBuiltin::BaseInstance) + { + ops.push_back(SPIRVOperation( + spv::OpStore, {ins[i].variableID, editor.AddConstantImmediate( + int32_t(draw->instanceOffset & 0x7fffffff))})); + } + else if(builtin == ShaderBuiltin::DrawIndex) + { + ops.push_back(SPIRVOperation( + spv::OpStore, {ins[i].variableID, + editor.AddConstantImmediate(int32_t(draw->drawIndex & 0x7fffffff))})); + } else if(builtin != ShaderBuiltin::Undefined) { RDCERR("Unsupported/unsupported built-in input %s", ToStr(builtin).c_str()); diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index 3477b14b5..cfdce96a7 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -483,6 +483,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndirect(SerialiserType &ser, VkCommandBu multi.numInstances = params.instanceCount; multi.vertexOffset = params.firstVertex; multi.instanceOffset = params.firstInstance; + multi.drawIndex = i; multi.name = "vkCmdDrawIndirect[" + ToStr(i) + "](<" + ToStr(multi.numIndices) + ", " + ToStr(multi.numInstances) + ">)"; @@ -800,6 +801,7 @@ bool WrappedVulkan::Serialise_vkCmdDrawIndexedIndirect(SerialiserType &ser, multi.vertexOffset = params.vertexOffset; multi.indexOffset = params.firstIndex; multi.instanceOffset = params.firstInstance; + multi.drawIndex = i; multi.name = "vkCmdDrawIndexedIndirect[" + ToStr(i) + "](<" + ToStr(multi.numIndices) + ", " + ToStr(multi.numInstances) + ">)"; diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index de5f8045e..a7f106a5a 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -480,6 +480,7 @@ void DoSerialise(SerialiserType &ser, DrawcallDescription &el) SERIALISE_MEMBER(indexOffset); SERIALISE_MEMBER(vertexOffset); SERIALISE_MEMBER(instanceOffset); + SERIALISE_MEMBER(drawIndex); SERIALISE_MEMBER(dispatchDimension); SERIALISE_MEMBER(dispatchThreadsDimension); @@ -501,7 +502,7 @@ void DoSerialise(SerialiserType &ser, DrawcallDescription &el) SERIALISE_MEMBER(events); SERIALISE_MEMBER(children); - SIZE_CHECK(256); + SIZE_CHECK(264); } template