Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 1 | // Copyright 2019 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "ComputeProgram.hpp" |
Chris Forbes | 548e366 | 2019-04-25 10:00:06 -0700 | [diff] [blame] | 16 | #include "Constants.hpp" |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 17 | |
Ben Clayton | 25e06e0 | 2020-02-07 11:19:08 +0000 | [diff] [blame] | 18 | #include "System/Debug.hpp" |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 19 | #include "Vulkan/VkPipelineLayout.hpp" |
| 20 | |
Ben Clayton | e693b62 | 2019-09-05 12:48:37 +0100 | [diff] [blame] | 21 | #include "marl/defer.h" |
| 22 | #include "marl/trace.h" |
| 23 | #include "marl/waitgroup.h" |
Ben Clayton | f7b7b70 | 2019-08-27 10:23:29 +0100 | [diff] [blame] | 24 | |
Ben Clayton | ecfeede | 2019-05-08 08:51:01 +0100 | [diff] [blame] | 25 | #include <queue> |
| 26 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 27 | namespace { |
| 28 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 29 | enum |
| 30 | { |
| 31 | X, |
| 32 | Y, |
| 33 | Z |
| 34 | }; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 35 | |
| 36 | } // anonymous namespace |
| 37 | |
| 38 | namespace sw { |
| 39 | |
| 40 | ComputeProgram::ComputeProgram(SpirvShader const *shader, vk::PipelineLayout const *pipelineLayout, const vk::DescriptorSet::Bindings &descriptorSets) |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 41 | : shader(shader) |
| 42 | , pipelineLayout(pipelineLayout) |
| 43 | , descriptorSets(descriptorSets) |
Ben Clayton | c2bb50b | 2019-03-13 14:28:32 +0000 | [diff] [blame] | 44 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 45 | } |
Ben Clayton | c2bb50b | 2019-03-13 14:28:32 +0000 | [diff] [blame] | 46 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 47 | ComputeProgram::~ComputeProgram() |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 48 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | void ComputeProgram::generate() |
| 52 | { |
| 53 | MARL_SCOPED_EVENT("ComputeProgram::generate"); |
| 54 | |
| 55 | SpirvRoutine routine(pipelineLayout); |
| 56 | shader->emitProlog(&routine); |
| 57 | emit(&routine); |
| 58 | shader->emitEpilog(&routine); |
| 59 | } |
| 60 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 61 | void ComputeProgram::setWorkgroupBuiltins(Pointer<Byte> data, SpirvRoutine *routine, Int workgroupID[3]) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 62 | { |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 63 | // TODO(b/146486064): Consider only assigning these to the SpirvRoutine iff |
| 64 | // they are ever going to be read. |
| 65 | routine->numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups)); |
| 66 | routine->workgroupID = Insert(Insert(Insert(Int4(0), workgroupID[X], X), workgroupID[Y], Y), workgroupID[Z], Z); |
| 67 | routine->workgroupSize = *Pointer<Int4>(data + OFFSET(Data, workgroupSize)); |
| 68 | routine->subgroupsPerWorkgroup = *Pointer<Int>(data + OFFSET(Data, subgroupsPerWorkgroup)); |
| 69 | routine->invocationsPerSubgroup = *Pointer<Int>(data + OFFSET(Data, invocationsPerSubgroup)); |
| 70 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 71 | routine->setInputBuiltin(shader, spv::BuiltInNumWorkgroups, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 72 | for(uint32_t component = 0; component < builtin.SizeInComponents; component++) |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 73 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 74 | value[builtin.FirstComponent + component] = |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 75 | As<SIMD::Float>(SIMD::Int(Extract(routine->numWorkgroups, component))); |
Ben Clayton | 13dcbec | 2019-05-08 08:43:55 +0100 | [diff] [blame] | 76 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 77 | }); |
Ben Clayton | 13dcbec | 2019-05-08 08:43:55 +0100 | [diff] [blame] | 78 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 79 | routine->setInputBuiltin(shader, spv::BuiltInWorkgroupId, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 80 | for(uint32_t component = 0; component < builtin.SizeInComponents; component++) |
Ben Clayton | 13dcbec | 2019-05-08 08:43:55 +0100 | [diff] [blame] | 81 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 82 | value[builtin.FirstComponent + component] = |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 83 | As<SIMD::Float>(SIMD::Int(workgroupID[component])); |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 84 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 85 | }); |
| 86 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 87 | routine->setInputBuiltin(shader, spv::BuiltInWorkgroupSize, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 88 | for(uint32_t component = 0; component < builtin.SizeInComponents; component++) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 89 | { |
| 90 | value[builtin.FirstComponent + component] = |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 91 | As<SIMD::Float>(SIMD::Int(Extract(routine->workgroupSize, component))); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 92 | } |
| 93 | }); |
| 94 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 95 | routine->setInputBuiltin(shader, spv::BuiltInNumSubgroups, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 96 | ASSERT(builtin.SizeInComponents == 1); |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 97 | value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine->subgroupsPerWorkgroup)); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 98 | }); |
| 99 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 100 | routine->setInputBuiltin(shader, spv::BuiltInSubgroupSize, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 101 | ASSERT(builtin.SizeInComponents == 1); |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 102 | value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(routine->invocationsPerSubgroup)); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 103 | }); |
| 104 | |
| 105 | routine->setImmutableInputBuiltins(shader); |
| 106 | } |
| 107 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 108 | void ComputeProgram::setSubgroupBuiltins(Pointer<Byte> data, SpirvRoutine *routine, Int workgroupID[3], SIMD::Int localInvocationIndex, Int subgroupIndex) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 109 | { |
| 110 | Int4 numWorkgroups = *Pointer<Int4>(data + OFFSET(Data, numWorkgroups)); |
| 111 | Int4 workgroupSize = *Pointer<Int4>(data + OFFSET(Data, workgroupSize)); |
| 112 | |
| 113 | // TODO: Fix Int4 swizzles so we can just use workgroupSize.x, workgroupSize.y. |
| 114 | Int workgroupSizeX = Extract(workgroupSize, X); |
| 115 | Int workgroupSizeY = Extract(workgroupSize, Y); |
| 116 | |
| 117 | SIMD::Int localInvocationID[3]; |
| 118 | { |
| 119 | SIMD::Int idx = localInvocationIndex; |
| 120 | localInvocationID[Z] = idx / SIMD::Int(workgroupSizeX * workgroupSizeY); |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 121 | idx -= localInvocationID[Z] * SIMD::Int(workgroupSizeX * workgroupSizeY); // modulo |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 122 | localInvocationID[Y] = idx / SIMD::Int(workgroupSizeX); |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 123 | idx -= localInvocationID[Y] * SIMD::Int(workgroupSizeX); // modulo |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 124 | localInvocationID[X] = idx; |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 125 | } |
| 126 | |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 127 | Int4 wgID = Insert(Insert(Insert(SIMD::Int(0), workgroupID[X], X), workgroupID[Y], Y), workgroupID[Z], Z); |
| 128 | auto localBase = workgroupSize * wgID; |
| 129 | SIMD::Int globalInvocationID[3]; |
| 130 | globalInvocationID[X] = SIMD::Int(Extract(localBase, X)) + localInvocationID[X]; |
| 131 | globalInvocationID[Y] = SIMD::Int(Extract(localBase, Y)) + localInvocationID[Y]; |
| 132 | globalInvocationID[Z] = SIMD::Int(Extract(localBase, Z)) + localInvocationID[Z]; |
| 133 | |
| 134 | routine->localInvocationIndex = localInvocationIndex; |
| 135 | routine->subgroupIndex = subgroupIndex; |
| 136 | routine->localInvocationID[X] = localInvocationID[X]; |
| 137 | routine->localInvocationID[Y] = localInvocationID[Y]; |
| 138 | routine->localInvocationID[Z] = localInvocationID[Z]; |
| 139 | routine->globalInvocationID[X] = globalInvocationID[X]; |
| 140 | routine->globalInvocationID[Y] = globalInvocationID[Y]; |
| 141 | routine->globalInvocationID[Z] = globalInvocationID[Z]; |
| 142 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 143 | routine->setInputBuiltin(shader, spv::BuiltInLocalInvocationIndex, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 144 | ASSERT(builtin.SizeInComponents == 1); |
| 145 | value[builtin.FirstComponent] = As<SIMD::Float>(localInvocationIndex); |
| 146 | }); |
Ben Clayton | 13dcbec | 2019-05-08 08:43:55 +0100 | [diff] [blame] | 147 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 148 | routine->setInputBuiltin(shader, spv::BuiltInSubgroupId, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 149 | ASSERT(builtin.SizeInComponents == 1); |
| 150 | value[builtin.FirstComponent] = As<SIMD::Float>(SIMD::Int(subgroupIndex)); |
| 151 | }); |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 152 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 153 | routine->setInputBuiltin(shader, spv::BuiltInLocalInvocationId, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 154 | for(uint32_t component = 0; component < builtin.SizeInComponents; component++) |
Ben Clayton | f7b7b70 | 2019-08-27 10:23:29 +0100 | [diff] [blame] | 155 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 156 | value[builtin.FirstComponent + component] = |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 157 | As<SIMD::Float>(localInvocationID[component]); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 158 | } |
| 159 | }); |
Ben Clayton | f7b7b70 | 2019-08-27 10:23:29 +0100 | [diff] [blame] | 160 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 161 | routine->setInputBuiltin(shader, spv::BuiltInGlobalInvocationId, [&](const SpirvShader::BuiltinMapping &builtin, Array<SIMD::Float> &value) { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 162 | for(uint32_t component = 0; component < builtin.SizeInComponents; component++) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 163 | { |
Ben Clayton | 5beaef9 | 2019-12-03 12:23:35 +0000 | [diff] [blame] | 164 | value[builtin.FirstComponent + component] = |
| 165 | As<SIMD::Float>(globalInvocationID[component]); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 166 | } |
| 167 | }); |
| 168 | } |
| 169 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 170 | void ComputeProgram::emit(SpirvRoutine *routine) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 171 | { |
| 172 | Pointer<Byte> data = Arg<0>(); |
| 173 | Int workgroupX = Arg<1>(); |
| 174 | Int workgroupY = Arg<2>(); |
| 175 | Int workgroupZ = Arg<3>(); |
| 176 | Pointer<Byte> workgroupMemory = Arg<4>(); |
| 177 | Int firstSubgroup = Arg<5>(); |
| 178 | Int subgroupCount = Arg<6>(); |
| 179 | |
| 180 | routine->descriptorSets = data + OFFSET(Data, descriptorSets); |
| 181 | routine->descriptorDynamicOffsets = data + OFFSET(Data, descriptorDynamicOffsets); |
| 182 | routine->pushConstants = data + OFFSET(Data, pushConstants); |
| 183 | routine->constants = *Pointer<Pointer<Byte>>(data + OFFSET(Data, constants)); |
| 184 | routine->workgroupMemory = workgroupMemory; |
| 185 | |
| 186 | Int invocationsPerWorkgroup = *Pointer<Int>(data + OFFSET(Data, invocationsPerWorkgroup)); |
| 187 | |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 188 | Int workgroupID[3] = { workgroupX, workgroupY, workgroupZ }; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 189 | setWorkgroupBuiltins(data, routine, workgroupID); |
| 190 | |
| 191 | For(Int i = 0, i < subgroupCount, i++) |
| 192 | { |
| 193 | auto subgroupIndex = firstSubgroup + i; |
| 194 | |
| 195 | // TODO: Replace SIMD::Int(0, 1, 2, 3) with SIMD-width equivalent |
| 196 | auto localInvocationIndex = SIMD::Int(subgroupIndex * SIMD::Width) + SIMD::Int(0, 1, 2, 3); |
| 197 | |
| 198 | // Disable lanes where (invocationIDs >= invocationsPerWorkgroup) |
| 199 | auto activeLaneMask = CmpLT(localInvocationIndex, SIMD::Int(invocationsPerWorkgroup)); |
| 200 | |
| 201 | setSubgroupBuiltins(data, routine, workgroupID, localInvocationIndex, subgroupIndex); |
| 202 | |
| 203 | shader->emit(routine, activeLaneMask, activeLaneMask, descriptorSets); |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | void ComputeProgram::run( |
Alexis Hetu | 4f438a5 | 2020-06-15 16:13:51 -0400 | [diff] [blame] | 208 | vk::DescriptorSet::Array const &descriptorSetObjects, |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 209 | vk::DescriptorSet::Bindings const &descriptorSets, |
| 210 | vk::DescriptorSet::DynamicOffsets const &descriptorDynamicOffsets, |
| 211 | PushConstantStorage const &pushConstants, |
| 212 | uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, |
| 213 | uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 214 | { |
| 215 | auto &modes = shader->getModes(); |
| 216 | |
| 217 | auto invocationsPerSubgroup = SIMD::Width; |
| 218 | auto invocationsPerWorkgroup = modes.WorkgroupSizeX * modes.WorkgroupSizeY * modes.WorkgroupSizeZ; |
| 219 | auto subgroupsPerWorkgroup = (invocationsPerWorkgroup + invocationsPerSubgroup - 1) / invocationsPerSubgroup; |
| 220 | |
| 221 | Data data; |
| 222 | data.descriptorSets = descriptorSets; |
| 223 | data.descriptorDynamicOffsets = descriptorDynamicOffsets; |
| 224 | data.numWorkgroups[X] = groupCountX; |
| 225 | data.numWorkgroups[Y] = groupCountY; |
| 226 | data.numWorkgroups[Z] = groupCountZ; |
| 227 | data.numWorkgroups[3] = 0; |
| 228 | data.workgroupSize[X] = modes.WorkgroupSizeX; |
| 229 | data.workgroupSize[Y] = modes.WorkgroupSizeY; |
| 230 | data.workgroupSize[Z] = modes.WorkgroupSizeZ; |
| 231 | data.workgroupSize[3] = 0; |
| 232 | data.invocationsPerSubgroup = invocationsPerSubgroup; |
| 233 | data.invocationsPerWorkgroup = invocationsPerWorkgroup; |
| 234 | data.subgroupsPerWorkgroup = subgroupsPerWorkgroup; |
| 235 | data.pushConstants = pushConstants; |
| 236 | data.constants = &sw::constants; |
| 237 | |
| 238 | marl::WaitGroup wg; |
| 239 | const uint32_t batchCount = 16; |
| 240 | |
| 241 | auto groupCount = groupCountX * groupCountY * groupCountZ; |
| 242 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 243 | for(uint32_t batchID = 0; batchID < batchCount && batchID < groupCount; batchID++) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 244 | { |
| 245 | wg.add(1); |
Ben Clayton | bc1c067 | 2019-12-17 20:37:37 +0000 | [diff] [blame] | 246 | marl::schedule([=, &data] { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 247 | defer(wg.done()); |
| 248 | std::vector<uint8_t> workgroupMemory(shader->workgroupMemory.size()); |
| 249 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 250 | for(uint32_t groupIndex = batchID; groupIndex < groupCount; groupIndex += batchCount) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 251 | { |
| 252 | auto modulo = groupIndex; |
| 253 | auto groupOffsetZ = modulo / (groupCountX * groupCountY); |
| 254 | modulo -= groupOffsetZ * (groupCountX * groupCountY); |
| 255 | auto groupOffsetY = modulo / groupCountX; |
| 256 | modulo -= groupOffsetY * groupCountX; |
| 257 | auto groupOffsetX = modulo; |
| 258 | |
| 259 | auto groupZ = baseGroupZ + groupOffsetZ; |
| 260 | auto groupY = baseGroupY + groupOffsetY; |
| 261 | auto groupX = baseGroupX + groupOffsetX; |
| 262 | MARL_SCOPED_EVENT("groupX: %d, groupY: %d, groupZ: %d", groupX, groupY, groupZ); |
| 263 | |
| 264 | using Coroutine = std::unique_ptr<rr::Stream<SpirvShader::YieldResult>>; |
| 265 | std::queue<Coroutine> coroutines; |
| 266 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 267 | if(modes.ContainsControlBarriers) |
Ben Clayton | f7b7b70 | 2019-08-27 10:23:29 +0100 | [diff] [blame] | 268 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 269 | // Make a function call per subgroup so each subgroup |
| 270 | // can yield, bringing all subgroups to the barrier |
| 271 | // together. |
| 272 | for(int subgroupIndex = 0; subgroupIndex < subgroupsPerWorkgroup; subgroupIndex++) |
Ben Clayton | ecfeede | 2019-05-08 08:51:01 +0100 | [diff] [blame] | 273 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 274 | auto coroutine = (*this)(&data, groupX, groupY, groupZ, workgroupMemory.data(), subgroupIndex, 1); |
Ben Clayton | ecfeede | 2019-05-08 08:51:01 +0100 | [diff] [blame] | 275 | coroutines.push(std::move(coroutine)); |
| 276 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 277 | } |
| 278 | else |
| 279 | { |
| 280 | auto coroutine = (*this)(&data, groupX, groupY, groupZ, workgroupMemory.data(), 0, subgroupsPerWorkgroup); |
| 281 | coroutines.push(std::move(coroutine)); |
| 282 | } |
Ben Clayton | ecfeede | 2019-05-08 08:51:01 +0100 | [diff] [blame] | 283 | |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 284 | while(coroutines.size() > 0) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 285 | { |
| 286 | auto coroutine = std::move(coroutines.front()); |
| 287 | coroutines.pop(); |
| 288 | |
| 289 | SpirvShader::YieldResult result; |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 290 | if(coroutine->await(result)) |
Ben Clayton | ecfeede | 2019-05-08 08:51:01 +0100 | [diff] [blame] | 291 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 292 | // TODO: Consider result (when the enum is more than 1 entry). |
| 293 | coroutines.push(std::move(coroutine)); |
Ben Clayton | ecfeede | 2019-05-08 08:51:01 +0100 | [diff] [blame] | 294 | } |
Ben Clayton | f7b7b70 | 2019-08-27 10:23:29 +0100 | [diff] [blame] | 295 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 296 | } |
| 297 | }); |
Ben Clayton | f2be26a | 2019-03-08 12:02:05 +0000 | [diff] [blame] | 298 | } |
Ben Clayton | 13dcbec | 2019-05-08 08:43:55 +0100 | [diff] [blame] | 299 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 300 | wg.wait(); |
Alexis Hetu | 4f438a5 | 2020-06-15 16:13:51 -0400 | [diff] [blame] | 301 | |
| 302 | if(shader->containsImageWrite()) |
| 303 | { |
| 304 | vk::DescriptorSet::ContentsChanged(descriptorSetObjects, pipelineLayout); |
| 305 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 306 | } |
| 307 | |
| 308 | } // namespace sw |