diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2022-06-14 21:08:51 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-14 21:08:51 -0700 |
| commit | 69cb218100f593036d1a89357303f9c1368841ea (patch) | |
| tree | 7fe28be1c354267dd440bfbb4d1f37647436b769 /tools/gfx-unit-test/swap-chain-resize-test.cpp | |
| parent | ebcda2ec8b1cfb54f52329bb1134511ca4d4dbff (diff) | |
Swapchain resize now draws both before and after the resize operation (#2281)
Diffstat (limited to 'tools/gfx-unit-test/swap-chain-resize-test.cpp')
| -rw-r--r-- | tools/gfx-unit-test/swap-chain-resize-test.cpp | 165 |
1 files changed, 161 insertions, 4 deletions
diff --git a/tools/gfx-unit-test/swap-chain-resize-test.cpp b/tools/gfx-unit-test/swap-chain-resize-test.cpp index 903deba30..3940ebd6d 100644 --- a/tools/gfx-unit-test/swap-chain-resize-test.cpp +++ b/tools/gfx-unit-test/swap-chain-resize-test.cpp @@ -11,6 +11,20 @@ using namespace Slang; namespace gfx_test { + struct Vertex + { + float position[3]; + }; + + static const int kVertexCount = 3; + static const Vertex kVertexData[kVertexCount] = + { + // Triangle 1 + { 0, 0, 1 }, + { 4, 0, 1 }, + { 0, 4, 1 }, + }; + struct SwapchainResizeTest { IDevice* device; @@ -20,9 +34,18 @@ namespace gfx_test ComPtr<ICommandQueue> queue; ComPtr<ISwapchain> swapchain; - static const GfxCount width = 500; - static const GfxCount height = 500; + ComPtr<ITransientResourceHeap> transientHeap; + ComPtr<gfx::IFramebufferLayout> framebufferLayout; + ComPtr<IPipelineState> pipelineState; + ComPtr<IRenderPassLayout> renderPass; + List<ComPtr<IFramebuffer>> framebuffers; + + ComPtr<IBufferResource> vertexBuffer; + + GfxCount width = 500; + GfxCount height = 500; static const int kSwapchainImageCount = 2; + const Format format = Format::R8G8B8A8_UNORM; void init(IDevice* device, UnitTestContext* context) { @@ -30,6 +53,33 @@ namespace gfx_test this->context = context; } + void createSwapchainFramebuffers() + { + framebuffers.clear(); + for (GfxIndex i = 0; i < kSwapchainImageCount; ++i) + { + ComPtr<ITextureResource> colorBuffer; + swapchain->getImage(i, colorBuffer.writeRef()); + + gfx::IResourceView::Desc colorBufferViewDesc; + memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc)); + colorBufferViewDesc.format = swapchain->getDesc().format; + colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; + colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; + auto rtv = device->createTextureView(colorBuffer.get(), colorBufferViewDesc); + + gfx::IFramebuffer::Desc framebufferDesc; + framebufferDesc.renderTargetCount = 1; + framebufferDesc.depthStencilView = nullptr; + framebufferDesc.renderTargetViews = rtv.readRef(); + framebufferDesc.layout = framebufferLayout; + ComPtr<IFramebuffer> framebuffer; + GFX_CHECK_CALL_ABORT(device->createFramebuffer(framebufferDesc, framebuffer.writeRef())); + + framebuffers.add(framebuffer); + } + } + void createRequiredResources() { platform::Application::init(); @@ -52,15 +102,122 @@ namespace gfx_test swapchainDesc.imageCount = kSwapchainImageCount; swapchainDesc.queue = queue; WindowHandle windowHandle = window->getNativeHandle().convert<WindowHandle>(); - if (SLANG_FAILED(device->createSwapchain(swapchainDesc, windowHandle, swapchain.writeRef()))) + auto createSwapchainResult = device->createSwapchain(swapchainDesc, windowHandle, swapchain.writeRef()); + if (SLANG_FAILED(createSwapchainResult)) + { SLANG_IGNORE_TEST; + } + + VertexStreamDesc vertexStreams[] = { + { sizeof(Vertex), InputSlotClass::PerVertex, 0 }, + }; + + InputElementDesc inputElements[] = { + // Vertex buffer data + { "POSITIONA", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position), 0 }, + }; + IInputLayout::Desc inputLayoutDesc = {}; + inputLayoutDesc.inputElementCount = SLANG_COUNT_OF(inputElements); + inputLayoutDesc.inputElements = inputElements; + inputLayoutDesc.vertexStreamCount = SLANG_COUNT_OF(vertexStreams); + inputLayoutDesc.vertexStreams = vertexStreams; + auto inputLayout = device->createInputLayout(inputLayoutDesc); + SLANG_CHECK_ABORT(inputLayout != nullptr); + + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::ShaderResource; + vertexBuffer = device->createBufferResource(vertexBufferDesc, &kVertexData[0]); + SLANG_CHECK_ABORT(vertexBuffer != nullptr); + + ITransientResourceHeap::Desc transientHeapDesc = {}; + transientHeapDesc.constantBufferSize = 4096 * 1024; + GFX_CHECK_CALL_ABORT( + device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef())); + + ComPtr<IShaderProgram> shaderProgram; + slang::ProgramLayout* slangReflection; + GFX_CHECK_CALL_ABORT(loadGraphicsProgram(device, shaderProgram, "swapchain-shader", "vertexMain", "fragmentMain", slangReflection)); + + IFramebufferLayout::TargetLayout targetLayout; + targetLayout.format = format; + targetLayout.sampleCount = 1; + + IFramebufferLayout::Desc framebufferLayoutDesc; + framebufferLayoutDesc.renderTargetCount = 1; + framebufferLayoutDesc.renderTargets = &targetLayout; + framebufferLayout = device->createFramebufferLayout(framebufferLayoutDesc); + SLANG_CHECK_ABORT(framebufferLayout != nullptr); + + GraphicsPipelineStateDesc pipelineDesc = {}; + pipelineDesc.program = shaderProgram.get(); + pipelineDesc.inputLayout = inputLayout; + pipelineDesc.framebufferLayout = framebufferLayout; + pipelineDesc.depthStencil.depthTestEnable = false; + pipelineDesc.depthStencil.depthWriteEnable = false; + GFX_CHECK_CALL_ABORT( + device->createGraphicsPipelineState(pipelineDesc, pipelineState.writeRef())); + + IRenderPassLayout::Desc renderPassDesc = {}; + renderPassDesc.framebufferLayout = framebufferLayout; + renderPassDesc.renderTargetCount = 1; + IRenderPassLayout::TargetAccessDesc renderTargetAccess = {}; + renderTargetAccess.loadOp = IRenderPassLayout::TargetLoadOp::Clear; + renderTargetAccess.storeOp = IRenderPassLayout::TargetStoreOp::Store; + renderTargetAccess.initialState = ResourceState::Undefined; + renderTargetAccess.finalState = ResourceState::Present; + renderPassDesc.renderTargetAccess = &renderTargetAccess; + GFX_CHECK_CALL_ABORT(device->createRenderPassLayout(renderPassDesc, renderPass.writeRef())); + + createSwapchainFramebuffers(); + } + + void renderFrame(GfxIndex framebufferIndex) + { + auto commandBuffer = transientHeap->createCommandBuffer(); + + auto encoder = commandBuffer->encodeRenderCommands(renderPass, framebuffers[framebufferIndex]); + auto rootObject = encoder->bindPipeline(pipelineState); + + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)width; + viewport.extentY = (float)height; + encoder->setViewportAndScissor(viewport); + + encoder->setVertexBuffer(0, vertexBuffer); + encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + + encoder->draw(kVertexCount); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + swapchain->present(); } void run() { createRequiredResources(); - // TODO: Extend test by drawing for a few frames before and after resize to ensure swapchain remains usable + // Render for 5 frames then resize the swapchain and render for another 5 frames to ensure the + // swapchain remains usable after resizing. + for (GfxIndex i = 0; i < 5; ++i) + { + renderFrame(i % kSwapchainImageCount); + } + queue->waitOnHost(); + + framebuffers = decltype(framebuffers)(); GFX_CHECK_CALL(swapchain->resize(700, 700)); + createSwapchainFramebuffers(); + width = 700; + height = 700; + + for (GfxIndex i = 0; i < 5; ++i) + { + renderFrame(i % kSwapchainImageCount); + } + queue->waitOnHost(); } }; |
