diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2024-08-27 11:53:16 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-27 09:53:16 -0700 |
| commit | 59c23b96b3649e77f5428c32e47b4401a802c604 (patch) | |
| tree | 54fe251ddbdbbfd03967f5a12eeed56480184e5c | |
| parent | f0ba756c2f982aac8095ff0928d048fc97548315 (diff) | |
Migrate examples (#4920)
* Migrate cpu-hello-world to new slang API
Migrate cpu-hello-world to new slang API, and also convert this example
as one of the unit test.
* Add 'shader-object' to slang-unit-test
* Convert ray-tracing example into unit-test
Convert ray-tracing example into unit-test
* Fix some replay bugs:
- Wrong decode type in 'getEntryPointHostCallable'.
- Mistakes in computing the output buffer size.
- Wrong decode type in array size in specialize() call.
- When capture entrypoint, we should increase the reference count
for the allocated entrypoint recorder object, because that is
allocated by record layer, it should be owned by the layer, user
should not be able to free it.
- Improve json consumer on the prelude text.
* Test verify change:
In our test, we add a "callIdx" string at beginning of the hash-code
string, as there could be more than one modules in the example, so they
could call 'getEntryPointHash' multiple times, in order for the test
can identify them, add "callIdx: <number>" as the key word.
| -rw-r--r-- | examples/cpu-hello-world/main.cpp | 102 | ||||
| -rw-r--r-- | examples/example-base/example-base.cpp | 22 | ||||
| -rw-r--r-- | examples/example-base/test-base.cpp | 3 | ||||
| -rw-r--r-- | examples/example-base/test-base.h | 3 | ||||
| -rw-r--r-- | examples/ray-tracing/main.cpp | 29 | ||||
| -rw-r--r-- | examples/shader-object/main.cpp | 11 | ||||
| -rw-r--r-- | source/slang-record-replay/record/slang-module.cpp | 13 | ||||
| -rw-r--r-- | source/slang-record-replay/record/slang-module.h | 3 | ||||
| -rw-r--r-- | source/slang-record-replay/record/slang-session.cpp | 12 | ||||
| -rw-r--r-- | source/slang-record-replay/record/slang-session.h | 3 | ||||
| -rw-r--r-- | source/slang-record-replay/replay/json-consumer.cpp | 15 | ||||
| -rw-r--r-- | source/slang-record-replay/replay/parameter-decoder.h | 17 | ||||
| -rw-r--r-- | source/slang-record-replay/replay/replay-consumer.cpp | 3 | ||||
| -rw-r--r-- | source/slang-record-replay/replay/replay-consumer.h | 1 | ||||
| -rw-r--r-- | source/slang-record-replay/replay/slang-decoder.cpp | 64 | ||||
| -rw-r--r-- | tools/slang-unit-test/unit-test-record-replay.cpp | 19 |
16 files changed, 189 insertions, 131 deletions
diff --git a/examples/cpu-hello-world/main.cpp b/examples/cpu-hello-world/main.cpp index 7eb897cc2..059efc8d3 100644 --- a/examples/cpu-hello-world/main.cpp +++ b/examples/cpu-hello-world/main.cpp @@ -47,6 +47,9 @@ struct UniformState; static SlangResult _innerMain(int argc, char** argv) { + TestBase testBase; + testBase.parseOption(argc, argv); + // First, we need to create a "session" for interacting with the Slang // compiler. This scopes all of our application's interactions // with the Slang library. At the moment, creating a session causes @@ -57,14 +60,15 @@ static SlangResult _innerMain(int argc, char** argv) // NOTE that we use attach instead of setting via assignment, as assignment will increase // the refcount. spCreateSession returns a IGlobalSession with a refcount of 1. ComPtr<slang::IGlobalSession> slangSession; - slangSession.attach(spCreateSession(NULL)); + + SLANG_RETURN_ON_FAIL(slang::createGlobalSession(slangSession.writeRef())); // As touched on earlier, in order to generate the final executable code, // the slang code is converted into C++, and that C++ needs a 'prelude' which // is just definitions that the generated code needed to work correctly. // There is a simple default definition of a prelude provided in the prelude // directory called 'slang-cpp-prelude.h'. - // + // // We need to tell slang either the contents of the prelude, or suitable include/s // that will work. The actual API call to set the prelude is `setPrelude` // and this just sets for a specific language a bit of text placed before generated code. @@ -75,72 +79,68 @@ static SlangResult _innerMain(int argc, char** argv) // is for the prelude code to be an *absolute* path to the 'slang-cpp-prelude.h' - which means // this will work wherever the generated code is, and allows accessing other files via relative paths. // - // Look at the source to TestToolUtil::setSessionDefaultPreludeFromExePath to see what's involed. + // Look at the source to TestToolUtil::setSessionDefaultPreludeFromExePath to see what's involed. TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], slangSession); - // A compile request represents a single invocation of the compiler, - // to process some inputs and produce outputs (or errors). - // - SlangCompileRequest* slangRequest = spCreateCompileRequest(slangSession); - - // We would like to request a CPU code that can be executed directly on the host - - // which is the 'SLANG_HOST_CALLABLE' target. - // If we wanted a just a shared library/dll, we could have used SLANG_SHARED_LIBRARY. - int targetIndex = spAddCodeGenTarget(slangRequest, SLANG_SHADER_HOST_CALLABLE); + slang::SessionDesc sessionDesc = {}; + slang::TargetDesc targetDesc = {}; + targetDesc.format = SLANG_SHADER_HOST_CALLABLE; + targetDesc.flags = SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM; - // Set the target flag to indicate that we want to compile all the entrypoints in the - // slang shader file into a library. - spSetTargetFlags(slangRequest, targetIndex, SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM); + sessionDesc.targets = &targetDesc; + sessionDesc.targetCount = 1; - // A compile request can include one or more "translation units," which more or - // less amount to individual source files (think `.c` files, not the `.h` files they - // might include). - // - // For this example, our code will all be in the Slang language. The user may - // also specify HLSL input here, but that currently doesn't affect the compiler's - // behavior much. - // - int translationUnitIndex = spAddTranslationUnit(slangRequest, SLANG_SOURCE_LANGUAGE_SLANG, nullptr); - - // We will load source code for our translation unit from the file `shader.slang`. - // There are also variations of this API for adding source code from application-provided buffers. - // - Slang::String path = resourceBase.resolveResource("shader.slang"); - spAddTranslationUnitSourceFile(slangRequest, translationUnitIndex, path.getBuffer()); + ComPtr<slang::ISession> session; + SLANG_RETURN_ON_FAIL(slangSession->createSession(sessionDesc, session.writeRef())); - // Once all of the input options for the compiler have been specified, - // we can invoke `spCompile` to run the compiler and see if any errors - // were detected. - // - const SlangResult compileRes = spCompile(slangRequest); - - // Even if there were no errors that forced compilation to fail, the - // compiler may have produced "diagnostic" output such as warnings. - // We will go ahead and print that output here. - // - if(auto diagnostics = spGetDiagnosticOutput(slangRequest)) + slang::IModule* slangModule = nullptr; { - printf("%s", diagnostics); + ComPtr<slang::IBlob> diagnosticBlob; + Slang::String path = resourceBase.resolveResource("shader.slang"); + slangModule = session->loadModule(path.getBuffer(), diagnosticBlob.writeRef()); + diagnoseIfNeeded(diagnosticBlob); + if (!slangModule) + return -1; } - // If compilation failed, there is no point in continuing any further. - if(SLANG_FAILED(compileRes)) + ComPtr<slang::IEntryPoint> entryPoint; + slangModule->findEntryPointByName("computeMain", entryPoint.writeRef()); + + Slang::List<slang::IComponentType*> componentTypes; + componentTypes.add(slangModule); + componentTypes.add(entryPoint); + + ComPtr<slang::IComponentType> composedProgram; { - spDestroyCompileRequest(slangRequest); - return compileRes; + ComPtr<slang::IBlob> diagnosticsBlob; + SlangResult result = session->createCompositeComponentType( + componentTypes.getBuffer(), + componentTypes.getCount(), + composedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); } // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library // it's just an interface to executable code). ComPtr<ISlangSharedLibrary> sharedLibrary; - SLANG_RETURN_ON_FAIL(spGetTargetHostCallable(slangRequest, 0, sharedLibrary.writeRef())); - + { + ComPtr<slang::IBlob> diagnosticsBlob; + SlangResult result = composedProgram->getEntryPointHostCallable( + 0, 0, sharedLibrary.writeRef(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + if (testBase.isTestMode()) + { + testBase.printEntrypointHashes(1, 1, composedProgram); + } + } // Once we have the sharedLibrary, we no longer need the request // unless we want to use reflection, to for example workout how 'UniformState' and 'UniformEntryPointParams' are laid out - // at runtime. We don't do that here - as we hard code the structures. - spDestroyCompileRequest(slangRequest); + // at runtime. We don't do that here - as we hard code the structures. - // Get the function we are going to execute + // Get the function we are going to execute const char entryPointName[] = "computeMain"; CPPPrelude::ComputeFunc func = (CPPPrelude::ComputeFunc)sharedLibrary->findFuncByName(entryPointName); if (!func) diff --git a/examples/example-base/example-base.cpp b/examples/example-base/example-base.cpp index fb11105f5..344611bed 100644 --- a/examples/example-base/example-base.cpp +++ b/examples/example-base/example-base.cpp @@ -34,6 +34,16 @@ Slang::Result WindowedAppBase::initializeBase( windowWidth = width; windowHeight = height; + + IFramebufferLayout::TargetLayout renderTargetLayout = {gfx::Format::R8G8B8A8_UNORM, 1}; + IFramebufferLayout::TargetLayout depthLayout = {gfx::Format::D32_FLOAT, 1}; + IFramebufferLayout::Desc framebufferLayoutDesc; + framebufferLayoutDesc.renderTargetCount = 1; + framebufferLayoutDesc.renderTargets = &renderTargetLayout; + framebufferLayoutDesc.depthStencil = &depthLayout; + SLANG_RETURN_ON_FAIL( + gDevice->createFramebufferLayout(framebufferLayoutDesc, gFramebufferLayout.writeRef())); + // Do not create swapchain and windows in test mode, because there won't be any display. if (!isTestMode()) { @@ -64,17 +74,7 @@ Slang::Result WindowedAppBase::initializeBase( gSwapchain = gDevice->createSwapchain(swapchainDesc, windowHandle); createSwapchainFramebuffers(); } - - IFramebufferLayout::TargetLayout renderTargetLayout = {gfx::Format::R8G8B8A8_UNORM, 1}; - IFramebufferLayout::TargetLayout depthLayout = {gfx::Format::D32_FLOAT, 1}; - IFramebufferLayout::Desc framebufferLayoutDesc; - framebufferLayoutDesc.renderTargetCount = 1; - framebufferLayoutDesc.renderTargets = &renderTargetLayout; - framebufferLayoutDesc.depthStencil = &depthLayout; - SLANG_RETURN_ON_FAIL( - gDevice->createFramebufferLayout(framebufferLayoutDesc, gFramebufferLayout.writeRef())); - - if (isTestMode()) + else { createOfflineFramebuffers(); } diff --git a/examples/example-base/test-base.cpp b/examples/example-base/test-base.cpp index 5c727aabe..0e0f8a69c 100644 --- a/examples/example-base/test-base.cpp +++ b/examples/example-base/test-base.cpp @@ -37,7 +37,8 @@ void TestBase::printEntrypointHashes(int entryPointCount, int targetCount, ComPt composedProgram->getEntryPointHash(entryPointIndex, targetIndex, entryPointHashBlob.writeRef()); Slang::StringBuilder strBuilder; - strBuilder << "entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + strBuilder << "callIdx: " << m_globalCounter << ", entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + m_globalCounter++; uint8_t* buffer = (uint8_t*)entryPointHashBlob->getBufferPointer(); for (size_t i = 0; i < entryPointHashBlob->getBufferSize(); i++) diff --git a/examples/example-base/test-base.h b/examples/example-base/test-base.h index 22cd70d09..cdd72c580 100644 --- a/examples/example-base/test-base.h +++ b/examples/example-base/test-base.h @@ -17,5 +17,6 @@ public: bool isTestMode() const { return m_isTestMode; } private: - bool m_isTestMode = false; + bool m_isTestMode = false; + uint64_t m_globalCounter = 0; }; diff --git a/examples/ray-tracing/main.cpp b/examples/ray-tracing/main.cpp index 2eb0a8481..4ec5070d8 100644 --- a/examples/ray-tracing/main.cpp +++ b/examples/ray-tracing/main.cpp @@ -195,6 +195,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)); @@ -288,11 +293,15 @@ void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } Slang::Result initialize() { initializeBase("Ray Tracing", 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; @@ -635,9 +644,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/examples/shader-object/main.cpp b/examples/shader-object/main.cpp index 15e2df54c..603278bcf 100644 --- a/examples/shader-object/main.cpp +++ b/examples/shader-object/main.cpp @@ -21,6 +21,8 @@ using namespace gfx; static const ExampleResources resourceBase("shader-object"); +static TestBase testBase; + // Loads the shader code defined in `shader-object.slang` for use by the `gfx` layer. // Result loadShaderProgram( @@ -108,6 +110,11 @@ Result loadShaderProgram( diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); SLANG_RETURN_ON_FAIL(result); + if (testBase.isTestMode()) + { + testBase.printEntrypointHashes(1, 1, composedProgram); + } + slangReflection = composedProgram->getLayout(); // At this point, `composedProgram` represents the shader program @@ -124,8 +131,10 @@ Result loadShaderProgram( } // Main body of the example. -int main() +int main(int argc, char* argv[]) { + testBase.parseOption(argc, argv); + // Creates a `gfx` renderer, which provides the main interface for // interacting with the graphics API. Slang::ComPtr<gfx::IDevice> device; diff --git a/source/slang-record-replay/record/slang-module.cpp b/source/slang-record-replay/record/slang-module.cpp index b116fa99b..3acda5d22 100644 --- a/source/slang-record-replay/record/slang-module.cpp +++ b/source/slang-record-replay/record/slang-module.cpp @@ -88,8 +88,9 @@ namespace SlangRecord if (*outEntryPoint) { - EntryPointRecorder* entryPointRecord = m_mapEntryPointToRecord.tryGetValue(*outEntryPoint); - if (!entryPointRecord) + EntryPointRecorder* entryPointRecord = nullptr; + bool ret = m_mapEntryPointToRecord.tryGetValue(*outEntryPoint, entryPointRecord); + if (!ret) { SLANG_RECORD_ASSERT(!"Entrypoint not found in mapEntryPointToRecord"); } @@ -490,12 +491,14 @@ namespace SlangRecord EntryPointRecorder* ModuleRecorder::getEntryPointRecorder(slang::IEntryPoint* entryPoint) { EntryPointRecorder* entryPointRecord = nullptr; - entryPointRecord = m_mapEntryPointToRecord.tryGetValue(entryPoint); - if (!entryPointRecord) + bool ret = m_mapEntryPointToRecord.tryGetValue(entryPoint, entryPointRecord); + if (!ret) { entryPointRecord = new EntryPointRecorder(entryPoint, m_recordManager); Slang::ComPtr<EntryPointRecorder> result(entryPointRecord); - m_mapEntryPointToRecord.add(entryPoint, *result.detach()); + + m_entryPointsRecordAllocation.add(result); + m_mapEntryPointToRecord.add(entryPoint, result.detach()); } return entryPointRecord; } diff --git a/source/slang-record-replay/record/slang-module.h b/source/slang-record-replay/record/slang-module.h index 1b1cc5de9..ed684c680 100644 --- a/source/slang-record-replay/record/slang-module.h +++ b/source/slang-record-replay/record/slang-module.h @@ -97,7 +97,8 @@ namespace SlangRecord // `IEntryPoint` can only be created from 'IModule', so we need to record it in // this class, and create a map such that we don't create new `EntryPointRecorder` // for the same `IEntryPoint`. - Dictionary<slang::IEntryPoint*, EntryPointRecorder> m_mapEntryPointToRecord; + Dictionary<slang::IEntryPoint*, EntryPointRecorder*> m_mapEntryPointToRecord; + List<ComPtr<EntryPointRecorder>> m_entryPointsRecordAllocation; }; } // namespace SlangRecord diff --git a/source/slang-record-replay/record/slang-session.cpp b/source/slang-record-replay/record/slang-session.cpp index 3eb944082..f38d18aa1 100644 --- a/source/slang-record-replay/record/slang-session.cpp +++ b/source/slang-record-replay/record/slang-session.cpp @@ -444,8 +444,9 @@ namespace SlangRecord if (pModule) { - ModuleRecorder* moduleRecord = m_mapModuleToRecord.tryGetValue(pModule); - if (!moduleRecord) + ModuleRecorder* moduleRecord = nullptr; + bool ret = m_mapModuleToRecord.tryGetValue(pModule, moduleRecord); + if (!ret) { SLANG_RECORD_ASSERT(!"Module not found in mapModuleToRecord"); } @@ -466,12 +467,13 @@ namespace SlangRecord ModuleRecorder* SessionRecorder::getModuleRecorder(slang::IModule* module) { ModuleRecorder* moduleRecord = nullptr; - moduleRecord = m_mapModuleToRecord.tryGetValue(module); - if (!moduleRecord) + bool ret = m_mapModuleToRecord.tryGetValue(module, moduleRecord); + if (!ret) { moduleRecord = new ModuleRecorder(module, m_recordManager); Slang::ComPtr<ModuleRecorder> result(moduleRecord); - m_mapModuleToRecord.add(module, *result.detach()); + m_moduleRecordersAlloation.add(result); + m_mapModuleToRecord.add(module, result.detach()); } return moduleRecord; } diff --git a/source/slang-record-replay/record/slang-session.h b/source/slang-record-replay/record/slang-session.h index bc56003a9..644c975ff 100644 --- a/source/slang-record-replay/record/slang-session.h +++ b/source/slang-record-replay/record/slang-session.h @@ -101,7 +101,8 @@ namespace SlangRecord Slang::ComPtr<slang::ISession> m_actualSession; uint64_t m_sessionHandle = 0; - Dictionary<slang::IModule*, ModuleRecorder> m_mapModuleToRecord; + Dictionary<slang::IModule*, ModuleRecorder*> m_mapModuleToRecord; + List<ComPtr<ModuleRecorder>> m_moduleRecordersAlloation; RecordManager* m_recordManager = nullptr; }; } diff --git a/source/slang-record-replay/replay/json-consumer.cpp b/source/slang-record-replay/replay/json-consumer.cpp index 456988bdb..455a36627 100644 --- a/source/slang-record-replay/replay/json-consumer.cpp +++ b/source/slang-record-replay/replay/json-consumer.cpp @@ -216,7 +216,7 @@ namespace SlangRecord for(int i = 0; i < specializationArgCount; i++) { bool isLastField = (i == specializationArgCount - 1); - ScopeWritterForKey scopeWritterForArg(&builder, &indent, Slang::StringUtil::makeStringWithFormat("[%d]\n", i), isLastField); + ScopeWritterForKey scopeWritterForArg(&builder, &indent, Slang::StringUtil::makeStringWithFormat("[%d]", i), isLastField); { _writePair(builder, indent, "kind", SpecializationArgKindToString(specializationArgs[i].kind)); _writePairNoComma(builder, indent, "type", Slang::StringUtil::makeStringWithFormat("0x%X", specializationArgs[i].type)); @@ -473,13 +473,11 @@ namespace SlangRecord SANITY_CHECK(); Slang::StringBuilder builder; int indent = 0; - _writeString(builder, indent, "GlobalFunction::createGlobalSession: {\n"); + { - indent++; + ScopeWritterForKey scopeWritter(&builder, &indent, "IGlobalSession::createGlobalSession"); _writePairNoComma(builder, indent, "outGlobalSession", Slang::StringUtil::makeStringWithFormat("0x%X", outGlobalSessionId)); - indent--; } - _writeString(builder, indent, "}\n"); m_fileStream.write(builder.produceString().begin(), builder.produceString().getLength()); m_fileStream.flush(); @@ -490,7 +488,6 @@ namespace SlangRecord SANITY_CHECK(); Slang::StringBuilder builder; int indent = 0; - _writeString(builder, indent, "IGlobalSession::createSession: {\n"); { ScopeWritterForKey scopeWritter(&builder, &indent, "IGlobalSession::createSession"); @@ -633,14 +630,14 @@ namespace SlangRecord SANITY_CHECK(); Slang::StringBuilder builder; int indent = 0; - _writeString(builder, indent, "IGlobalSession::setLanguagePrelude: {\n"); { ScopeWritterForKey scopeWritter(&builder, &indent, "IGlobalSession::setLanguagePrelude"); { _writePair(builder, indent, "this", Slang::StringUtil::makeStringWithFormat("0x%X", objectId)); _writePair(builder, indent, "sourceLanguage", SlangSourceLanguageToString(inSourceLanguage)); - _writePairNoComma(builder, indent, "preludeText", (prelude != nullptr ? prelude : "nullptr")); + _writePairNoComma(builder, indent, "preludeText", Slang::StringUtil::makeStringWithFormat("\"%s\"", + prelude != nullptr ? prelude : "nullptr")); } } @@ -1231,7 +1228,7 @@ namespace SlangRecord _writePair(builder, indent, "type", Slang::StringUtil::makeStringWithFormat("0x%X", typeId)); _writePair(builder, indent, "rules", LayoutRulesToString(rules)); _writePair(builder, indent, "outDiagnostics", outDiagnosticsId); - _writePair(builder, indent, "retTypeReflectionId", outTypeLayoutReflectionId); + _writePairNoComma(builder, indent, "retTypeReflectionId", outTypeLayoutReflectionId); } } diff --git a/source/slang-record-replay/replay/parameter-decoder.h b/source/slang-record-replay/replay/parameter-decoder.h index 5d6f40987..d1deca3eb 100644 --- a/source/slang-record-replay/replay/parameter-decoder.h +++ b/source/slang-record-replay/replay/parameter-decoder.h @@ -54,7 +54,10 @@ namespace SlangRecord template <typename T> static size_t decodeValueArray(const uint8_t* buffer, int64_t bufferSize, ValueDecoder<T>* valueArray, size_t count) { - SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); + if (count == 0 && bufferSize == 0) + { + return 0; + } size_t readByte = 0; for (size_t i = 0; i < count; ++i) @@ -66,6 +69,10 @@ namespace SlangRecord static size_t decodeStringArray(const uint8_t* buffer, int64_t bufferSize, char** outputArray, size_t count) { + if (count == 0 && bufferSize == 0) + { + return 0; + } SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); size_t readByte = 0; @@ -83,6 +90,10 @@ namespace SlangRecord template <typename T> static size_t decodeStructArray(const uint8_t* buffer, int64_t bufferSize, T* outputArray, size_t count) { + if (count == 0 && bufferSize == 0) + { + return 0; + } SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); size_t bufferRead = 0; @@ -97,6 +108,10 @@ namespace SlangRecord static size_t decodeAddressArray(const uint8_t* buffer, int64_t bufferSize, uint64_t* addressArray, size_t count) { + if (count == 0 && bufferSize == 0) + { + return 0; + } SLANG_RECORD_ASSERT((buffer != nullptr) && (bufferSize > 0)); size_t bufferRead = 0; diff --git a/source/slang-record-replay/replay/replay-consumer.cpp b/source/slang-record-replay/replay/replay-consumer.cpp index 7710b50e9..01de2f828 100644 --- a/source/slang-record-replay/replay/replay-consumer.cpp +++ b/source/slang-record-replay/replay/replay-consumer.cpp @@ -118,7 +118,8 @@ namespace SlangRecord { uint8_t* buffer = (uint8_t*)outHash->getBufferPointer(); Slang::StringBuilder strBuilder; - strBuilder << "entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + strBuilder << "callIdx: " << m_globalCounter << ", entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + m_globalCounter++; for (size_t i = 0; i < outHash->getBufferSize(); i++) { diff --git a/source/slang-record-replay/replay/replay-consumer.h b/source/slang-record-replay/replay/replay-consumer.h index 8a38d6202..5618598e1 100644 --- a/source/slang-record-replay/replay/replay-consumer.h +++ b/source/slang-record-replay/replay/replay-consumer.h @@ -52,6 +52,7 @@ namespace SlangRecord } Slang::Dictionary<ObjectID, void*>& m_objectMap; + uint32_t m_globalCounter = 0; }; class ReplayConsumer : public IDecoderConsumer diff --git a/source/slang-record-replay/replay/slang-decoder.cpp b/source/slang-record-replay/replay/slang-decoder.cpp index e30bd4584..30d182729 100644 --- a/source/slang-record-replay/replay/slang-decoder.cpp +++ b/source/slang-record-replay/replay/slang-decoder.cpp @@ -872,7 +872,7 @@ namespace SlangRecord ObjectID outDiagnosticsId = 0; ObjectID outTypeReflectionId = 0; - readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize, outDiagnosticsId); readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outTypeReflectionId); for (auto consumer: m_consumers) @@ -895,7 +895,7 @@ namespace SlangRecord ObjectID outDiagnosticsId = 0; ObjectID outTypeLayoutReflectionId = 0; - readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize, outDiagnosticsId); readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outTypeLayoutReflectionId); for (auto consumer: m_consumers) @@ -916,7 +916,7 @@ namespace SlangRecord ObjectID outDiagnosticsId = 0; ObjectID outTypeReflectionId = 0; - readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize, outDiagnosticsId); readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outTypeReflectionId); for (auto consumer: m_consumers) @@ -1005,7 +1005,7 @@ namespace SlangRecord ObjectID outDiagnosticsId = 0; ObjectID outConformanceId = 0; - readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outConformanceId); + readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize, outConformanceId); readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); for (auto consumer: m_consumers) @@ -1256,8 +1256,8 @@ namespace SlangRecord slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); size_t readByte = 0; - uint32_t specializationArgCount = 0; - readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + int64_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); std::vector<slang::SpecializationArg> specializationArgs; @@ -1299,15 +1299,15 @@ namespace SlangRecord void SlangDecoder::IModule_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) { size_t readByte = 0; - int64_t entryPointIndex = 0; - int64_t targetIndex = 0; - readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); - readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + int32_t entryPointIndex = 0; + int32_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); ObjectID outSharedLibraryId = 0; ObjectID outDiagnosticsId = 0; readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); - readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); for (auto consumer: m_consumers) { @@ -1465,8 +1465,8 @@ namespace SlangRecord slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); size_t readByte = 0; - uint32_t specializationArgCount = 0; - readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + int64_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); std::vector<slang::SpecializationArg> specializationArgs; @@ -1508,15 +1508,15 @@ namespace SlangRecord void SlangDecoder::IEntryPoint_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) { size_t readByte = 0; - int64_t entryPointIndex = 0; - int64_t targetIndex = 0; - readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); - readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + int32_t entryPointIndex = 0; + int32_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); ObjectID outSharedLibraryId = 0; ObjectID outDiagnosticsId = 0; readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); - readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); for (auto consumer: m_consumers) { @@ -1674,8 +1674,8 @@ namespace SlangRecord slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); size_t readByte = 0; - uint32_t specializationArgCount = 0; - readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + int64_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); std::vector<slang::SpecializationArg> specializationArgs; @@ -1717,15 +1717,15 @@ namespace SlangRecord void SlangDecoder::ICompositeComponentType_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) { size_t readByte = 0; - int64_t entryPointIndex = 0; - int64_t targetIndex = 0; - readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); - readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + int32_t entryPointIndex = 0; + int32_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); ObjectID outSharedLibraryId = 0; ObjectID outDiagnosticsId = 0; readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); - readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); for (auto consumer: m_consumers) { @@ -1883,8 +1883,8 @@ namespace SlangRecord slangRecordLog(LogLevel::Error, "%s: The shader reflection interfaces are not recordd\n", __PRETTY_FUNCTION__); size_t readByte = 0; - uint32_t specializationArgCount = 0; - readByte = ParameterDecoder::decodeUint32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); + int64_t specializationArgCount = 0; + readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, specializationArgCount); std::vector<slang::SpecializationArg> specializationArgs; @@ -1926,15 +1926,15 @@ namespace SlangRecord void SlangDecoder::ITypeConformance_getEntryPointHostCallable(ObjectID objectId, ParameterBlock const& parameterBlock) { size_t readByte = 0; - int64_t entryPointIndex = 0; - int64_t targetIndex = 0; - readByte = ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); - readByte += ParameterDecoder::decodeInt64(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); + int32_t entryPointIndex = 0; + int32_t targetIndex = 0; + readByte = ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer, parameterBlock.parameterBufferSize, entryPointIndex); + readByte += ParameterDecoder::decodeInt32(parameterBlock.parameterBuffer + readByte, parameterBlock.parameterBufferSize - readByte, targetIndex); ObjectID outSharedLibraryId = 0; ObjectID outDiagnosticsId = 0; readByte = ParameterDecoder::decodeAddress(parameterBlock.outputBuffer, parameterBlock.outputBufferSize, outSharedLibraryId); - readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.parameterBufferSize - readByte, outDiagnosticsId); + readByte += ParameterDecoder::decodeAddress(parameterBlock.outputBuffer + readByte, parameterBlock.outputBufferSize - readByte, outDiagnosticsId); for (auto consumer: m_consumers) { diff --git a/tools/slang-unit-test/unit-test-record-replay.cpp b/tools/slang-unit-test/unit-test-record-replay.cpp index 2d5619f71..654fb6823 100644 --- a/tools/slang-unit-test/unit-test-record-replay.cpp +++ b/tools/slang-unit-test/unit-test-record-replay.cpp @@ -37,6 +37,7 @@ static SlangResult createProcess(UnitTestContext* context, const char* processNa struct entryHashInfo { + int64_t callIdx = -1; int64_t targetIndex = -1; int64_t entryPointIndex = -1; String hash; @@ -60,7 +61,7 @@ static SlangResult parseHashes(List<String> const& lines, List<entryHashInfo>& o } StringUtil::split(UnownedStringSlice(line.getBuffer() + skipCharacters), ',', tokens); - if (tokens.getCount() != 3) + if (tokens.getCount() != 4) { return SLANG_FAIL; } @@ -83,7 +84,7 @@ static SlangResult parseHashes(List<String> const& lines, List<entryHashInfo>& o SLANG_RETURN_ON_FAIL(extractToken(tokens[0], ':', subToken)); int64_t outNumer = 0; StringUtil::parseInt64(subToken, outNumer); - hashInfo.entryPointIndex = outNumer; + hashInfo.callIdx = outNumer; } { @@ -91,12 +92,21 @@ static SlangResult parseHashes(List<String> const& lines, List<entryHashInfo>& o SLANG_RETURN_ON_FAIL(extractToken(tokens[1], ':', subToken)); int64_t outNumer = 0; StringUtil::parseInt64(subToken, outNumer); - hashInfo.targetIndex = outNumer; + hashInfo.entryPointIndex = outNumer; } { UnownedStringSlice subToken; SLANG_RETURN_ON_FAIL(extractToken(tokens[2], ':', subToken)); + int64_t outNumer = 0; + StringUtil::parseInt64(subToken, outNumer); + hashInfo.targetIndex = outNumer; + } + + { + UnownedStringSlice subToken; + SLANG_RETURN_ON_FAIL(extractToken(tokens[3], ':', subToken)); + // remove the white space after ":" hashInfo.hash = subToken.begin() + 1; } @@ -406,7 +416,10 @@ error: static SlangResult runTests(UnitTestContext* context) { const char* testBinaryNames[] = { + "cpu-hello-world", "triangle", + "shader-object", + "ray-tracing" }; SlangResult finalRes = SLANG_OK; |
