From efda04f3cc784dde42bd15fd1d33edeea0f3cd92 Mon Sep 17 00:00:00 2001 From: kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:36:31 -0500 Subject: [PATCH] Migrate 3 more examples to slang-unit-test (#4927) * Convert 'ray-tracing-pipeline' example into slang-test * Convert model-view and 'autodiff-texture' examples to slang-test * Add more error message in RecordReplay test * Fix a shader issue in autodiff-texture --- examples/autodiff-texture/main.cpp | 42 +++++++++++++---- examples/autodiff-texture/train.slang | 4 +- examples/model-viewer/main.cpp | 45 +++++++++++++++---- examples/ray-tracing-pipeline/main.cpp | 28 ++++++++---- .../replay/json-consumer.cpp | 4 +- .../unit-test-record-replay.cpp | 27 +++++++++-- 6 files changed, 118 insertions(+), 32 deletions(-) diff --git a/examples/autodiff-texture/main.cpp b/examples/autodiff-texture/main.cpp index 01cad6fe4e..8bffadd84b 100644 --- a/examples/autodiff-texture/main.cpp +++ b/examples/autodiff-texture/main.cpp @@ -78,6 +78,11 @@ struct AutoDiffTexture : public WindowedAppBase diagnoseIfNeeded(diagnosticsBlob); SLANG_RETURN_ON_FAIL(result); + if (isTestMode()) + { + printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + } + gfx::IShaderProgram::Desc programDesc = {}; programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); @@ -114,6 +119,11 @@ struct AutoDiffTexture : public WindowedAppBase diagnoseIfNeeded(diagnosticsBlob); SLANG_RETURN_ON_FAIL(result); + if (isTestMode()) + { + printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + } + gfx::IShaderProgram::Desc programDesc = {}; programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); @@ -266,18 +276,31 @@ struct AutoDiffTexture : public WindowedAppBase initializeBase("autodiff-texture", 1024, 768); srand(20421); - gWindow->events.keyPress = [this](platform::KeyEventArgs& e) + if (!isTestMode()) { - if (e.keyChar == 'R' || e.keyChar == 'r') - resetLearntTexture = true; - }; + gWindow->events.keyPress = [this](platform::KeyEventArgs& e) + { + if (e.keyChar == 'R' || e.keyChar == 'r') + resetLearntTexture = true; + }; + } kClearValue.color.floatValues[0] = 0.3f; kClearValue.color.floatValues[1] = 0.5f; kClearValue.color.floatValues[2] = 0.7f; kClearValue.color.floatValues[3] = 1.0f; - auto clientRect = gWindow->getClientRect(); + platform::Rect clientRect{}; + if (isTestMode()) + { + clientRect.width = 1024; + clientRect.height = 768; + } + else + { + clientRect = getWindow()->getClientRect(); + } + windowWidth = clientRect.width; windowHeight = clientRect.height; @@ -321,7 +344,7 @@ struct AutoDiffTexture : public WindowedAppBase } { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadComputeProgram(gDevice, "convert", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL(loadComputeProgram(gDevice, "convert.slang", shaderProgram.writeRef())); gConvertPipelineState = createComputePipelineState(shaderProgram); } { @@ -619,7 +642,7 @@ struct AutoDiffTexture : public WindowedAppBase commandBuffer->close(); gQueue->executeCommandBuffer(commandBuffer); } - + // Draw currently learnt texture. { ComPtr commandBuffer = @@ -635,7 +658,10 @@ struct AutoDiffTexture : public WindowedAppBase gQueue->executeCommandBuffer(commandBuffer); } - gSwapchain->present(); + if (!isTestMode()) + { + gSwapchain->present(); + } } void drawTexturedQuad(IRenderCommandEncoder* renderEncoder, int x, int y, int w, int h, IResourceView* srv) diff --git a/examples/autodiff-texture/train.slang b/examples/autodiff-texture/train.slang index c6a819d2f2..7126cbde97 100644 --- a/examples/autodiff-texture/train.slang +++ b/examples/autodiff-texture/train.slang @@ -15,12 +15,12 @@ struct DifferentiableTexture float minLOD; [BackwardDerivative(bwd_LoadTexel)] - float4 LoadTexel(int3 location, int2 offset, uint dLayerW, uint dMipOffset) + float4 LoadTexel(int3 location, constexpr int2 offset, uint dLayerW, uint dMipOffset) { return texture.Load(location, offset); } - void bwd_LoadTexel(int3 location, int2 offset, uint dLayerW, uint dMipOffset, float4 val) + void bwd_LoadTexel(int3 location, constexpr int2 offset, uint dLayerW, uint dMipOffset, float4 val) { // Ignore alpha dimension for this example.. int4 uval = int4(int3(val.xyz * 65536), 1); diff --git a/examples/model-viewer/main.cpp b/examples/model-viewer/main.cpp index 8627fe2c45..7ca5eeb74d 100644 --- a/examples/model-viewer/main.cpp +++ b/examples/model-viewer/main.cpp @@ -51,10 +51,14 @@ struct RendererContext slang::TypeReflection* perViewShaderType; slang::TypeReflection* perModelShaderType; - Result init(IDevice* inDevice) + TestBase *pTestBase; + + Result init(IDevice* inDevice, TestBase* inTestBase) { device = inDevice; ComPtr diagnostic; + pTestBase = inTestBase; + Slang::String path = resourceBase.resolveResource("shaders.slang").getBuffer(); shaderModule = device->getSlangSession()->loadModule( path.getBuffer(), @@ -108,6 +112,12 @@ struct RendererContext diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); SLANG_RETURN_ON_FAIL(result); + + if (pTestBase && pTestBase->isTestMode()) + { + pTestBase->printEntrypointHashes(componentTypes.getCount() - 1, 1, composedProgram); + } + slangReflection = composedProgram->getLayout(); // At this point, `composedProgram` represents the shader program @@ -740,14 +750,18 @@ void onMouseUp(platform::MouseEventArgs args) Result initialize() { initializeBase("Model Viewer", 1024, 768); - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; - gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; - gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + if (!isTestMode()) + { + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; + gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; + gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + } // Initialize `RendererContext`, which loads the shader module from file. - SLANG_RETURN_ON_FAIL(context.init(gDevice)); + SLANG_RETURN_ON_FAIL(context.init(gDevice, this)); + InputElementDesc inputElements[] = { {"POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Model::Vertex, position) }, @@ -817,7 +831,17 @@ void renderFrame(int frameIndex) override // to set up our various transformation matrices. // glm::mat4x4 identity = glm::mat4x4(1.0f); - auto clientRect = getWindow()->getClientRect(); + + platform::Rect clientRect{}; + if (isTestMode()) + { + clientRect.width = 1024; + clientRect.height = 768; + } + else + { + clientRect = getWindow()->getClientRect(); + } if (clientRect.height == 0) return; glm::mat4x4 projection = glm::perspectiveRH_ZO( @@ -933,7 +957,10 @@ void renderFrame(int frameIndex) override drawCommandBuffer->close(); gQueue->executeCommandBuffer(drawCommandBuffer); - gSwapchain->present(); + if (!isTestMode()) + { + gSwapchain->present(); + } } }; diff --git a/examples/ray-tracing-pipeline/main.cpp b/examples/ray-tracing-pipeline/main.cpp index c4da87756f..562eca4dc8 100644 --- a/examples/ray-tracing-pipeline/main.cpp +++ b/examples/ray-tracing-pipeline/main.cpp @@ -203,6 +203,11 @@ gfx::Result loadShaderProgram( diagnoseIfNeeded(diagnosticsBlob); SLANG_RETURN_ON_FAIL(result); + if (isTestMode()) + { + printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + } + gfx::IShaderProgram::Desc programDesc = {}; programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); @@ -297,11 +302,14 @@ void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } Slang::Result initialize() { initializeBase("Ray Tracing Pipeline", 1024, 768); - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; - gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; - gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + if (!isTestMode()) + { + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; + gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; + gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + } IBufferResource::Desc vertexBufferDesc; vertexBufferDesc.type = IResource::Type::Buffer; @@ -670,9 +678,13 @@ virtual void renderFrame(int frameBufferIndex) override presentCommandBuffer->close(); gQueue->executeCommandBuffer(presentCommandBuffer); } - // With that, we are done drawing for one frame, and ready for the next. - // - gSwapchain->present(); + + if (!isTestMode()) + { + // With that, we are done drawing for one frame, and ready for the next. + // + gSwapchain->present(); + } } }; diff --git a/source/slang-record-replay/replay/json-consumer.cpp b/source/slang-record-replay/replay/json-consumer.cpp index 455a36627a..d8079c2552 100644 --- a/source/slang-record-replay/replay/json-consumer.cpp +++ b/source/slang-record-replay/replay/json-consumer.cpp @@ -1227,8 +1227,8 @@ namespace SlangRecord _writePair(builder, indent, "this", Slang::StringUtil::makeStringWithFormat("0x%X", objectId)); _writePair(builder, indent, "type", Slang::StringUtil::makeStringWithFormat("0x%X", typeId)); _writePair(builder, indent, "rules", LayoutRulesToString(rules)); - _writePair(builder, indent, "outDiagnostics", outDiagnosticsId); - _writePairNoComma(builder, indent, "retTypeReflectionId", outTypeLayoutReflectionId); + _writePair(builder, indent, "outDiagnostics", Slang::StringUtil::makeStringWithFormat("0x%X", outDiagnosticsId)); + _writePairNoComma(builder, indent, "retTypeReflectionId", Slang::StringUtil::makeStringWithFormat("0x%X", outTypeLayoutReflectionId)); } } diff --git a/tools/slang-unit-test/unit-test-record-replay.cpp b/tools/slang-unit-test/unit-test-record-replay.cpp index 654fb68234..81e74a4070 100644 --- a/tools/slang-unit-test/unit-test-record-replay.cpp +++ b/tools/slang-unit-test/unit-test-record-replay.cpp @@ -189,6 +189,16 @@ static SlangResult launchProcessAndReadStdout(UnitTestContext* context, const Li return res; } + if (exeRes.resultCode != 0) + { + msgBuilder << "'" << exampleName << "' exits with failure\n"; + msgBuilder << "Process ret code: " << exeRes.resultCode << "\n"; + msgBuilder << "Standard output:\n" << exeRes.standardOutput; + msgBuilder << "Standard error:\n" << exeRes.standardError; + getTestReporter()->message(TestMessageType::TestFailure, msgBuilder.toString().getBuffer()); + return SLANG_FAIL; + } + if (exeRes.standardOutput.getLength() == 0) { msgBuilder << "No stdout found in '" << exampleName << "'\n"; @@ -300,12 +310,20 @@ static SlangResult replayExample(UnitTestContext* context, List& static SlangResult resultCompare(List const& expectHashes, List const& resultHashes) { - if (expectHashes.getCount() != resultHashes.getCount()) + if (expectHashes.getCount() == 0) { + getTestReporter()->message(TestMessageType::TestFailure, "No hash found\n"); return SLANG_FAIL; } StringBuilder msgBuilder; + if (expectHashes.getCount() != resultHashes.getCount()) + { + msgBuilder << "The number of hashes doesn't match, expect: " << expectHashes.getCount() << ", actual: " << resultHashes.getCount() << "\n"; + getTestReporter()->message(TestMessageType::TestFailure, msgBuilder.toString().getBuffer()); + return SLANG_FAIL; + } + for (Index i = 0; i < expectHashes.getCount(); i++) { if (expectHashes[i].targetIndex != resultHashes[i].targetIndex) @@ -419,7 +437,10 @@ static SlangResult runTests(UnitTestContext* context) "cpu-hello-world", "triangle", "shader-object", - "ray-tracing" + "ray-tracing", + "ray-tracing-pipeline", + "model-viewer", + "autodiff-texture" }; SlangResult finalRes = SLANG_OK; @@ -435,7 +456,7 @@ static SlangResult runTests(UnitTestContext* context) } } - return SLANG_OK; + return finalRes; } // Those examples all depend on the Vulkan, so we only run them on non-Apple platforms.