diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp index 21b76b071..3668e7492 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp @@ -468,6 +468,21 @@ StructSizes CalculateStructProps(uint32_t emptyStructSize, const ShaderConstant return ret; } +void CalculateScalarLayout(uint32_t offset, rdcarray &consts) +{ + for(size_t i = 0; i < consts.size(); i++) + { + consts[i].byteOffset = offset; + + CalculateScalarLayout(offset, consts[i].type.members); + + StructSizes sizes = CalculateStructProps(1, consts[i]); + if(consts[i].type.elements > 1) + consts[i].type.arrayByteStride = sizes.scalarSize / consts[i].type.elements; + offset += sizes.scalarSize; + } +} + namespace rdcspv { Reflector::Reflector() @@ -857,7 +872,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st } // pick up execution mode size - if(stage == ShaderStage::Compute) + if(stage == ShaderStage::Compute || stage == ShaderStage::Task || stage == ShaderStage::Mesh) { const EntryPoint &e = *entry; @@ -1082,6 +1097,9 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st // $Globals gathering - for GL global values ConstantBlock globalsblock; + // for mesh shaders, the task-mesh communication payload + ConstantBlock taskPayloadBlock; + // specialisation constant gathering ConstantBlock specblock; @@ -1222,7 +1240,8 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st global.storage == StorageClass::UniformConstant || global.storage == StorageClass::AtomicCounter || global.storage == StorageClass::StorageBuffer || - global.storage == StorageClass::PushConstant) + global.storage == StorageClass::PushConstant || + global.storage == StorageClass::TaskPayloadWorkgroupEXT) { // variable type must be a pointer of the same storage class RDCASSERT(dataTypes[global.type].type == DataType::PointerType); @@ -1250,6 +1269,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st (decorations[varType->id].flags & Decorations::BufferBlock); const bool pushConst = (global.storage == StorageClass::PushConstant); const bool atomicCounter = (global.storage == StorageClass::AtomicCounter); + const bool taskPayload = (global.storage == StorageClass::TaskPayloadWorkgroupEXT); rdcspv::StorageClass effectiveStorage = global.storage; if(ssbo) @@ -1392,6 +1412,18 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st globalsblock.variables.push_back(constant); } + else if(taskPayload) + { + taskPayloadBlock.name = strings[global.id]; + if(taskPayloadBlock.name.empty()) + taskPayloadBlock.name = StringFormat::Fmt("payload%u", global.id.value()); + taskPayloadBlock.bufferBacked = false; + + MakeConstantBlockVariables(effectiveStorage, *varType, 0, 0, taskPayloadBlock.variables, + pointerTypes, specInfo); + + CalculateScalarLayout(0, taskPayloadBlock.variables); + } else { // on Vulkan should never have elements that have no binding declared but are used, unless @@ -1513,6 +1545,8 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st cblocks.push_back(cblockpair(bindmap, globalsblock)); } + reflection.taskPayload = taskPayloadBlock; + // look for execution modes that affect the reflection and apply them { const EntryPoint &e = *entry; @@ -1534,7 +1568,14 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st } } - patchData.outTopo = e.executionModes.outTopo; + reflection.outputTopology = e.executionModes.outTopo; + + if(e.executionModes.others.contains(rdcspv::ExecutionMode::OutputPoints)) + reflection.outputTopology = Topology::PointList; + else if(e.executionModes.others.contains(rdcspv::ExecutionMode::OutputLinesEXT)) + reflection.outputTopology = Topology::LineList; + else if(e.executionModes.others.contains(rdcspv::ExecutionMode::OutputTrianglesEXT)) + reflection.outputTopology = Topology::TriangleList; } for(auto it = extSets.begin(); it != extSets.end(); it++) diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.h b/renderdoc/driver/shaders/spirv/spirv_reflect.h index c72b70cba..d7babb5c4 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.h +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.h @@ -72,9 +72,6 @@ struct SPIRVPatchData // for mesh shaders, the maximum number of vertices/primitives generated by each meshlet uint32_t maxVertices = 0, maxPrimitives = 0; - // the output topology for tessellation and geometry shaders - Topology outTopo = Topology::Unknown; - bool usesPrintf = false; }; diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index f5010040f..01305d77d 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -2990,7 +2990,7 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state) uint32_t primitiveMultiplier = 1; // transform feedback expands strips to lists - switch(pipeInfo.shaders[stageIndex].patchData->outTopo) + switch(lastRefl->outputTopology) { case Topology::PointList: ret.gsout.topo = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; break; case Topology::LineList: @@ -2999,8 +2999,7 @@ void VulkanReplay::FetchTessGSOut(uint32_t eventId, VulkanRenderState &state) primitiveMultiplier = 2; break; default: - RDCERR("Unexpected output topology %s", - ToStr(pipeInfo.shaders[stageIndex].patchData->outTopo).c_str()); + RDCERR("Unexpected output topology %s", ToStr(lastRefl->outputTopology).c_str()); DELIBERATE_FALLTHROUGH(); case Topology::TriangleList: case Topology::TriangleStrip: