Factor simple framebuffer creation in end2end tests

This commit is contained in:
Corentin Wallez 2018-02-09 16:51:02 -05:00 committed by Corentin Wallez
parent 0dbf74b068
commit a88ec74e60
5 changed files with 103 additions and 117 deletions

View File

@ -47,30 +47,7 @@ class BlendStateTest : public NXTTest {
.SetBindGroupLayout(0, bindGroupLayout) .SetBindGroupLayout(0, bindGroupLayout)
.GetResult(); .GetResult();
renderTarget = device.CreateTextureBuilder() fb = utils::CreateBasicFramebuffer(device, kRTSize, kRTSize);
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.SetSubpassCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetView)
.GetResult();
} }
struct TriangleSpec { struct TriangleSpec {
@ -94,14 +71,14 @@ class BlendStateTest : public NXTTest {
)"); )");
basePipeline = device.CreateRenderPipelineBuilder() basePipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0) .SetSubpass(fb.renderPass, 0)
.SetLayout(pipelineLayout) .SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main") .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main") .SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult(); .GetResult();
testPipeline = device.CreateRenderPipelineBuilder() testPipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0) .SetSubpass(fb.renderPass, 0)
.SetLayout(pipelineLayout) .SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main") .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main") .SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@ -137,10 +114,10 @@ class BlendStateTest : public NXTTest {
// Test that after drawing a triangle with the base color, and then the given triangle spec, the color is as expected // Test that after drawing a triangle with the base color, and then the given triangle spec, the color is as expected
void DoSingleSourceTest(RGBA8 base, const TriangleSpec& triangle, const RGBA8& expected) { void DoSingleSourceTest(RGBA8 base, const TriangleSpec& triangle, const RGBA8& expected) {
renderTarget.TransitionUsage(nxt::TextureUsageBit::OutputAttachment); fb.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer) .BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass() .BeginRenderSubpass()
// First use the base pipeline to draw a triangle with no blending // First use the base pipeline to draw a triangle with no blending
.SetRenderPipeline(basePipeline) .SetRenderPipeline(basePipeline)
@ -159,7 +136,7 @@ class BlendStateTest : public NXTTest {
queue.Submit(1, &commands); queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(expected, renderTarget, kRTSize / 2, kRTSize / 2); EXPECT_PIXEL_RGBA8_EQ(expected, fb.color, kRTSize / 2, kRTSize / 2);
} }
// Given a vector of tests where each element is <testColor, expectedColor>, check that all expectations are true for the given blend operation // Given a vector of tests where each element is <testColor, expectedColor>, check that all expectations are true for the given blend operation
@ -200,12 +177,9 @@ class BlendStateTest : public NXTTest {
CheckBlendFactor(base, nxt::BlendFactor::One, colorFactor, nxt::BlendFactor::One, alphaFactor, tests); CheckBlendFactor(base, nxt::BlendFactor::One, colorFactor, nxt::BlendFactor::One, alphaFactor, tests);
} }
nxt::Framebuffer framebuffer; utils::BasicFramebuffer fb;
nxt::RenderPass renderpass;
nxt::RenderPipeline basePipeline; nxt::RenderPipeline basePipeline;
nxt::RenderPipeline testPipeline; nxt::RenderPipeline testPipeline;
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
nxt::ShaderModule vsModule; nxt::ShaderModule vsModule;
nxt::BindGroupLayout bindGroupLayout; nxt::BindGroupLayout bindGroupLayout;
nxt::PipelineLayout pipelineLayout; nxt::PipelineLayout pipelineLayout;
@ -713,7 +687,7 @@ TEST_P(BlendStateTest, IndependentBlendState) {
renderTargetViews[i] = renderTargets[i].CreateTextureViewBuilder().GetResult(); renderTargetViews[i] = renderTargets[i].CreateTextureViewBuilder().GetResult();
} }
renderpass = device.CreateRenderPassBuilder() nxt::RenderPass renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(5) .SetAttachmentCount(5)
.SetSubpassCount(1) .SetSubpassCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm) .AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
@ -729,7 +703,7 @@ TEST_P(BlendStateTest, IndependentBlendState) {
.SubpassSetColorAttachment(0, 3, 0) .SubpassSetColorAttachment(0, 3, 0)
.GetResult(); .GetResult();
framebuffer = device.CreateFramebufferBuilder() nxt::Framebuffer framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass) .SetRenderPass(renderpass)
.SetDimensions(kRTSize, kRTSize) .SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetViews[0]) .SetAttachment(0, renderTargetViews[0])
@ -852,7 +826,7 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
.SetAlphaBlend(nxt::BlendOperation::Add, nxt::BlendFactor::BlendColor, nxt::BlendFactor::One) .SetAlphaBlend(nxt::BlendOperation::Add, nxt::BlendFactor::BlendColor, nxt::BlendFactor::One)
.GetResult(); .GetResult();
renderpass = device.CreateRenderPassBuilder() nxt::RenderPass renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1) .SetAttachmentCount(1)
.SetSubpassCount(2) .SetSubpassCount(2)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm) .AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
@ -860,7 +834,18 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
.SubpassSetColorAttachment(1, 0, 0) .SubpassSetColorAttachment(1, 0, 0)
.GetResult(); .GetResult();
framebuffer = device.CreateFramebufferBuilder() nxt::Texture renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
nxt::TextureView renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
nxt::Framebuffer framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass) .SetRenderPass(renderpass)
.SetDimensions(kRTSize, kRTSize) .SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetView) .SetAttachment(0, renderTargetView)

View File

@ -37,30 +37,7 @@ class InputStateTest : public NXTTest {
void SetUp() override { void SetUp() override {
NXTTest::SetUp(); NXTTest::SetUp();
renderpass = device.CreateRenderPassBuilder() fb = utils::CreateBasicFramebuffer(device, kRTSize, kRTSize);
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetAttachment(0, renderTargetView)
.SetDimensions(400, 400)
.GetResult();
} }
bool ShouldComponentBeDefault(VertexFormat format, int component) { bool ShouldComponentBeDefault(VertexFormat format, int component) {
@ -142,7 +119,7 @@ class InputStateTest : public NXTTest {
); );
return device.CreateRenderPipelineBuilder() return device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0) .SetSubpass(fb.renderPass, 0)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main") .SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main") .SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState) .SetInputState(inputState)
@ -189,8 +166,8 @@ class InputStateTest : public NXTTest {
nxt::CommandBufferBuilder builder = device.CreateCommandBufferBuilder(); nxt::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
renderTarget.TransitionUsage(nxt::TextureUsageBit::OutputAttachment); fb.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
builder.BeginRenderPass(renderpass, framebuffer) builder.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass() .BeginRenderSubpass()
.SetRenderPipeline(pipeline); .SetRenderPipeline(pipeline);
@ -214,18 +191,15 @@ class InputStateTest : public NXTTest {
unsigned int x = kRTCellOffset + kRTCellSize * triangle; unsigned int x = kRTCellOffset + kRTCellSize * triangle;
unsigned int y = kRTCellOffset + kRTCellSize * instance; unsigned int y = kRTCellOffset + kRTCellSize * instance;
if (triangle < triangles && instance < instances) { if (triangle < triangles && instance < instances) {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, x, y); EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, x, y);
} else { } else {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderTarget, x, y); EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, x, y);
} }
} }
} }
} }
nxt::RenderPass renderpass; utils::BasicFramebuffer fb;
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
nxt::Framebuffer framebuffer;
}; };
// Test compilation and usage of the fixture :) // Test compilation and usage of the fixture :)

View File

@ -22,41 +22,6 @@
class PushConstantTest: public NXTTest { class PushConstantTest: public NXTTest {
protected: protected:
void SetUp() override {
NXTTest::SetUp();
// Simple framebuffer and render pass for render stage tests
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(1, 1, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetAttachment(0, renderTargetView)
.SetDimensions(1, 1)
.GetResult();
}
nxt::RenderPass renderpass;
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
nxt::Framebuffer framebuffer;
// Layout, bind group and friends to store results for compute tests, can have an extra buffer // Layout, bind group and friends to store results for compute tests, can have an extra buffer
// so that two different pipeline layout can be created. // so that two different pipeline layout can be created.
struct TestBindings { struct TestBindings {
@ -271,7 +236,7 @@ TEST_P(PushConstantTest, ComputePassDefaultsToZero) {
// Test that push constants default to zero at the beginning of every render subpasses. // Test that push constants default to zero at the beginning of every render subpasses.
TEST_P(PushConstantTest, RenderSubpassDefaultsToZero) { TEST_P(PushConstantTest, RenderSubpassDefaultsToZero) {
// Change the renderpass to be a two subpass renderpass just for this test. // Change the renderpass to be a two subpass renderpass just for this test.
renderpass = device.CreateRenderPassBuilder() nxt::RenderPass renderPass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1) .SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm) .AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear) .AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
@ -280,8 +245,19 @@ TEST_P(PushConstantTest, RenderSubpassDefaultsToZero) {
.SubpassSetColorAttachment(1, 0, 0) .SubpassSetColorAttachment(1, 0, 0)
.GetResult(); .GetResult();
framebuffer = device.CreateFramebufferBuilder() nxt::Texture renderTarget = device.CreateTextureBuilder()
.SetRenderPass(renderpass) .SetDimension(nxt::TextureDimension::e2D)
.SetExtent(1, 1, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
nxt::TextureView renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
nxt::Framebuffer framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderPass)
.SetAttachment(0, renderTargetView) .SetAttachment(0, renderTargetView)
.SetDimensions(1, 1) .SetDimensions(1, 1)
.GetResult(); .GetResult();
@ -289,12 +265,12 @@ TEST_P(PushConstantTest, RenderSubpassDefaultsToZero) {
// Expect push constants to be zero in all draws of this test. // Expect push constants to be zero in all draws of this test.
PushConstantSpec allZeros = MakeAllZeroSpec(); PushConstantSpec allZeros = MakeAllZeroSpec();
nxt::PipelineLayout layout = MakeEmptyLayout(); nxt::PipelineLayout layout = MakeEmptyLayout();
nxt::RenderPipeline pipeline1 = MakeTestRenderPipeline(layout, renderpass, 0, MakeAllZeroSpec(), MakeAllZeroSpec()); nxt::RenderPipeline pipeline1 = MakeTestRenderPipeline(layout, renderPass, 0, MakeAllZeroSpec(), MakeAllZeroSpec());
nxt::RenderPipeline pipeline2 = MakeTestRenderPipeline(layout, renderpass, 1, MakeAllZeroSpec(), MakeAllZeroSpec()); nxt::RenderPipeline pipeline2 = MakeTestRenderPipeline(layout, renderPass, 1, MakeAllZeroSpec(), MakeAllZeroSpec());
uint32_t notZero = 42; uint32_t notZero = 42;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer) .BeginRenderPass(renderPass, framebuffer)
.BeginRenderSubpass() .BeginRenderSubpass()
// Test render push constants are set to zero by default. // Test render push constants are set to zero by default.
.SetRenderPipeline(pipeline1) .SetRenderPipeline(pipeline1)
@ -413,13 +389,15 @@ TEST_P(PushConstantTest, SeparateVertexAndFragmentConstants) {
PushConstantSpec vsSpec = {{Int, 1}}; PushConstantSpec vsSpec = {{Int, 1}};
PushConstantSpec fsSpec = {{Int, 2}}; PushConstantSpec fsSpec = {{Int, 2}};
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 1, 1);
nxt::PipelineLayout layout = MakeEmptyLayout(); nxt::PipelineLayout layout = MakeEmptyLayout();
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, renderpass, 0, vsSpec, fsSpec); nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, fb.renderPass, 0, vsSpec, fsSpec);
uint32_t one = 1; uint32_t one = 1;
uint32_t two = 2; uint32_t two = 2;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer) .BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass() .BeginRenderSubpass()
.SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, &one) .SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, &one)
.SetPushConstants(nxt::ShaderStageBit::Fragment, 0, 1, &two) .SetPushConstants(nxt::ShaderStageBit::Fragment, 0, 1, &two)
@ -431,19 +409,21 @@ TEST_P(PushConstantTest, SeparateVertexAndFragmentConstants) {
queue.Submit(1, &commands); queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderTarget, 0, 0); EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), fb.color, 0, 0);
} }
// Try setting push constants for vertex and fragment stage simulteanously // Try setting push constants for vertex and fragment stage simulteanously
TEST_P(PushConstantTest, SimultaneousVertexAndFragmentConstants) { TEST_P(PushConstantTest, SimultaneousVertexAndFragmentConstants) {
PushConstantSpec spec = {{Int, 2}}; PushConstantSpec spec = {{Int, 2}};
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 1, 1);
nxt::PipelineLayout layout = MakeEmptyLayout(); nxt::PipelineLayout layout = MakeEmptyLayout();
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, renderpass, 0, spec, spec); nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, fb.renderPass, 0, spec, spec);
uint32_t two = 2; uint32_t two = 2;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer) .BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass() .BeginRenderSubpass()
.SetPushConstants(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, 0, 1, &two) .SetPushConstants(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, 0, 1, &two)
.SetRenderPipeline(pipeline) .SetRenderPipeline(pipeline)
@ -454,6 +434,6 @@ TEST_P(PushConstantTest, SimultaneousVertexAndFragmentConstants) {
queue.Submit(1, &commands); queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderTarget, 0, 0); EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), fb.color, 0, 0);
} }
NXT_INSTANTIATE_TEST(PushConstantTest, MetalBackend, OpenGLBackend) NXT_INSTANTIATE_TEST(PushConstantTest, MetalBackend, OpenGLBackend)

View File

@ -111,4 +111,40 @@ namespace utils {
return buffer; return buffer;
} }
BasicFramebuffer CreateBasicFramebuffer(const nxt::Device& device,
uint32_t width,
uint32_t height) {
BasicFramebuffer result;
result.width = width;
result.height = height;
result.renderPass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
result.color = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(width, height, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment |
nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
nxt::TextureView colorView = result.color.CreateTextureViewBuilder().GetResult();
result.framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(result.renderPass)
.SetAttachment(0, colorView)
.SetDimensions(width, height)
.GetResult();
return result;
}
} // namespace utils } // namespace utils

View File

@ -37,4 +37,15 @@ namespace utils {
usage); usage);
} }
struct BasicFramebuffer {
uint32_t width;
uint32_t height;
nxt::RenderPass renderPass;
nxt::Texture color;
nxt::Framebuffer framebuffer;
};
BasicFramebuffer CreateBasicFramebuffer(const nxt::Device& device,
uint32_t width,
uint32_t height);
} // namespace utils } // namespace utils