summaryrefslogtreecommitdiffstats
path: root/tools/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx')
-rw-r--r--tools/gfx/d3d12/d3d12-shader-program.cpp6
-rw-r--r--tools/gfx/d3d12/d3d12-shader-program.h2
-rw-r--r--tools/gfx/metal/metal-shader-program.cpp8
-rw-r--r--tools/gfx/metal/metal-shader-program.h2
-rw-r--r--tools/gfx/renderer-shared.cpp114
-rw-r--r--tools/gfx/renderer-shared.h2
-rw-r--r--tools/gfx/slang-context.h2
-rw-r--r--tools/gfx/vulkan/glslang-module.cpp108
-rw-r--r--tools/gfx/vulkan/glslang-module.h36
-rw-r--r--tools/gfx/vulkan/vk-device.cpp1
-rw-r--r--tools/gfx/vulkan/vk-device.h2
-rw-r--r--tools/gfx/vulkan/vk-shader-program.cpp14
-rw-r--r--tools/gfx/vulkan/vk-shader-program.h2
13 files changed, 265 insertions, 34 deletions
diff --git a/tools/gfx/d3d12/d3d12-shader-program.cpp b/tools/gfx/d3d12/d3d12-shader-program.cpp
index a39f20465..e52fa320e 100644
--- a/tools/gfx/d3d12/d3d12-shader-program.cpp
+++ b/tools/gfx/d3d12/d3d12-shader-program.cpp
@@ -10,14 +10,14 @@ using namespace Slang;
Result ShaderProgramImpl::createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode)
+ List<ComPtr<ISlangBlob>>& kernelCodes)
{
ShaderBinary shaderBin;
shaderBin.stage = entryPointInfo->getStage();
shaderBin.entryPointInfo = entryPointInfo;
shaderBin.code.addRange(
- reinterpret_cast<const uint8_t*>(kernelCode->getBufferPointer()),
- (Index)kernelCode->getBufferSize());
+ reinterpret_cast<const uint8_t*>(kernelCodes[0]->getBufferPointer()),
+ (Index)kernelCodes[0]->getBufferSize());
m_shaders.add(_Move(shaderBin));
return SLANG_OK;
}
diff --git a/tools/gfx/d3d12/d3d12-shader-program.h b/tools/gfx/d3d12/d3d12-shader-program.h
index 669bce960..b95eb030c 100644
--- a/tools/gfx/d3d12/d3d12-shader-program.h
+++ b/tools/gfx/d3d12/d3d12-shader-program.h
@@ -27,7 +27,7 @@ public:
virtual Result createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode) override;
+ List<ComPtr<ISlangBlob>>& kernelCodes) override;
};
} // namespace d3d12
diff --git a/tools/gfx/metal/metal-shader-program.cpp b/tools/gfx/metal/metal-shader-program.cpp
index c95e99d04..3e7818454 100644
--- a/tools/gfx/metal/metal-shader-program.cpp
+++ b/tools/gfx/metal/metal-shader-program.cpp
@@ -21,16 +21,16 @@ ShaderProgramImpl::~ShaderProgramImpl() {}
Result ShaderProgramImpl::createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode)
+ List<ComPtr<ISlangBlob>>& kernelCodes)
{
Module module;
module.stage = entryPointInfo->getStage();
module.entryPointName = entryPointInfo->getNameOverride();
- module.code = kernelCode;
+ module.code = kernelCodes[0];
dispatch_data_t data = dispatch_data_create(
- kernelCode->getBufferPointer(),
- kernelCode->getBufferSize(),
+ kernelCodes[0]->getBufferPointer(),
+ kernelCodes[0]->getBufferSize(),
dispatch_get_main_queue(),
NULL);
NS::Error* error;
diff --git a/tools/gfx/metal/metal-shader-program.h b/tools/gfx/metal/metal-shader-program.h
index 691e12c9e..c92e432be 100644
--- a/tools/gfx/metal/metal-shader-program.h
+++ b/tools/gfx/metal/metal-shader-program.h
@@ -33,7 +33,7 @@ public:
virtual Result createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode) override;
+ List<ComPtr<ISlangBlob>>& kernelCodes) override;
};
diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp
index 9f5574dcc..ae4ea3eef 100644
--- a/tools/gfx/renderer-shared.cpp
+++ b/tools/gfx/renderer-shared.cpp
@@ -1103,32 +1103,106 @@ void ShaderProgramBase::init(const IShaderProgram::Desc& inDesc)
Result ShaderProgramBase::compileShaders(RendererBase* device)
{
+ auto compileTarget = device->slangContext.compileTarget;
// For a fully specialized program, read and store its kernel code in `shaderProgram`.
auto compileShader = [&](slang::EntryPointReflection* entryPointInfo,
slang::IComponentType* entryPointComponent,
SlangInt entryPointIndex)
{
auto stage = entryPointInfo->getStage();
- ComPtr<ISlangBlob> kernelCode;
- ComPtr<ISlangBlob> diagnostics;
- auto compileResult = device->getEntryPointCodeFromShaderCache(
- entryPointComponent,
- entryPointIndex,
- 0,
- kernelCode.writeRef(),
- diagnostics.writeRef());
- if (diagnostics)
+ List<ComPtr<ISlangBlob>> kernelCodes;
{
- DebugMessageType msgType = DebugMessageType::Warning;
- if (compileResult != SLANG_OK)
- msgType = DebugMessageType::Error;
- getDebugCallback()->handleMessage(
- msgType,
- DebugMessageSource::Slang,
- (char*)diagnostics->getBufferPointer());
+ ComPtr<ISlangBlob> downstreamIR;
+ ComPtr<ISlangBlob> diagnostics;
+ auto compileResult = device->getEntryPointCodeFromShaderCache(
+ entryPointComponent,
+ entryPointIndex,
+ 0,
+ downstreamIR.writeRef(),
+ diagnostics.writeRef());
+ if (diagnostics)
+ {
+ DebugMessageType msgType = DebugMessageType::Warning;
+ if (compileResult != SLANG_OK)
+ msgType = DebugMessageType::Error;
+ getDebugCallback()->handleMessage(
+ msgType,
+ DebugMessageSource::Slang,
+ (char*)diagnostics->getBufferPointer());
+ }
+ kernelCodes.add(downstreamIR);
}
- SLANG_RETURN_ON_FAIL(compileResult);
- SLANG_RETURN_ON_FAIL(createShaderModule(entryPointInfo, kernelCode));
+
+ // If target precompilation was used, kernelCode may only represent the
+ // glue code holding together the bits of precompiled target IR.
+ // Collect those dependency target IRs too.
+ ComPtr<slang::IModulePrecompileService_Experimental> componentPrecompileService;
+ if (entryPointComponent->queryInterface(
+ slang::IModulePrecompileService_Experimental::getTypeGuid(),
+ (void**)componentPrecompileService.writeRef()) == SLANG_OK)
+ {
+ SlangInt dependencyCount = componentPrecompileService->getModuleDependencyCount();
+ if (dependencyCount > 0)
+ {
+ for (int dependencyIndex = 0; dependencyIndex < dependencyCount; dependencyIndex++)
+ {
+ ComPtr<slang::IModule> dependencyModule;
+ {
+ ComPtr<slang::IBlob> diagnosticsBlob;
+ auto result = componentPrecompileService->getModuleDependency(
+ dependencyIndex,
+ dependencyModule.writeRef(),
+ diagnosticsBlob.writeRef());
+ if (diagnosticsBlob)
+ {
+ DebugMessageType msgType = DebugMessageType::Warning;
+ if (result != SLANG_OK)
+ msgType = DebugMessageType::Error;
+ getDebugCallback()->handleMessage(
+ msgType,
+ DebugMessageSource::Slang,
+ (char*)diagnosticsBlob->getBufferPointer());
+ }
+ SLANG_RETURN_ON_FAIL(result);
+ }
+
+ ComPtr<slang::IBlob> downstreamIR;
+ {
+ ComPtr<slang::IBlob> diagnosticsBlob;
+ SlangResult result = SLANG_OK;
+ ComPtr<slang::IModulePrecompileService_Experimental> precompileService;
+ result = dependencyModule->queryInterface(
+ slang::IModulePrecompileService_Experimental::getTypeGuid(),
+ (void**)precompileService.writeRef());
+ if (result == SLANG_OK)
+ {
+ ComPtr<slang::IBlob> diagnosticsBlob;
+ auto result = precompileService->getPrecompiledTargetCode(
+ compileTarget,
+ downstreamIR.writeRef(),
+ diagnosticsBlob.writeRef());
+ if (result == SLANG_OK)
+ {
+ kernelCodes.add(downstreamIR);
+ }
+ if (diagnosticsBlob)
+ {
+ DebugMessageType msgType = DebugMessageType::Warning;
+ if (result != SLANG_OK)
+ msgType = DebugMessageType::Error;
+ getDebugCallback()->handleMessage(
+ msgType,
+ DebugMessageSource::Slang,
+ (char*)diagnosticsBlob->getBufferPointer());
+ }
+ }
+ SLANG_RETURN_ON_FAIL(result);
+ }
+ }
+ }
+ }
+
+ SLANG_RETURN_ON_FAIL(createShaderModule(entryPointInfo, kernelCodes));
return SLANG_OK;
};
@@ -1160,10 +1234,10 @@ Result ShaderProgramBase::compileShaders(RendererBase* device)
Result ShaderProgramBase::createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode)
+ List<ComPtr<ISlangBlob>>& kernelCodes)
{
SLANG_UNUSED(entryPointInfo);
- SLANG_UNUSED(kernelCode);
+ SLANG_UNUSED(kernelCodes);
return SLANG_OK;
}
diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h
index c763c9ba2..18270c6cd 100644
--- a/tools/gfx/renderer-shared.h
+++ b/tools/gfx/renderer-shared.h
@@ -877,7 +877,7 @@ public:
Slang::Result compileShaders(RendererBase* device);
virtual Slang::Result createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- Slang::ComPtr<ISlangBlob> kernelCode);
+ Slang::List<Slang::ComPtr<ISlangBlob>>& kernelCodes);
virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL
findTypeByName(const char* name) override
diff --git a/tools/gfx/slang-context.h b/tools/gfx/slang-context.h
index 719c70b50..5494ccfce 100644
--- a/tools/gfx/slang-context.h
+++ b/tools/gfx/slang-context.h
@@ -10,6 +10,7 @@ class SlangContext
public:
Slang::ComPtr<slang::IGlobalSession> globalSession;
Slang::ComPtr<slang::ISession> session;
+ SlangCompileTarget compileTarget;
Result initialize(
const gfx::IDevice::SlangDesc& desc,
uint32_t extendedDescCount,
@@ -27,6 +28,7 @@ public:
SLANG_RETURN_ON_FAIL(slang::createGlobalSession(globalSession.writeRef()));
}
+ this->compileTarget = compileTarget;
slang::SessionDesc slangSessionDesc = {};
slangSessionDesc.defaultMatrixLayoutMode = desc.defaultMatrixLayoutMode;
slangSessionDesc.searchPathCount = desc.searchPathCount;
diff --git a/tools/gfx/vulkan/glslang-module.cpp b/tools/gfx/vulkan/glslang-module.cpp
new file mode 100644
index 000000000..03afef794
--- /dev/null
+++ b/tools/gfx/vulkan/glslang-module.cpp
@@ -0,0 +1,108 @@
+// glslang-module.cpp
+#include "glslang-module.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if SLANG_WINDOWS_FAMILY
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+#include "../renderer-shared.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! GlslangModule
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Slang::Result GlslangModule::init()
+{
+ if (isInitialized())
+ {
+ destroy();
+ }
+
+ const char* dynamicLibraryName = "Unknown";
+
+#if SLANG_WINDOWS_FAMILY
+ dynamicLibraryName = "slang-glslang.dll";
+ HMODULE module = ::LoadLibraryA(dynamicLibraryName);
+ m_module = (void*)module;
+#elif SLANG_APPLE_FAMILY
+ dynamicLibraryName = "libslang_glslang.dylib";
+ m_module = dlopen(dynamicLibraryName, RTLD_NOW | RTLD_GLOBAL);
+#else
+ dynamicLibraryName = "libslang_glslang.so";
+ m_module = dlopen(dynamicLibraryName, RTLD_NOW);
+#endif
+
+ if (!m_module)
+ {
+ return SLANG_FAIL;
+ }
+
+ // Load functions
+#if SLANG_WINDOWS_FAMILY
+ m_linkSPIRVFunc = (glslang_LinkSPIRVFunc)GetProcAddress((HMODULE)m_module, "glslang_linkSPIRV");
+#else
+ m_linkSPIRVFunc = (glslang_LinkSPIRVFunc)dlsym(m_module, "glslang_linkSPIRV");
+#endif
+ if (!m_linkSPIRVFunc)
+ {
+ return SLANG_FAIL;
+ }
+
+ return SLANG_OK;
+}
+
+void GlslangModule::destroy()
+{
+ if (!isInitialized())
+ {
+ return;
+ }
+
+#if SLANG_WINDOWS_FAMILY
+ ::FreeLibrary((HMODULE)m_module);
+#else
+ dlclose(m_module);
+#endif
+ m_module = nullptr;
+}
+
+ComPtr<ISlangBlob> GlslangModule::linkSPIRV(List<ComPtr<ISlangBlob>> spirvModules)
+{
+
+ if (!m_linkSPIRVFunc)
+ {
+ return nullptr;
+ }
+
+ glslang_LinkRequest request = {};
+
+ std::vector<const uint32_t*> moduleCodePtrs(spirvModules.getCount());
+ std::vector<uint32_t> moduleSizes(spirvModules.getCount());
+ for (Index i = 0; i < spirvModules.getCount(); ++i)
+ {
+ moduleCodePtrs[i] = (const uint32_t*)spirvModules[i]->getBufferPointer();
+ moduleSizes[i] = spirvModules[i]->getBufferSize() / sizeof(uint32_t);
+ SLANG_ASSERT(spirvModules[i]->getBufferSize() % sizeof(uint32_t) == 0);
+ }
+ request.modules = moduleCodePtrs.data();
+ request.moduleSizes = moduleSizes.data();
+ request.moduleCount = spirvModules.getCount();
+ request.linkResult = nullptr;
+
+ m_linkSPIRVFunc(&request);
+
+ ComPtr<ISlangBlob> linkedSPIRV;
+ linkedSPIRV = RawBlob::create(request.linkResult, request.linkResultSize * sizeof(uint32_t));
+ return linkedSPIRV;
+}
+
+} // namespace gfx
diff --git a/tools/gfx/vulkan/glslang-module.h b/tools/gfx/vulkan/glslang-module.h
new file mode 100644
index 000000000..cda903577
--- /dev/null
+++ b/tools/gfx/vulkan/glslang-module.h
@@ -0,0 +1,36 @@
+// glslang-module.h
+#pragma once
+
+#include "core/slang-list.h"
+#include "external/spirv-tools/include/spirv-tools/linker.hpp"
+#include "slang-com-helper.h"
+#include "slang-com-ptr.h"
+#include "slang-glslang/slang-glslang.h"
+#include "slang.h"
+
+namespace gfx
+{
+
+struct GlslangModule
+{
+ /// true if has been initialized
+ SLANG_FORCE_INLINE bool isInitialized() const { return m_module != nullptr; }
+
+ /// Initialize
+ Slang::Result init();
+
+ /// Destroy
+ void destroy();
+
+ /// Dtor
+ ~GlslangModule() { destroy(); }
+
+ Slang::ComPtr<ISlangBlob> linkSPIRV(Slang::List<Slang::ComPtr<ISlangBlob>> spirvModules);
+
+protected:
+ void* m_module = nullptr;
+
+ glslang_LinkSPIRVFunc m_linkSPIRVFunc = nullptr;
+};
+
+} // namespace gfx
diff --git a/tools/gfx/vulkan/vk-device.cpp b/tools/gfx/vulkan/vk-device.cpp
index cffa094ae..981b5abac 100644
--- a/tools/gfx/vulkan/vk-device.cpp
+++ b/tools/gfx/vulkan/vk-device.cpp
@@ -1019,6 +1019,7 @@ SlangResult DeviceImpl::initialize(const Desc& desc)
SLANG_RETURN_ON_FAIL(RendererBase::initialize(desc));
SlangResult initDeviceResult = SLANG_OK;
+ m_glslang.init();
for (int forceSoftware = 0; forceSoftware <= 1; forceSoftware++)
{
initDeviceResult = m_module.init(forceSoftware != 0);
diff --git a/tools/gfx/vulkan/vk-device.h b/tools/gfx/vulkan/vk-device.h
index 3b6c83103..27cc4c3ce 100644
--- a/tools/gfx/vulkan/vk-device.h
+++ b/tools/gfx/vulkan/vk-device.h
@@ -1,6 +1,7 @@
// vk-device.h
#pragma once
+#include "glslang-module.h"
#include "vk-base.h"
#include "vk-framebuffer.h"
@@ -196,6 +197,7 @@ public:
VulkanModule m_module;
VulkanApi m_api;
+ GlslangModule m_glslang;
VulkanDeviceQueue m_deviceQueue;
uint32_t m_queueFamilyIndex;
diff --git a/tools/gfx/vulkan/vk-shader-program.cpp b/tools/gfx/vulkan/vk-shader-program.cpp
index 43a295786..1627c95a7 100644
--- a/tools/gfx/vulkan/vk-shader-program.cpp
+++ b/tools/gfx/vulkan/vk-shader-program.cpp
@@ -1,6 +1,7 @@
// vk-shader-program.cpp
#include "vk-shader-program.h"
+#include "external/spirv-tools/include/spirv-tools/linker.hpp"
#include "vk-device.h"
#include "vk-util.h"
@@ -71,15 +72,22 @@ VkPipelineShaderStageCreateInfo ShaderProgramImpl::compileEntryPoint(
Result ShaderProgramImpl::createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode)
+ List<ComPtr<ISlangBlob>>& kernelCodes)
{
- m_codeBlobs.add(kernelCode);
+ ComPtr<ISlangBlob> linkedKernel = m_device->m_glslang.linkSPIRV(kernelCodes);
+ if (!linkedKernel)
+ {
+ return SLANG_FAIL;
+ }
+
+ m_codeBlobs.add(linkedKernel);
+
VkShaderModule shaderModule;
auto realEntryPointName = entryPointInfo->getNameOverride();
const char* spirvBinaryEntryPointName = "main";
m_stageCreateInfos.add(compileEntryPoint(
spirvBinaryEntryPointName,
- kernelCode,
+ linkedKernel,
(VkShaderStageFlagBits)VulkanUtil::getShaderStage(entryPointInfo->getStage()),
shaderModule));
m_entryPointNames.add(realEntryPointName);
diff --git a/tools/gfx/vulkan/vk-shader-program.h b/tools/gfx/vulkan/vk-shader-program.h
index 3fd56669a..56b354612 100644
--- a/tools/gfx/vulkan/vk-shader-program.h
+++ b/tools/gfx/vulkan/vk-shader-program.h
@@ -37,7 +37,7 @@ public:
virtual Result createShaderModule(
slang::EntryPointReflection* entryPointInfo,
- ComPtr<ISlangBlob> kernelCode) override;
+ List<ComPtr<ISlangBlob>>& kernelCodes) override;
};