From 62161b802a8efbf6820ba79f880c99e455ab3bf6 Mon Sep 17 00:00:00 2001 From: lucy96chen <47800040+lucy96chen@users.noreply.github.com> Date: Thu, 9 Dec 2021 15:15:16 -0800 Subject: Implement instanced and indirect draw calls (#2053) * Added implementations of drawInstanced, drawIndexedInstanced, drawIndirect, and drawIndexedIndirect to both render-d3d12 and render-vk * drawInstanced test WIP * Draw calls implemented, working on debugging test * Added new test and accompanying shader file * Fixes. * Fixes. Co-authored-by: Yong He Co-authored-by: Yong He --- tools/gfx-unit-test/draw-instanced-test.cpp | 156 ++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 tools/gfx-unit-test/draw-instanced-test.cpp (limited to 'tools/gfx-unit-test/draw-instanced-test.cpp') diff --git a/tools/gfx-unit-test/draw-instanced-test.cpp b/tools/gfx-unit-test/draw-instanced-test.cpp new file mode 100644 index 000000000..e15e6beda --- /dev/null +++ b/tools/gfx-unit-test/draw-instanced-test.cpp @@ -0,0 +1,156 @@ +#include "tools/unit-test/slang-unit-test.h" + +#include "slang-gfx.h" +#include "gfx-test-util.h" +#include "tools/gfx-util/shader-cursor.h" +#include "source/core/slang-basic.h" + +using namespace gfx; + +namespace gfx_test +{ + struct Vertex + { + float position[3]; + float color[3]; + }; + + static const int kVertexCount = 3; + static const Vertex kVertexData[kVertexCount] = + { + { { -1, -1, 0.5 }, { 1, 0, 0 } }, + { { -1, 3, 0.5 }, { 1, 0, 0 } }, + { { 3, -1, 0.5 }, { 1, 0, 0 } }, + }; + + void drawInstancedTestImpl(IDevice* device, UnitTestContext* context) + { + Slang::ComPtr transientHeap; + ITransientResourceHeap::Desc transientHeapDesc = {}; + transientHeapDesc.constantBufferSize = 4096; + GFX_CHECK_CALL_ABORT( + device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef())); + + ComPtr shaderProgram; + slang::ProgramLayout* slangReflection; + GFX_CHECK_CALL_ABORT(loadGraphicsProgram(device, shaderProgram, "graphics-smoke", "vertexMain", "fragmentMain", slangReflection)); + + Format format = Format::R32G32B32A32_FLOAT; + + InputElementDesc inputElements[] = { + { "POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position) }, + { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color) }, + }; + ComPtr inputLayout = device->createInputLayout(inputElements, 2); + SLANG_CHECK_ABORT(inputLayout != nullptr); + + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::VertexBuffer; + vertexBufferDesc.allowedStates = ResourceState::VertexBuffer; + ComPtr vertexBuffer = device->createBufferResource(vertexBufferDesc, &kVertexData[0]); + SLANG_CHECK_ABORT(vertexBuffer != nullptr); + + IFramebufferLayout::AttachmentLayout attachmentLayout; + attachmentLayout.format = format; + attachmentLayout.sampleCount = 1; + + IFramebufferLayout::Desc framebufferLayoutDesc; + framebufferLayoutDesc.renderTargetCount = 1; + framebufferLayoutDesc.renderTargets = &attachmentLayout; + ComPtr framebufferLayout = device->createFramebufferLayout(framebufferLayoutDesc); + + GraphicsPipelineStateDesc pipelineDesc = {}; + pipelineDesc.program = shaderProgram.get(); + pipelineDesc.inputLayout = inputLayout; + pipelineDesc.framebufferLayout = framebufferLayout; + pipelineDesc.depthStencil.depthTestEnable = false; + pipelineDesc.depthStencil.depthWriteEnable = false; + ComPtr pipelineState; + GFX_CHECK_CALL_ABORT( + device->createGraphicsPipelineState(pipelineDesc, pipelineState.writeRef())); + + ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics }; + auto queue = device->createCommandQueue(queueDesc); + auto commandBuffer = transientHeap->createCommandBuffer(); + + IRenderPassLayout::Desc renderPassDesc = {}; + renderPassDesc.framebufferLayout = framebufferLayout; + renderPassDesc.renderTargetCount = 1; + IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {}; + renderTargetAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear; + renderTargetAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store; + renderTargetAccess.initialState = ResourceState::Undefined; + renderTargetAccess.finalState = ResourceState::CopySource; + renderPassDesc.renderTargetAccess = &renderTargetAccess; + ComPtr renderPass = device->createRenderPassLayout(renderPassDesc); + + const int width = 2; + const int height = 2; + + gfx::ITextureResource::Desc colorBufferDesc; + colorBufferDesc.type = IResource::Type::Texture2D; + colorBufferDesc.size.width = width; + colorBufferDesc.size.height = height; + colorBufferDesc.size.depth = 1; + colorBufferDesc.numMipLevels = 1; + colorBufferDesc.format = format; + colorBufferDesc.defaultState = ResourceState::RenderTarget; + colorBufferDesc.allowedStates = { ResourceState::RenderTarget, ResourceState::CopySource }; + ComPtr colorBuffer = device->createTextureResource(colorBufferDesc, nullptr); + + gfx::IResourceView::Desc colorBufferViewDesc; + memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc)); + colorBufferViewDesc.format = format; + colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; + colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; + ComPtr rtv = + device->createTextureView(colorBuffer.get(), colorBufferViewDesc); + + gfx::IFramebuffer::Desc framebufferDesc; + framebufferDesc.renderTargetCount = 1; + framebufferDesc.depthStencilView = nullptr; + framebufferDesc.renderTargetViews = rtv.readRef(); + framebufferDesc.layout = framebufferLayout; + ComPtr framebuffer = device->createFramebuffer(framebufferDesc); + + auto encoder = commandBuffer->encodeRenderCommands(renderPass, framebuffer); + auto rootObject = encoder->bindPipeline(pipelineState); + + UInt vertexCount = 3; + UInt instanceCount = 1; + UInt startVertex = 0; + UInt startInstanceLocation = 0; + + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = width; + viewport.extentY = height; + encoder->setViewportAndScissor(viewport); + + encoder->setVertexBuffer(0, vertexBuffer, sizeof(Vertex)); + encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + encoder->drawInstanced(vertexCount, instanceCount, startVertex, startInstanceLocation); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + queue->waitOnHost(); + + float expectedResult[] = { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }; + compareComputeResult(device, colorBuffer, ResourceState::CopySource, expectedResult, 32, 2); + } + + SLANG_UNIT_TEST(drawInstancedD3D12) + { + runTestImpl(drawInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + } + +#if 0 + SLANG_UNIT_TEST(drawInstancedVulkan) + { + runTestImpl(drawInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + } +#endif + } -- cgit v1.2.3