diff --git a/filament/backend/test/test_Blit.cpp b/filament/backend/test/test_Blit.cpp index f986031721a1..7b1ee6d77446 100644 --- a/filament/backend/test/test_Blit.cpp +++ b/filament/backend/test/test_Blit.cpp @@ -145,7 +145,6 @@ static void createFaces(DriverApi& dapi, Handle texture, int baseWidt TEST_F(BlitTest, ColorMagnify) { auto& api = getDriverApi(); - mCleanup.addPostCall([&]() { executeCommands(); }); constexpr int kSrcTexWidth = 256; constexpr int kSrcTexHeight = 256; @@ -207,7 +206,6 @@ TEST_F(BlitTest, ColorMagnify) { TEST_F(BlitTest, ColorMinify) { auto& api = getDriverApi(); - mCleanup.addPostCall([&]() { executeCommands(); }); constexpr int kSrcTexWidth = 1024; constexpr int kSrcTexHeight = 1024; @@ -342,7 +340,6 @@ TEST_F(BlitTest, ColorResolve) { TEST_F(BlitTest, Blit2DTextureArray) { auto& api = getDriverApi(); - mCleanup.addPostCall([&]() { executeCommands(); }); api.startCapture(0); mCleanup.addPostCall([&]() { api.stopCapture(0); }); @@ -412,7 +409,6 @@ TEST_F(BlitTest, Blit2DTextureArray) { TEST_F(BlitTest, BlitRegion) { auto& api = getDriverApi(); - mCleanup.addPostCall([&]() { executeCommands(); }); constexpr int kSrcTexWidth = 1024; constexpr int kSrcTexHeight = 1024; @@ -488,7 +484,6 @@ TEST_F(BlitTest, BlitRegion) { TEST_F(BlitTest, BlitRegionToSwapChain) { FAIL_IF(Backend::VULKAN, "Crashes due to not finding color attachment, see b/417481493"); auto& api = getDriverApi(); - mCleanup.addPostCall([&]() { executeCommands(); }); constexpr int kSrcTexWidth = 1024; constexpr int kSrcTexHeight = 1024; @@ -541,13 +536,13 @@ TEST_F(BlitTest, BlitRegionToSwapChain) { dstRect, srcRenderTargets[srcLevel], srcRect, SamplerMagFilter::LINEAR); - api.commit(swapChain); - } + api.commit(swapChain); - // TODO: for some reason, this test has been disabled. It needs to be tested on all - // machines. - // EXPECT_IMAGE(dstRenderTarget, - // ScreenshotParams(kDstTexWidth, kDstTexHeight, "BlitRegionToSwapChain", 0x0)); + // TODO: for some reason, this test has been disabled. It needs to be tested on all + // machines. + // EXPECT_IMAGE(dstRenderTarget, + // ScreenshotParams(kDstTexWidth, kDstTexHeight, "BlitRegionToSwapChain", 0x0)); + } } } // namespace test diff --git a/filament/backend/test/test_BufferUpdates.cpp b/filament/backend/test/test_BufferUpdates.cpp index eb071bdaff3d..0e92cb1471bc 100644 --- a/filament/backend/test/test_BufferUpdates.cpp +++ b/filament/backend/test/test_BufferUpdates.cpp @@ -91,6 +91,7 @@ TEST_F(BufferUpdatesTest, VertexBufferUpdate) { shader.bindUniform(api, ubuffer, kBindingConfig); api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); // Upload the uniform, but with an offset to accommodate the padding in the shader's // uniform definition. @@ -101,29 +102,42 @@ TEST_F(BufferUpdatesTest, VertexBufferUpdate) { }); api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - - // Draw 10 triangles, updating the vertex buffer / index buffer each time. - size_t triangleIndex = 0; - for (float i = -1.0f; i < 1.0f; i += 0.2f) { - const float low = i, high = i + 0.2; - const filament::math::float2 v[3]{{ low, low }, - { high, low }, - { low, high }}; - triangle.updateVertices(v); - - if (updateIndices) { - if (triangleIndex % 2 == 0) { - // Upload each index separately, to test offsets. - const TrianglePrimitive::index_type i[3]{ 0, 1, 2 }; - triangle.updateIndices(i + 0, 1, 0); - triangle.updateIndices(i + 1, 1, 1); - triangle.updateIndices(i + 2, 1, 2); - } else { - // This effectively hides this triangle. - const TrianglePrimitive::index_type i[3]{ 0, 0, 0 }; - triangle.updateIndices(i); + { + RenderFrame frame(api); + + // Draw 10 triangles, updating the vertex buffer / index buffer each time. + size_t triangleIndex = 0; + for (float i = -1.0f; i < 1.0f; i += 0.2f) { + const float low = i, high = i + 0.2; + const filament::math::float2 v[3]{{ low, low }, + { high, low }, + { low, high }}; + triangle.updateVertices(v); + + if (updateIndices) { + if (triangleIndex % 2 == 0) { + // Upload each index separately, to test offsets. + const TrianglePrimitive::index_type i[3]{ 0, 1, 2 }; + triangle.updateIndices(i + 0, 1, 0); + triangle.updateIndices(i + 1, 1, 1); + triangle.updateIndices(i + 2, 1, 2); + } else { + // This effectively hides this triangle. + const TrianglePrimitive::index_type i[3]{ 0, 0, 0 }; + triangle.updateIndices(i); + } } + + if (triangleIndex > 0) { + params.flags.clear = TargetBufferFlags::NONE; + params.flags.discardStart = TargetBufferFlags::NONE; + } + + api.beginRenderPass(defaultRenderTarget, params); + api.draw(state, triangle.getRenderPrimitive(), 0, 3, 1); + api.endRenderPass(); + + triangleIndex++; } if (triangleIndex > 0) { @@ -141,15 +155,7 @@ TEST_F(BufferUpdatesTest, VertexBufferUpdate) { triangleIndex++; } - - api.flush(); - api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); } - - executeCommands(); } // This test renders two triangles in two separate draw calls. Between the draw calls, a uniform @@ -241,15 +247,13 @@ TEST_F(BufferUpdatesTest, BufferObjectUpdateWithOffset) { "BufferObjectUpdateWithOffset", 2320747245)); api.flush(); - api.commit(swapChain); - api.endFrame(0); + { + RenderFrame frame(api); + api.commit(swapChain); + } // This ensures all driver commands have finished before exiting the test. api.finish(); - - executeCommands(); - - getDriver().purge(); } } // namespace test diff --git a/filament/backend/test/test_Callbacks.cpp b/filament/backend/test/test_Callbacks.cpp index 8fb5fac34f7c..c65db9fb47da 100644 --- a/filament/backend/test/test_Callbacks.cpp +++ b/filament/backend/test/test_Callbacks.cpp @@ -29,58 +29,61 @@ TEST_F(BackendTest, FrameScheduledCallback) { SKIP_IF(Backend::VULKAN, "Frame callbacks are unsupported in Vulkan, see b/417254479"); SKIP_IF(Backend::WEBGPU, "Frame callbacks are unsupported in WebGPU"); - auto& api = getDriverApi(); - Cleanup cleanup(api); - - // Create a SwapChain. - // In order for the frameScheduledCallback to be called, this must be a real SwapChain (not - // headless) so we obtain a drawable. - auto swapChain = cleanup.add(createSwapChain()); - - Handle renderTarget = cleanup.add(api.createDefaultRenderTarget()); - int callbackCountA = 0; - api.setFrameScheduledCallback(swapChain, nullptr, [&callbackCountA](PresentCallable callable) { - callable(); - callbackCountA++; - }, 0); - - // Render the first frame. - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - api.beginRenderPass(renderTarget, {}); - api.endRenderPass(0); - api.commit(swapChain); - api.endFrame(0); - - // Render the next frame. The same callback should be called. - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - api.beginRenderPass(renderTarget, {}); - api.endRenderPass(0); - api.commit(swapChain); - api.endFrame(0); - - // Now switch out the callback. int callbackCountB = 0; - api.setFrameScheduledCallback(swapChain, nullptr, [&callbackCountB](PresentCallable callable) { - callable(); - callbackCountB++; - }, 0); - - // Render one final frame. - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - api.beginRenderPass(renderTarget, {}); - api.endRenderPass(0); - api.commit(swapChain); - api.endFrame(0); - - api.finish(); - - executeCommands(); - getDriver().purge(); - + { + auto& api = getDriverApi(); + Cleanup cleanup(api); + cleanup.addPostCall([&]() { executeCommands(); }); + cleanup.addPostCall([&]() { getDriver().purge(); }); + + // Create a SwapChain. + // In order for the frameScheduledCallback to be called, this must be a real SwapChain (not + // headless) so we obtain a drawable. + auto swapChain = cleanup.add(createSwapChain()); + + Handle renderTarget = cleanup.add(api.createDefaultRenderTarget()); + + api.setFrameScheduledCallback(swapChain, nullptr, [&callbackCountA](PresentCallable callable) { + callable(); + callbackCountA++; + }, 0); + + // Render the first frame. + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + api.beginRenderPass(renderTarget, {}); + api.endRenderPass(0); + api.commit(swapChain); + } + + // Render the next frame. The same callback should be called. + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + api.beginRenderPass(renderTarget, {}); + api.endRenderPass(0); + api.commit(swapChain); + } + + // Now switch out the callback. + api.setFrameScheduledCallback(swapChain, nullptr, [&callbackCountB](PresentCallable callable) { + callable(); + callbackCountB++; + }, 0); + + // Render one final frame. + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + api.beginRenderPass(renderTarget, {}); + api.endRenderPass(0); + api.commit(swapChain); + } + + api.finish(); + } EXPECT_EQ(callbackCountA, 2); EXPECT_EQ(callbackCountB, 1); } @@ -90,43 +93,47 @@ TEST_F(BackendTest, FrameCompletedCallback) { SKIP_IF(Backend::VULKAN, "Frame callbacks are unsupported in Vulkan, see b/417254479"); SKIP_IF(Backend::WEBGPU, "Frame callbacks are unsupported in WebGPU"); - auto& api = getDriverApi(); - Cleanup cleanup(api); - - // Create a SwapChain. - auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0)); - int callbackCountA = 0; - api.setFrameCompletedCallback(swapChain, nullptr, - [&callbackCountA]() { callbackCountA++; }); - - // Render the first frame. - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - api.commit(swapChain); - api.endFrame(0); - - // Render the next frame. The same callback should be called. - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - api.commit(swapChain); - api.endFrame(0); - - // Now switch out the callback. int callbackCountB = 0; - api.setFrameCompletedCallback(swapChain, nullptr, - [&callbackCountB]() { callbackCountB++; }); - - // Render one final frame. - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - api.commit(swapChain); - api.endFrame(0); - - api.finish(); - - executeCommands(); - getDriver().purge(); + { + auto& api = getDriverApi(); + Cleanup cleanup(api); + cleanup.addPostCall([&]() { executeCommands(); }); + cleanup.addPostCall([&]() { getDriver().purge(); }); + + // Create a SwapChain. + auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0)); + + api.setFrameCompletedCallback(swapChain, nullptr, + [&callbackCountA]() { callbackCountA++; }); + + // Render the first frame. + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + api.commit(swapChain); + } + + // Render the next frame. The same callback should be called. + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + api.commit(swapChain); + } + + // Now switch out the callback. + api.setFrameCompletedCallback(swapChain, nullptr, + [&callbackCountB]() { callbackCountB++; }); + + // Render one final frame. + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + api.commit(swapChain); + } + + api.finish(); + } EXPECT_EQ(callbackCountA, 2); EXPECT_EQ(callbackCountB, 1); diff --git a/filament/backend/test/test_FeedbackLoops.cpp b/filament/backend/test/test_FeedbackLoops.cpp index e3a33e7d0683..f9629f7bf948 100644 --- a/filament/backend/test/test_FeedbackLoops.cpp +++ b/filament/backend/test/test_FeedbackLoops.cpp @@ -158,7 +158,10 @@ TEST_F(BackendTest, FeedbackLoops) { PixelBufferDescriptor pb(buffer, size, PixelDataFormat::RGBA, PixelDataType::UBYTE, cb); api.update3DImage(texture, 0, 0, 0, 0, kTexWidth, kTexHeight, 1, std::move(pb)); - for (int frame = 0; frame < kNumFrames; frame++) { + for (int frameCount = 0; frameCount < kNumFrames; frameCount++) { + Cleanup frameCleanup(api); + frameCleanup.addPostCall([&]() { executeCommands(); }); + frameCleanup.addPostCall([&]() { getDriver().purge(); }); // Prep for rendering. PipelineState state = getColorWritePipelineState(); @@ -191,9 +194,9 @@ TEST_F(BackendTest, FeedbackLoops) { }; shader.bindUniform(api, ubuffer, uniformBinding); shader.uploadUniform(api, ubuffer, uniformBinding, MaterialParams{ - .fbWidth = float(params.viewport.width), - .fbHeight = float(params.viewport.height), - .sourceLevel = float(sourceLevel), + .fbWidth = float(params.viewport.width), + .fbHeight = float(params.viewport.height), + .sourceLevel = float(sourceLevel), }); api.beginRenderPass(renderTargets[targetLevel], params); @@ -246,7 +249,7 @@ TEST_F(BackendTest, FeedbackLoops) { // // NOTE: Calling glReadPixels on any miplevel other than the base level // seems to be un-reliable on some GPU's. - if (frame == kNumFrames - 1) { + if (frameCount == kNumFrames - 1) { EXPECT_IMAGE(renderTargets[0], ScreenshotParams(kTexWidth, kTexHeight, "FeedbackLoops", 4192780705)); } @@ -255,8 +258,6 @@ TEST_F(BackendTest, FeedbackLoops) { api.commit(swapChain); api.endFrame(0); api.finish(); - executeCommands(); - getDriver().purge(); } } } diff --git a/filament/backend/test/test_LoadImage.cpp b/filament/backend/test/test_LoadImage.cpp index 5a5cbf76dc5c..cfbb58a49089 100644 --- a/filament/backend/test/test_LoadImage.cpp +++ b/filament/backend/test/test_LoadImage.cpp @@ -314,15 +314,19 @@ TEST_F(LoadImageTest, UpdateImage2D) { api.startCapture(); + Cleanup cleanup(api); + cleanup.addPostCall([&]() { api.finish(); }); + cleanup.addPostCall([&]() { api.stopCapture(); }); + // The test is executed within this block scope to force destructors to run before // executeCommands(). for (const auto& t : testCases) { - Cleanup cleanup(api); + Cleanup caseCleanup(api); // Create a platform-specific SwapChain and make it current. - auto swapChain = cleanup.add(createSwapChain()); + auto swapChain = caseCleanup.add(createSwapChain()); api.makeCurrent(swapChain, swapChain); - auto defaultRenderTarget = cleanup.add(api.createDefaultRenderTarget(0)); + auto defaultRenderTarget = caseCleanup.add(api.createDefaultRenderTarget(0)); // Create a program. filament::SamplerInterfaceBlock::SamplerInfo samplerInfo { "test", "tex", 0, @@ -386,8 +390,6 @@ TEST_F(LoadImageTest, UpdateImage2D) { api.commit(swapChain); api.endFrame(0); } - - api.stopCapture(); } TEST_F(LoadImageTest, UpdateImageSRGB) { @@ -398,6 +400,7 @@ TEST_F(LoadImageTest, UpdateImageSRGB) { auto& api = getDriverApi(); Cleanup cleanup(api); api.startCapture(); + cleanup.addPostCall([&]() { api.stopCapture(); }); PixelDataFormat const pixelFormat = PixelDataFormat::RGBA; PixelDataType const pixelType = PixelDataType::UBYTE; @@ -445,37 +448,36 @@ TEST_F(LoadImageTest, UpdateImageSRGB) { api.update3DImage(texture, 0, 0, 0, 0, kTexSize, kTexSize, 1, std::move(descriptor)); - api.beginFrame(0, 0, 0); + { + RenderFrame frame(api); - // Update samplers. - DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); - api.updateDescriptorSetTexture(descriptorSet, 0, texture, { - .filterMag = SamplerMagFilter::LINEAR, - .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST - }); + // Update samplers. + DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); + api.updateDescriptorSetTexture(descriptorSet, 0, texture, { + .filterMag = SamplerMagFilter::LINEAR, + .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST + }); - api.bindDescriptorSet(descriptorSet, 0, {}); - - RenderPassParams params = getClearColorRenderPass(); - params.viewport.width = kTexSize; - params.viewport.height = kTexSize; - PipelineState state = getColorWritePipelineState(); - shader.addProgramToPipelineState(state); - state.primitiveType = PrimitiveType::TRIANGLES; - state.vertexBufferInfo = mTriangle.getVertexBufferInfo(); - api.beginRenderPass(defaultRenderTarget, params); - api.bindPipeline(state); - api.bindRenderPrimitive(mTriangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); + api.bindDescriptorSet(descriptorSet, 0, {}); - EXPECT_IMAGE(defaultRenderTarget, - ScreenshotParams(kTexSize, kTexSize, "UpdateImageSRGB", 3300305265)); + RenderPassParams params = getClearColorRenderPass(); + params.viewport.width = kTexSize; + params.viewport.height = kTexSize; + PipelineState state = getColorWritePipelineState(); + shader.addProgramToPipelineState(state); + state.primitiveType = PrimitiveType::TRIANGLES; + state.vertexBufferInfo = mTriangle.getVertexBufferInfo(); + api.beginRenderPass(defaultRenderTarget, params); + api.bindPipeline(state); + api.bindRenderPrimitive(mTriangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); - api.commit(swapChain); - api.endFrame(0); + EXPECT_IMAGE(defaultRenderTarget, + ScreenshotParams(kTexSize, kTexSize, "UpdateImageSRGB", 3300305265)); - api.stopCapture(); + api.commit(swapChain); + } } TEST_F(LoadImageTest, UpdateImageMipLevel) { @@ -486,6 +488,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) { auto& api = getDriverApi(); Cleanup cleanup(api); api.startCapture(); + cleanup.addPostCall([&]() { api.stopCapture(); }); PixelDataFormat pixelFormat = PixelDataFormat::RGBA; PixelDataType pixelType = PixelDataType::HALF; @@ -518,17 +521,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) { PixelBufferDescriptor descriptor = checkerboardPixelBuffer(pixelFormat, pixelType, kTexSize); api.update3DImage(texture, /* level*/ 1, 0, 0, 0, kTexSize, kTexSize, 1, std::move(descriptor)); - api.beginFrame(0, 0, 0); - - // Update samplers. - DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); - api.updateDescriptorSetTexture(descriptorSet, 0, texture, { - .filterMag = SamplerMagFilter::LINEAR, - .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST - }); - - api.bindDescriptorSet(descriptorSet, 0, {}); - + RenderFrame outerFrame(api); { RenderFrame frame(api); RenderPassParams params = getClearColorRenderPass(); @@ -549,9 +542,6 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) { ScreenshotParams(kTexSize, kTexSize, "UpdateImageMipLevel", 1875922935)); api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(); } TEST_F(LoadImageTest, UpdateImage3D) { @@ -564,6 +554,7 @@ TEST_F(LoadImageTest, UpdateImage3D) { auto& api = getDriverApi(); Cleanup cleanup(api); api.startCapture(); + cleanup.addPostCall([&]() { api.stopCapture(); }); PixelDataFormat pixelFormat = PixelDataFormat::RGBA; PixelDataType pixelType = PixelDataType::FLOAT; @@ -634,8 +625,6 @@ TEST_F(LoadImageTest, UpdateImage3D) { EXPECT_IMAGE(defaultRenderTarget, ScreenshotParams(kTexSize, kTexSize, "UpdateImage3D", 1875922935)); } - - api.stopCapture(); } } // namespace test diff --git a/filament/backend/test/test_MRT.cpp b/filament/backend/test/test_MRT.cpp index 71e573bf1898..67d9a88d0024 100644 --- a/filament/backend/test/test_MRT.cpp +++ b/filament/backend/test/test_MRT.cpp @@ -108,28 +108,27 @@ TEST_F(BackendTest, MRT) { RenderPassParams params = getClearColorRenderPass(); params.viewport = getFullViewport(); + Cleanup captureCleanup(api); api.startCapture(0); + captureCleanup.addPostCall([&]() { api.stopCapture(0); }); api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - - // Draw a triangle. - api.beginRenderPass(renderTarget, params); - state.primitiveType = PrimitiveType::TRIANGLES; - state.vertexBufferInfo = triangle.getVertexBufferInfo(); - api.bindPipeline(state); - api.bindRenderPrimitive(triangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); - - api.flush(); - api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); + { + RenderFrame frame(api); + + // Draw a triangle. + api.beginRenderPass(renderTarget, params); + state.primitiveType = PrimitiveType::TRIANGLES; + state.vertexBufferInfo = triangle.getVertexBufferInfo(); + api.bindPipeline(state); + api.bindRenderPrimitive(triangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); + + api.flush(); + api.commit(swapChain); + } } - - executeCommands(); } } // namespace test diff --git a/filament/backend/test/test_MipLevels.cpp b/filament/backend/test/test_MipLevels.cpp index 876aab0a60ed..b3097575fdd5 100644 --- a/filament/backend/test/test_MipLevels.cpp +++ b/filament/backend/test/test_MipLevels.cpp @@ -56,8 +56,9 @@ using namespace filament::backend; TEST_F(BackendTest, TextureViewLod) { auto& api = getDriverApi(); - api.startCapture(0); Cleanup cleanup(api); + api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); // The test is executed within this block scope to force destructors to run before // executeCommands(). @@ -123,7 +124,7 @@ TEST_F(BackendTest, TextureViewLod) { TrianglePrimitive triangle(api); - api.beginFrame(0, 0, 0); + RenderFrame frame(api); // We set the base mip to 1, and the max mip to 3 // Level 0: 128x128 (red) @@ -211,15 +212,9 @@ TEST_F(BackendTest, TextureViewLod) { api.endRenderPass(); api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); } api.finish(); - - executeCommands(); - getDriver().purge(); } } // namespace test diff --git a/filament/backend/test/test_MissingRequiredAttributes.cpp b/filament/backend/test/test_MissingRequiredAttributes.cpp index 6cc67c55a6b5..231b49b5b8af 100644 --- a/filament/backend/test/test_MissingRequiredAttributes.cpp +++ b/filament/backend/test/test_MissingRequiredAttributes.cpp @@ -59,10 +59,11 @@ using namespace filament::backend; * successfully. */ TEST_F(BackendTest, MissingRequiredAttributes) { + DriverApi& api = getDriverApi(); + // The test is executed within this block scope to force destructors to run before // executeCommands(). { - DriverApi& api = getDriverApi(); Cleanup cleanup(api); // Create a platform-specific SwapChain and make it current. auto swapChain = cleanup.add(createSwapChain()); @@ -86,9 +87,10 @@ TEST_F(BackendTest, MissingRequiredAttributes) { params.viewport = getFullViewport(); api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); + RenderFrame frame(api); // Render a triangle. api.beginRenderPass(defaultRenderTarget, params); @@ -101,12 +103,7 @@ TEST_F(BackendTest, MissingRequiredAttributes) { api.flush(); api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); } - - executeCommands(); } } // namespace test diff --git a/filament/backend/test/test_PushConstants.cpp b/filament/backend/test/test_PushConstants.cpp index 313b4d3686ef..4a5b43cbd46a 100644 --- a/filament/backend/test/test_PushConstants.cpp +++ b/filament/backend/test/test_PushConstants.cpp @@ -111,12 +111,13 @@ TEST_F(BackendTest, PushConstants) { auto& api = getDriverApi(); - api.startCapture(0); - Cleanup cleanup(api); - // The test is executed within this block scope to force destructors to run before // executeCommands(). { + Cleanup cleanup(api); + api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); + // Create a SwapChain and make it current. auto swapChain = cleanup.add(createSwapChain()); api.makeCurrent(swapChain, swapChain); @@ -141,7 +142,7 @@ TEST_F(BackendTest, PushConstants) { ps.rasterState.depthWrite = false; api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); + RenderFrame frame(api); api.beginRenderPass(renderTarget, params); api.bindPipeline(ps); @@ -183,10 +184,7 @@ TEST_F(BackendTest, PushConstants) { "pushConstants", 3575588741)); api.commit(swapChain); - api.endFrame(0); } - - api.stopCapture(0); } } // namespace test diff --git a/filament/backend/test/test_ReadPixels.cpp b/filament/backend/test/test_ReadPixels.cpp index 356ec046d6d5..8c0906c72da3 100644 --- a/filament/backend/test/test_ReadPixels.cpp +++ b/filament/backend/test/test_ReadPixels.cpp @@ -288,7 +288,7 @@ TEST_F(ReadPixelsTest, ReadPixels) { params.viewport.height = t.getRenderTargetSize(); api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); + RenderFrame frame (api); // Render a white triangle over blue. api.beginRenderPass(renderTarget, params); @@ -350,11 +350,7 @@ TEST_F(ReadPixelsTest, ReadPixels) { api.endRenderPass(); api.commit(swapChain); - api.endFrame(0); } - - // This ensures all driver commands have finished before exiting the test. - flushAndWait(); } TEST_F(ReadPixelsTest, ReadPixelsPerformance) { @@ -363,6 +359,7 @@ TEST_F(ReadPixelsTest, ReadPixelsPerformance) { DriverApi& api = getDriverApi(); Cleanup cleanup(api); + cleanup.addPostCall([&]() { executeCommands(); }); // Create a platform-specific SwapChain and make it current. auto swapChain = cleanup.add( @@ -416,28 +413,29 @@ TEST_F(ReadPixelsTest, ReadPixelsPerformance) { } api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - - // Render some content, just so we don't read back uninitialized data. - api.beginRenderPass(renderTarget, params); - state.primitiveType = PrimitiveType::TRIANGLES; - state.vertexBufferInfo = triangle.getVertexBufferInfo(); - api.bindPipeline(state); - api.bindRenderPrimitive(triangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); + { + RenderFrame frame(api); + + // Render some content, just so we don't read back uninitialized data. + api.beginRenderPass(renderTarget, params); + state.primitiveType = PrimitiveType::TRIANGLES; + state.vertexBufferInfo = triangle.getVertexBufferInfo(); + api.bindPipeline(state); + api.bindRenderPrimitive(triangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); - PixelBufferDescriptor descriptor(buffer, renderTargetSize * renderTargetSize * 4, - PixelDataFormat::RGBA, PixelDataType::UBYTE, 1, 0, 0, renderTargetSize, - [](void* buffer, size_t size, void* user) { - ReadPixelsTest* test = (ReadPixelsTest*)user; - test->readPixelsFinished = true; - }, this); + PixelBufferDescriptor descriptor(buffer, renderTargetSize * renderTargetSize * 4, + PixelDataFormat::RGBA, PixelDataType::UBYTE, 1, 0, 0, renderTargetSize, + [](void* buffer, size_t size, void* user) { + ReadPixelsTest* test = (ReadPixelsTest*) user; + test->readPixelsFinished = true; + }, this); - api.readPixels(renderTarget, 0, 0, renderTargetSize, renderTargetSize, - std::move(descriptor)); - api.commit(swapChain); - api.endFrame(0); + api.readPixels(renderTarget, 0, 0, renderTargetSize, renderTargetSize, + std::move(descriptor)); + api.commit(swapChain); + } flushAndWait(); getDriver().purge(); @@ -448,7 +446,6 @@ TEST_F(ReadPixelsTest, ReadPixelsPerformance) { free(buffer); api.finish(); - executeCommands(); } } // namespace test diff --git a/filament/backend/test/test_RenderExternalImage.cpp b/filament/backend/test/test_RenderExternalImage.cpp index cad0c896cd37..b809cf591ce1 100644 --- a/filament/backend/test/test_RenderExternalImage.cpp +++ b/filament/backend/test/test_RenderExternalImage.cpp @@ -81,31 +81,31 @@ TEST_F(BackendTest, RenderExternalImageWithoutSet) { DescriptorSetHandle descriptorSet = shader.createDescriptorSet(api); - api.startCapture(0); - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - - api.updateDescriptorSetTexture(descriptorSet, 0, texture, {}); - api.bindDescriptorSet(descriptorSet, 0, {}); - - // Render a triangle. - api.beginRenderPass(defaultRenderTarget, params); - state.primitiveType = PrimitiveType::TRIANGLES; - state.vertexBufferInfo = triangle.getVertexBufferInfo(); - api.bindPipeline(state); - api.bindRenderPrimitive(triangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); - - api.flush(); - api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); - + { + Cleanup cleanupCapture(api); + api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + + api.updateDescriptorSetTexture(descriptorSet, 0, texture, {}); + api.bindDescriptorSet(descriptorSet, 0, {}); + + // Render a triangle. + api.beginRenderPass(defaultRenderTarget, params); + state.primitiveType = PrimitiveType::TRIANGLES; + state.vertexBufferInfo = triangle.getVertexBufferInfo(); + api.bindPipeline(state); + api.bindRenderPrimitive(triangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); + + api.flush(); + api.commit(swapChain); + } + } api.finish(); - - executeCommands(); } TEST_F(BackendTest, RenderExternalImage) { @@ -180,32 +180,32 @@ TEST_F(BackendTest, RenderExternalImage) { RenderPassParams params = getClearColorRenderPass(); params.viewport = getFullViewport(); - api.startCapture(0); - api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); - - api.updateDescriptorSetTexture(descriptorSet, 0, texture, {}); - api.bindDescriptorSet(descriptorSet, 0, {}); - - // Render a triangle. - api.beginRenderPass(defaultRenderTarget, params); - state.primitiveType = PrimitiveType::TRIANGLES; - state.vertexBufferInfo = triangle.getVertexBufferInfo(); - api.bindPipeline(state); - api.bindRenderPrimitive(triangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); - - api.flush(); - api.commit(swapChain); - api.endFrame(0); - EXPECT_IMAGE(defaultRenderTarget, - ScreenshotParams(screenWidth(), screenHeight(), "RenderExternalImage", 1206264951)); - - api.stopCapture(0); - api.finish(); - flushAndWait(); - + { + Cleanup cleanupCapture(api); + api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); + api.makeCurrent(swapChain, swapChain); + { + RenderFrame frame(api); + + api.updateDescriptorSetTexture(descriptorSet, 0, texture, {}); + api.bindDescriptorSet(descriptorSet, 0, {}); + + // Render a triangle. + api.beginRenderPass(defaultRenderTarget, params); + state.primitiveType = PrimitiveType::TRIANGLES; + state.vertexBufferInfo = triangle.getVertexBufferInfo(); + api.bindPipeline(state); + api.bindRenderPrimitive(triangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); + + api.flush(); + api.commit(swapChain); + } + EXPECT_IMAGE(defaultRenderTarget, + ScreenshotParams(screenWidth(), screenHeight(), "RenderExternalImage", 1206264951)); + } } } // namespace test diff --git a/filament/backend/test/test_Scissor.cpp b/filament/backend/test/test_Scissor.cpp index 92f1218797f4..8b37158ee36e 100644 --- a/filament/backend/test/test_Scissor.cpp +++ b/filament/backend/test/test_Scissor.cpp @@ -43,8 +43,9 @@ TEST_F(BackendTest, ScissorViewportRegion) { constexpr int kSrcRtWidth = 384; constexpr int kSrcRtHeight = 384; - api.startCapture(0); Cleanup cleanup(api); + api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); // color texture (mip level 1) 512x512 depth texture (mip level 0) 512x512 // +----------------------------------------+ +------------------------------------------+ @@ -121,7 +122,7 @@ TEST_F(BackendTest, ScissorViewportRegion) { shader.addProgramToPipelineState(ps); api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); + RenderFrame frame(api); api.beginRenderPass(srcRenderTarget, params); api.scissor(scissor); @@ -136,9 +137,6 @@ TEST_F(BackendTest, ScissorViewportRegion) { ScreenshotParams(kSrcTexWidth >> 1, kSrcTexHeight >> 1, "scissor", 15842520)); api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); } } @@ -146,12 +144,11 @@ TEST_F(BackendTest, ScissorViewportRegion) { TEST_F(BackendTest, ScissorViewportEdgeCases) { auto& api = getDriverApi(); - api.startCapture(0); - Cleanup cleanup(api); - // The test is executed within this block scope to force destructors to run before // executeCommands(). { + Cleanup cleanup(api); + api.startCapture(0); // Create a SwapChain and make it current. We don't really use it so the res doesn't matter. auto swapChain = cleanup.add(api.createSwapChainHeadless(256, 256, 0)); api.makeCurrent(swapChain, swapChain); @@ -201,7 +198,7 @@ TEST_F(BackendTest, ScissorViewportEdgeCases) { shader.addProgramToPipelineState(ps); api.makeCurrent(swapChain, swapChain); - api.beginFrame(0, 0, 0); + RenderFrame frame(api); api.beginRenderPass(renderTarget, params); api.scissor(scissor); @@ -228,9 +225,6 @@ TEST_F(BackendTest, ScissorViewportEdgeCases) { ScreenshotParams(512, 512, "ScissorViewportEdgeCases", 2199186852)); api.commit(swapChain); - api.endFrame(0); - - api.stopCapture(0); } } diff --git a/filament/backend/test/test_StencilBuffer.cpp b/filament/backend/test/test_StencilBuffer.cpp index b8715869bfb2..63133f6f31d6 100644 --- a/filament/backend/test/test_StencilBuffer.cpp +++ b/filament/backend/test/test_StencilBuffer.cpp @@ -89,7 +89,7 @@ class BasicStencilBufferTest : public BackendTest { ps.stencilState.front.stencilOpDepthStencilPass = StencilOperation::INCR; api.makeCurrent(mSwapChain, mSwapChain); - api.beginFrame(0, 0, 0); + RenderFrame frame(api); api.beginRenderPass(renderTarget, params); ps.primitiveType = PrimitiveType::TRIANGLES; @@ -117,7 +117,6 @@ class BasicStencilBufferTest : public BackendTest { api.endRenderPass(); api.commit(mSwapChain); - api.endFrame(0); } void TearDown() override { @@ -146,9 +145,6 @@ TEST_F(BasicStencilBufferTest, StencilBuffer) { EXPECT_IMAGE(renderTarget, ScreenshotParams(screenWidth(), screenHeight(), "StencilBuffer", 0x3B1AEF0F)); - - flushAndWait(); - getDriver().purge(); } TEST_F(BasicStencilBufferTest, DepthAndStencilBuffer) { @@ -172,9 +168,6 @@ TEST_F(BasicStencilBufferTest, DepthAndStencilBuffer) { EXPECT_IMAGE(renderTarget, ScreenshotParams(screenWidth(), screenHeight(), "DepthAndStencilBuffer", 0x3B1AEF0F)); - - flushAndWait(); - getDriver().purge(); } TEST_F(BasicStencilBufferTest, StencilBufferMSAA) { @@ -204,6 +197,7 @@ TEST_F(BasicStencilBufferTest, StencilBufferMSAA) { { depthStencilTextureMSAA }, { depthStencilTextureMSAA })); api.startCapture(0); + cleanup.addPostCall([&]() { api.stopCapture(0); }); // We'll be using a triangle as geometry. TrianglePrimitive smallTriangle(api); @@ -233,44 +227,41 @@ TEST_F(BasicStencilBufferTest, StencilBufferMSAA) { ps.stencilState.front.stencilOpDepthStencilPass = StencilOperation::INCR; api.makeCurrent(mSwapChain, mSwapChain); - api.beginFrame(0, 0, 0); - - api.beginRenderPass(renderTarget0, params); - ps.primitiveType = PrimitiveType::TRIANGLES; - ps.vertexBufferInfo = smallTriangle.getVertexBufferInfo(); - api.bindPipeline(ps); - api.bindRenderPrimitive(smallTriangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); - - // Step 2: Render a larger triangle with the stencil test enabled. - params.flags.clear = TargetBufferFlags::COLOR0; - params.flags.discardStart = TargetBufferFlags::COLOR0; - params.flags.discardEnd = TargetBufferFlags::STENCIL; - params.clearColor = math::float4(0.0f, 0.0f, 1.0f, 1.0f); - ps.rasterState.colorWrite = true; - ps.stencilState.stencilWrite = false; - ps.stencilState.front.stencilOpDepthStencilPass = StencilOperation::KEEP; - ps.stencilState.front.stencilFunc = StencilState::StencilFunction::E; - ps.stencilState.front.ref = 0u; - - api.beginRenderPass(renderTarget1, params); - ps.primitiveType = PrimitiveType::TRIANGLES; - ps.vertexBufferInfo = triangle.getVertexBufferInfo(); - api.bindPipeline(ps); - api.bindRenderPrimitive(triangle.getRenderPrimitive()); - api.draw2(0, 3, 1); - api.endRenderPass(); - - api.commit(mSwapChain); - api.stopCapture(0); - api.endFrame(0); + { + RenderFrame frame(api); + + api.beginRenderPass(renderTarget0, params); + ps.primitiveType = PrimitiveType::TRIANGLES; + ps.vertexBufferInfo = smallTriangle.getVertexBufferInfo(); + api.bindPipeline(ps); + api.bindRenderPrimitive(smallTriangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); + // Step 2: Render a larger triangle with the stencil test enabled. + params.flags.clear = TargetBufferFlags::COLOR0; + params.flags.discardStart = TargetBufferFlags::COLOR0; + params.flags.discardEnd = TargetBufferFlags::STENCIL; + params.clearColor = math::float4(0.0f, 0.0f, 1.0f, 1.0f); + ps.rasterState.colorWrite = true; + ps.stencilState.stencilWrite = false; + ps.stencilState.front.stencilOpDepthStencilPass = StencilOperation::KEEP; + ps.stencilState.front.stencilFunc = StencilState::StencilFunction::E; + ps.stencilState.front.ref = 0u; + + api.beginRenderPass(renderTarget1, params); + ps.primitiveType = PrimitiveType::TRIANGLES; + ps.vertexBufferInfo = triangle.getVertexBufferInfo(); + api.bindPipeline(ps); + api.bindRenderPrimitive(triangle.getRenderPrimitive()); + api.draw2(0, 3, 1); + api.endRenderPass(); + + api.commit(mSwapChain); + api.stopCapture(0); + } EXPECT_IMAGE(renderTarget1, ScreenshotParams(screenWidth(), screenHeight(), "StencilBufferAutoResolve", 3353562179)); - - flushAndWait(); - getDriver().purge(); } } // namespace test