summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-03-04 16:25:58 -0800
committerGitHub <noreply@github.com>2021-03-04 16:25:58 -0800
commita5ac4999b4dea546a7ef824669ab1809224b6448 (patch)
tree15bb22eb98a94f7f81489deef55396461501d3dc /examples
parent13ff0bd345990c0fdfb7b52ebd5339cddb04889e (diff)
Refactor `gfx` to surface `CommandBuffer` interface. (#1735)
* Refactor `gfx` to surface `CommandBuffer` interface. * Fixes. * Fix code review issues, and make vulkan runnable on devices without VK_EXT_extended_dynamic_states. * Update solution files * Move out-of-date examples to examples/experimental Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/experimental/heterogeneous-hello-world/README.md (renamed from examples/heterogeneous-hello-world/README.md)0
-rw-r--r--examples/experimental/heterogeneous-hello-world/main.cpp (renamed from examples/heterogeneous-hello-world/main.cpp)36
-rw-r--r--examples/experimental/heterogeneous-hello-world/shader.cpp (renamed from examples/heterogeneous-hello-world/shader.cpp)3
-rw-r--r--examples/experimental/heterogeneous-hello-world/shader.slang (renamed from examples/heterogeneous-hello-world/shader.slang)0
-rw-r--r--examples/experimental/model-viewer/README.md (renamed from examples/model-viewer/README.md)0
-rw-r--r--examples/experimental/model-viewer/cube.mtl (renamed from examples/model-viewer/cube.mtl)0
-rw-r--r--examples/experimental/model-viewer/main.cpp (renamed from examples/model-viewer/main.cpp)13
-rw-r--r--examples/experimental/model-viewer/shaders.slang (renamed from examples/model-viewer/shaders.slang)0
-rw-r--r--examples/gpu-printing/main.cpp19
-rw-r--r--examples/hello-world/main.cpp68
-rw-r--r--examples/model-viewer/cube.obj43
-rw-r--r--examples/shader-object/main.cpp29
-rw-r--r--examples/shader-toy/main.cpp87
13 files changed, 163 insertions, 135 deletions
diff --git a/examples/heterogeneous-hello-world/README.md b/examples/experimental/heterogeneous-hello-world/README.md
index 709652922..709652922 100644
--- a/examples/heterogeneous-hello-world/README.md
+++ b/examples/experimental/heterogeneous-hello-world/README.md
diff --git a/examples/heterogeneous-hello-world/main.cpp b/examples/experimental/heterogeneous-hello-world/main.cpp
index 010434bfa..372fcd615 100644
--- a/examples/heterogeneous-hello-world/main.cpp
+++ b/examples/experimental/heterogeneous-hello-world/main.cpp
@@ -1,3 +1,9 @@
+// This example is out of date and currently disabled from build.
+// The `gfx` layer has been refactored with a new command list based
+// model. The example must be updated to use the new `gfx` interface
+// before it can be included in build.
+
+#if 0
// main.cpp
// This file implements an extremely simple example of loading and
@@ -236,7 +242,7 @@ void printInitialValues(float* initialArray, int length)
}
void dispatchComputation(
- gfx::IRenderer* gRenderer,
+ gfx::ICommandQueue* gQueue,
gfx::IPipelineState* gPipelineState,
gfx::IPipelineLayout* gPipelineLayout,
gfx::IDescriptorSet* gDescriptorSet,
@@ -244,11 +250,13 @@ void dispatchComputation(
unsigned int gridDimsY,
unsigned int gridDimsZ)
{
-
- gRenderer->setPipelineState(gPipelineState);
- gRenderer->setDescriptorSet(PipelineType::Compute, gPipelineLayout, 0, gDescriptorSet);
-
- gRenderer->dispatchCompute(gridDimsX, gridDimsY, gridDimsZ);
+ auto cmdBuf = gQueue->createCommandBuffer();
+ auto encoder = cmdBuf->encodeComputeCommands();
+ encoder->setPipelineState(gPipelineState);
+ encoder->setDescriptorSet(PipelineType::Compute, gPipelineLayout, 0, gDescriptorSet);
+ encoder->dispatchCompute(gridDimsX, gridDimsY, gridDimsZ);
+ encoder->endEncoding();
+ gQueue->executeCommandBuffer(cmdBuf);
}
void print_output(
@@ -256,7 +264,9 @@ void print_output(
gfx::IBufferResource* structuredBuffer,
int length)
{
- if (float* outputData = (float*)renderer->map(structuredBuffer, MapFlavor::HostRead))
+ ComPtr<ISlangBlob> blob;
+ renderer->readBufferResource(structuredBuffer, 0, length * sizeof(float), blob.writeRef());
+ if (float* outputData = (float*)blob->getBufferPointer())
{
// Print out the values the the kernel produced
printf("After: \n");
@@ -265,8 +275,6 @@ void print_output(
printf("%f, ", outputData[i]);
}
printf("\n");
-
- renderer->unmap(structuredBuffer);
}
}
@@ -321,10 +329,10 @@ 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, unsigned int gridDimsX, unsigned int gridDimsY, unsigned int gridDimsZ)
+void dispatchComputation_0(gfx_CommandQueue_0* _0, gfx_PipelineState_0* _1, gfx_PipelineLayout_0* _2, gfx_DescriptorSet_0* _3, unsigned int gridDimsX, unsigned int gridDimsY, unsigned int gridDimsZ)
{
dispatchComputation(
- (gfx::IRenderer*)_0,
+ (gfx::ICommandQueue*)_0,
(gfx::IPipelineState*)_1,
(gfx::IPipelineLayout*)_2,
(gfx::IDescriptorSet*)_3,
@@ -343,9 +351,9 @@ gfx_BufferResource_0* unconvertBuffer_0(RWStructuredBuffer<float> _0) {
return (gfx_BufferResource_0*)(_0.data);
}
-void print_output_0(gfx_Renderer_0* _0, gfx_BufferResource_0* _1, int32_t _2)
+void print_output_0(gfx_CommandQueue_0* _0, gfx_BufferResource_0* _1, int32_t _2)
{
- print_output((gfx::IRenderer*)_0, (gfx::IBufferResource*)_1, _2);
+ print_output((gfx::ICommandQueue*)_0, (gfx::IBufferResource*)_1, _2);
}
// This "inner" main function is used by the platform abstraction
@@ -368,3 +376,5 @@ void innerMain(ApplicationContext* context)
// invoke the `innerMain` above.
//
GFX_CONSOLE_MAIN(innerMain)
+
+#endif
diff --git a/examples/heterogeneous-hello-world/shader.cpp b/examples/experimental/heterogeneous-hello-world/shader.cpp
index 640e8aa3c..5a8dd7815 100644
--- a/examples/heterogeneous-hello-world/shader.cpp
+++ b/examples/experimental/heterogeneous-hello-world/shader.cpp
@@ -1,3 +1,4 @@
+#if 0
#include "../../prelude/slang-cpp-prelude.h"
@@ -140,6 +141,7 @@ bool executeComputation_0()
gfx_Window_0* _S9 = createWindow_0(int(1024), int(768));
gfx_Renderer_0* _S10 = createRenderer_0(int(1024), int(768), _S9);
+ gfx_CommandQueue_0* _
gfx_BufferResource_0* _S11 = createStructuredBuffer_0(_S10, initialArray_0);
Vector<uint32_t, 3> _S12 = make_VecU3(uint32_t(int(4)), uint32_t(int(1)), uint32_t(int(1)));
RWStructuredBuffer<float> _S13 = convertBuffer_0(_S11);
@@ -192,3 +194,4 @@ void computeMain(ComputeVaryingInput* varyingInput, void* entryPointParams, void
}
}
}
+#endif
diff --git a/examples/heterogeneous-hello-world/shader.slang b/examples/experimental/heterogeneous-hello-world/shader.slang
index 47c883b39..47c883b39 100644
--- a/examples/heterogeneous-hello-world/shader.slang
+++ b/examples/experimental/heterogeneous-hello-world/shader.slang
diff --git a/examples/model-viewer/README.md b/examples/experimental/model-viewer/README.md
index a350a48a2..a350a48a2 100644
--- a/examples/model-viewer/README.md
+++ b/examples/experimental/model-viewer/README.md
diff --git a/examples/model-viewer/cube.mtl b/examples/experimental/model-viewer/cube.mtl
index 6c8eeb10b..6c8eeb10b 100644
--- a/examples/model-viewer/cube.mtl
+++ b/examples/experimental/model-viewer/cube.mtl
diff --git a/examples/model-viewer/main.cpp b/examples/experimental/model-viewer/main.cpp
index c9693e529..d4bc21776 100644
--- a/examples/model-viewer/main.cpp
+++ b/examples/experimental/model-viewer/main.cpp
@@ -1,3 +1,9 @@
+// This example is out of date and currently disabled from build.
+// The `gfx` layer has been refactored with a new shader-object model
+// that will greatly simplify shader binding and specialization.
+// This example should be updated to use the shader-object API in `gfx`.
+
+#if 0
// main.cpp
//
@@ -2214,7 +2220,6 @@ Result initialize()
//
void renderFrame()
{
- gRenderer->beginFrame();
gui->beginFrame();
// In order to see that things are rendering properly we need some
@@ -2402,10 +2407,6 @@ void renderFrame()
ImGui::End();
- gui->endFrame();
-
- gRenderer->makeSwapchainImagePresentable(gSwapchain);
- gRenderer->endFrame();
gSwapchain->present();
}
@@ -2441,3 +2442,5 @@ void innerMain(ApplicationContext* context)
app.finalize();
}
GFX_UI_MAIN(innerMain)
+
+#endif
diff --git a/examples/model-viewer/shaders.slang b/examples/experimental/model-viewer/shaders.slang
index 15ce0120d..15ce0120d 100644
--- a/examples/model-viewer/shaders.slang
+++ b/examples/experimental/model-viewer/shaders.slang
diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp
index 4f79147f6..63eb31a82 100644
--- a/examples/gpu-printing/main.cpp
+++ b/examples/gpu-printing/main.cpp
@@ -175,19 +175,26 @@ Result execute()
printBufferViewDesc.type = IResourceView::Type::UnorderedAccess;
auto printBufferView = gRenderer->createBufferView(printBuffer, printBufferViewDesc);
+ ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics};
+ auto queue = gRenderer->createCommandQueue(queueDesc);
+ auto commandBuffer = queue->createCommandBuffer();
+ auto encoder = commandBuffer->encodeComputeCommands();
// TODO: need to copy a zero into the start of the print buffer!
gDescriptorSet->setResource(0, 0, printBufferView);
- gRenderer->setDescriptorSet(PipelineType::Compute, gPipelineLayout, 0, gDescriptorSet);
-
- gRenderer->setPipelineState(gPipelineState);
- gRenderer->dispatchCompute(1, 1, 1);
+ encoder->setDescriptorSet(gPipelineLayout, 0, gDescriptorSet);
+ encoder->setPipelineState(gPipelineState);
+ encoder->dispatchCompute(1, 1, 1);
+ encoder->endEncoding();
+ commandBuffer->close();
+ queue->executeCommandBuffer(commandBuffer);
// TODO: need to copy from the print buffer to a staging buffer...
- auto printBufferData = (uint32_t*) gRenderer->map(printBuffer, MapFlavor::HostRead);
+ ComPtr<ISlangBlob> blob;
+ gRenderer->readBufferResource(printBuffer, 0, printBufferSize, blob.writeRef());
- gGPUPrinting.processGPUPrintCommands(printBufferData, printBufferSize);
+ gGPUPrinting.processGPUPrintCommands(blob->getBufferPointer(), printBufferSize);
return SLANG_OK;
}
diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp
index f0ea3eb2a..47016b48d 100644
--- a/examples/hello-world/main.cpp
+++ b/examples/hello-world/main.cpp
@@ -219,6 +219,8 @@ ComPtr<gfx::IShaderObject> gRootObject;
ComPtr<gfx::ISwapchain> gSwapchain;
List<ComPtr<gfx::IFramebuffer>> gFramebuffers;
ComPtr<gfx::IBufferResource> gVertexBuffer;
+ComPtr<gfx::IRenderPassLayout> gRenderPass;
+ComPtr<gfx::ICommandQueue> gQueue;
// Now that we've covered the function that actually loads and
// compiles our Slang shade code, we can go through the rest
@@ -246,6 +248,10 @@ Slang::Result initialize()
gfx::Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
if(SLANG_FAILED(res)) return res;
+ ICommandQueue::Desc queueDesc = {};
+ queueDesc.type = ICommandQueue::QueueType::Graphics;
+ gQueue = gRenderer->createCommandQueue(queueDesc);
+
// Now we will create objects needed to configur the "input assembler"
// (IA) stage of the D3D pipeline.
//
@@ -316,6 +322,7 @@ Slang::Result initialize()
swapchainDesc.width = gWindowWidth;
swapchainDesc.height = gWindowHeight;
swapchainDesc.imageCount = kSwapchainImageCount;
+ swapchainDesc.queue = gQueue;
gSwapchain = gRenderer->createSwapchain(
swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
@@ -331,7 +338,7 @@ Slang::Result initialize()
for (uint32_t i = 0; i < kSwapchainImageCount; i++)
{
- gfx::ITextureResource::Desc depthBufferDesc;
+ gfx::ITextureResource::Desc depthBufferDesc = {};
depthBufferDesc.setDefaults(gfx::IResource::Usage::DepthWrite);
depthBufferDesc.init2D(
gfx::IResource::Type::Texture2D,
@@ -345,23 +352,21 @@ Slang::Result initialize()
ComPtr<gfx::ITextureResource> colorBuffer;
gSwapchain->getImage(i, colorBuffer.writeRef());
- gfx::IResourceView::Desc colorBufferViewDesc;
- memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc));
+ gfx::IResourceView::Desc colorBufferViewDesc = {};
colorBufferViewDesc.format = gSwapchain->getDesc().format;
colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D;
colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget;
ComPtr<gfx::IResourceView> rtv =
gRenderer->createTextureView(colorBuffer.get(), colorBufferViewDesc);
- gfx::IResourceView::Desc depthBufferViewDesc;
- memset(&depthBufferViewDesc, 0, sizeof(depthBufferViewDesc));
+ gfx::IResourceView::Desc depthBufferViewDesc = {};
depthBufferViewDesc.format = gfx::Format::D_Float32;
depthBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D;
depthBufferViewDesc.type = gfx::IResourceView::Type::DepthStencil;
ComPtr<gfx::IResourceView> dsv =
gRenderer->createTextureView(depthBufferResource.get(), depthBufferViewDesc);
- gfx::IFramebuffer::Desc framebufferDesc;
+ gfx::IFramebuffer::Desc framebufferDesc = {};
framebufferDesc.renderTargetCount = 1;
framebufferDesc.depthStencilView = dsv.get();
framebufferDesc.renderTargetViews = rtv.readRef();
@@ -383,6 +388,23 @@ Slang::Result initialize()
gPipelineState = pipelineState;
+ gfx::IRenderPassLayout::Desc renderPassDesc = {};
+ renderPassDesc.framebufferLayout = framebufferLayout;
+ renderPassDesc.renderTargetCount = 1;
+ IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {};
+ IRenderPassLayout::AttachmentAccessDesc depthStencilAccess = {};
+ renderTargetAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear;
+ renderTargetAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store;
+ renderTargetAccess.initialState = ResourceState::Undefined;
+ renderTargetAccess.finalState = ResourceState::Present;
+ depthStencilAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear;
+ depthStencilAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store;
+ depthStencilAccess.initialState = ResourceState::Undefined;
+ depthStencilAccess.finalState = ResourceState::DepthWrite;
+ renderPassDesc.renderTargetAccess = &renderTargetAccess;
+ renderPassDesc.depthStencilAccess = &depthStencilAccess;
+ gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc);
+
// Once we've initialized all the graphics API objects,
// it is time to show our application window and start rendering.
//
@@ -398,22 +420,16 @@ Slang::Result initialize()
//
void renderFrame()
{
- gRenderer->beginFrame();
uint32_t frameBufferIndex = gSwapchain->acquireNextImage();
- gRenderer->setFramebuffer(gFramebuffers[frameBufferIndex]);
+
+ ComPtr<ICommandBuffer> commandBuffer = gQueue->createCommandBuffer();
+ auto renderEncoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]);
gfx::Viewport viewport = {};
viewport.maxZ = 1.0f;
viewport.extentX = (float)gWindowWidth;
viewport.extentY = (float)gWindowHeight;
- gRenderer->setViewportAndScissor(viewport);
-
-
- // We start by clearing our framebuffer, which only has a color target.
- //
- static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
- gRenderer->setClearColor(kClearColor);
- gRenderer->clearFrame();
+ renderEncoder->setViewportAndScissor(viewport);
// We will update the model-view-projection matrix that is passed
// into the shader code via the `Uniforms` buffer on a per-frame
@@ -485,31 +501,31 @@ void renderFrame()
// PSO, binding our root shader object to it (which references
// the `Uniforms` buffer that will filled in above).
//
- gRenderer->setPipelineState(gPipelineState);
- gRenderer->bindRootShaderObject(PipelineType::Graphics, gRootObject);
+ renderEncoder->setPipelineState(gPipelineState);
+ renderEncoder->bindRootShaderObject(gRootObject);
// We also need to set up a few pieces of fixed-function pipeline
// state that are not bound by the pipeline state above.
//
- gRenderer->setVertexBuffer(0, gVertexBuffer, sizeof(Vertex));
- gRenderer->setPrimitiveTopology(PrimitiveTopology::TriangleList);
+ renderEncoder->setVertexBuffer(0, gVertexBuffer, sizeof(Vertex));
+ renderEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList);
// Finally, we are ready to issue a draw call for a single triangle.
//
- gRenderer->draw(3);
+ renderEncoder->draw(3);
+ renderEncoder->endEncoding();
+ commandBuffer->close();
+ gQueue->executeCommandBuffer(commandBuffer);
// With that, we are done drawing for one frame, and ready for the next.
//
- gRenderer->makeSwapchainImagePresentable(gSwapchain);
-
- gRenderer->endFrame();
-
gSwapchain->present();
}
void finalize()
{
- gRenderer->waitForGpu();
+ gQueue->wait();
+ gSwapchain = nullptr;
destroyWindow(gWindow);
}
diff --git a/examples/model-viewer/cube.obj b/examples/model-viewer/cube.obj
deleted file mode 100644
index 2f7de8a92..000000000
--- a/examples/model-viewer/cube.obj
+++ /dev/null
@@ -1,43 +0,0 @@
-mtllib cube.mtl
-o Cube
-v 1.000000 -1.000000 -1.000000
-v 1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 -1.000000
-v 1.000000 1.000000 -1.000000
-v 1.000000 1.000000 1.000000
-v -1.000000 1.000000 1.000000
-v -1.000000 1.000000 -1.000000
-vn 0.000000 -1.000000 0.000000
-vn 0.000000 1.000000 0.000000
-vn 1.000000 0.000000 0.000000
-vn 0.000000 0.000000 1.000000
-vn -1.000000 0.000000 0.000000
-vn 0.000000 0.000000 -1.000000
-
-v -10 -1 -10
-v 10 -1 -10
-v 10 -1 10
-v -10 -1 10
-vn 0 1 0
-
-usemtl Red
-s off
-f 2//3 6//3 5//3 1//3
-f 4//5 8//5 7//5 3//5
-
-usemtl Green
-s off
-f 4//1 3//1 2//1 1//1
-f 6//2 7//2 8//2 5//2
-
-usemtl Blue
-s off
-f 3//4 7//4 6//4 2//4
-f 8//6 4//6 1//6 5//6
-
-o Ground
-usemtl Ground
-s off
-f 9//7 10//7 11//7 12//7
-
diff --git a/examples/shader-object/main.cpp b/examples/shader-object/main.cpp
index 9b1b4de72..d368cd9aa 100644
--- a/examples/shader-object/main.cpp
+++ b/examples/shader-object/main.cpp
@@ -136,7 +136,7 @@ int main()
// interacting with the graphics API.
Slang::ComPtr<gfx::IRenderer> renderer;
IRenderer::Desc rendererDesc = {};
- rendererDesc.rendererType = RendererType::CUDA;
+ rendererDesc.rendererType = RendererType::DirectX11;
SLANG_RETURN_ON_FAIL(gfxCreateRenderer(&rendererDesc, renderer.writeRef()));
// Now we can load the shader code.
@@ -146,7 +146,7 @@ int main()
slang::ProgramLayout* slangReflection;
SLANG_RETURN_ON_FAIL(loadShaderProgram(renderer, shaderProgram, slangReflection));
- // Create a pipelien state with the loaded shader.
+ // Create a pipeline state with the loaded shader.
gfx::ComputePipelineStateDesc pipelineDesc = {};
pipelineDesc.program = shaderProgram.get();
ComPtr<gfx::IPipelineState> pipelineState;
@@ -211,17 +211,26 @@ int main()
// We have set up all required parameters in entry-point object, now it is time
// to bind the pipeline and root object and launch the kernel.
- renderer->beginFrame();
- renderer->setPipelineState(pipelineState);
- SLANG_RETURN_ON_FAIL(renderer->bindRootShaderObject(gfx::PipelineType::Compute, rootObject));
- renderer->dispatchCompute(1, 1, 1);
- renderer->endFrame();
+ {
+ ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics};
+ auto queue = renderer->createCommandQueue(queueDesc);
+ auto commandBuffer = queue->createCommandBuffer();
+ auto encoder = commandBuffer->encodeComputeCommands();
+ encoder->setPipelineState(pipelineState);
+ encoder->bindRootShaderObject(rootObject);
+ encoder->dispatchCompute(1, 1, 1);
+ encoder->endEncoding();
+ commandBuffer->close();
+ queue->executeCommandBuffer(commandBuffer);
+ queue->wait();
+ }
// Read back the results.
- renderer->waitForGpu();
- float* result = (float*)renderer->map(numbersBuffer, gfx::MapFlavor::HostRead);
+ ComPtr<ISlangBlob> resultBlob;
+ SLANG_RETURN_ON_FAIL(renderer->readBufferResource(
+ numbersBuffer, 0, numberCount * sizeof(float), resultBlob.writeRef()));
+ auto result = reinterpret_cast<const float*>(resultBlob->getBufferPointer());
for (int i = 0; i < numberCount; i++)
printf("%f\n", result[i]);
- renderer->unmap(numbersBuffer);
return SLANG_OK;
}
diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp
index 697bb1044..0d058fa2c 100644
--- a/examples/shader-toy/main.cpp
+++ b/examples/shader-toy/main.cpp
@@ -339,6 +339,8 @@ ComPtr<gfx::IDescriptorSet> gDescriptorSet;
ComPtr<gfx::IBufferResource> gVertexBuffer;
ComPtr<gfx::ISwapchain> gSwapchain;
Slang::List<ComPtr<gfx::IFramebuffer>> gFramebuffers;
+ComPtr<gfx::IRenderPassLayout> gRenderPass;
+ComPtr<gfx::ICommandQueue> gQueue;
Result initialize()
{
@@ -355,6 +357,10 @@ Result initialize()
Result res = gfxCreateRenderer(&rendererDesc, gRenderer.writeRef());
if(SLANG_FAILED(res)) return res;
+ ICommandQueue::Desc queueDesc = {};
+ queueDesc.type = ICommandQueue::QueueType::Graphics;
+ gQueue = gRenderer->createCommandQueue(queueDesc);
+
int constantBufferSize = sizeof(Uniforms);
IBufferResource::Desc constantBufferDesc;
@@ -423,6 +429,7 @@ Result initialize()
swapchainDesc.width = gWindowWidth;
swapchainDesc.height = gWindowHeight;
swapchainDesc.imageCount = kSwapchainImageCount;
+ swapchainDesc.queue = gQueue;
gSwapchain = gRenderer->createSwapchain(
swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow)));
@@ -489,6 +496,24 @@ Result initialize()
gPipelineState = pipelineState;
+ // Create render pass.
+ gfx::IRenderPassLayout::Desc renderPassDesc = {};
+ renderPassDesc.framebufferLayout = framebufferLayout;
+ renderPassDesc.renderTargetCount = 1;
+ IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {};
+ IRenderPassLayout::AttachmentAccessDesc depthStencilAccess = {};
+ renderTargetAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear;
+ renderTargetAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store;
+ renderTargetAccess.initialState = ResourceState::Undefined;
+ renderTargetAccess.finalState = ResourceState::Present;
+ depthStencilAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear;
+ depthStencilAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store;
+ depthStencilAccess.initialState = ResourceState::Undefined;
+ depthStencilAccess.finalState = ResourceState::DepthWrite;
+ renderPassDesc.renderTargetAccess = &renderTargetAccess;
+ renderPassDesc.depthStencilAccess = &depthStencilAccess;
+ gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc);
+
showWindow(gWindow);
return SLANG_OK;
@@ -506,26 +531,18 @@ uint64_t startTime = 0;
void renderFrame()
{
- gRenderer->beginFrame();
auto frameIndex = gSwapchain->acquireNextImage();
- gRenderer->setFramebuffer(gFramebuffers[frameIndex]);
+ auto commandBuffer = gQueue->createCommandBuffer();
if( firstTime )
{
startTime = getCurrentTime();
firstTime = false;
}
- gfx::Viewport viewport = {};
- viewport.maxZ = 1.0f;
- viewport.extentX = (float)gWindowWidth;
- viewport.extentY = (float)gWindowHeight;
- gRenderer->setViewportAndScissor(viewport);
-
- static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
- gRenderer->setClearColor(kClearColor);
- gRenderer->clearFrame();
+ // Update uniform buffer.
+ auto uploadEncoder = commandBuffer->encodeResourceCommands();
- if(Uniforms* uniforms = (Uniforms*) gRenderer->map(gConstantBuffer, MapFlavor::WriteDiscard))
+ Uniforms uniforms = {};
{
bool isMouseClick = isMouseDown && !wasMouseDown;
wasMouseDown = isMouseDown;
@@ -536,35 +553,41 @@ void renderFrame()
clickMouseY = lastMouseY;
}
- uniforms->iMouse[0] = lastMouseX;
- uniforms->iMouse[1] = lastMouseY;
- uniforms->iMouse[2] = isMouseDown ? clickMouseX : -clickMouseX;
- uniforms->iMouse[3] = isMouseClick ? clickMouseY : -clickMouseY;
- uniforms->iTime = float( double(getCurrentTime() - startTime) / double(getTimerFrequency()) );
- uniforms->iResolution[0] = float(gWindowWidth);
- uniforms->iResolution[1] = float(gWindowHeight);
+ uniforms.iMouse[0] = lastMouseX;
+ uniforms.iMouse[1] = lastMouseY;
+ uniforms.iMouse[2] = isMouseDown ? clickMouseX : -clickMouseX;
+ uniforms.iMouse[3] = isMouseClick ? clickMouseY : -clickMouseY;
+ uniforms.iTime = float( double(getCurrentTime() - startTime) / double(getTimerFrequency()) );
+ uniforms.iResolution[0] = float(gWindowWidth);
+ uniforms.iResolution[1] = float(gWindowHeight);
- gRenderer->unmap(gConstantBuffer);
+ uploadEncoder->uploadBufferData(gConstantBuffer, 0, sizeof(Uniforms), &uniforms);
}
+ uploadEncoder->endEncoding();
- gRenderer->setPipelineState(gPipelineState);
- gRenderer->setDescriptorSet(PipelineType::Graphics, gPipelineLayout, 0, gDescriptorSet);
-
- gRenderer->setVertexBuffer(0, gVertexBuffer, sizeof(FullScreenTriangle::Vertex));
- gRenderer->setPrimitiveTopology(PrimitiveTopology::TriangleList);
-
- gRenderer->draw(3);
-
- gRenderer->makeSwapchainImagePresentable(gSwapchain);
-
- gRenderer->endFrame();
+ // Encode render commands.
+ auto encoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameIndex]);
+ gfx::Viewport viewport = {};
+ viewport.maxZ = 1.0f;
+ viewport.extentX = (float)gWindowWidth;
+ viewport.extentY = (float)gWindowHeight;
+ encoder->setViewportAndScissor(viewport);
+ encoder->setPipelineState(gPipelineState);
+ encoder->setDescriptorSet(gPipelineLayout, 0, gDescriptorSet);
+ encoder->setVertexBuffer(0, gVertexBuffer, sizeof(FullScreenTriangle::Vertex));
+ encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList);
+ encoder->draw(3);
+ encoder->endEncoding();
+ commandBuffer->close();
+
+ gQueue->executeCommandBuffer(commandBuffer);
gSwapchain->present();
}
void finalize()
{
- gRenderer->waitForGpu();
+ gQueue->wait();
destroyWindow(gWindow);
}