summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorDietrich Geisler <dag368@cornell.edu>2020-07-27 12:14:17 -0400
committerGitHub <noreply@github.com>2020-07-27 09:14:17 -0700
commit348058f96e81d11da2698acf8343a99a199f1f24 (patch)
treeb795625654f7696b50e98127a9b745bdb8f68fc3 /examples
parent87940a649e3b4f757905015de95225d57ec2f27c (diff)
Baseline Heterogeneous Example (#1460)
* Baseline Heterogeneous Example This PR introduces a baseline heterogeneous example, including both a Slang file and an associated C++ helper file. This refactoring primarily moves the Slang file "into the driver's seat" while maintaining that the C++ side still does most of the actual work. * Fix to prelude path
Diffstat (limited to 'examples')
-rw-r--r--examples/heterogeneous-hello-world/main.cpp253
-rw-r--r--examples/heterogeneous-hello-world/shader.cpp192
-rw-r--r--examples/heterogeneous-hello-world/shader.slang72
3 files changed, 336 insertions, 181 deletions
diff --git a/examples/heterogeneous-hello-world/main.cpp b/examples/heterogeneous-hello-world/main.cpp
index 8d5540a32..a590f8c4b 100644
--- a/examples/heterogeneous-hello-world/main.cpp
+++ b/examples/heterogeneous-hello-world/main.cpp
@@ -35,18 +35,36 @@
#include "gfx/render.h"
#include "gfx/d3d11/render-d3d11.h"
#include "gfx/window.h"
+#include "../../prelude/slang-cpp-types.h";
using namespace gfx;
-// We will start with a function that will invoke the Slang compiler
-// to generate target-specific code from a shader file, and then
-// use that to initialize an API shader program.
+// We create global ref pointers to avoid dereferencing values
//
-// Note that `Renderer` and `ShaderProgram` here are types from
-// the graphics API abstraction layer, and *not* part of the
-// Slang API. This function is representative of code that a user
-// might write to integrate Slang into their renderer/engine.
+RefPtr<gfx::ShaderProgram> gShaderProgram;
+RefPtr<gfx::ApplicationContext> gAppContext;
+RefPtr<gfx::Renderer> gRenderer;
+
+RefPtr<gfx::BufferResource> gStructuredBuffer;
+
+RefPtr<gfx::PipelineLayout> gPipelineLayout;
+RefPtr<gfx::PipelineState> gPipelineState;
+RefPtr<gfx::DescriptorSetLayout> gDescriptorSetLayout;
+RefPtr<gfx::DescriptorSet> gDescriptorSet;
+
+// Boilerplate types to help the slan-generated file
//
-RefPtr<gfx::ShaderProgram> loadShaderProgram(gfx::Renderer* renderer)
+struct gfx_Window_0;
+struct gfx_Renderer_0;
+struct gfx_BufferResource_0;
+struct gfx_ShaderProgram_0;
+struct gfx_DescriptorSetLayout_0;
+struct gfx_PipelineLayout_0;
+struct gfx_DescriptorSet_0;
+struct gfx_PipelineState_0;
+
+bool executeComputation_0();
+
+gfx::ShaderProgram* loadShaderProgram(gfx::Renderer* renderer)
{
// First, we need to create a "session" for interacting with the Slang
// compiler. This scopes all of our application's interactions
@@ -159,54 +177,37 @@ RefPtr<gfx::ShaderProgram> loadShaderProgram(gfx::Renderer* renderer)
programDesc.kernels = &kernelDescs[0];
programDesc.kernelCount = 2;
- auto shaderProgram = renderer->createProgram(programDesc);
+ gShaderProgram = renderer->createProgram(programDesc);
// Once we've used the output blobs from the Slang compiler to initialize
// the API-specific shader program, we can release their memory.
//
computeShaderBlob->release();
- return shaderProgram;
+ return gShaderProgram;
}
// Now that we've covered the function that actually loads and
// compiles our Slang shade code, we can go through the rest
// of the application code without as much commentary.
//
-Result computeMain()
+gfx::Window* createWindow(int windowWidth, int windowHeight)
{
- // We will hard-code the size of our rendering window and initial array.
- //
- int gWindowWidth = 1024;
- int gWindowHeight = 768;
- float initialArray[4] = { 3.0f, -20.0f, -6.0f, 8.0f };
-
- // We will define global variables for the various platform and
- // graphics API objects that our application needs:
- //
- // As a reminder, *none* of these are Slang API objects. All
- // of them come from the utility library we are using to simplify
- // building an example program.
- //
- gfx::ApplicationContext* gAppContext;
- gfx::Window* gWindow;
- RefPtr<gfx::Renderer> gRenderer;
-
- RefPtr<gfx::BufferResource> gUnorderedAccess;
- RefPtr<gfx::BufferResource> gReadBuffer;
-
- RefPtr<gfx::PipelineLayout> gPipelineLayout;
- RefPtr<gfx::PipelineState> gPipelineState;
- RefPtr<gfx::DescriptorSet> gDescriptorSet;
-
// Create a window for our application to render into.
//
WindowDesc windowDesc;
windowDesc.title = "Hello, World!";
- windowDesc.width = gWindowWidth;
- windowDesc.height = gWindowHeight;
- gWindow = createWindow(windowDesc);
+ windowDesc.width = windowWidth;
+ windowDesc.height = windowHeight;
+ return createWindow(windowDesc);
+ //return globalWindow;
+}
+gfx::Renderer* createRenderer(
+ int windowWidth,
+ int windowHeight,
+ gfx::Window* window)
+{
// Initialize the rendering layer.
//
// Note: for now we are hard-coding logic to use the
@@ -216,14 +217,18 @@ Result computeMain()
//
gRenderer = createD3D11Renderer();
Renderer::Desc rendererDesc;
- rendererDesc.width = gWindowWidth;
- rendererDesc.height = gWindowHeight;
+ rendererDesc.width = windowWidth;
+ rendererDesc.height = windowHeight;
{
- Result res = gRenderer->initialize(rendererDesc, getPlatformWindowHandle(gWindow));
- if(SLANG_FAILED(res)) return res;
+ Result res = gRenderer->initialize(rendererDesc, getPlatformWindowHandle(window));
+ if (SLANG_FAILED(res)) return nullptr;
}
+ return gRenderer;
+}
- // Create a structured buffer for passing the compute data
+gfx::BufferResource* createStructuredBuffer(gfx::Renderer* renderer, float* initialArray)
+{
+ // Create a structured buffer for storing the data for computation
//
int structuredBufferSize = 4 * sizeof(float);
@@ -233,23 +238,21 @@ Result computeMain()
structuredBufferDesc.elementSize = 4;
structuredBufferDesc.cpuAccessFlags = Resource::AccessFlag::Read;
- gUnorderedAccess = gRenderer->createBufferResource(
+ gStructuredBuffer = renderer->createBufferResource(
Resource::Usage::UnorderedAccess,
structuredBufferDesc,
initialArray);
- if(!gUnorderedAccess) return SLANG_FAIL;
-
- // Now we will use our `loadShaderProgram` function to load
- // the code from `shader.slang` into the graphics API.
- //
- RefPtr<ShaderProgram> shaderProgram = loadShaderProgram(gRenderer);
- if(!shaderProgram) return SLANG_FAIL;
+ return gStructuredBuffer;
+}
+gfx::DescriptorSetLayout* buildDescriptorSetLayout(gfx::Renderer* renderer)
+{
// Our example graphics API usess a "modern" D3D12/Vulkan style
// of resource binding, so now we will dive into describing and
// allocating "descriptor sets."
//
// First, we need to construct a descriptor set *layout*.
+ //
DescriptorSetLayout::SlotRangeDesc slotRanges[] =
{
DescriptorSetLayout::SlotRangeDesc(DescriptorSlotType::StorageBuffer),
@@ -257,78 +260,96 @@ Result computeMain()
DescriptorSetLayout::Desc descriptorSetLayoutDesc;
descriptorSetLayoutDesc.slotRangeCount = 1;
descriptorSetLayoutDesc.slotRanges = &slotRanges[0];
- auto descriptorSetLayout = gRenderer->createDescriptorSetLayout(descriptorSetLayoutDesc);
- if(!descriptorSetLayout) return SLANG_FAIL;
+ gDescriptorSetLayout = renderer->createDescriptorSetLayout(descriptorSetLayoutDesc);
+ return gDescriptorSetLayout;
+}
+gfx::PipelineLayout* buildPipeline(gfx::Renderer* renderer, gfx::DescriptorSetLayout* descriptorSetLayout)
+{
// Next we will allocate a pipeline layout, which specifies
// that we will render with only a single descriptor set bound.
//
PipelineLayout::DescriptorSetDesc descriptorSets[] =
{
- PipelineLayout::DescriptorSetDesc( descriptorSetLayout ),
+ PipelineLayout::DescriptorSetDesc(descriptorSetLayout),
};
PipelineLayout::Desc pipelineLayoutDesc;
pipelineLayoutDesc.renderTargetCount = 1;
pipelineLayoutDesc.descriptorSetCount = 1;
pipelineLayoutDesc.descriptorSets = &descriptorSets[0];
- auto pipelineLayout = gRenderer->createPipelineLayout(pipelineLayoutDesc);
- if(!pipelineLayout) return SLANG_FAIL;
+ gPipelineLayout = renderer->createPipelineLayout(pipelineLayoutDesc);
- gPipelineLayout = pipelineLayout;
+ return gPipelineLayout;
+}
+gfx::DescriptorSet* buildDescriptorSet(
+ gfx::Renderer* renderer,
+ gfx::DescriptorSetLayout* descriptorSetLayout,
+ gfx::BufferResource* structuredBuffer)
+{
// Once we have the descriptor set layout, we can allocate
// and fill in a descriptor set to hold our parameters.
//
- auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout);
- if(!descriptorSet) return SLANG_FAIL;
+ gDescriptorSet = renderer->createDescriptorSet(descriptorSetLayout);
+ if(!gDescriptorSet) return nullptr;
// Once we have the bufferResource created, we can fill in
// a descriptor set for creating a structured buffer
//
ResourceView::Desc resourceViewDesc;
resourceViewDesc.type = ResourceView::Type::UnorderedAccess;
- auto resourceView = gRenderer->createBufferView(gUnorderedAccess, resourceViewDesc);
- descriptorSet->setResource(0, 0, resourceView);
+ auto resourceView = renderer->createBufferView(structuredBuffer, resourceViewDesc);
+ gDescriptorSet->setResource(0, 0, resourceView);
- gDescriptorSet = descriptorSet;
+ return gDescriptorSet;
+}
+gfx::PipelineState* buildPipelineState(
+ gfx::ShaderProgram* shaderProgram,
+ gfx::Renderer* renderer,
+ gfx::PipelineLayout* pipelineLayout)
+{
// Following the D3D12/Vulkan style of API, we need a pipeline state object
// (PSO) to encapsulate the configuration of the overall graphics pipeline.
//
ComputePipelineStateDesc desc;
- desc.pipelineLayout = gPipelineLayout;
+ desc.pipelineLayout = pipelineLayout;
desc.program = shaderProgram;
- auto pipelineState = gRenderer->createComputePipelineState(desc);
- if(!pipelineState) return SLANG_FAIL;
-
- gPipelineState = pipelineState;
-
- // Once we've initialized all the graphics API objects,
- // it is time to show our application window and start rendering.
- //
- //showWindow(gWindow);
-
- // Now we configure our graphics pipeline state by setting the
- // PSO, binding our descriptor set (which references the
- // constant buffer that we wrote to above), and setting
- // some additional bits of state, before drawing our triangle.
- //
+ gPipelineState = renderer->createComputePipelineState(desc);
+ return gPipelineState;
+}
+void printInitialValues(float* initialArray, int length)
+{
// Print out the values before the computation
printf("Before:\n");
- for (float v : initialArray)
+ for (int i = 0; i < length; i++)
{
- printf("%f, ", v);
+ printf("%f, ", initialArray[i]);
}
printf("\n");
+}
+
+void dispatchComputation(
+ gfx::Renderer* gRenderer,
+ gfx::PipelineState* gPipelineState,
+ gfx::PipelineLayout* gPipelineLayout,
+ gfx::DescriptorSet* gDescriptorSet)
+{
gRenderer->setPipelineState(PipelineType::Compute, gPipelineState);
gRenderer->setDescriptorSet(PipelineType::Compute, gPipelineLayout, 0, gDescriptorSet);
gRenderer->dispatchCompute(4, 1, 1);
+}
- if(float* outputData = (float*) gRenderer->map(gUnorderedAccess, MapFlavor::HostRead))
+void print_output(
+ gfx::Renderer* renderer,
+ gfx::BufferResource* structuredBuffer,
+ int length)
+{
+ if (float* outputData = (float*)renderer->map(structuredBuffer, MapFlavor::HostRead))
{
// Print out the values the the kernel produced
printf("After: \n");
@@ -338,10 +359,74 @@ Result computeMain()
}
printf("\n");
- gRenderer->unmap(gUnorderedAccess);
+ renderer->unmap(structuredBuffer);
}
+}
+
+// Boilerplate functions to help the slang-generated file and types
+gfx_Window_0* createWindow_0(int32_t _0, int32_t _1)
+{
+ return (gfx_Window_0*)createWindow(_0, _1);
+}
+
+gfx_Renderer_0* createRenderer_0(int32_t _0, int32_t _1, gfx_Window_0* _2)
+{
+ return (gfx_Renderer_0*)createRenderer(_0, _1, (gfx::Window*)_2);
+}
+
+gfx_BufferResource_0* createStructuredBuffer_0(gfx_Renderer_0* _0, FixedArray<float, 4> _1)
+{
+ return (gfx_BufferResource_0*)createStructuredBuffer((gfx::Renderer*)_0, (float*)&_1);
+}
+
+gfx_ShaderProgram_0* loadShaderProgram_0(gfx_Renderer_0* _0)
+{
+ return (gfx_ShaderProgram_0*)loadShaderProgram((gfx::Renderer*)_0);
+}
+
+gfx_DescriptorSetLayout_0* buildDescriptorSetLayout_0(gfx_Renderer_0* _0)
+{
+ return (gfx_DescriptorSetLayout_0*)buildDescriptorSetLayout((gfx::Renderer*)_0);
+}
- return SLANG_OK;
+gfx_PipelineLayout_0* buildPipeline_0(gfx_Renderer_0* _0, gfx_DescriptorSetLayout_0* _1)
+{
+ return (gfx_PipelineLayout_0*)buildPipeline((gfx::Renderer*)_0, (gfx::DescriptorSetLayout*)_1);
+}
+
+gfx_DescriptorSet_0* buildDescriptorSet_0(gfx_Renderer_0* _0, gfx_DescriptorSetLayout_0* _1, gfx_BufferResource_0* _2)
+{
+ return (gfx_DescriptorSet_0*)buildDescriptorSet(
+ (gfx::Renderer*)_0,
+ (gfx::DescriptorSetLayout*)_1,
+ (gfx::BufferResource*)_2);
+}
+
+gfx_PipelineState_0* buildPipelineState_0(gfx_ShaderProgram_0* _0, gfx_Renderer_0* _1, gfx_PipelineLayout_0* _2)
+{
+ return (gfx_PipelineState_0*)buildPipelineState(
+ (gfx::ShaderProgram*)_0,
+ (gfx::Renderer*)_1,
+ (gfx::PipelineLayout*)_2);
+}
+
+void printInitialValues_0(FixedArray<float, 4> _0, int32_t _1)
+{
+ printInitialValues((float*)&_0, _1);
+}
+
+void dispatchComputation_0(gfx_Renderer_0* _0, gfx_PipelineState_0* _1, gfx_PipelineLayout_0* _2, gfx_DescriptorSet_0* _3)
+{
+ dispatchComputation(
+ (gfx::Renderer*)_0,
+ (gfx::PipelineState*)_1,
+ (gfx::PipelineLayout*)_2,
+ (gfx::DescriptorSet*)_3);
+}
+
+void print_output_0(gfx_Renderer_0* _0, gfx_BufferResource_0* _1, int32_t _2)
+{
+ print_output((gfx::Renderer*)_0, (gfx::BufferResource*)_1, _2);
}
// This "inner" main function is used by the platform abstraction
@@ -354,7 +439,7 @@ void innerMain(ApplicationContext* context)
// `struct` type, and then walk through the lifecyle
// of the application.
- if (SLANG_FAILED(computeMain()))
+ if (!(executeComputation_0()))
{
return exitApplication(context, 1);
}
diff --git a/examples/heterogeneous-hello-world/shader.cpp b/examples/heterogeneous-hello-world/shader.cpp
index 396b78cb4..e8656bed7 100644
--- a/examples/heterogeneous-hello-world/shader.cpp
+++ b/examples/heterogeneous-hello-world/shader.cpp
@@ -1,126 +1,130 @@
#include "../../prelude/slang-cpp-prelude.h"
-namespace { // anonymous
+//namespace { // anonymous
#ifdef SLANG_PRELUDE_NAMESPACE
using namespace SLANG_PRELUDE_NAMESPACE;
#endif
-struct KernelContext;
+#line 21 "../../examples/heterogeneous-hello-world/shader.slang"
+struct gfx_Window_0
+{
+};
-#line 13 "shader.slang"
-struct UniformState
+
+#line 22
+struct gfx_Renderer_0
{
+};
-#line 4
- RWStructuredBuffer<float> ioBuffer_0;
+#line 23
+struct gfx_BufferResource_0
+{
+};
+struct gfx_ShaderProgram_0
+{
};
-struct KernelContext
+
+#line 26
+struct gfx_DescriptorSetLayout_0
{
- UniformState* uniformState;
- uint3 dispatchThreadID;
- uint3 groupID;
- uint3 groupDispatchThreadID;
- uint3 calcGroupThreadID() const
- {
- uint3 v = { dispatchThreadID.x - groupDispatchThreadID.x, dispatchThreadID.y - groupDispatchThreadID.y, dispatchThreadID.z - groupDispatchThreadID.z };
- return v;
- }
+};
-#line 8
- void _computeMain()
- {
+#line 24
+struct gfx_PipelineLayout_0
+{
+};
-#line 10
- uint32_t tid_0 = dispatchThreadID.x;
- float i_0 = (uniformState->ioBuffer_0)[tid_0];
- bool _S1 = i_0 < 0.50000000000000000000f;
+#line 27
+struct gfx_DescriptorSet_0
+{
+};
-#line 13
- float _S2 = i_0 + i_0;
-#line 13
- float _S3 = (F32_sqrt((i_0)));
+#line 25
+struct gfx_PipelineState_0
+{
+};
-#line 13
- float o_0 = _S1 ? _S2 : _S3;
- (uniformState->ioBuffer_0)[tid_0] = o_0;
+#line 34
+gfx_Window_0* createWindow_0(int32_t _0, int32_t _1);
-#line 8
- return;
- }
-};
+#line 35
+gfx_Renderer_0* createRenderer_0(int32_t _0, int32_t _1, gfx_Window_0* _2);
-} // anonymous
-// [numthreads(4, 1, 1)]
-SLANG_PRELUDE_EXPORT
-void computeMain_Thread(ComputeThreadVaryingInput* varyingInput, void* params, void* uniformState)
-{
- KernelContext context = {};
- context.uniformState = (UniformState*)uniformState;
- context.dispatchThreadID = {
- varyingInput->groupID.x * 4 + varyingInput->groupThreadID.x,
- varyingInput->groupID.y * 1 + varyingInput->groupThreadID.y,
- varyingInput->groupID.z * 1 + varyingInput->groupThreadID.z
- };
- context._computeMain();
-}
-// [numthreads(4, 1, 1)]
-SLANG_PRELUDE_EXPORT
-void computeMain_Group(ComputeVaryingInput* varyingInput, void* params, void* uniformState)
-{
- KernelContext context = {};
- context.uniformState = (UniformState*)uniformState;
- const uint3 start = {
- varyingInput->startGroupID.x * 4,
- varyingInput->startGroupID.y * 1,
- varyingInput->startGroupID.z * 1
- };
- context.dispatchThreadID = start;
- for (uint32_t x = start.x; x < start.x + 4; ++x)
- {
- context.dispatchThreadID.x = x;
- context._computeMain();
- }
-}
-// [numthreads(4, 1, 1)]
-SLANG_PRELUDE_EXPORT
-void computeMain(ComputeVaryingInput* varyingInput, void* params, void* uniformState)
+
+gfx_BufferResource_0* createStructuredBuffer_0(gfx_Renderer_0* _0, FixedArray<float, 4> _1);
+
+
+#line 33
+gfx_ShaderProgram_0* loadShaderProgram_0(gfx_Renderer_0* _0);
+
+
+#line 40
+gfx_DescriptorSetLayout_0* buildDescriptorSetLayout_0(gfx_Renderer_0* _0);
+
+
+#line 41
+gfx_PipelineLayout_0* buildPipeline_0(gfx_Renderer_0* _0, gfx_DescriptorSetLayout_0* _1);
+
+
+#line 42
+gfx_DescriptorSet_0* buildDescriptorSet_0(gfx_Renderer_0* _0, gfx_DescriptorSetLayout_0* _1, gfx_BufferResource_0* _2);
+
+
+
+gfx_PipelineState_0* buildPipelineState_0(gfx_ShaderProgram_0* _0, gfx_Renderer_0* _1, gfx_PipelineLayout_0* _2);
+
+
+
+void printInitialValues_0(FixedArray<float, 4> _0, int32_t _1);
+
+
+#line 51
+void dispatchComputation_0(gfx_Renderer_0* _0, gfx_PipelineState_0* _1, gfx_PipelineLayout_0* _2, gfx_DescriptorSet_0* _3);
+
+
+
+
+void print_output_0(gfx_Renderer_0* _0, gfx_BufferResource_0* _1, int32_t _2);
+
+
+
+
+bool executeComputation_0()
{
- KernelContext context = {};
- context.uniformState = (UniformState*)uniformState;
- const uint3 start = {
- varyingInput->startGroupID.x * 4,
- varyingInput->startGroupID.y * 1,
- varyingInput->startGroupID.z * 1
- };
- const uint3 end = {
- varyingInput->endGroupID.x * 4,
- varyingInput->endGroupID.y * 1,
- varyingInput->endGroupID.z * 1
- };
- for (uint32_t z = start.z; z < end.z; ++z)
- {
- context.dispatchThreadID.z = z;
- for (uint32_t y = start.y; y < end.y; ++y)
- {
- context.dispatchThreadID.y = y;
- for (uint32_t x = start.x; x < end.x; ++x)
- {
- context.dispatchThreadID.x = x;
- context._computeMain();
- }
- }
- }
+
+
+
+ FixedArray<float, 4> initialArray_0 = { 3.00000000000000000000f, -20.00000000000000000000f, -6.00000000000000000000f, 8.00000000000000000000f };
+
+
+ gfx_Window_0* _S1 = createWindow_0(int(1024), int(768));
+ gfx_Renderer_0* _S2 = createRenderer_0(int(1024), int(768), _S1);
+ gfx_BufferResource_0* _S3 = createStructuredBuffer_0(_S2, initialArray_0);
+ gfx_ShaderProgram_0* _S4 = loadShaderProgram_0(_S2);
+ gfx_DescriptorSetLayout_0* _S5 = buildDescriptorSetLayout_0(_S2);
+ gfx_PipelineLayout_0* _S6 = buildPipeline_0(_S2, _S5);
+ gfx_DescriptorSet_0* _S7 = buildDescriptorSet_0(_S2, _S5, _S3);
+ gfx_PipelineState_0* _S8 = buildPipelineState_0(_S4, _S2, _S6);
+ printInitialValues_0(initialArray_0, int(4));
+ dispatchComputation_0(_S2, _S8, _S6, _S7);
+ print_output_0(_S2, _S3, int(4));
+
+
+ return true;
}
+
+//} // anonymous
+
diff --git a/examples/heterogeneous-hello-world/shader.slang b/examples/heterogeneous-hello-world/shader.slang
index 036f63c85..a9ad66cc7 100644
--- a/examples/heterogeneous-hello-world/shader.slang
+++ b/examples/heterogeneous-hello-world/shader.slang
@@ -3,10 +3,8 @@
//TEST_INPUT:ubuffer(random(float, 4096, -1.0, 1.0), stride=4):name=ioBuffer
RWStructuredBuffer<float> ioBuffer;
-// There's some weird duplication going on here. It's not clear how we should introduce UniformState
-
[numthreads(4, 1, 1)]
-public void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
uint tid = dispatchThreadID.x;
@@ -15,3 +13,71 @@ public void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
ioBuffer[tid] = o;
}
+
+// Forward declarations of gfx types
+//
+namespace gfx {
+ struct ApplicationContext{};
+ struct Window{};
+ struct Renderer{};
+ struct BufferResource{};
+ struct PipelineLayout{};
+ struct PipelineState{};
+ struct DescriptorSetLayout{};
+ struct DescriptorSet{};
+ struct ShaderProgram{};
+}
+
+// Forward declarations of cpp functions
+//
+Ptr<gfx::ShaderProgram> loadShaderProgram(Ptr<gfx::Renderer> renderer);
+Ptr<gfx::Window> createWindow(int gWindowWidth, int gWindowHeight);
+Ptr<gfx::Renderer> createRenderer(
+ int gWindowWidth,
+ int gWindowHeight,
+ Ptr<gfx::Window> gWindow);
+Ptr<gfx::BufferResource> createStructuredBuffer(Ptr<gfx::Renderer> gRenderer, float[4] initialArray);
+Ptr<gfx::DescriptorSetLayout> buildDescriptorSetLayout(Ptr<gfx::Renderer> gRenderer);
+Ptr<gfx::PipelineLayout> buildPipeline(Ptr<gfx::Renderer> gRenderer, Ptr<gfx::DescriptorSetLayout> descriptorSetLayout);
+Ptr<gfx::DescriptorSet> buildDescriptorSet(
+ Ptr<gfx::Renderer> gRenderer,
+ Ptr<gfx::DescriptorSetLayout> descriptorSetLayout,
+ Ptr<gfx::BufferResource> gStructuredBuffer);
+Ptr<gfx::PipelineState> buildPipelineState(
+ Ptr<gfx::ShaderProgram> shaderProgram,
+ Ptr<gfx::Renderer> gRenderer,
+ Ptr<gfx::PipelineLayout> gPipelineLayout);
+void printInitialValues(float[4] initialArray, int length);
+void dispatchComputation(
+ Ptr<gfx::Renderer> gRenderer,
+ Ptr<gfx::PipelineState> gPipelineState,
+ Ptr<gfx::PipelineLayout> gPipelineLayout,
+ Ptr<gfx::DescriptorSet> gDescriptorSet);
+void print_output(
+ Ptr<gfx::Renderer> gRenderer,
+ Ptr<gfx::BufferResource> gStructuredBuffer,
+ int length);
+
+public bool executeComputation() {
+ // We will hard-code the size of our rendering window and initial array.
+ //
+ int windowWidth = 1024;
+ int windowHeight = 768;
+ float initialArray[4] = { 3.0f, -20.0f, -6.0f, 8.0f };
+
+ // Declare functions
+ let window = createWindow(windowWidth, windowHeight);
+ let renderer = createRenderer(windowWidth, windowHeight, window);
+ let structuredBuffer = createStructuredBuffer(renderer, initialArray);
+ let shaderProgram = loadShaderProgram(renderer);
+ let descriptorSetLayout = buildDescriptorSetLayout(renderer);
+ let pipelineLayout = buildPipeline(renderer, descriptorSetLayout);
+ let descriptorSet = buildDescriptorSet(renderer, descriptorSetLayout, structuredBuffer);
+ let pipelineState = buildPipelineState(shaderProgram, renderer, pipelineLayout);
+ printInitialValues(initialArray, 4);
+ dispatchComputation(renderer, pipelineState, pipelineLayout, descriptorSet);
+ print_output(renderer, structuredBuffer, 4);
+
+
+ return true;
+}