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);