From 615dfba810964bed1caad8ecb87850c8eb1544b4 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 27 Jan 2021 10:02:44 -0800 Subject: Make own a slang session. (#1678) --- build/visual-studio/gfx/gfx.vcxproj | 1 + build/visual-studio/gfx/gfx.vcxproj.filters | 3 ++ examples/hello-world/main.cpp | 71 +++-------------------------- examples/shader-toy/main.cpp | 49 +++----------------- tools/gfx/cuda/render-cuda.cpp | 11 +++++ tools/gfx/d3d11/render-d3d11.cpp | 2 + tools/gfx/d3d12/render-d3d12.cpp | 3 ++ tools/gfx/open-gl/render-gl.cpp | 2 + tools/gfx/render-graphics-common.cpp | 7 +++ tools/gfx/render-graphics-common.h | 5 ++ tools/gfx/render.h | 38 ++++++++++++--- tools/gfx/slang-context.h | 43 +++++++++++++++++ tools/gfx/vulkan/render-vk.cpp | 2 + tools/render-test/render-test-main.cpp | 2 +- 14 files changed, 124 insertions(+), 115 deletions(-) create mode 100644 tools/gfx/slang-context.h diff --git a/build/visual-studio/gfx/gfx.vcxproj b/build/visual-studio/gfx/gfx.vcxproj index 0ed5ed233..09555f45c 100644 --- a/build/visual-studio/gfx/gfx.vcxproj +++ b/build/visual-studio/gfx/gfx.vcxproj @@ -193,6 +193,7 @@ + diff --git a/build/visual-studio/gfx/gfx.vcxproj.filters b/build/visual-studio/gfx/gfx.vcxproj.filters index 97658fffa..d034fc847 100644 --- a/build/visual-studio/gfx/gfx.vcxproj.filters +++ b/build/visual-studio/gfx/gfx.vcxproj.filters @@ -51,6 +51,9 @@ Header Files + + Header Files + Header Files diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp index cdd998e35..e8e3c45e0 100644 --- a/examples/hello-world/main.cpp +++ b/examples/hello-world/main.cpp @@ -65,24 +65,6 @@ static const Vertex kVertexData[kVertexCount] = struct HelloWorld { -// We will start with the code related to loading and using the Slang compiler. -// -// Applications interact with the Slang compiler through a "session" object. -// There are actually two types of session: -// -// * The *global session* represents a loaded instance of the Slang library -// (e.g., `slang.dll` and is used to scope allocations/resources that are -// truly global across all compiles, such as the Slang "standard library") -// -// * A *session* is used to scope one or more compile actions such as -// loading modules, generating code, and performing reflection. -// -// For our simple application, we will allocate a single session that is used -// for all compilation. -// -ComPtr slangGlobalSession; -ComPtr slangSession; - // Many Slang API functions return detailed diagnostic information // (error messages, warnings, etc.) as a "blob" of data, or return // a null blob pointer instead if there were no issues. @@ -108,56 +90,15 @@ gfx::Result loadShaderProgram( gfx::IRenderer* renderer, gfx::IShaderProgram** outProgram) { - // The first step in interacting with the Slang API is to create a "global session," - // which represents an instance of the Slang API loaded from the library. - // - if( !slangGlobalSession ) - { - SLANG_RETURN_ON_FAIL(slang_createGlobalSession(SLANG_API_VERSION, slangGlobalSession.writeRef())); - } - - // Next, we need to create a compilation session (`slang::ISession`) that will provide + // We need to obatin a compilation session (`slang::ISession`) that will provide // a scope to all the compilation and loading of code we do. // - // In an application like this, which doesn't make use of preprocessor-based specialization, - // we can create a single session and use it for the duration of the application. - // One important service the session provides is re-use of modules that have already - // been compiled, so that if two Slang files `import` the same module, the compiler - // will only load and check that module once. - // - if( !slangSession ) - { - // When creating a session we need to tell it what code generation targets we may - // want code generated for. It is valid to have zero or more targets, but many - // applications will only want one, corresponding to the graphics API they plan to use. - // This application is currently hard-coded to use D3D11, so we set up for compilation - // to DX bytecode. - // - // Note: the `TargetDesc` can also be used to set things like optimization settings - // for each target, but this application doesn't care to set any of that stuff. - // - slang::TargetDesc targetDesc = {}; - targetDesc.format = SLANG_DXBC; - targetDesc.profile = spFindProfile(slangGlobalSession, "sm_4_0"); - - // The session can be set up with a few other options, notably: - // - // * Any search paths that should be used when resolving `import` or `#include` directives. - // - // * Any preprocessor macros to pre-define when reading in files. - // - // This application doesn't plan to make heavy use of the preprocessor, and all its - // shader files are in the same directory, so we just use the default options (which - // will lead to the only search path being the current working directory). - // - slang::SessionDesc sessionDesc = {}; - sessionDesc.targetCount = 1; - sessionDesc.targets = &targetDesc; - - SLANG_RETURN_ON_FAIL(slangGlobalSession->createSession(sessionDesc, slangSession.writeRef())); - } + // Our example application uses the `gfx` graphics API abstraction layer, which already + // creates a Slang compilation session for us, so we just grab and use it here. + ComPtr slangSession; + slangSession = renderer->getSlangSession(); - // Once the session has been created, we can start loading code into it. + // We can now start loading code into the slang session. // // The simplest way to load code is by calling `loadModule` with the name of a Slang // module. A call to `loadModule("MyStuff")` will behave more or less as if you diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp index 044c1805b..a1408e38e 100644 --- a/examples/shader-toy/main.cpp +++ b/examples/shader-toy/main.cpp @@ -91,52 +91,15 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) // Result loadShaderProgram(gfx::IRenderer* renderer, ComPtr& outShaderProgram) { - // The first step in interacting with the Slang API is to create a "global session," - // which represents an instance of the Slang API loaded from the library. - // - ComPtr slangGlobalSession; - SLANG_RETURN_ON_FAIL(slang_createGlobalSession(SLANG_API_VERSION, slangGlobalSession.writeRef())); - - // Next, we need to create a compilation session (`slang::ISession`) that will provide + // We need to obatin a compilation session (`slang::ISession`) that will provide // a scope to all the compilation and loading of code we do. // - // In an application like this, which doesn't make use of preprocessor-based specialization, - // we can create a single session and use it for the duration of the application. - // One important service the session provides is re-use of modules that have already - // been compiled, so that if two Slang files `import` the same module, the compiler - // will only load and check that module once. - // - // When creating a session we need to tell it what code generation targets we may - // want code generated for. It is valid to have zero or more targets, but many - // applications will only want one, corresponding to the graphics API they plan to use. - // This application is currently hard-coded to use D3D11, so we set up for compilation - // to DX bytecode. - // - // Note: the `TargetDesc` can also be used to set things like optimization settings - // for each target, but this application doesn't care to set any of that stuff. - // - slang::TargetDesc targetDesc = {}; - targetDesc.format = SLANG_DXBC; - targetDesc.profile = spFindProfile(slangGlobalSession, "sm_4_0"); - - // The session can be set up with a few other options, notably: - // - // * Any search paths that should be used when resolving `import` or `#include` directives. - // - // * Any preprocessor macros to pre-define when reading in files. - // - // This application doesn't plan to make heavy use of the preprocessor, and all its - // shader files are in the same directory, so we just use the default options (which - // will lead to the only search path being the current working directory). - // - slang::SessionDesc sessionDesc = {}; - sessionDesc.targetCount = 1; - sessionDesc.targets = &targetDesc; - + // Our example application uses the `gfx` graphics API abstraction layer, which already + // creates a Slang compilation session for us, so we just grab and use it here. ComPtr slangSession; - SLANG_RETURN_ON_FAIL(slangGlobalSession->createSession(sessionDesc, slangSession.writeRef())); - - // Once the session has been created, we can start loading code into it. + SLANG_RETURN_ON_FAIL(renderer->getSlangSession(slangSession.writeRef())); + + // Once the session has been obtained, we can start loading code into it. // // The simplest way to load code is by calling `loadModule` with the name of a Slang // module. A call to `loadModule("MyStuff")` will behave more or less as if you diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index d1e320224..057674550 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -6,6 +6,7 @@ #include "../renderer-shared.h" #include "../render-graphics-common.h" +#include "../slang-context.h" #ifdef GFX_ENABLE_CUDA #include @@ -782,6 +783,7 @@ private: CUcontext m_context = nullptr; CUDAPipelineState* currentPipeline = nullptr; CUDARootShaderObject* currentRootObject = nullptr; + SlangContext slangContext; public: ~CUDARenderer() { @@ -792,6 +794,8 @@ private: } virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override { + SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_PTX, "sm_5_1")); + SLANG_RETURN_ON_FAIL(_initCuda(reportType)); SLANG_RETURN_ON_FAIL(_findMaxFlopsDeviceIndex(&m_deviceIndex)); @@ -809,6 +813,13 @@ private: return SLANG_OK; } + virtual SLANG_NO_THROW Result SLANG_MCALL getSlangSession(slang::ISession** outSlangSession) override + { + *outSlangSession = slangContext.session.get(); + slangContext.session->addRef(); + return SLANG_OK; + } + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( IResource::Usage initialUsage, const ITextureResource::Desc& desc, diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index 40e617a1f..3df5e25bc 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -664,6 +664,8 @@ static bool _isSupportedNVAPIOp(IUnknown* dev, uint32_t op) SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle) { + SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_DXBC, "sm_5_0")); + auto windowHandle = (HWND)inWindowHandle; m_desc = desc; diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 648fc3052..407f0dbf2 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -1348,7 +1348,10 @@ static bool _isSupportedNVAPIOp(ID3D12Device* dev, uint32_t op) Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle) { + SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_DXBC, "sm_5_1")); + m_hwnd = (HWND)inWindowHandle; + // Rather than statically link against D3D, we load it dynamically. HMODULE d3dModule = LoadLibraryA("d3d12.dll"); diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index 49fd6b005..80edbdceb 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -785,6 +785,8 @@ void GLRenderer::destroyBindingEntries(const BindingState::Desc& desc, const Bin SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void* inWindowHandle) { + SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_GLSL, "sm_5_0")); + auto windowHandle = (HWND)inWindowHandle; m_desc = desc; diff --git a/tools/gfx/render-graphics-common.cpp b/tools/gfx/render-graphics-common.cpp index 593d4708c..adc943d1d 100644 --- a/tools/gfx/render-graphics-common.cpp +++ b/tools/gfx/render-graphics-common.cpp @@ -1372,6 +1372,13 @@ SLANG_NO_THROW bool SLANG_MCALL gfx::GraphicsAPIRenderer::hasFeature(const char* return m_features.findFirstIndex([&](Slang::String x) { return x == featureName; }) != -1; } +SLANG_NO_THROW Result SLANG_MCALL gfx::GraphicsAPIRenderer::getSlangSession(slang::ISession** outSlangSession) +{ + *outSlangSession = slangContext.session.get(); + slangContext.session->addRef(); + return SLANG_OK; +} + GraphicsCommonShaderProgram::~GraphicsCommonShaderProgram() { // Note: It might not seem like this destructor is needed at all, since diff --git a/tools/gfx/render-graphics-common.h b/tools/gfx/render-graphics-common.h index 3a07f2993..f4d9567e3 100644 --- a/tools/gfx/render-graphics-common.h +++ b/tools/gfx/render-graphics-common.h @@ -2,9 +2,11 @@ #include "tools/gfx/render.h" #include "core/slang-basic.h" +#include "tools/gfx/slang-context.h" namespace gfx { + class GraphicsCommonProgramLayout; class GraphicsCommonShaderProgram : public IShaderProgram, public Slang::RefObject @@ -32,6 +34,8 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL getFeatures( const char** outFeatures, UInt bufferSize, UInt* outFeatureCount) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* featureName) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL getSlangSession(slang::ISession** outSlangSession) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectLayout( slang::TypeLayoutReflection* typeLayout, IShaderObjectLayout** outLayout) SLANG_OVERRIDE; virtual SLANG_NO_THROW Result SLANG_MCALL @@ -51,6 +55,7 @@ public: protected: Slang::List m_features; + SlangContext slangContext; }; struct GfxGUID diff --git a/tools/gfx/render.h b/tools/gfx/render.h index 4c3b71645..325bab4ee 100644 --- a/tools/gfx/render.h +++ b/tools/gfx/render.h @@ -1085,15 +1085,32 @@ struct Viewport class IRenderer: public ISlangUnknown { public: + struct SlangDesc + { + slang::IGlobalSession* slangGlobalSession = nullptr; // (optional) A slang global session object. If null will create automatically. + + SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + char const* const* searchPaths = nullptr; + SlangInt searchPathCount = 0; + + slang::PreprocessorMacroDesc const* preprocessorMacros = nullptr; + SlangInt preprocessorMacroCount = 0; + + const char* targetProfile = nullptr; // (optional) Target shader profile. If null this will be set to platform dependent default. + SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT; + SlangOptimizationLevel optimizationLevel = SLANG_OPTIMIZATION_LEVEL_DEFAULT; + }; struct Desc { - int width = 0; ///< Width in pixels - int height = 0; ///< height in pixels - const char* adapter = nullptr; ///< Name to identify the adapter to use - int requiredFeatureCount = 0; ///< Number of required features. - const char** requiredFeatures = nullptr; ///< Array of required feature names, whose size is `requiredFeatureCount`. - int nvapiExtnSlot = -1; ///< The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required. + int width = 0; // Width in pixels + int height = 0; // height in pixels + const char* adapter = nullptr; // Name to identify the adapter to use + int requiredFeatureCount = 0; // Number of required features. + const char** requiredFeatures = nullptr; // Array of required feature names, whose size is `requiredFeatureCount`. + int nvapiExtnSlot = -1; // The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required. + SlangDesc slang = {}; // Configurations for Slang. }; // Will return with SLANG_E_NOT_AVAILABLE if NVAPI can't be initialized and nvapiExtnSlot >= 0 @@ -1104,6 +1121,15 @@ public: /// Returns a list of features supported by the renderer. virtual SLANG_NO_THROW Result SLANG_MCALL getFeatures(const char** outFeatures, UInt bufferSize, UInt* outFeatureCount) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL getSlangSession(slang::ISession** outSlangSession) = 0; + + inline ComPtr getSlangSession() + { + ComPtr result; + getSlangSession(result.writeRef()); + return result; + } + virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) = 0; virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() = 0; diff --git a/tools/gfx/slang-context.h b/tools/gfx/slang-context.h new file mode 100644 index 000000000..e6168deed --- /dev/null +++ b/tools/gfx/slang-context.h @@ -0,0 +1,43 @@ +#pragma once + +#include "tools/gfx/render.h" + +namespace gfx +{ + class SlangContext + { + public: + Slang::ComPtr globalSession; + Slang::ComPtr session; + Result initialize(const gfx::IRenderer::SlangDesc& desc, SlangCompileTarget compileTarget, const char* defaultProfileName) + { + if (desc.slangGlobalSession) + { + globalSession = desc.slangGlobalSession; + } + else + { + SLANG_RETURN_ON_FAIL(slang::createGlobalSession(globalSession.writeRef())); + } + + slang::SessionDesc slangSessionDesc = {}; + slangSessionDesc.defaultMatrixLayoutMode = desc.defaultMatrixLayoutMode; + slangSessionDesc.searchPathCount = desc.searchPathCount; + slangSessionDesc.searchPaths = desc.searchPaths; + slangSessionDesc.preprocessorMacroCount = desc.preprocessorMacroCount; + slangSessionDesc.preprocessorMacros = desc.preprocessorMacros; + slang::TargetDesc targetDesc = {}; + targetDesc.format = compileTarget; + auto targetProfile = desc.targetProfile; + if (targetProfile == nullptr) + targetProfile = defaultProfileName; + targetDesc.profile = globalSession->findProfile(targetProfile); + targetDesc.optimizationLevel = desc.optimizationLevel; + targetDesc.floatingPointMode = desc.floatingPointMode; + slangSessionDesc.targetCount = 1; + slangSessionDesc.targets = &targetDesc; + SLANG_RETURN_ON_FAIL(globalSession->createSession(slangSessionDesc, session.writeRef())); + return SLANG_OK; + } + }; +} diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 5afe3e3b4..21034d167 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -1033,6 +1033,8 @@ VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint( SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle) { + SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_SPIRV, "sm_5_1")); + SLANG_RETURN_ON_FAIL(m_module.init()); SLANG_RETURN_ON_FAIL(m_api.initGlobalProcs(m_module)); diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 6e35db639..27070154e 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -1304,7 +1304,7 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi desc.requiredFeatures = requiredFeatureList.getBuffer(); desc.requiredFeatureCount = (int)requiredFeatureList.getCount(); desc.nvapiExtnSlot = int(nvapiExtnSlot); - + desc.slang.slangGlobalSession = session; window = renderer_test::Window::create(); SLANG_RETURN_ON_FAIL(window->initialize(gWindowWidth, gWindowHeight)); -- cgit v1.2.3