From 785e9a98fc5355eb906875f5d0d6e73fc9d31009 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 13 Nov 2018 15:45:51 +0000 Subject: [PATCH] Handle unsigned and signed variants for vertex builtins. Refs #1166 --- renderdoc/driver/vulkan/vk_postvs.cpp | 188 ++++++++++++++------------ 1 file changed, 99 insertions(+), 89 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index aa1b5bd41..a94936e85 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -524,9 +524,9 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } SPIRVId outBufferVarID = 0; - SPIRVId numVertsConstID = editor.AddConstantImmediate((int32_t)numVerts); - SPIRVId numInstConstID = editor.AddConstantImmediate((int32_t)draw->numInstances); - SPIRVId numViewsConstID = editor.AddConstantImmediate((int32_t)numViews); + SPIRVId numVertsConstID = editor.AddConstantImmediate(numVerts); + SPIRVId numInstConstID = editor.AddConstantImmediate(draw->numInstances); + SPIRVId numViewsConstID = editor.AddConstantImmediate(numViews); editor.SetName(numVertsConstID, "numVerts"); editor.SetName(numInstConstID, "numInsts"); @@ -698,7 +698,6 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV MeshOutputDispatchWidth, 1, 1})); SPIRVId uint32ID = editor.DeclareType(scalar()); - SPIRVId sint32ID = editor.DeclareType(scalar()); // add the wrapper function { @@ -717,33 +716,29 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV ops.push_back(SPIRVOperation(spv::OpLoad, {uint32Vec3ID, invocationVector, invocationId})); // uint invocation = invocationVec.x - uint32_t invocationID = editor.MakeId(); - ops.push_back( - SPIRVOperation(spv::OpCompositeExtract, {uint32ID, invocationID, invocationVector, 0U})); + uint32_t uintInvocationID = editor.MakeId(); + ops.push_back(SPIRVOperation(spv::OpCompositeExtract, + {uint32ID, uintInvocationID, invocationVector, 0U})); - // int intInvocationID = int(invocation); - uint32_t intInvocationID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpBitcast, {sint32ID, intInvocationID, invocationID})); + // arraySlotID = uintInvocationID; + uint32_t arraySlotID = uintInvocationID; - // arraySlotID = intInvocationID; - uint32_t arraySlotID = intInvocationID; + editor.SetName(uintInvocationID, "arraySlot"); - editor.SetName(intInvocationID, "arraySlot"); - - // int viewinst = intInvocationID / numVerts + // uint viewinst = uintInvocationID / numVerts uint32_t viewinstID = editor.MakeId(); ops.push_back( - SPIRVOperation(spv::OpSDiv, {sint32ID, viewinstID, intInvocationID, numVertsConstID})); + SPIRVOperation(spv::OpUDiv, {uint32ID, viewinstID, uintInvocationID, numVertsConstID})); editor.SetName(viewinstID, "viewInstance"); uint32_t instID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpSMod, {sint32ID, instID, viewinstID, numInstConstID})); + ops.push_back(SPIRVOperation(spv::OpUMod, {uint32ID, instID, viewinstID, numInstConstID})); editor.SetName(instID, "instanceID"); uint32_t viewID = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpSDiv, {sint32ID, viewID, viewinstID, numInstConstID})); + ops.push_back(SPIRVOperation(spv::OpUDiv, {uint32ID, viewID, viewinstID, numInstConstID})); editor.SetName(viewID, "viewID"); @@ -761,13 +756,13 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // continueLabel: ops.push_back(SPIRVOperation(spv::OpLabel, {continueLabel})); - // int vtx = intInvocationID % numVerts - uint32_t vtx = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpSMod, {sint32ID, vtx, intInvocationID, numVertsConstID})); + // uint vtx = uintInvocationID % numVerts + uint32_t vtxID = editor.MakeId(); + ops.push_back(SPIRVOperation(spv::OpUMod, {uint32ID, vtxID, uintInvocationID, numVertsConstID})); - editor.SetName(vtx, "vertexID"); + editor.SetName(vtxID, "vertexID"); - uint32_t vertexIndex = vtx; + uint32_t vertexIndexID = vtxID; // if we're indexing, look up the index buffer. We don't have to apply vertexOffset - it was // already applied when we read back and uniq-ified the index buffer. @@ -783,85 +778,100 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // uvec4 result = texelFetch(rawimg, vtxID); uint32_t result = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpImageFetch, {uint32Vec4ID, result, rawimg, vertexIndex})); + ops.push_back( + SPIRVOperation(spv::OpImageFetch, {uint32Vec4ID, result, rawimg, vertexIndexID})); - // uint vtxID = result.x; - uint32_t uintIndex = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpCompositeExtract, {uint32ID, uintIndex, result, 0})); - - vertexIndex = editor.MakeId(); - ops.push_back(SPIRVOperation(spv::OpBitcast, {sint32ID, vertexIndex, uintIndex})); + // vertexIndex = result.x; + vertexIndexID = editor.MakeId(); + ops.push_back(SPIRVOperation(spv::OpCompositeExtract, {uint32ID, vertexIndexID, result, 0})); } // we use the current value of vertexIndex and use instID, to lookup per-vertex and // per-instance attributes. This is because when we fetched the vertex data, we advanced by // (in non-indexed draws) vertexOffset, and by instanceOffset. Rather than fetching data // that's only used as padding skipped over by these offsets. - uint32_t vertexLookup = vertexIndex; - uint32_t instanceLookup = instID; + uint32_t vertexLookupID = vertexIndexID; + uint32_t instanceLookupID = instID; if(!(draw->flags & DrawFlags::Indexed)) { // for non-indexed draws, we manually apply the vertex offset, but here after we used the // 0-based one to calculate the array slot - vertexIndex = editor.MakeId(); - ops.push_back(SPIRVOperation( - spv::OpIAdd, {sint32ID, vertexIndex, vtx, - editor.AddConstantImmediate(int32_t(draw->vertexOffset & 0x7fffffff))})); + vertexIndexID = editor.MakeId(); + ops.push_back(SPIRVOperation(spv::OpIAdd, + {uint32ID, vertexIndexID, vtxID, + editor.AddConstantImmediate(draw->vertexOffset)})); } - editor.SetName(vertexIndex, "vertexIndex"); + editor.SetName(vertexIndexID, "vertexIndex"); // instIndex = inst + instOffset - uint32_t instIndex = editor.MakeId(); - ops.push_back(SPIRVOperation( - spv::OpIAdd, {sint32ID, instIndex, instID, - editor.AddConstantImmediate(int32_t(draw->instanceOffset & 0x7fffffff))})); - editor.SetName(instIndex, "instanceIndex"); + uint32_t instIndexID = editor.MakeId(); + ops.push_back(SPIRVOperation(spv::OpIAdd, + {uint32ID, instIndexID, instID, + editor.AddConstantImmediate(draw->instanceOffset)})); + editor.SetName(instIndexID, "instanceIndex"); uint32_t idxs[64] = {}; for(size_t i = 0; i < refl.inputSignature.size(); i++) { ShaderBuiltin builtin = refl.inputSignature[i].systemValue; + if(builtin != ShaderBuiltin::Undefined) + { + uint32_t valueID = 0; + CompType compType = CompType::UInt; - if(builtin == ShaderBuiltin::VertexIndex) - { - ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, vertexIndex})); - } - else if(builtin == ShaderBuiltin::InstanceIndex) - { - ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, instIndex})); - } - else if(builtin == ShaderBuiltin::ViewportIndex) - { - ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, viewID})); - } - else if(builtin == ShaderBuiltin::BaseVertex) - { - if(draw->flags & DrawFlags::Indexed) - ops.push_back(SPIRVOperation( - spv::OpStore, {ins[i].variableID, editor.AddConstantImmediate( - int32_t(draw->vertexOffset & 0x7fffffff))})); + if(builtin == ShaderBuiltin::VertexIndex) + { + valueID = vertexIndexID; + } + else if(builtin == ShaderBuiltin::InstanceIndex) + { + valueID = instIndexID; + } + else if(builtin == ShaderBuiltin::ViewportIndex) + { + valueID = viewID; + } + else if(builtin == ShaderBuiltin::BaseVertex) + { + if(draw->flags & DrawFlags::Indexed) + { + valueID = editor.AddConstantImmediate(draw->vertexOffset); + } + else + { + valueID = editor.AddConstantImmediate(draw->baseVertex); + compType = CompType::SInt; + } + } + else if(builtin == ShaderBuiltin::BaseInstance) + { + valueID = editor.AddConstantImmediate(draw->instanceOffset); + } + else if(builtin == ShaderBuiltin::DrawIndex) + { + valueID = editor.AddConstantImmediate(draw->drawIndex); + } + + if(valueID) + { + if(refl.inputSignature[i].compType == compType) + { + ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, valueID})); + } + else + { + uint32_t castedValue = editor.MakeId(); + // assume we can just bitcast + ops.push_back(SPIRVOperation(spv::OpBitcast, {ins[i].basetypeID, castedValue, valueID})); + ops.push_back(SPIRVOperation(spv::OpStore, {ins[i].variableID, castedValue})); + } + } 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()); + { + RDCERR("Unsupported/unsupported built-in input %s", ToStr(builtin).c_str()); + } } else { @@ -870,7 +880,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV if(idxs[refl.inputSignature[i].regIndex] == 0) idxs[refl.inputSignature[i].regIndex] = - editor.AddConstantImmediate((uint32_t)refl.inputSignature[i].regIndex); + editor.AddConstantImmediate(refl.inputSignature[i].regIndex); tbufferIDs tb = tbuffers[ins[i].tbuffer]; @@ -890,7 +900,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV ops.push_back(SPIRVOperation(spv::OpImage, {tb.imageTypeID, rawimg, loaded})); // vec4 result = texelFetch(rawimg, vtxID or instID); - uint32_t idx = vertexLookup; + uint32_t idx = vertexLookupID; if(location < instDivisor.size()) { @@ -899,24 +909,24 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV if(divisor == ~0U) { // this magic value indicates vertex-rate data - idx = vertexLookup; + idx = vertexLookupID; } else if(divisor == 0) { // if the divisor is 0, all instances read the first value. - idx = editor.AddConstantImmediate(0); + idx = editor.AddConstantImmediate(0); } else if(divisor == 1) { // if the divisor is 1, it's just regular instancing - idx = instanceLookup; + idx = instanceLookupID; } else { // otherwise we divide by the divisor idx = editor.MakeId(); - divisor = editor.AddConstantImmediate(int32_t(divisor & 0x7fffffff)); - ops.push_back(SPIRVOperation(spv::OpSDiv, {sint32ID, idx, instanceLookup, divisor})); + divisor = editor.AddConstantImmediate(divisor); + ops.push_back(SPIRVOperation(spv::OpUDiv, {uint32ID, idx, instanceLookupID, divisor})); } } @@ -925,7 +935,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // since doubles are packed into two uints, we need to multiply the index by two uint32_t doubled = editor.MakeId(); ops.push_back(SPIRVOperation( - spv::OpIMul, {sint32ID, doubled, idx, editor.AddConstantImmediate(int32_t(2))})); + spv::OpIMul, {uint32ID, doubled, idx, editor.AddConstantImmediate(2)})); idx = doubled; } @@ -940,7 +950,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV uint32_t nextidx = editor.MakeId(); ops.push_back(SPIRVOperation( - spv::OpIAdd, {sint32ID, nextidx, idx, editor.AddConstantImmediate(int32_t(1))})); + spv::OpIAdd, {uint32ID, nextidx, idx, editor.AddConstantImmediate(1)})); uint32_t result2 = editor.MakeId(); ops.push_back( @@ -1032,7 +1042,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV for(uint32_t accessIdx : patchData.inputs[i].accessChain) { if(idxs[accessIdx] == 0) - idxs[accessIdx] = editor.AddConstantImmediate((uint32_t)accessIdx); + idxs[accessIdx] = editor.AddConstantImmediate(accessIdx); words.push_back(idxs[accessIdx]); }