diff options
24 files changed, 384 insertions, 135 deletions
diff --git a/examples/example-base/example-base.cpp b/examples/example-base/example-base.cpp index 82d474f06..fb11105f5 100644 --- a/examples/example-base/example-base.cpp +++ b/examples/example-base/example-base.cpp @@ -17,19 +17,6 @@ Slang::Result WindowedAppBase::initializeBase( int height, DeviceType deviceType) { - // Create a window for our application to render into. - // - platform::WindowDesc windowDesc; - windowDesc.title = title; - windowDesc.width = width; - windowDesc.height = height; - windowWidth = width; - windowHeight = height; - windowDesc.style = platform::WindowStyle::Default; - gWindow = platform::Application::createWindow(windowDesc); - gWindow->events.mainLoop = [this]() { mainLoop(); }; - gWindow->events.sizeChanged = Slang::Action<>(this, &WindowedAppBase::windowSizeChanged); - // Initialize the rendering layer. #ifdef _DEBUG // Enable debug layer in debug config. @@ -41,26 +28,44 @@ Slang::Result WindowedAppBase::initializeBase( if (SLANG_FAILED(res)) return res; - auto deviceInfo = gDevice->getDeviceInfo(); - Slang::StringBuilder titleSb; - titleSb << title << " (" << deviceInfo.apiName << ": " << deviceInfo.adapterName << ")"; - gWindow->setText(titleSb.getBuffer()); - ICommandQueue::Desc queueDesc = {}; queueDesc.type = ICommandQueue::QueueType::Graphics; gQueue = gDevice->createCommandQueue(queueDesc); - // Create swapchain and framebuffers. - gfx::ISwapchain::Desc swapchainDesc = {}; - swapchainDesc.format = gfx::Format::R8G8B8A8_UNORM; - swapchainDesc.width = width; - swapchainDesc.height = height; - swapchainDesc.imageCount = kSwapchainImageCount; - swapchainDesc.queue = gQueue; - gfx::WindowHandle windowHandle = gWindow->getNativeHandle().convert<gfx::WindowHandle>(); - gSwapchain = gDevice->createSwapchain(swapchainDesc, windowHandle); - - IFramebufferLayout::TargetLayout renderTargetLayout = {gSwapchain->getDesc().format, 1}; + windowWidth = width; + windowHeight = height; + // Do not create swapchain and windows in test mode, because there won't be any display. + if (!isTestMode()) + { + // Create a window for our application to render into. + // + platform::WindowDesc windowDesc; + windowDesc.title = title; + windowDesc.width = width; + windowDesc.height = height; + windowDesc.style = platform::WindowStyle::Default; + gWindow = platform::Application::createWindow(windowDesc); + gWindow->events.mainLoop = [this]() { mainLoop(); }; + gWindow->events.sizeChanged = Slang::Action<>(this, &WindowedAppBase::windowSizeChanged); + + auto deviceInfo = gDevice->getDeviceInfo(); + Slang::StringBuilder titleSb; + titleSb << title << " (" << deviceInfo.apiName << ": " << deviceInfo.adapterName << ")"; + gWindow->setText(titleSb.getBuffer()); + + // Create swapchain and framebuffers. + gfx::ISwapchain::Desc swapchainDesc = {}; + swapchainDesc.format = gfx::Format::R8G8B8A8_UNORM; + swapchainDesc.width = width; + swapchainDesc.height = height; + swapchainDesc.imageCount = kSwapchainImageCount; + swapchainDesc.queue = gQueue; + gfx::WindowHandle windowHandle = gWindow->getNativeHandle().convert<gfx::WindowHandle>(); + 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; @@ -69,7 +74,10 @@ Slang::Result WindowedAppBase::initializeBase( SLANG_RETURN_ON_FAIL( gDevice->createFramebufferLayout(framebufferLayoutDesc, gFramebufferLayout.writeRef())); - createSwapchainFramebuffers(); + if (isTestMode()) + { + createOfflineFramebuffers(); + } for (uint32_t i = 0; i < kSwapchainImageCount; i++) { @@ -102,23 +110,27 @@ Slang::Result WindowedAppBase::initializeBase( void WindowedAppBase::mainLoop() { int frameBufferIndex = gSwapchain->acquireNextImage(); - if (frameBufferIndex == -1) - return; gTransientHeaps[frameBufferIndex]->synchronizeAndReset(); renderFrame(frameBufferIndex); gTransientHeaps[frameBufferIndex]->finish(); } -void WindowedAppBase::createSwapchainFramebuffers() +void WindowedAppBase::offlineRender() { - gFramebuffers.clear(); - for (uint32_t i = 0; i < kSwapchainImageCount; i++) + gTransientHeaps[0]->synchronizeAndReset(); + renderFrame(0); + gTransientHeaps[0]->finish(); +} + +void WindowedAppBase::createFramebuffers(uint32_t width, uint32_t height, gfx::Format colorFormat, uint32_t frameBufferCount) +{ + for (uint32_t i = 0; i < frameBufferCount; i++) { gfx::ITextureResource::Desc depthBufferDesc; depthBufferDesc.type = IResource::Type::Texture2D; - depthBufferDesc.size.width = gSwapchain->getDesc().width; - depthBufferDesc.size.height = gSwapchain->getDesc().height; + depthBufferDesc.size.width = width; + depthBufferDesc.size.height = height; depthBufferDesc.size.depth = 1; depthBufferDesc.format = gfx::Format::D32_FLOAT; depthBufferDesc.defaultState = ResourceState::DepthWrite; @@ -127,12 +139,28 @@ void WindowedAppBase::createSwapchainFramebuffers() depthBufferDesc.optimalClearValue = &depthClearValue; ComPtr<gfx::ITextureResource> depthBufferResource = gDevice->createTextureResource(depthBufferDesc, nullptr); + ComPtr<gfx::ITextureResource> colorBuffer; - gSwapchain->getImage(i, colorBuffer.writeRef()); + if (isTestMode()) + { + gfx::ITextureResource::Desc colorBufferDesc; + colorBufferDesc.type = IResource::Type::Texture2D; + colorBufferDesc.size.width = width; + colorBufferDesc.size.height = height; + colorBufferDesc.size.depth = 1; + colorBufferDesc.format = colorFormat; + colorBufferDesc.defaultState = ResourceState::RenderTarget; + colorBufferDesc.allowedStates = ResourceStateSet(ResourceState::RenderTarget, ResourceState::CopyDestination); + colorBuffer = gDevice->createTextureResource(colorBufferDesc, nullptr); + } + else + { + gSwapchain->getImage(i, colorBuffer.writeRef()); + } gfx::IResourceView::Desc colorBufferViewDesc; memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc)); - colorBufferViewDesc.format = gSwapchain->getDesc().format; + colorBufferViewDesc.format = colorFormat; colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; ComPtr<gfx::IResourceView> rtv = @@ -152,10 +180,24 @@ void WindowedAppBase::createSwapchainFramebuffers() framebufferDesc.renderTargetViews = rtv.readRef(); framebufferDesc.layout = gFramebufferLayout; ComPtr<gfx::IFramebuffer> frameBuffer = gDevice->createFramebuffer(framebufferDesc); + gFramebuffers.add(frameBuffer); } } +void WindowedAppBase::createOfflineFramebuffers() +{ + gFramebuffers.clear(); + createFramebuffers(windowWidth, windowHeight, gfx::Format::R8G8B8A8_UNORM, 1); +} + +void WindowedAppBase::createSwapchainFramebuffers() +{ + gFramebuffers.clear(); + createFramebuffers(gSwapchain->getDesc().width, gSwapchain->getDesc().height, + gSwapchain->getDesc().format, kSwapchainImageCount); +} + ComPtr<gfx::IResourceView> WindowedAppBase::createTextureFromFile(String fileName, int& textureWidth, int& textureHeight) { int channelsInFile = 0; diff --git a/examples/example-base/example-base.h b/examples/example-base/example-base.h index 8943323da..b97728e17 100644 --- a/examples/example-base/example-base.h +++ b/examples/example-base/example-base.h @@ -4,12 +4,13 @@ #include "tools/platform/window.h" #include "source/core/slang-basic.h" #include "source/core/slang-io.h" +#include "test-base.h" #ifdef _WIN32 void _Win32OutputDebugString(const char* str); #endif -struct WindowedAppBase +struct WindowedAppBase : public TestBase { protected: static const int kSwapchainImageCount = 2; @@ -32,8 +33,13 @@ protected: int width, int height, gfx::DeviceType deviceType = gfx::DeviceType::Default); + + void createFramebuffers(uint32_t width, uint32_t height, gfx::Format colorFormat, uint32_t frameBufferCount); void createSwapchainFramebuffers(); + void createOfflineFramebuffers(); + void mainLoop(); + Slang::ComPtr<gfx::IResourceView> createTextureFromFile(Slang::String fileName, int& textureWidth, int& textureHeight); virtual void windowSizeChanged(); @@ -42,6 +48,7 @@ protected: public: platform::Window* getWindow() { return gWindow.Ptr(); } virtual void finalize() { gQueue->waitOnHost(); } + void offlineRender(); }; struct ExampleResources { @@ -103,18 +110,26 @@ inline void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) void initDebugCallback(); template<typename TApp> -int innerMain() +int innerMain(int argc, char** argv) { initDebugCallback(); TApp app; + app.parseOption(argc, argv); if (SLANG_FAILED(app.initialize())) { return -1; } - platform::Application::run(app.getWindow()); + if (!app.isTestMode()) + { + platform::Application::run(app.getWindow()); + } + else + { + app.offlineRender(); + } app.finalize(); return 0; diff --git a/examples/example-base/test-base.cpp b/examples/example-base/test-base.cpp new file mode 100644 index 000000000..5c727aabe --- /dev/null +++ b/examples/example-base/test-base.cpp @@ -0,0 +1,50 @@ +#include "test-base.h" + +#ifdef _WIN32 +#include <windows.h> +#include <shellapi.h> +#endif + +int TestBase::parseOption(int argc, char** argv) +{ + // We only make the parse in a very loose way for only extracting the test option. +#ifdef _WIN32 + wchar_t** szArglist; + szArglist = CommandLineToArgvW(GetCommandLineW(), &argc); +#endif + + for (int i = 0; i < argc; i++) + { +#ifdef _WIN32 + if (wcscmp(szArglist[i], L"--test-mode") == 0) +#else + if (strcmp(argv[i], "--test-mode") == 0) +#endif + { + m_isTestMode = true; + } + } + return 0; +} + +void TestBase::printEntrypointHashes(int entryPointCount, int targetCount, ComPtr<slang::IComponentType>& composedProgram) +{ + for (int targetIndex = 0; targetIndex < targetCount; targetIndex++) + { + for (int entryPointIndex = 0; entryPointIndex < entryPointCount; entryPointIndex++) + { + ComPtr<slang::IBlob> entryPointHashBlob; + composedProgram->getEntryPointHash(entryPointIndex, targetIndex, entryPointHashBlob.writeRef()); + + Slang::StringBuilder strBuilder; + strBuilder << "entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + + uint8_t* buffer = (uint8_t*)entryPointHashBlob->getBufferPointer(); + for (size_t i = 0; i < entryPointHashBlob->getBufferSize(); i++) + { + strBuilder<<Slang::StringUtil::makeStringWithFormat("%.2X", buffer[i]); + } + fprintf(stdout, "%s\n", strBuilder.begin()); + } + } +} diff --git a/examples/example-base/test-base.h b/examples/example-base/test-base.h new file mode 100644 index 000000000..22cd70d09 --- /dev/null +++ b/examples/example-base/test-base.h @@ -0,0 +1,21 @@ +#pragma once + +#include "slang.h" +#include "slang-com-ptr.h" +#include "source/core/slang-string-util.h" + +using Slang::ComPtr; + +class TestBase { + +public: + // Parses command line options. This example only has one option for testing purpose. + int parseOption(int argc, char** argv); + + void printEntrypointHashes(int entryPointCount, int targetCount, ComPtr<slang::IComponentType>& composedProgram); + + bool isTestMode() const { return m_isTestMode; } + +private: + bool m_isTestMode = false; +}; diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp index 53285ae51..87d440901 100644 --- a/examples/hello-world/main.cpp +++ b/examples/hello-world/main.cpp @@ -12,12 +12,14 @@ #include "vulkan-api.h" #include "examples/example-base/example-base.h" +#include "examples/example-base/test-base.h" +#include "source/core/slang-string-util.h" using Slang::ComPtr; static const ExampleResources resourceBase("hello-world"); -struct HelloWorldExample +struct HelloWorldExample : public TestBase { // The Vulkan functions pointers result from loading the vulkan library. VulkanAPI vkAPI; @@ -66,10 +68,11 @@ struct HelloWorldExample }; -int main() +int main(int argc, char* argv[]) { initDebugCallback(); HelloWorldExample example; + example.parseOption(argc, argv); return example.run(); } @@ -204,6 +207,11 @@ int HelloWorldExample::createComputePipelineFromShader() 0, 0, spirvCode.writeRef(), diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); RETURN_ON_FAIL(result); + + if (isTestMode()) + { + printEntrypointHashes(1, 1, composedProgram); + } } // The following steps are all Vulkan API calls to create a pipeline. diff --git a/examples/triangle/main.cpp b/examples/triangle/main.cpp index 93ae1bd2e..88c55c416 100644 --- a/examples/triangle/main.cpp +++ b/examples/triangle/main.cpp @@ -187,6 +187,11 @@ gfx::Result loadShaderProgram( programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); + if (isTestMode()) + { + printEntrypointHashes(entryPointCount, 1, linkedProgram); + } + return SLANG_OK; } @@ -387,9 +392,12 @@ virtual void renderFrame(int frameBufferIndex) override commandBuffer->close(); gQueue->executeCommandBuffer(commandBuffer); - // 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/record/slang-composite-component-type.cpp b/source/slang-record-replay/record/slang-composite-component-type.cpp index e3c339adb..29ac5da8d 100644 --- a/source/slang-record-replay/record/slang-composite-component-type.cpp +++ b/source/slang-record-replay/record/slang-composite-component-type.cpp @@ -15,11 +15,6 @@ namespace SlangRecord slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, componentType); } - CompositeComponentTypeRecorder::~CompositeComponentTypeRecorder() - { - m_actualCompositeComponentType->release(); - } - ISlangUnknown* CompositeComponentTypeRecorder::getInterface(const Guid& guid) { if (guid == IComponentType::getTypeGuid()) @@ -65,7 +60,7 @@ namespace SlangRecord slang::ProgramLayout* programLayout = m_actualCompositeComponentType->getLayout(targetIndex, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(programLayout); m_recordManager->apendOutput(); } @@ -101,7 +96,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -126,7 +121,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -201,7 +196,7 @@ namespace SlangRecord { recorder->recordAddress(*outSpecializedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -224,7 +219,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -251,7 +246,7 @@ namespace SlangRecord { recorder->recordAddress(*outSharedLibrary); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -300,7 +295,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } diff --git a/source/slang-record-replay/record/slang-composite-component-type.h b/source/slang-record-replay/record/slang-composite-component-type.h index 758a59434..2374bcda2 100644 --- a/source/slang-record-replay/record/slang-composite-component-type.h +++ b/source/slang-record-replay/record/slang-composite-component-type.h @@ -19,7 +19,6 @@ namespace SlangRecord ISlangUnknown* getInterface(const Guid& guid); explicit CompositeComponentTypeRecorder(slang::IComponentType* componentType, RecordManager* recordManager); - ~CompositeComponentTypeRecorder(); // Interfaces for `IComponentType` virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; diff --git a/source/slang-record-replay/record/slang-entrypoint.cpp b/source/slang-record-replay/record/slang-entrypoint.cpp index e5c76a5af..7d43700e2 100644 --- a/source/slang-record-replay/record/slang-entrypoint.cpp +++ b/source/slang-record-replay/record/slang-entrypoint.cpp @@ -14,11 +14,6 @@ namespace SlangRecord slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, entryPoint); } - EntryPointRecorder::~EntryPointRecorder() - { - m_actualEntryPoint->release(); - } - ISlangUnknown* EntryPointRecorder::getInterface(const Guid& guid) { if(guid == EntryPointRecorder::getTypeGuid()) @@ -63,7 +58,7 @@ namespace SlangRecord slang::ProgramLayout* programLayout = m_actualEntryPoint->getLayout(targetIndex, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(programLayout); m_recordManager->apendOutput(); } @@ -99,7 +94,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -124,7 +119,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -199,7 +194,7 @@ namespace SlangRecord { recorder->recordAddress(*outSpecializedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -222,7 +217,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -249,7 +244,7 @@ namespace SlangRecord { recorder->recordAddress(*outSharedLibrary); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -298,7 +293,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } diff --git a/source/slang-record-replay/record/slang-entrypoint.h b/source/slang-record-replay/record/slang-entrypoint.h index 17c6fab6f..60c1bf369 100644 --- a/source/slang-record-replay/record/slang-entrypoint.h +++ b/source/slang-record-replay/record/slang-entrypoint.h @@ -21,7 +21,6 @@ namespace SlangRecord ISlangUnknown* getInterface(const Guid& guid); explicit EntryPointRecorder(slang::IEntryPoint* entryPoint, RecordManager* recordManager); - ~EntryPointRecorder(); // Interfaces for `IComponentType` virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; diff --git a/source/slang-record-replay/record/slang-filesystem.cpp b/source/slang-record-replay/record/slang-filesystem.cpp index 310fecd78..87a7182fc 100644 --- a/source/slang-record-replay/record/slang-filesystem.cpp +++ b/source/slang-record-replay/record/slang-filesystem.cpp @@ -18,11 +18,6 @@ namespace SlangRecord slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, m_actualFileSystem.get()); } - FileSystemRecorder::~FileSystemRecorder() - { - m_actualFileSystem->release(); - } - void* FileSystemRecorder::castAs(const Slang::Guid& guid) { return getInterface(guid); diff --git a/source/slang-record-replay/record/slang-filesystem.h b/source/slang-record-replay/record/slang-filesystem.h index ff7004fa1..6f73e479c 100644 --- a/source/slang-record-replay/record/slang-filesystem.h +++ b/source/slang-record-replay/record/slang-filesystem.h @@ -18,7 +18,6 @@ namespace SlangRecord { public: explicit FileSystemRecorder(ISlangFileSystemExt* fileSystem, RecordManager* recordManager); - ~FileSystemRecorder(); // ISlangUnknown SLANG_REF_OBJECT_IUNKNOWN_ALL diff --git a/source/slang-record-replay/record/slang-global-session.cpp b/source/slang-record-replay/record/slang-global-session.cpp index f8fe6c65b..c5350f760 100644 --- a/source/slang-record-replay/record/slang-global-session.cpp +++ b/source/slang-record-replay/record/slang-global-session.cpp @@ -29,11 +29,6 @@ namespace SlangRecord m_recordManager->apendOutput(); } - GlobalSessionRecorder::~GlobalSessionRecorder() - { - m_actualGlobalSession->release(); - } - SLANG_NO_THROW SlangResult SLANG_MCALL GlobalSessionRecorder::queryInterface(SlangUUID const& uuid, void** outObject) { if (uuid == Session::getTypeGuid()) diff --git a/source/slang-record-replay/record/slang-global-session.h b/source/slang-record-replay/record/slang-global-session.h index 3fd584ef4..4242f4bff 100644 --- a/source/slang-record-replay/record/slang-global-session.h +++ b/source/slang-record-replay/record/slang-global-session.h @@ -15,7 +15,6 @@ namespace SlangRecord { public: explicit GlobalSessionRecorder(slang::IGlobalSession* session); - virtual ~GlobalSessionRecorder(); SLANG_REF_OBJECT_IUNKNOWN_ADD_REF SLANG_REF_OBJECT_IUNKNOWN_RELEASE diff --git a/source/slang-record-replay/record/slang-module.cpp b/source/slang-record-replay/record/slang-module.cpp index 42dcd9eea..b116fa99b 100644 --- a/source/slang-record-replay/record/slang-module.cpp +++ b/source/slang-record-replay/record/slang-module.cpp @@ -14,11 +14,6 @@ namespace SlangRecord slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, module); } - ModuleRecorder::~ModuleRecorder() - { - m_actualModule->release(); - } - ISlangUnknown* ModuleRecorder::getInterface(const Guid& guid) { if(guid == ModuleRecorder::getTypeGuid()) @@ -185,7 +180,7 @@ namespace SlangRecord { recorder->recordAddress(*outEntryPoint); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -249,7 +244,7 @@ namespace SlangRecord slang::ProgramLayout* programLayout = m_actualModule->getLayout(targetIndex, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(programLayout); m_recordManager->apendOutput(); } @@ -285,7 +280,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -310,7 +305,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -386,7 +381,7 @@ namespace SlangRecord { recorder->recordAddress(*outSpecializedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -409,7 +404,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -436,7 +431,7 @@ namespace SlangRecord { recorder->recordAddress(*outSharedLibrary); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -485,7 +480,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } diff --git a/source/slang-record-replay/record/slang-module.h b/source/slang-record-replay/record/slang-module.h index 22339f1cd..1b1cc5de9 100644 --- a/source/slang-record-replay/record/slang-module.h +++ b/source/slang-record-replay/record/slang-module.h @@ -21,7 +21,6 @@ namespace SlangRecord ISlangUnknown* getInterface(const Guid& guid); explicit ModuleRecorder(slang::IModule* module, RecordManager* recordManager); - ~ModuleRecorder(); // Interfaces for `IModule` virtual SLANG_NO_THROW SlangResult SLANG_MCALL findEntryPointByName( diff --git a/source/slang-record-replay/record/slang-session.cpp b/source/slang-record-replay/record/slang-session.cpp index 7c0ccd2e1..3eb944082 100644 --- a/source/slang-record-replay/record/slang-session.cpp +++ b/source/slang-record-replay/record/slang-session.cpp @@ -17,11 +17,6 @@ namespace SlangRecord slangRecordLog(LogLevel::Verbose, "%s: %p\n", "SessionRecorder create:", session); } - SessionRecorder::~SessionRecorder() - { - m_actualSession->release(); - } - ISlangUnknown* SessionRecorder::getInterface(const Guid& guid) { if(guid == ISlangUnknown::getTypeGuid() || guid == ISession::getTypeGuid()) @@ -54,7 +49,7 @@ namespace SlangRecord slang::IModule* pModule = m_actualSession->loadModule(moduleName, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pModule); m_recordManager->apendOutput(); } @@ -83,7 +78,7 @@ namespace SlangRecord slang::IModule* pModule = m_actualSession->loadModuleFromIRBlob(moduleName, path, source, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pModule); m_recordManager->apendOutput(); } @@ -112,7 +107,7 @@ namespace SlangRecord slang::IModule* pModule = m_actualSession->loadModuleFromSource(moduleName, path, source, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pModule); m_recordManager->apendOutput(); } @@ -142,7 +137,7 @@ namespace SlangRecord { // TODO: Not sure if we need to record the diagnostics blob. - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pModule); m_recordManager->apendOutput(); } @@ -179,7 +174,7 @@ namespace SlangRecord { recorder->recordAddress(*outCompositeComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -213,7 +208,7 @@ namespace SlangRecord slang::TypeReflection* pTypeReflection = m_actualSession->specializeType(type, specializationArgs, specializationArgCount, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pTypeReflection); m_recordManager->apendOutput(); } @@ -241,7 +236,7 @@ namespace SlangRecord slang::TypeLayoutReflection* pTypeLayoutReflection = m_actualSession->getTypeLayout(type, targetIndex, rules, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pTypeLayoutReflection); m_recordManager->apendOutput(); } @@ -267,7 +262,7 @@ namespace SlangRecord slang::TypeReflection* pTypeReflection = m_actualSession->getContainerType(elementType, containerType, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(pTypeReflection); m_recordManager->apendOutput(); } @@ -386,7 +381,7 @@ namespace SlangRecord { recorder->recordAddress(*outConformance); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } diff --git a/source/slang-record-replay/record/slang-session.h b/source/slang-record-replay/record/slang-session.h index ca06e25a0..bc56003a9 100644 --- a/source/slang-record-replay/record/slang-session.h +++ b/source/slang-record-replay/record/slang-session.h @@ -20,7 +20,6 @@ namespace SlangRecord ISlangUnknown* getInterface(const Guid& guid); explicit SessionRecorder(slang::ISession* session, RecordManager* recordManager); - ~SessionRecorder(); SLANG_NO_THROW slang::IGlobalSession* SLANG_MCALL getGlobalSession() override; SLANG_NO_THROW slang::IModule* SLANG_MCALL loadModule( diff --git a/source/slang-record-replay/record/slang-type-conformance.cpp b/source/slang-record-replay/record/slang-type-conformance.cpp index 91f108786..56433f700 100644 --- a/source/slang-record-replay/record/slang-type-conformance.cpp +++ b/source/slang-record-replay/record/slang-type-conformance.cpp @@ -14,11 +14,6 @@ namespace SlangRecord slangRecordLog(LogLevel::Verbose, "%s: %p\n", __PRETTY_FUNCTION__, typeConformance); } - TypeConformanceRecorder::~TypeConformanceRecorder() - { - m_actualTypeConformance->release(); - } - ISlangUnknown* TypeConformanceRecorder::getInterface(const Guid& guid) { if (guid == TypeConformanceRecorder::getTypeGuid()) @@ -67,7 +62,7 @@ namespace SlangRecord slang::ProgramLayout* programLayout = m_actualTypeConformance->getLayout(targetIndex, outDiagnostics); { - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); recorder->recordAddress(programLayout); m_recordManager->apendOutput(); } @@ -102,7 +97,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -127,7 +122,7 @@ namespace SlangRecord { recorder->recordAddress(*outCode); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -202,7 +197,7 @@ namespace SlangRecord { recorder->recordAddress(*outSpecializedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -225,7 +220,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -252,7 +247,7 @@ namespace SlangRecord { recorder->recordAddress(*outSharedLibrary); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } @@ -301,7 +296,7 @@ namespace SlangRecord { recorder->recordAddress(*outLinkedComponentType); - recorder->recordAddress(*outDiagnostics); + recorder->recordAddress(outDiagnostics ? *outDiagnostics : nullptr); m_recordManager->apendOutput(); } diff --git a/source/slang-record-replay/record/slang-type-conformance.h b/source/slang-record-replay/record/slang-type-conformance.h index 7bcae0d15..7beabcca5 100644 --- a/source/slang-record-replay/record/slang-type-conformance.h +++ b/source/slang-record-replay/record/slang-type-conformance.h @@ -21,7 +21,6 @@ namespace SlangRecord ISlangUnknown* getInterface(const Guid& guid); explicit TypeConformanceRecorder(slang::ITypeConformance* typeConformance, RecordManager* recordManager); - ~TypeConformanceRecorder(); // Interfaces for `IComponentType` virtual SLANG_NO_THROW slang::ISession* SLANG_MCALL getSession() override; diff --git a/source/slang-record-replay/replay/json-consumer.cpp b/source/slang-record-replay/replay/json-consumer.cpp index 0faf5267b..456988bdb 100644 --- a/source/slang-record-replay/replay/json-consumer.cpp +++ b/source/slang-record-replay/replay/json-consumer.cpp @@ -448,7 +448,7 @@ namespace SlangRecord _writePair(builder, indent, "name", Slang::StringUtil::makeStringWithFormat("\"%s\"", desc.preprocessorMacros[i].name != nullptr ? desc.preprocessorMacros[i].name : "nullptr")); - _writePair(builder, indent, "value", Slang::StringUtil::makeStringWithFormat("\"%s\"", + _writePairNoComma(builder, indent, "value", Slang::StringUtil::makeStringWithFormat("\"%s\"", desc.preprocessorMacros[i].value != nullptr ? desc.preprocessorMacros[i].value : "nullptr")); } } diff --git a/source/slang-record-replay/replay/replay-consumer.cpp b/source/slang-record-replay/replay/replay-consumer.cpp index cb1117bc0..7710b50e9 100644 --- a/source/slang-record-replay/replay/replay-consumer.cpp +++ b/source/slang-record-replay/replay/replay-consumer.cpp @@ -106,7 +106,6 @@ namespace SlangRecord SlangResult CommonInterfaceReplayer::getEntryPointHash(ObjectID objectId, SlangInt entryPointIndex, SlangInt targetIndex, ObjectID outHashId) { InputObjectSanityCheck(objectId); - OutputObjectSanityCheck(outHashId); SlangResult res = SLANG_OK; slang::IComponentType* pObj = getObjectPointer(objectId); @@ -115,16 +114,17 @@ namespace SlangRecord if (outHash) { - m_objectMap.add(outHashId, outHash); if (outHash->getBufferSize()) { uint8_t* buffer = (uint8_t*)outHash->getBufferPointer(); Slang::StringBuilder strBuilder; + strBuilder << "entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + for (size_t i = 0; i < outHash->getBufferSize(); i++) { - strBuilder<<Slang::StringUtil::makeStringWithFormat("%.2X ", buffer[i]); + strBuilder<<Slang::StringUtil::makeStringWithFormat("%.2X", buffer[i]); } - slangRecordLog(LogLevel::Verbose, "getEntryPointHash: %s\n", strBuilder.begin()); + slangRecordLog(LogLevel::Verbose, "%s\n", strBuilder.begin()); } else { diff --git a/test-record-replay.sh b/test-record-replay.sh new file mode 100755 index 000000000..2faabe954 --- /dev/null +++ b/test-record-replay.sh @@ -0,0 +1,147 @@ +#!/usr/bin/env bash + +RED='\033[0;31m' +Green='\033[0;32m' +NC='\033[0m' +matchPattern="entrypoint: [0-9]+, target: [0-9]+, hash: [0-9a-fA-F]+" + +getHash() +{ + matchedLine=$1 + local -n outputVar=$2 + + entrypointIdx=$(echo $matchedLine | grep -oE "entrypoint: [0-9]+" | grep -oE "[0-9]+") + targetIdx=$(echo $matchedLine | grep -oE "target: [0-9]+" | grep -oE "[0-9]+") + hashCode=$(echo $matchedLine | grep -oE "hash: .*" | grep -oE ": [0-9a-fA-F]+" | grep -oE "[0-9a-fA-F]+") + + outputVar="$entrypointIdx-$targetIdx-$hashCode" +} + +log() +{ + msg=$1 + color=$2 + printf "${color}$1${NC}\n" +} + +parseStandardOutput() +{ + local -n resultArray=$1 + lines=$2 + + for line in "${lines[@]}" + do + matchLine=$(echo $line | grep -oE "$matchPattern") + + if [ -n "$matchLine" ]; then + result="" + getHash "$matchLine" result + + if [ -n "$result" ]; then + resultArray+=("$result") + fi + fi + done +} + +resultCheck() +{ + local -n inExpectedResults=$1 + local -n inReplayResults=$2 + local -n outFailedResults=$3 + + found="" + for expectedResult in ${inExpectedResults[@]}; do + + for replayResult in ${inReplayResults[@]}; do + if [ "$replayResult" == "$expectedResult" ]; then + found="1" + fi + done + + if [ -z "$found" ]; then + echo "$expectedResult is not Found in replay" + outFailedResults+=("$expectedResult") + else + echo "$expectedResult is Found in replay" + fi + done +} + +# TODO: Add more test commands here in this array +testCommands=("./build/Debug/bin/hello-world" "./build/Debug/bin/triangle") + +# Enable hash code generation for the test such that +# we can have something to compare with replaying the test +argsToEnableHashCode="--test-mode" + +declare -A testStats + +for ((i = 0; i < ${#testCommands[@]}; i++)) +do + testCommand=${testCommands[$i]} + echo "Start running test: $testCommand" + + # Run the test executable + export SLANG_RECORD_LAYER=1 + mapfile -t lines < <(${testCommand} ${argsToEnableHashCode}) + unset SLANG_RECORD_LAYER + + # parse the output from stdout + expectedResults=() + parseStandardOutput expectedResults "${lines[@]}" + + echo "Expected Results: ${expectedResults[@]}" + if [ ${#expectedResults[@]} -eq 0 ]; then + log "No expected results found" $RED + rm -rf ./slang-record/* + continue + fi + + # Replay the record file + export SLANG_RECORD_LOG_LEVEL=3 + replayTestCommand="./build/Debug/bin/slang-replay ./slang-record/*.cap" + echo "Start replaying the test ..." + mapfile -t lines < <(${replayTestCommand}) + unset SLANG_RECORD_LOG_LEVEL + + # parse the output from stdout + replayResults=() + parseStandardOutput replayResults "${lines[@]}" + + echo "Replay Results: ${replayResults[@]}" + if [ ${#replayResults[@]} -eq 0 ]; then + log "No replay results found" $RED + rm -rf ./slang-record/* + continue + fi + + # Check the results + failedResults=() + resultCheck expectedResults replayResults failedResults + + rm -rf ./slang-record/* + + if [ ${#failedResults[@]} -eq 0 ]; then + testStats[$testCommand]="PASSED" + else + testStats[$testCommand]="FAILED" + fi + printf "\n" +done + +for testName in "${!testStats[@]}" +do + if [ "${testStats[$testName]}" == "PASSED" ]; then + log "$testName: PASSED" $Green + else + log "$testName: FAILED" $RED + fi +done + +# Notify the CI if any of the tests failed +if [ ${#testStats[@]} -eq 0 ]; then + exit 0 +else + exit 1 +fi diff --git a/tools/platform/window.h b/tools/platform/window.h index efbe139a7..29327def3 100644 --- a/tools/platform/window.h +++ b/tools/platform/window.h @@ -242,7 +242,7 @@ public: int /*showCommand*/) \ { \ platform::Application::init(); \ - auto result = APPLICATION_ENTRY(); \ + auto result = APPLICATION_ENTRY(0, nullptr); \ platform::Application::dispose(); \ GFX_DUMP_LEAK \ return result; \ @@ -251,10 +251,10 @@ public: #else #define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \ - int main() \ + int main(int argc, char** argv) \ { \ platform::Application::init(); \ - auto rs = APPLICATION_ENTRY(); \ + auto rs = APPLICATION_ENTRY(argc, argv); \ platform::Application::dispose(); \ return rs; \ } |
