Commit 62758f58 by Ben Clayton

Compute: WorkgroupSize decorations take precedence over LocalSize

Test: dEQP-VK.subgroups.builtin_var.compute.* Bug: b/126871859 Change-Id: Ida9cb49548ec984039d8730d50be7c8b22c3bfb8 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27092 Presubmit-Ready: Ben Clayton <bclayton@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent 4af8826e
...@@ -49,15 +49,17 @@ namespace sw ...@@ -49,15 +49,17 @@ namespace sw
auto &modes = shader->getModes(); auto &modes = shader->getModes();
int localSize[3] = {modes.WorkgroupSizeX, modes.WorkgroupSizeY, modes.WorkgroupSizeZ};
const int subgroupSize = SIMD::Width;
// Total number of invocations required to execute this workgroup. // Total number of invocations required to execute this workgroup.
const int numInvocations = modes.LocalSizeX * modes.LocalSizeY * modes.LocalSizeZ; int numInvocations = localSize[0] * localSize[1] * localSize[2];
Int4 numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups)); Int4 numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups));
Int4 workgroupID = *Pointer<Int4>(data + OFFSET(Data, workgroupID)); Int4 workgroupID = *Pointer<Int4>(data + OFFSET(Data, workgroupID));
Int4 workgroupSize = Int4(modes.LocalSizeX, modes.LocalSizeY, modes.LocalSizeZ, 0); Int4 workgroupSize = Int4(localSize[0], localSize[1], localSize[2], 0);
const int subgroupSize = SIMD::Width; Int numSubgroups = (numInvocations + subgroupSize - 1) / subgroupSize;
const int numSubgroups = (numInvocations + subgroupSize - 1) / subgroupSize;
setInputBuiltin(spv::BuiltInNumWorkgroups, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value) setInputBuiltin(spv::BuiltInNumWorkgroups, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
{ {
...@@ -107,10 +109,10 @@ namespace sw ...@@ -107,10 +109,10 @@ namespace sw
Int4 localInvocationID[3]; Int4 localInvocationID[3];
{ {
Int4 idx = localInvocationIndex; Int4 idx = localInvocationIndex;
localInvocationID[ZZZZ] = idx / Int4(modes.LocalSizeX * modes.LocalSizeY); localInvocationID[ZZZZ] = idx / Int4(localSize[0] * localSize[1]);
idx -= localInvocationID[ZZZZ] * Int4(modes.LocalSizeX * modes.LocalSizeY); // modulo idx -= localInvocationID[ZZZZ] * Int4(localSize[0] * localSize[1]); // modulo
localInvocationID[YYYY] = idx / Int4(modes.LocalSizeX); localInvocationID[YYYY] = idx / Int4(localSize[0]);
idx -= localInvocationID[YYYY] * Int4(modes.LocalSizeX); // modulo idx -= localInvocationID[YYYY] * Int4(localSize[0]); // modulo
localInvocationID[XXXX] = idx; localInvocationID[XXXX] = idx;
} }
......
...@@ -236,6 +236,25 @@ namespace sw ...@@ -236,6 +236,25 @@ namespace sw
for (auto j = 0u; j < constituentTy.sizeInComponents; j++) for (auto j = 0u; j < constituentTy.sizeInComponents; j++)
object.constantValue[offset++] = constituent.constantValue[j]; object.constantValue[offset++] = constituent.constantValue[j];
} }
auto objectId = Object::ID(insn.word(2));
auto decorationsIt = decorations.find(objectId);
if (decorationsIt != decorations.end() &&
decorationsIt->second.BuiltIn == spv::BuiltInWorkgroupSize)
{
// https://www.khronos.org/registry/vulkan/specs/1.1/html/vkspec.html#interfaces-builtin-variables :
// Decorating an object with the WorkgroupSize built-in
// decoration will make that object contain the dimensions
// of a local workgroup. If an object is decorated with the
// WorkgroupSize decoration, this must take precedence over
// any execution mode set for LocalSize.
// The object decorated with WorkgroupSize must be declared
// as a three-component vector of 32-bit integers.
ASSERT(getType(object.type).sizeInComponents == 3);
modes.WorkgroupSizeX = object.constantValue[0];
modes.WorkgroupSizeY = object.constantValue[1];
modes.WorkgroupSizeZ = object.constantValue[2];
}
break; break;
} }
...@@ -555,9 +574,9 @@ namespace sw ...@@ -555,9 +574,9 @@ namespace sw
modes.DepthUnchanged = true; modes.DepthUnchanged = true;
break; break;
case spv::ExecutionModeLocalSize: case spv::ExecutionModeLocalSize:
modes.LocalSizeX = insn.word(3); modes.WorkgroupSizeX = insn.word(3);
modes.LocalSizeZ = insn.word(5); modes.WorkgroupSizeY = insn.word(4);
modes.LocalSizeY = insn.word(4); modes.WorkgroupSizeZ = insn.word(5);
break; break;
case spv::ExecutionModeOriginUpperLeft: case spv::ExecutionModeOriginUpperLeft:
// This is always the case for a Vulkan shader. Do nothing. // This is always the case for a Vulkan shader. Do nothing.
......
...@@ -289,7 +289,7 @@ namespace sw ...@@ -289,7 +289,7 @@ namespace sw
bool NeedsCentroid : 1; bool NeedsCentroid : 1;
// Compute workgroup dimensions // Compute workgroup dimensions
int LocalSizeX, LocalSizeY, LocalSizeZ; int WorkgroupSizeX = 1, WorkgroupSizeY = 1, WorkgroupSizeZ = 1;
}; };
Modes const &getModes() const Modes const &getModes() const
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "spirv-tools/optimizer.hpp" #include "spirv-tools/optimizer.hpp"
#include <iostream>
namespace namespace
{ {
...@@ -230,6 +232,17 @@ std::vector<uint32_t> preprocessSpirv( ...@@ -230,6 +232,17 @@ std::vector<uint32_t> preprocessSpirv(
std::vector<uint32_t> optimized; std::vector<uint32_t> optimized;
opt.Run(code.data(), code.size(), &optimized); opt.Run(code.data(), code.size(), &optimized);
if (false) {
spvtools::SpirvTools core(SPV_ENV_VULKAN_1_1);
std::string preOpt;
core.Disassemble(code, &preOpt);
std::string postOpt;
core.Disassemble(optimized, &postOpt);
std::cout << "PRE-OPT: " << preOpt << std::endl
<< "POST-OPT: " << postOpt << std::endl;
}
return optimized; return optimized;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment