Skip to content

Commit 62758f5

Browse files
committed
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 <[email protected]> Tested-by: Ben Clayton <[email protected]> Kokoro-Presubmit: kokoro <[email protected]> Reviewed-by: Chris Forbes <[email protected]>
1 parent 4af8826 commit 62758f5

File tree

4 files changed

+46
-12
lines changed

4 files changed

+46
-12
lines changed

src/Pipeline/ComputeProgram.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,17 @@ namespace sw
4949

5050
auto &modes = shader->getModes();
5151

52+
int localSize[3] = {modes.WorkgroupSizeX, modes.WorkgroupSizeY, modes.WorkgroupSizeZ};
53+
54+
const int subgroupSize = SIMD::Width;
5255

5356
// Total number of invocations required to execute this workgroup.
54-
const int numInvocations = modes.LocalSizeX * modes.LocalSizeY * modes.LocalSizeZ;
57+
int numInvocations = localSize[0] * localSize[1] * localSize[2];
5558

5659
Int4 numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups));
5760
Int4 workgroupID = *Pointer<Int4>(data + OFFSET(Data, workgroupID));
58-
Int4 workgroupSize = Int4(modes.LocalSizeX, modes.LocalSizeY, modes.LocalSizeZ, 0);
59-
const int subgroupSize = SIMD::Width;
60-
const int numSubgroups = (numInvocations + subgroupSize - 1) / subgroupSize;
61+
Int4 workgroupSize = Int4(localSize[0], localSize[1], localSize[2], 0);
62+
Int numSubgroups = (numInvocations + subgroupSize - 1) / subgroupSize;
6163

6264
setInputBuiltin(spv::BuiltInNumWorkgroups, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
6365
{
@@ -107,10 +109,10 @@ namespace sw
107109
Int4 localInvocationID[3];
108110
{
109111
Int4 idx = localInvocationIndex;
110-
localInvocationID[ZZZZ] = idx / Int4(modes.LocalSizeX * modes.LocalSizeY);
111-
idx -= localInvocationID[ZZZZ] * Int4(modes.LocalSizeX * modes.LocalSizeY); // modulo
112-
localInvocationID[YYYY] = idx / Int4(modes.LocalSizeX);
113-
idx -= localInvocationID[YYYY] * Int4(modes.LocalSizeX); // modulo
112+
localInvocationID[ZZZZ] = idx / Int4(localSize[0] * localSize[1]);
113+
idx -= localInvocationID[ZZZZ] * Int4(localSize[0] * localSize[1]); // modulo
114+
localInvocationID[YYYY] = idx / Int4(localSize[0]);
115+
idx -= localInvocationID[YYYY] * Int4(localSize[0]); // modulo
114116
localInvocationID[XXXX] = idx;
115117
}
116118

src/Pipeline/SpirvShader.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,25 @@ namespace sw
236236
for (auto j = 0u; j < constituentTy.sizeInComponents; j++)
237237
object.constantValue[offset++] = constituent.constantValue[j];
238238
}
239+
240+
auto objectId = Object::ID(insn.word(2));
241+
auto decorationsIt = decorations.find(objectId);
242+
if (decorationsIt != decorations.end() &&
243+
decorationsIt->second.BuiltIn == spv::BuiltInWorkgroupSize)
244+
{
245+
// https://www.khronos.org/registry/vulkan/specs/1.1/html/vkspec.html#interfaces-builtin-variables :
246+
// Decorating an object with the WorkgroupSize built-in
247+
// decoration will make that object contain the dimensions
248+
// of a local workgroup. If an object is decorated with the
249+
// WorkgroupSize decoration, this must take precedence over
250+
// any execution mode set for LocalSize.
251+
// The object decorated with WorkgroupSize must be declared
252+
// as a three-component vector of 32-bit integers.
253+
ASSERT(getType(object.type).sizeInComponents == 3);
254+
modes.WorkgroupSizeX = object.constantValue[0];
255+
modes.WorkgroupSizeY = object.constantValue[1];
256+
modes.WorkgroupSizeZ = object.constantValue[2];
257+
}
239258
break;
240259
}
241260

@@ -555,9 +574,9 @@ namespace sw
555574
modes.DepthUnchanged = true;
556575
break;
557576
case spv::ExecutionModeLocalSize:
558-
modes.LocalSizeX = insn.word(3);
559-
modes.LocalSizeZ = insn.word(5);
560-
modes.LocalSizeY = insn.word(4);
577+
modes.WorkgroupSizeX = insn.word(3);
578+
modes.WorkgroupSizeY = insn.word(4);
579+
modes.WorkgroupSizeZ = insn.word(5);
561580
break;
562581
case spv::ExecutionModeOriginUpperLeft:
563582
// This is always the case for a Vulkan shader. Do nothing.

src/Pipeline/SpirvShader.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ namespace sw
289289
bool NeedsCentroid : 1;
290290

291291
// Compute workgroup dimensions
292-
int LocalSizeX, LocalSizeY, LocalSizeZ;
292+
int WorkgroupSizeX = 1, WorkgroupSizeY = 1, WorkgroupSizeZ = 1;
293293
};
294294

295295
Modes const &getModes() const

src/Vulkan/VkPipeline.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "spirv-tools/optimizer.hpp"
2222

23+
#include <iostream>
24+
2325
namespace
2426
{
2527

@@ -230,6 +232,17 @@ std::vector<uint32_t> preprocessSpirv(
230232

231233
std::vector<uint32_t> optimized;
232234
opt.Run(code.data(), code.size(), &optimized);
235+
236+
if (false) {
237+
spvtools::SpirvTools core(SPV_ENV_VULKAN_1_1);
238+
std::string preOpt;
239+
core.Disassemble(code, &preOpt);
240+
std::string postOpt;
241+
core.Disassemble(optimized, &postOpt);
242+
std::cout << "PRE-OPT: " << preOpt << std::endl
243+
<< "POST-OPT: " << postOpt << std::endl;
244+
}
245+
233246
return optimized;
234247
}
235248

0 commit comments

Comments
 (0)