summaryrefslogtreecommitdiffstats
path: root/tools/gfx-unit-test/swap-chain-resize-test.cpp
diff options
context:
space:
mode:
authorGangzheng Tong <tonggangzheng@gmail.com>2025-07-08 23:44:56 -0700
committerGitHub <noreply@github.com>2025-07-09 06:44:56 +0000
commit43d0c2100ef1a5df4b54525e50eb29fe7c39ec16 (patch)
tree25ec4fb9c726115f90bdaa9878f2f4ca372ad0a6 /tools/gfx-unit-test/swap-chain-resize-test.cpp
parent00746bf09047cdf01c19dac513a532bcf3ed3ea3 (diff)
Convert gfx unit tests and examples to use slang-rhi (#7577)
* Port first gfx unit test to slang-rhi * port triangle example to use slang-rhi * port platform-test to slang-rhi * Update platform-test to throttle mouse move events * port gpu-printing example to use slang-rhi * port model-viewer example to use slang-rhi * port ray-tracing example to use slang-rhi * port ray-tracing pipeline example to use slang-rhi * port reflection parameter blocks example to use slang-rhi * port shader-object example to use slang-rhi * port shader-toy example to use slang-rhi * Port most of tests to slang-rhi * port link-time-constant-array-size to use slang-rhi * Fix tests and find matching tests in slang-rhi * port autodiff-texture * remove gfx target; port nv-aftermath-example * update include path for shader-cursor.h * Disabled 2 more ported tests * fix build error * remove gfx test * put slang-rhi (static-lib) before slang (shared) * format code (#7621) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * add debug callback * format code (#7649) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * Address review comments; revert back to use SLANG_CHECK_MSG --------- Co-authored-by: slangbot <ellieh+slangbot@nvidia.com> Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'tools/gfx-unit-test/swap-chain-resize-test.cpp')
-rw-r--r--tools/gfx-unit-test/swap-chain-resize-test.cpp281
1 files changed, 129 insertions, 152 deletions
diff --git a/tools/gfx-unit-test/swap-chain-resize-test.cpp b/tools/gfx-unit-test/swap-chain-resize-test.cpp
index 23f39fd8a..c12c856b7 100644
--- a/tools/gfx-unit-test/swap-chain-resize-test.cpp
+++ b/tools/gfx-unit-test/swap-chain-resize-test.cpp
@@ -1,12 +1,15 @@
-#include "core/slang-basic.h"
+#if 0
+
+// Duplicated: This test is similar to slang-rhi\tests\test-surface.cpp
+
#include "gfx-test-util.h"
-#include "gfx-util/shader-cursor.h"
#include "platform/window.h"
-#include "slang-gfx.h"
#include "unit-test/slang-unit-test.h"
-using namespace gfx;
-using namespace Slang;
+#include <slang-rhi.h>
+#include <slang-rhi/shader-cursor.h>
+
+using namespace rhi;
namespace gfx_test
{
@@ -17,7 +20,6 @@ struct Vertex
static const int kVertexCount = 3;
static const Vertex kVertexData[kVertexCount] = {
- // Triangle 1
{0, 0, 1},
{4, 0, 1},
{0, 4, 1},
@@ -28,22 +30,22 @@ struct SwapchainResizeTest
IDevice* device;
UnitTestContext* context;
- RefPtr<platform::Window> window;
+ ComPtr<platform::Window> window;
ComPtr<ICommandQueue> queue;
- ComPtr<ISwapchain> swapchain;
+ ComPtr<ISurface> surface;
- ComPtr<ITransientResourceHeap> transientHeap;
- ComPtr<gfx::IFramebufferLayout> framebufferLayout;
- ComPtr<IPipelineState> pipelineState;
- ComPtr<IRenderPassLayout> renderPass;
- List<ComPtr<IFramebuffer>> framebuffers;
+ ComPtr<ITexture> swapchainImages[2];
+ uint32_t swapchainImageCount = 2;
+ Format desiredFormat = Format::RGBA8Unorm;
- ComPtr<IBufferResource> vertexBuffer;
+ ComPtr<IBuffer> vertexBuffer;
+ ComPtr<IInputLayout> inputLayout;
+ ComPtr<IRenderPipeline> pipeline;
+ ComPtr<IShaderProgram> shaderProgram;
+ ComPtr<IShaderObject> rootShaderObject;
- GfxCount width = 500;
- GfxCount height = 500;
- static const int kSwapchainImageCount = 2;
- const Format desiredFormat = Format::R8G8B8A8_UNORM;
+ uint32_t width = 500;
+ uint32_t height = 500;
void init(IDevice* device, UnitTestContext* context)
{
@@ -51,38 +53,10 @@ struct SwapchainResizeTest
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()
+ void createSwapchainAndResources()
{
+ // Create window
platform::Application::init();
-
platform::WindowDesc windowDesc;
windowDesc.title = "";
windowDesc.width = width;
@@ -90,140 +64,141 @@ struct SwapchainResizeTest
windowDesc.style = platform::WindowStyle::Default;
window = platform::Application::createWindow(windowDesc);
- ICommandQueue::Desc queueDesc = {};
- queueDesc.type = ICommandQueue::QueueType::Graphics;
- queue = device->createCommandQueue(queueDesc);
-
- ISwapchain::Desc swapchainDesc = {};
- swapchainDesc.format = desiredFormat;
- swapchainDesc.width = width;
- swapchainDesc.height = height;
- swapchainDesc.imageCount = kSwapchainImageCount;
- swapchainDesc.queue = queue;
- WindowHandle windowHandle = window->getNativeHandle().convert<WindowHandle>();
- auto createSwapchainResult =
- device->createSwapchain(swapchainDesc, windowHandle, swapchain.writeRef());
- if (SLANG_FAILED(createSwapchainResult))
- {
- SLANG_IGNORE_TEST;
- }
+ // Create surface
+ WindowHandle windowHandle = WindowHandle::fromHwnd((void*)window->getNativeHandle().handleValues[0]);
+ surface = device->createSurface(windowHandle);
+
+ // Configure surface (swapchain)
+ SurfaceConfig config = {};
+ config.format = desiredFormat;
+ config.width = width;
+ config.height = height;
+ config.desiredImageCount = swapchainImageCount;
+ config.vsync = true;
+ surface->configure(config);
+
+ // Create vertex buffer
+ BufferDesc vertexBufferDesc = {};
+ vertexBufferDesc.size = sizeof(Vertex) * kVertexCount;
+ vertexBufferDesc.memoryType = MemoryType::DeviceLocal;
+ vertexBufferDesc.usage = BufferUsage::VertexBuffer;
+ vertexBufferDesc.defaultState = ResourceState::VertexBuffer;
+ vertexBuffer = device->createBuffer(vertexBufferDesc, kVertexData);
+ // Input layout
+ InputElementDesc inputElements[] = {
+ {"POSITIONA", 0, Format::RGB32Float, offsetof(Vertex, position), 0},
+ };
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 inputLayoutDesc = {};
+ inputLayoutDesc.inputElementCount = sizeof(inputElements) / sizeof(InputElementDesc);
inputLayoutDesc.inputElements = inputElements;
- inputLayoutDesc.vertexStreamCount = SLANG_COUNT_OF(vertexStreams);
+ inputLayoutDesc.vertexStreamCount = sizeof(vertexStreams) / sizeof(VertexStreamDesc);;
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::VertexBuffer;
- 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()));
+ GFX_CHECK_CALL_ABORT(device->createInputLayout(inputLayoutDesc, inputLayout.writeRef()));
ComPtr<IShaderProgram> shaderProgram;
- slang::ProgramLayout* slangReflection;
+ slang::ProgramLayout* slangReflection = nullptr;
GFX_CHECK_CALL_ABORT(loadGraphicsProgram(
device,
shaderProgram,
"swapchain-shader",
"vertexMain",
"fragmentMain",
- slangReflection));
-
- IFramebufferLayout::TargetLayout targetLayout;
- targetLayout.format = swapchain->getDesc().format;
- targetLayout.sampleCount = 1;
+ slangReflection
+ ));
- IFramebufferLayout::Desc framebufferLayoutDesc;
- framebufferLayoutDesc.renderTargetCount = 1;
- framebufferLayoutDesc.renderTargets = &targetLayout;
- framebufferLayout = device->createFramebufferLayout(framebufferLayoutDesc);
- SLANG_CHECK_ABORT(framebufferLayout != nullptr);
- GraphicsPipelineStateDesc pipelineDesc = {};
+ // Pipeline
+ ColorTargetDesc colorTarget = {};
+ colorTarget.format = desiredFormat;
+ RenderPipelineDesc 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();
+ pipelineDesc.inputLayout = inputLayout.get();
+ pipelineDesc.primitiveTopology = PrimitiveTopology::TriangleList;
+ pipelineDesc.targets = &colorTarget;
+ pipelineDesc.targetCount = 1;
+ pipeline = device->createRenderPipeline(pipelineDesc);
}
- 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);
-
- swapchain->acquireNextImage();
- encoder->draw(kVertexCount);
- encoder->endEncoding();
- commandBuffer->close();
- queue->executeCommandBuffer(commandBuffer);
- swapchain->present();
+ void renderFrame(uint32_t imageIndex)
+ {
+ // Acquire next image
+ ComPtr<ITexture> backBuffer;
+ if (SLANG_FAILED(surface->acquireNextImage(backBuffer.writeRef())))
+ {
+ return;
+ }
+
+ // Create command encoder
+ ComPtr<ICommandQueue> queue = device->getQueue(QueueType::Graphics);
+ ComPtr<ICommandEncoder> encoder = queue->createCommandEncoder();
+
+ // Render pass setup
+ RenderPassColorAttachment colorAttachment = {};
+ colorAttachment.view = backBuffer->getDefaultView();
+ colorAttachment.loadOp = LoadOp::Clear;
+ colorAttachment.storeOp = StoreOp::Store;
+ float clearColor[4] = {0.2f, 0.2f, 0.2f, 1.0f};
+ memcpy(colorAttachment.clearValue, clearColor, sizeof(clearColor));
+ RenderPassDesc passDesc = {};
+ passDesc.colorAttachments = &colorAttachment;
+ passDesc.colorAttachmentCount = 1;
+
+ // Begin render pass
+ auto pass = encoder->beginRenderPass(passDesc);
+
+ // Bind pipeline and root object
+ pass->bindPipeline(pipeline, rootShaderObject);
+
+ // Set render state
+ RenderState state = {};
+ state.vertexBuffers[0] = BufferOffsetPair(vertexBuffer, 0);
+ state.vertexBufferCount = 1;
+ // Set viewport
+ Viewport viewport = Viewport::fromSize((float)width, (float)height);
+ state.viewportCount = 1;
+ state.viewports[0] = viewport;
+
+ pass->setRenderState(state);
+
+ // Draw
+ DrawArguments args = {};
+ args.vertexCount = kVertexCount;
+ pass->draw(args);
+
+ pass->end();
+ ComPtr<ICommandBuffer> cmdBuffer;
+ encoder->finish(cmdBuffer.writeRef());
+ queue->submit(cmdBuffer);
+
+ // Present
+ surface->present();
}
void run()
{
- createRequiredResources();
- // 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)
+ createSwapchainAndResources();
+ for (uint32_t i = 0; i < 5; ++i)
{
- renderFrame(i % kSwapchainImageCount);
+ renderFrame(i % swapchainImageCount);
}
queue->waitOnHost();
- framebuffers = decltype(framebuffers)();
- GFX_CHECK_CALL(swapchain->resize(700, 700));
- createSwapchainFramebuffers();
+ // Resize swapchain
width = 700;
height = 700;
+ SurfaceConfig config = surface->getConfig();
+ config.width = width;
+ config.height = height;
+ surface->configure(config);
- for (GfxIndex i = 0; i < 5; ++i)
+ for (uint32_t i = 0; i < 5; ++i)
{
- renderFrame(i % kSwapchainImageCount);
+ renderFrame(i % swapchainImageCount);
}
queue->waitOnHost();
}
@@ -238,12 +213,14 @@ void swapchainResizeTestImpl(IDevice* device, UnitTestContext* context)
SLANG_UNIT_TEST(swapchainResizeD3D12)
{
- runTestImpl(swapchainResizeTestImpl, unitTestContext, RenderApiFlag::D3D12);
+ runTestImpl(swapchainResizeTestImpl, unitTestContext, DeviceType::D3D12);
}
SLANG_UNIT_TEST(swapchainResizeVulkan)
{
- runTestImpl(swapchainResizeTestImpl, unitTestContext, RenderApiFlag::Vulkan);
+ runTestImpl(swapchainResizeTestImpl, unitTestContext, DeviceType::Vulkan);
}
} // namespace gfx_test
+
+#endif