OSDN Git Service

ComputeProgram: Add subgroup builtins.
authorBen Clayton <bclayton@google.com>
Wed, 13 Mar 2019 09:16:50 +0000 (09:16 +0000)
committerBen Clayton <bclayton@google.com>
Fri, 15 Mar 2019 18:23:25 +0000 (18:23 +0000)
Test: dEQP-VK.subgroups.builtin_var.compute.*

Bug: b/126871859
Change-Id: If1585778ca5a85e2b8a66f4ddf6a58050620a112
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/27089
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
src/Pipeline/ComputeProgram.cpp
src/Vulkan/VkPhysicalDevice.cpp

index 6ddd192..ab390e6 100644 (file)
@@ -49,9 +49,15 @@ namespace sw
 
                auto &modes = shader->getModes();
 
+
+               // Total number of invocations required to execute this workgroup.
+               const int numInvocations = modes.LocalSizeX * modes.LocalSizeY * modes.LocalSizeZ;
+
                Int4 numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups));
                Int4 workgroupID = *Pointer<Int4>(data + OFFSET(Data, workgroupID));
                Int4 workgroupSize = Int4(modes.LocalSizeX, modes.LocalSizeY, modes.LocalSizeZ, 0);
+               const int subgroupSize = SIMD::Width;
+               const int numSubgroups = (numInvocations + subgroupSize - 1) / subgroupSize;
 
                setInputBuiltin(spv::BuiltInNumWorkgroups, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
                {
@@ -71,14 +77,29 @@ namespace sw
                        }
                });
 
-               // Total number of invocations required to execute this workgroup.
-               const int numInvocations = modes.LocalSizeX * modes.LocalSizeY * modes.LocalSizeZ;
+               setInputBuiltin(spv::BuiltInNumSubgroups, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
+               {
+                       ASSERT(builtin.SizeInComponents == 1);
+                       value[builtin.FirstComponent] = As<Float4>(Int4(numSubgroups));
+               });
+
+               setInputBuiltin(spv::BuiltInSubgroupSize, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
+               {
+                       ASSERT(builtin.SizeInComponents == 1);
+                       value[builtin.FirstComponent] = As<Float4>(Int4(subgroupSize));
+               });
+
+               setInputBuiltin(spv::BuiltInSubgroupLocalInvocationId, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
+               {
+                       ASSERT(builtin.SizeInComponents == 1);
+                       value[builtin.FirstComponent] = As<Float4>(Int4(0, 1, 2, 3));
+               });
 
                enum { XXXX, YYYY, ZZZZ };
 
-               For(Int invocationIndex = 0, invocationIndex < numInvocations, invocationIndex += SIMD::Width)
+               For(Int subgroupIndex = 0, subgroupIndex < numSubgroups, subgroupIndex++)
                {
-                       Int4 localInvocationIndex = Int4(invocationIndex) + Int4(0, 1, 2, 3);
+                       Int4 localInvocationIndex = Int4(subgroupIndex * 4) + Int4(0, 1, 2, 3);
 
                        // Disable lanes where (invocationIDs >= numInvocations)
                        routine.activeLaneMask = CmpLT(localInvocationIndex, Int4(numInvocations));
@@ -99,6 +120,12 @@ namespace sw
                                value[builtin.FirstComponent] = As<Float4>(localInvocationIndex);
                        });
 
+                       setInputBuiltin(spv::BuiltInSubgroupId, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
+                       {
+                               ASSERT(builtin.SizeInComponents == 1);
+                               value[builtin.FirstComponent] = As<Float4>(Int4(subgroupIndex));
+                       });
+
                        setInputBuiltin(spv::BuiltInLocalInvocationId, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
                        {
                                for (uint32_t component = 0; component < builtin.SizeInComponents; component++)
@@ -109,14 +136,11 @@ namespace sw
 
                        setInputBuiltin(spv::BuiltInGlobalInvocationId, [&](const SpirvShader::BuiltinMapping& builtin, Array<Float4>& value)
                        {
+                               Int4 localBase = workgroupID * workgroupSize;
                                for (uint32_t component = 0; component < builtin.SizeInComponents; component++)
                                {
-                                       Int4 globalInvocationID =
-                                               Int4(Extract(workgroupID, component)) *
-                                               Int4(Extract(workgroupSize, component)) +
-                                               localInvocationID[component];
+                                       Int4 globalInvocationID = Int4(Extract(localBase, component)) + localInvocationID[component];
                                        value[builtin.FirstComponent + component] = As<Float4>(globalInvocationID);
-                                       // RR_WATCH(component, globalInvocationID, routine.activeLaneMask);
                                }
                        });
 
index 08a7b9a..95cf71d 100644 (file)
@@ -15,6 +15,8 @@
 #include "VkPhysicalDevice.hpp"
 #include "VkConfig.h"
 
+#include "Pipeline/SpirvShader.hpp" // sw::SIMD::Width
+
 #include <cstring>
 
 namespace vk
@@ -303,7 +305,7 @@ void PhysicalDevice::getProperties(VkPhysicalDeviceProtectedMemoryProperties* pr
 
 void PhysicalDevice::getProperties(VkPhysicalDeviceSubgroupProperties* properties) const
 {
-       properties->subgroupSize = 1;
+       properties->subgroupSize = sw::SIMD::Width;
        properties->supportedStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
        properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT;
        properties->quadOperationsInAllStages = VK_FALSE;