summaryrefslogtreecommitdiffstats
path: root/tools/gfx-unit-test/swap-chain-resize-test.cpp
diff options
context:
space:
mode:
authorlucy96chen <47800040+lucy96chen@users.noreply.github.com>2022-06-14 21:08:51 -0700
committerGitHub <noreply@github.com>2022-06-14 21:08:51 -0700
commit69cb218100f593036d1a89357303f9c1368841ea (patch)
tree7fe28be1c354267dd440bfbb4d1f37647436b769 /tools/gfx-unit-test/swap-chain-resize-test.cpp
parentebcda2ec8b1cfb54f52329bb1134511ca4d4dbff (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.cpp165
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();
}
};