From 8471ad55b2dda6ed38389883a291511c1f8ab0c2 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Wed, 25 May 2016 08:40:02 +0100 Subject: [PATCH] Add atomics C++ sample. --- samples/cpp/atomics.comp | 29 +++++++++++++ samples/cpp/atomics.cpp | 90 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 samples/cpp/atomics.comp create mode 100644 samples/cpp/atomics.cpp diff --git a/samples/cpp/atomics.comp b/samples/cpp/atomics.comp new file mode 100644 index 00000000..0bf6d2ad --- /dev/null +++ b/samples/cpp/atomics.comp @@ -0,0 +1,29 @@ +#version 310 es +layout(local_size_x = 64) in; + +layout(set = 0, binding = 0, std430) readonly buffer SSBO0 +{ + float inputs[]; +}; + +layout(set = 0, binding = 1, std430) writeonly buffer SSBO1 +{ + float outputs[]; +}; + +layout(set = 0, binding = 2, std430) buffer SSBO2 +{ + uint counter; +}; + +void main() +{ + // Builds a tightly packed list of all values less than 10.0. + // The output order is random. + float value = inputs[gl_GlobalInvocationID.x]; + if (value < 10.0) + { + uint output_index = atomicAdd(counter, 1u); + outputs[output_index] = value; + } +} diff --git a/samples/cpp/atomics.cpp b/samples/cpp/atomics.cpp new file mode 100644 index 00000000..e11fc1b9 --- /dev/null +++ b/samples/cpp/atomics.cpp @@ -0,0 +1,90 @@ +/* + * Copyright 2015-2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "spirv_cross/external_interface.h" +#include + +#ifndef GLM_SWIZZLE +#define GLM_SWIZZLE +#endif + +#ifndef GLM_FORCE_RADIANS +#define GLM_FORCE_RADIANS +#endif + +#include +using namespace glm; + +int main() +{ + // First, we get the C interface to the shader. + // This can be loaded from a dynamic library, or as here, + // linked in as a static library. + auto *iface = spirv_cross_get_interface(); + + // Create an instance of the shader interface. + auto *shader = iface->construct(); + + // Build some input data for our compute shader. +#define NUM_WORKGROUPS 4 + float a[64 * NUM_WORKGROUPS]; + float b[64 * NUM_WORKGROUPS] = {}; + uint32_t counter = 0; + + for (int i = 0; i < 64 * NUM_WORKGROUPS; i++) + { + a[i] = i * 0.46f; + } + + void *aptr = a; + void *bptr = b; + void *cptr = &counter; + + // Bind resources to the shader. + // For resources like samplers and buffers, we provide a list of pointers, + // since UBOs, SSBOs and samplers can be arrays, and can point to different types, + // which is especially true for samplers. + spirv_cross_set_resource(shader, 0, 0, &aptr, sizeof(aptr)); + spirv_cross_set_resource(shader, 0, 1, &bptr, sizeof(bptr)); + spirv_cross_set_resource(shader, 0, 2, &cptr, sizeof(cptr)); + + // We also have to set builtins. + // The relevant builtins will depend on the shader, + // but for compute, there are few builtins, which are gl_NumWorkGroups and gl_WorkGroupID. + // LocalInvocationID and GlobalInvocationID are inferred when executing the invocation. + uvec3 num_workgroups(NUM_WORKGROUPS, 1, 1); + uvec3 work_group_id(0, 0, 0); + spirv_cross_set_builtin(shader, SPIRV_CROSS_BUILTIN_NUM_WORK_GROUPS, &num_workgroups, sizeof(num_workgroups)); + spirv_cross_set_builtin(shader, SPIRV_CROSS_BUILTIN_WORK_GROUP_ID, &work_group_id, sizeof(work_group_id)); + + // Execute 4 work groups. + for (unsigned i = 0; i < NUM_WORKGROUPS; i++) + { + work_group_id.x = i; + iface->invoke(shader); + } + + // Call destructor. + iface->destruct(shader); + + // Verify our output. + // TODO: Implement a test framework that asserts results computed. + fprintf(stderr, "Counter = %u\n", counter); + for (unsigned i = 0; i < counter; i++) + { + fprintf(stderr, "[%3u] = %.1f\n", i, b[i]); + } +}