Pipeline: Store builtins on SpirvRoutine... ... even if they're not directly used by the SPIR-V shader code. This will let the debugger display these values in the locals window. Bug: b/145351270 Change-Id: I1d390e95bf38e89b072ef374e6a35cd8222a45c6 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38912 Tested-by: Ben Clayton <bclayton@google.com> Presubmit-Ready: Ben Clayton <bclayton@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/ComputeProgram.cpp b/src/Pipeline/ComputeProgram.cpp index 4ee8375..26d42d5 100644 --- a/src/Pipeline/ComputeProgram.cpp +++ b/src/Pipeline/ComputeProgram.cpp
@@ -60,12 +60,19 @@ void ComputeProgram::setWorkgroupBuiltins(Pointer<Byte> data, SpirvRoutine *routine, Int workgroupID[3]) { + // TODO(b/146486064): Consider only assigning these to the SpirvRoutine iff + // they are ever going to be read. + routine->numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups)); + routine->workgroupID = Insert(Insert(Insert(Int4(0), workgroupID[X], X), workgroupID[Y], Y), workgroupID[Z], Z); + routine->workgroupSize = *Pointer<Int4>(data + OFFSET(Data, workgroupSize)); + routine->subgroupsPerWorkgroup = *Pointer<Int>(data + OFFSET(Data, subgroupsPerWorkgroup)); + routine->invocationsPerSubgroup = *Pointer<Int>(data + OFFSET(Data, invocationsPerSubgroup)); + routine->setInputBuiltin(shader, spv::BuiltInNumWorkgroups, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { - auto numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups)); for(uint32_t component = 0; component < builtin.SizeInComponents; component++) { value[builtin.FirstComponent + component] = - As<SIMD::Float>(SIMD::Int(Extract(numWorkgroups, component))); + As<SIMD::Float>(SIMD::Int(Extract(routine->numWorkgroups, component))); } }); @@ -78,24 +85,21 @@ }); routine->setInputBuiltin(shader, spv::BuiltInWorkgroupSize, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { - auto workgroupSize = *Pointer<Int4>(data + OFFSET(Data, workgroupSize)); for(uint32_t component = 0; component < builtin.SizeInComponents; component++) { value[builtin.FirstComponent + component] = - As<SIMD::Float>(SIMD::Int(Extract(workgroupSize, component))); + As<SIMD::Float>(SIMD::Int(Extract(routine->workgroupSize, component))); } }); routine->setInputBuiltin(shader, spv::BuiltInNumSubgroups, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { ASSERT(builtin.SizeInComponents == 1); - auto subgroupsPerWorkgroup = *Pointer<Int>(data + OFFSET(Data, subgroupsPerWorkgroup)); - value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(subgroupsPerWorkgroup)); + value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine->subgroupsPerWorkgroup)); }); routine->setInputBuiltin(shader, spv::BuiltInSubgroupSize, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { ASSERT(builtin.SizeInComponents == 1); - auto invocationsPerSubgroup = *Pointer<Int>(data + OFFSET(Data, invocationsPerSubgroup)); - value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(invocationsPerSubgroup)); + value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine->invocationsPerSubgroup)); }); routine->setImmutableInputBuiltins(shader); @@ -120,6 +124,22 @@ localInvocationID[X] = idx; } + Int4 wgID = Insert(Insert(Insert(SIMD::Int(0), workgroupID[X], X), workgroupID[Y], Y), workgroupID[Z], Z); + auto localBase = workgroupSize * wgID; + SIMD::Int globalInvocationID[3]; + globalInvocationID[X] = SIMD::Int(Extract(localBase, X)) + localInvocationID[X]; + globalInvocationID[Y] = SIMD::Int(Extract(localBase, Y)) + localInvocationID[Y]; + globalInvocationID[Z] = SIMD::Int(Extract(localBase, Z)) + localInvocationID[Z]; + + routine->localInvocationIndex = localInvocationIndex; + routine->subgroupIndex = subgroupIndex; + routine->localInvocationID[X] = localInvocationID[X]; + routine->localInvocationID[Y] = localInvocationID[Y]; + routine->localInvocationID[Z] = localInvocationID[Z]; + routine->globalInvocationID[X] = globalInvocationID[X]; + routine->globalInvocationID[Y] = globalInvocationID[Y]; + routine->globalInvocationID[Z] = globalInvocationID[Z]; + routine->setInputBuiltin(shader, spv::BuiltInLocalInvocationIndex, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { ASSERT(builtin.SizeInComponents == 1); value[builtin.FirstComponent] = As<SIMD::Float>(localInvocationIndex); @@ -139,15 +159,10 @@ }); routine->setInputBuiltin(shader, spv::BuiltInGlobalInvocationId, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { - SIMD::Int wgID = 0; - wgID = Insert(wgID, workgroupID[X], X); - wgID = Insert(wgID, workgroupID[Y], Y); - wgID = Insert(wgID, workgroupID[Z], Z); - auto localBase = workgroupSize * wgID; for(uint32_t component = 0; component < builtin.SizeInComponents; component++) { - auto globalInvocationID = SIMD::Int(Extract(localBase, component)) + localInvocationID[component]; - value[builtin.FirstComponent + component] = As<SIMD::Float>(globalInvocationID); + value[builtin.FirstComponent + component] = + As<SIMD::Float>(globalInvocationID[component]); } }); }
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp index 21296ed..0bfd0b0 100644 --- a/src/Pipeline/PixelProgram.cpp +++ b/src/Pipeline/PixelProgram.cpp
@@ -60,17 +60,33 @@ { routine.setImmutableInputBuiltins(spirvShader); + // TODO(b/146486064): Consider only assigning these to the SpirvRoutine iff + // they are ever going to be read. + routine.fragCoord[0] = SIMD::Float(Float(x)) + SIMD::Float(0.5f, 1.5f, 0.5f, 1.5f); + routine.fragCoord[1] = SIMD::Float(Float(y)) + SIMD::Float(0.5f, 0.5f, 1.5f, 1.5f); + routine.fragCoord[2] = z[0]; // sample 0 + routine.fragCoord[3] = w; + routine.pointCoord[0] = SIMD::Float(0.5f) + + SIMD::Float(Float(x) - (*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordX)))); + routine.pointCoord[1] = SIMD::Float(0.5f) + + SIMD::Float(Float(y) - (*Pointer<Float>(primitive + OFFSET(Primitive, pointCoordY)))); + routine.invocationsPerSubgroup = SIMD::Width; + routine.helperInvocation = ~maskAny(cMask); + routine.windowSpacePosition[0] = x + SIMD::Int(0, 1, 0, 1); + routine.windowSpacePosition[1] = y + SIMD::Int(0, 0, 1, 1); + routine.viewID = *Pointer<Int>(data + OFFSET(DrawData, viewID)); + routine.setInputBuiltin(spirvShader, spv::BuiltInViewIndex, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { assert(builtin.SizeInComponents == 1); - value[builtin.FirstComponent] = As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, viewID))))); + value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine.viewID)); }); routine.setInputBuiltin(spirvShader, spv::BuiltInFragCoord, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { assert(builtin.SizeInComponents == 4); - value[builtin.FirstComponent + 0] = SIMD::Float(Float(x)) + SIMD::Float(0.5f, 1.5f, 0.5f, 1.5f); - value[builtin.FirstComponent + 1] = SIMD::Float(Float(y)) + SIMD::Float(0.5f, 0.5f, 1.5f, 1.5f); - value[builtin.FirstComponent + 2] = z[0]; // sample 0 - value[builtin.FirstComponent + 3] = w; + value[builtin.FirstComponent + 0] = routine.fragCoord[0]; + value[builtin.FirstComponent + 1] = routine.fragCoord[1]; + value[builtin.FirstComponent + 2] = routine.fragCoord[2]; + value[builtin.FirstComponent + 3] = routine.fragCoord[3]; }); routine.setInputBuiltin(spirvShader, spv::BuiltInPointCoord, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { @@ -88,12 +104,8 @@ routine.setInputBuiltin(spirvShader, spv::BuiltInHelperInvocation, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { assert(builtin.SizeInComponents == 1); - value[builtin.FirstComponent] = As<SIMD::Float>(~maskAny(cMask)); + value[builtin.FirstComponent] = As<SIMD::Float>(routine.helperInvocation); }); - - routine.windowSpacePosition[0] = x + SIMD::Int(0, 1, 0, 1); - routine.windowSpacePosition[1] = y + SIMD::Int(0, 0, 1, 1); - routine.viewID = *Pointer<Int>(data + OFFSET(DrawData, viewID)); } void PixelProgram::applyShader(Int cMask[4], Int sMask[4], Int zMask[4])
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp index db83240..f32cc63 100644 --- a/src/Pipeline/SpirvShader.hpp +++ b/src/Pipeline/SpirvShader.hpp
@@ -1163,8 +1163,28 @@ Pointer<Byte> pushConstants; Pointer<Byte> constants; Int killMask = Int{ 0 }; + + // Shader invocation state. + // Not all of these variables are used for every type of shader, and some + // are only used when debugging. See b/146486064 for more information. + // Give careful consideration to the runtime performance loss before adding + // more state here. SIMD::Int windowSpacePosition[2]; Int viewID; // slice offset into input attachments for multiview, even if the shader doesn't use ViewIndex + Int instanceID; + SIMD::Int vertexIndex; + std::array<SIMD::Float, 4> fragCoord; + std::array<SIMD::Float, 4> pointCoord; + SIMD::Int helperInvocation; + Int4 numWorkgroups; + Int4 workgroupID; + Int4 workgroupSize; + Int subgroupsPerWorkgroup; + Int invocationsPerSubgroup; + Int subgroupIndex; + SIMD::Int localInvocationIndex; + std::array<SIMD::Int, 3> localInvocationID; + std::array<SIMD::Int, 3> globalInvocationID; void createVariable(SpirvShader::Object::ID id, uint32_t size) {
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp index 615bcf3..4972ef2 100644 --- a/src/Pipeline/VertexProgram.cpp +++ b/src/Pipeline/VertexProgram.cpp
@@ -34,15 +34,20 @@ { routine.setImmutableInputBuiltins(spirvShader); + // TODO(b/146486064): Consider only assigning these to the SpirvRoutine iff + // they are ever going to be read. + routine.viewID = *Pointer<Int>(data + OFFSET(DrawData, viewID)); + routine.instanceID = *Pointer<Int>(data + OFFSET(DrawData, instanceID)); + routine.setInputBuiltin(spirvShader, spv::BuiltInViewIndex, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { assert(builtin.SizeInComponents == 1); - value[builtin.FirstComponent] = As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, viewID))))); + value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine.viewID)); }); routine.setInputBuiltin(spirvShader, spv::BuiltInInstanceIndex, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { // TODO: we could do better here; we know InstanceIndex is uniform across all lanes assert(builtin.SizeInComponents == 1); - value[builtin.FirstComponent] = As<Float4>(Int4((*Pointer<Int>(data + OFFSET(DrawData, instanceID))))); + value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine.instanceID)); }); routine.setInputBuiltin(spirvShader, spv::BuiltInSubgroupSize, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { @@ -62,14 +67,15 @@ void VertexProgram::program(Pointer<UInt> &batch, UInt &vertexCount) { + routine.vertexIndex = *Pointer<SIMD::Int>(As<Pointer<SIMD::Int>>(batch)) + + SIMD::Int(*Pointer<Int>(data + OFFSET(DrawData, baseVertex))); + auto it = spirvShader->inputBuiltins.find(spv::BuiltInVertexIndex); if(it != spirvShader->inputBuiltins.end()) { assert(it->second.SizeInComponents == 1); - routine.getVariable(it->second.Id)[it->second.FirstComponent] = - As<Float4>(*Pointer<Int4>(As<Pointer<Int4>>(batch)) + - Int4(*Pointer<Int>(data + OFFSET(DrawData, baseVertex)))); + As<SIMD::Float>(routine.vertexIndex); } auto activeLaneMask = SIMD::Int(0xFFFFFFFF);