diff options
| author | Yong He <yonghe@outlook.com> | 2021-03-04 16:25:58 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-04 16:25:58 -0800 |
| commit | a5ac4999b4dea546a7ef824669ab1809224b6448 (patch) | |
| tree | 15bb22eb98a94f7f81489deef55396461501d3dc /examples | |
| parent | 13ff0bd345990c0fdfb7b52ebd5339cddb04889e (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.cpp | 19 | ||||
| -rw-r--r-- | examples/hello-world/main.cpp | 68 | ||||
| -rw-r--r-- | examples/model-viewer/cube.obj | 43 | ||||
| -rw-r--r-- | examples/shader-object/main.cpp | 29 | ||||
| -rw-r--r-- | examples/shader-toy/main.cpp | 87 |
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); } |
