From 5eb835f0332868fd56ac14ce7560e0ae9cfafec9 Mon Sep 17 00:00:00 2001 From: David Siher <32305650+dsiher@users.noreply.github.com> Date: Thu, 3 Feb 2022 19:16:54 -0800 Subject: Fixed naming conflicts in heterogeneous-hello-world (#2114) * Fixed naming conflicts in heterogeneous-hello-world Added 3 new modifiers (`__unmangled`, `__exportDirectly`, `__externLib`) `__unmangled` causes mangleName() to return the normal name of the decl. `__exportDirectly` changes parent decl name concatenation behavior to use "::" instead of "." (for Name Hint) and emits the name hint when it exists, otherwise it emits the mangled name. `__externLib` stops Slang from emitting the corresponding struct. Also made necessary changes to heterogeneous-hello-world so that this new functionality is shown off. * Undo unintentional formatting changes Co-authored-by: Yong He --- .../heterogeneous-hello-world.vcxproj | 4 +- examples/heterogeneous-hello-world/main.cpp | 107 +++++---------------- examples/heterogeneous-hello-world/shader.slang | 65 +++++++------ prelude/slang-cpp-prelude.h | 16 +-- slang.sln | 30 ++++++ source/slang/core.meta.slang | 20 ++++ source/slang/slang-ast-modifier.h | 3 + source/slang/slang-emit-c-like.cpp | 29 ++++++ source/slang/slang-emit-cpp.cpp | 31 ++++-- source/slang/slang-ir-inst-defs.h | 3 + source/slang/slang-ir-insts.h | 12 +++ source/slang/slang-lower-to-ir.cpp | 17 +++- source/slang/slang-mangle.cpp | 12 ++- 13 files changed, 207 insertions(+), 142 deletions(-) diff --git a/build/visual-studio/heterogeneous-hello-world/heterogeneous-hello-world.vcxproj b/build/visual-studio/heterogeneous-hello-world/heterogeneous-hello-world.vcxproj index 70c173112..3e3049f65 100644 --- a/build/visual-studio/heterogeneous-hello-world/heterogeneous-hello-world.vcxproj +++ b/build/visual-studio/heterogeneous-hello-world/heterogeneous-hello-world.vcxproj @@ -165,7 +165,7 @@ Level3 _DEBUG;%(PreprocessorDefinitions) ..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories) - EditAndContinue + ProgramDatabase Disabled MultiThreadedDebug @@ -184,7 +184,7 @@ Level3 _DEBUG;%(PreprocessorDefinitions) ..\..\..;..\..\..\tools;%(AdditionalIncludeDirectories) - EditAndContinue + ProgramDatabase Disabled MultiThreadedDebug diff --git a/examples/heterogeneous-hello-world/main.cpp b/examples/heterogeneous-hello-world/main.cpp index 0d8d2ca73..e711d4486 100644 --- a/examples/heterogeneous-hello-world/main.cpp +++ b/examples/heterogeneous-hello-world/main.cpp @@ -27,13 +27,7 @@ ComPtr gQueue; // Boilerplate types to help the slang-generated file // -struct gfx_Device_0; -struct gfx_BufferResource_0; -struct gfx_ShaderProgram_0; -struct gfx_ResourceView_0; -struct gfx_TransientResourceHeap_0; -struct gfx_PipelineState_0; -bool executeComputation_0(); +bool executeComputation(); // Many Slang API functions return detailed diagnostic information // (error messages, warnings, etc.) as a "blob" of data, or return @@ -50,7 +44,7 @@ void diagnoseIfNeeded(slang::IBlob *diagnosticsBlob) } } -gfx::IDevice* createDevice() +gfx::IDevice *createDevice() { ComPtr device; IDevice::Desc deviceDesc = {}; @@ -62,7 +56,7 @@ gfx::IDevice* createDevice() // Loads the shader code defined in `shader.slang` for use by the `gfx` layer. // -gfx::IShaderProgram* loadShaderProgram(gfx::IDevice *device, String entryPoint, String moduleName) +gfx::IShaderProgram *loadShaderProgram(gfx::IDevice *device, char* entryPoint, char* moduleName) { // We need to obtain a compilation session (`slang::ISession`) that will provide // a scope to all the compilation and loading of code we do. @@ -83,17 +77,17 @@ gfx::IShaderProgram* loadShaderProgram(gfx::IDevice *device, String entryPoint, // already been loaded previously, that would be used directly. // ComPtr diagnosticsBlob; - slang::IModule *module = slangSession->loadModule(moduleName.getBuffer(), diagnosticsBlob.writeRef()); + slang::IModule *module = slangSession->loadModule(moduleName, diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); if (!module) return NULL; // Look up entry point // - char const *computeEntryPointName = entryPoint.getBuffer(); + // char const *computeEntryPointName = entryPoint.getBuffer(); ComPtr computeEntryPoint; SLANG_RETURN_NULL_ON_FAIL( - module->findEntryPointByName(computeEntryPointName, computeEntryPoint.writeRef())); + module->findEntryPointByName(entryPoint, computeEntryPoint.writeRef())); // At this point we have a few different Slang API objects that represent // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. @@ -139,9 +133,7 @@ gfx::IShaderProgram* loadShaderProgram(gfx::IDevice *device, String entryPoint, return gProgram; } -gfx::IBufferResource* createStructuredBuffer( - gfx::IDevice *device, - float *initialData) +gfx::IBufferResource* createStructuredBuffer(gfx::IDevice* device, FixedArray initialData) { // Create a structured buffer for storing computation data // @@ -160,15 +152,15 @@ gfx::IBufferResource* createStructuredBuffer( bufferDesc.memoryType = MemoryType::DeviceLocal; SlangResult result = device->createBufferResource(bufferDesc, - (void *)initialData, + (void *)&initialData, gBufferResource.writeRef()); SLANG_RETURN_NULL_ON_FAIL(result); return gBufferResource; } -gfx::IResourceView* createBufferView( - gfx::IDevice* device, - gfx::IBufferResource* buffer) +gfx::IResourceView *createBufferView( + gfx::IDevice *device, + gfx::IBufferResource *buffer) { // Create a resource view for the structured buffer // @@ -179,7 +171,7 @@ gfx::IResourceView* createBufferView( return gResourceView; } -gfx::ITransientResourceHeap* buildTransientHeap(gfx::IDevice *device) +gfx::ITransientResourceHeap *buildTransientHeap(gfx::IDevice *device) { ITransientResourceHeap::Desc transientHeapDesc = {}; transientHeapDesc.constantBufferSize = 4096; @@ -188,9 +180,9 @@ gfx::ITransientResourceHeap* buildTransientHeap(gfx::IDevice *device) return gTransientHeap; } -gfx::IPipelineState* buildPipelineState( +gfx::IPipelineState *buildPipelineState( gfx::IDevice *device, - gfx::IShaderProgram* shaderProgram) + gfx::IShaderProgram *shaderProgram) { gfx::ComputePipelineStateDesc pipelineDesc = {}; pipelineDesc.program = shaderProgram; @@ -199,7 +191,7 @@ gfx::IPipelineState* buildPipelineState( return gPipelineState; } -void printInitialValues(float *initialArray, int length) +void printInitialValues(FixedArray initialArray, int length) { printf("Before:\n"); for (int i = 0; i < length; i++) @@ -210,10 +202,10 @@ void printInitialValues(float *initialArray, int length) } void dispatchComputation( - gfx::IDevice* device, - gfx::ITransientResourceHeap* transientHeap, - gfx::IPipelineState* pipelineState, - gfx::IResourceView* bufferView, + gfx::IDevice *device, + gfx::ITransientResourceHeap *transientHeap, + gfx::IPipelineState *pipelineState, + gfx::IResourceView *bufferView, unsigned int gridDimsX, unsigned int gridDimsY, unsigned int gridDimsZ) @@ -257,68 +249,15 @@ bool printOutputValues( return true; } -// Boilerplate functions to help the slang-generated file and types - -gfx_Device_0* createDevice_0() -{ - return (gfx_Device_0*)createDevice(); -} - -gfx_BufferResource_0* createStructuredBuffer_0(gfx_Device_0* _0, FixedArray _1) -{ - return (gfx_BufferResource_0*)createStructuredBuffer((gfx::IDevice*)_0, (float*)&_1); -} - -gfx_ShaderProgram_0* loadShaderProgram_0(gfx_Device_0* _0, char* _1, char* _2) -{ - return (gfx_ShaderProgram_0*)loadShaderProgram((gfx::IDevice*)_0, _1, _2); -} - -gfx_ResourceView_0* createBufferView_0(gfx_Device_0* _0, gfx_BufferResource_0* _1) -{ - return (gfx_ResourceView_0*)createBufferView((gfx::IDevice*)_0, (gfx::IBufferResource*)_1); -} - -gfx_TransientResourceHeap_0* buildTransientHeap_0(gfx_Device_0* _0) -{ - return (gfx_TransientResourceHeap_0*)buildTransientHeap((gfx::IDevice*)_0); -} - -gfx_PipelineState_0* buildPipelineState_0(gfx_Device_0* _0, gfx_ShaderProgram_0* _1) -{ - return (gfx_PipelineState_0*)buildPipelineState((gfx::IDevice*)_0, (gfx::IShaderProgram*)_1); -} - -void printInitialValues_0(FixedArray _0, int32_t _1) -{ - printInitialValues((float*)&_0, _1); -} - -void dispatchComputation_0(gfx_Device_0* _0, gfx_TransientResourceHeap_0* _1, gfx_PipelineState_0* _2, gfx_ResourceView_0* _3, unsigned int gridDimsX, unsigned int gridDimsY, unsigned int gridDimsZ) -{ - dispatchComputation( - (gfx::IDevice*)_0, - (gfx::ITransientResourceHeap*)_1, - (gfx::IPipelineState*)_2, - (gfx::IResourceView*)_3, - gridDimsX, - gridDimsY, - gridDimsZ); -} - -RWStructuredBuffer convertBuffer_0(gfx_BufferResource_0* _0) { +RWStructuredBuffer convertBuffer(gfx::IBufferResource* _0) { RWStructuredBuffer result; result.data = (float*)_0; return result; } -gfx_BufferResource_0* unconvertBuffer_0(RWStructuredBuffer _0) { - return (gfx_BufferResource_0*)(_0.data); -} - -bool printOutputValues_0(gfx_Device_0* _0, gfx_BufferResource_0* _1, int32_t _2) +gfx::IBufferResource *unconvertBuffer(RWStructuredBuffer _0) { - return printOutputValues((gfx::IDevice*)_0, (gfx::IBufferResource*)_1, _2); + return (gfx::IBufferResource *)(_0.data); } int main() @@ -327,7 +266,7 @@ int main() // `struct` type, and then walk through the lifecyle // of the application. - if (!(executeComputation_0())) + if (!(executeComputation())) { return -1; } diff --git a/examples/heterogeneous-hello-world/shader.slang b/examples/heterogeneous-hello-world/shader.slang index d67fd5582..d87370be1 100644 --- a/examples/heterogeneous-hello-world/shader.slang +++ b/examples/heterogeneous-hello-world/shader.slang @@ -1,7 +1,7 @@ // shader.slang //TEST_INPUT:ubuffer(random(float, 4096, -1.0, 1.0), stride=4):name=ioBuffer -RWStructuredBuffer convertBuffer(Ptr x); +__unmangled __exportDirectly RWStructuredBuffer convertBuffer(Ptr x); [shader("compute")] [numthreads(4, 1, 1)] @@ -15,44 +15,49 @@ void computeMain(uniform RWStructuredBuffer ioBuffer, uint3 dispatchThrea ioBuffer[tid] = o; } + + // Forward declarations of gfx types // namespace gfx { - struct Device{}; - struct BufferResource{}; - struct ResourceView{}; - struct TransientResourceHeap{}; - struct PipelineState{}; - struct ShaderProgram{}; + __externLib __exportDirectly struct IDevice{}; + __externLib __exportDirectly struct IBufferResource{}; + __exportDirectly struct ITransientResourceHeap{}; + __exportDirectly struct IPipelineState{}; + __exportDirectly struct IShaderProgram{}; + __exportDirectly struct IResourceView{}; } // Forward declarations of cpp functions // -Ptr createDevice(); -Ptr loadShaderProgram(Ptr device, String entryPoint, String module); -Ptr createStructuredBuffer( - Ptr device, +__unmangled __exportDirectly Ptr createDevice(); +__unmangled __exportDirectly Ptr loadShaderProgram( + Ptr device, + String entryPoint, + String module); +__unmangled __exportDirectly Ptr createStructuredBuffer( + Ptr device, float[4] initialData); -Ptr createBufferView( - Ptr device, - Ptr buffer); -Ptr buildTransientHeap( - Ptr device); -Ptr buildPipelineState( - Ptr device, - Ptr shaderProgram); -void printInitialValues(float[4] initialArray, int length); -void dispatchComputation( - Ptr device, - Ptr transientHeap, - Ptr pipelineState, - Ptr bufferView); -bool printOutputValues( - Ptr device, - Ptr buffer, +__unmangled __exportDirectly Ptr createBufferView( + Ptr device, + Ptr buffer); +__unmangled __exportDirectly Ptr buildTransientHeap( + Ptr device); +__unmangled __exportDirectly Ptr buildPipelineState( + Ptr device, + Ptr shaderProgram); +__unmangled __exportDirectly void printInitialValues(float[4] initialArray, int length); +__unmangled __exportDirectly void dispatchComputation( + Ptr device, + Ptr transientHeap, + Ptr pipelineState, + Ptr bufferView); +__unmangled __exportDirectly bool printOutputValues( + Ptr device, + Ptr buffer, int length); -public bool executeComputation() { +public __unmangled __exportDirectly bool executeComputation() { // We will hard-code the size of our initial array. // float initialArray[4] = { 3.0f, -20.0f, -6.0f, 8.0f }; @@ -60,7 +65,7 @@ public bool executeComputation() { // Declare functions let device = createDevice(); let structuredBuffer = createStructuredBuffer(device, initialArray); - let bufferView = createBufferView(device, structuredBuffer); + // let bufferView = createBufferView(device, structuredBuffer); __GPU_FOREACH(device, uint3(4, 1, 1), LAMBDA(uint3 dispatchThreadID) { computeMain(convertBuffer(structuredBuffer), dispatchThreadID) ; }); printInitialValues(initialArray, 4); diff --git a/prelude/slang-cpp-prelude.h b/prelude/slang-cpp-prelude.h index b1b29284c..612f9ec9f 100644 --- a/prelude/slang-cpp-prelude.h +++ b/prelude/slang-cpp-prelude.h @@ -132,18 +132,4 @@ Any compilers not detected by the above logic are now now explicitly zeroed out. # define SLANG_UNROLL #endif -struct gfx_Device_0; -struct gfx_BufferResource_0; -struct gfx_ShaderProgram_0; -struct gfx_ResourceView_0; -struct gfx_TransientResourceHeap_0; -struct gfx_PipelineState_0; - -gfx_ShaderProgram_0* loadShaderProgram_0(gfx_Device_0* _0, char* _1, char* _2); -gfx_TransientResourceHeap_0* buildTransientHeap_0(gfx_Device_0* _0); -gfx_PipelineState_0* buildPipelineState_0(gfx_Device_0* _0, gfx_ShaderProgram_0* _1); -gfx_ResourceView_0* createBufferView_0(gfx_Device_0* _0, gfx_BufferResource_0* _1); -void dispatchComputation_0(gfx_Device_0* _0, gfx_TransientResourceHeap_0* _1, gfx_PipelineState_0* _2, gfx_ResourceView_0* _3, uint32_t gridDimsX, uint32_t gridDimsY, uint32_t gridDimsZ); -gfx_BufferResource_0* unconvertBuffer_0(RWStructuredBuffer _0); - -#endif +#endif \ No newline at end of file diff --git a/slang.sln b/slang.sln index b4b30eeee..8b7bf1cf5 100644 --- a/slang.sln +++ b/slang.sln @@ -35,6 +35,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpu-printing", "build\visua EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello-world", "build\visual-studio\hello-world\hello-world.vcxproj", "{010BE414-ED5B-CF56-16C0-BD18027062C0}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "heterogeneous-first-gen", "build\visual-studio\heterogeneous-hello-world\heterogeneous-first-gen.vcxproj", "{3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "heterogeneous-hello-world", "build\visual-studio\heterogeneous-hello-world\heterogeneous-hello-world.vcxproj", "{150CAA5A-0177-6A66-AA92-CFCB96DC2D49}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "model-viewer", "build\visual-studio\model-viewer\model-viewer.vcxproj", "{2F8724C6-1BC3-2730-84D5-3F277030D04A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ray-tracing", "build\visual-studio\ray-tracing\ray-tracing.vcxproj", "{71AC0F50-5DFD-FA91-8661-E95372118EFB}" @@ -267,6 +271,30 @@ Global {010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|Win32.Build.0 = Release|Win32 {010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|x64.ActiveCfg = Release|x64 {010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|x64.Build.0 = Release|x64 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|aarch64.Build.0 = Debug aarch64|ARM + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|Win32.ActiveCfg = Debug|Win32 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|Win32.Build.0 = Debug|Win32 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|x64.ActiveCfg = Debug|x64 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|x64.Build.0 = Debug|x64 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|aarch64.ActiveCfg = Release aarch64|ARM + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|aarch64.Build.0 = Release aarch64|ARM + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|Win32.ActiveCfg = Release|Win32 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|Win32.Build.0 = Release|Win32 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|x64.ActiveCfg = Release|x64 + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|x64.Build.0 = Release|x64 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|aarch64.Build.0 = Debug aarch64|ARM + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|Win32.ActiveCfg = Debug|Win32 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|Win32.Build.0 = Debug|Win32 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|x64.ActiveCfg = Debug|x64 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|x64.Build.0 = Debug|x64 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|aarch64.ActiveCfg = Release aarch64|ARM + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|aarch64.Build.0 = Release aarch64|ARM + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|Win32.ActiveCfg = Release|Win32 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|Win32.Build.0 = Release|Win32 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|x64.ActiveCfg = Release|x64 + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|x64.Build.0 = Release|x64 {2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM {2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|aarch64.Build.0 = Debug aarch64|ARM {2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -465,6 +493,8 @@ Global {37BED5B5-23FA-D81F-8C0C-F1167867813A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} {57C81DD3-4304-213D-AC16-39349871C957} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} {010BE414-ED5B-CF56-16C0-BD18027062C0} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} + {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} + {150CAA5A-0177-6A66-AA92-CFCB96DC2D49} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} {2F8724C6-1BC3-2730-84D5-3F277030D04A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} {71AC0F50-5DFD-FA91-8661-E95372118EFB} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} {17BA8E32-034E-84DA-6C12-DE8E58C5BECC} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231} diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index ca07b299d..779900fd5 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -63,6 +63,26 @@ syntax unorm : UNormModifier; /// syntax snorm : SNormModifier; +/// Modifier to indicate that a function name should not be mangled +/// by the Slang compiler. +/// +/// The `__unmangled` modifier should only be valid on functions +/// and is mainly useful for the experimental heterogeneous +/// features of Slang. +/// +syntax __unmangled : UnmangledModifier; + +/// Modifier to indicate that a function name should be exported +/// directly. Used in tandem with `__unmangled` in heterogeneous +/// features of Slang. +/// +syntax __exportDirectly : __exportDirectly; + +/// Modifier to indicate that a struct is defined externally and +/// should therefore not be exported by Slang. +/// +syntax __externLib : __externLib; + /// A type that can be used as an operand for builtins [sealed] [builtin] diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 2558d7c4b..ae9e0924e 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -28,6 +28,9 @@ class PostfixModifier : public Modifier { SLANG_AST_CLASS(PostfixModifier)}; class ExportedModifier : public Modifier { SLANG_AST_CLASS(ExportedModifier)}; class ConstExprModifier : public Modifier { SLANG_AST_CLASS(ConstExprModifier)}; class GloballyCoherentModifier : public Modifier { SLANG_AST_CLASS(GloballyCoherentModifier)}; +class UnmangledModifier : public Modifier { SLANG_AST_CLASS(UnmangledModifier)}; +class __exportDirectly : public Modifier { SLANG_AST_CLASS(__exportDirectly)}; +class __externLib : public Modifier { SLANG_AST_CLASS(__externLib)}; /// A modifier that indicates an `InheritanceDecl` should be ignored during name lookup (and related checks). class IgnoreForLookupModifier : public Modifier { SLANG_AST_CLASS(IgnoreForLookupModifier) }; diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index e04759773..c0106e9ad 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -740,6 +740,28 @@ String CLikeSourceEmitter::_generateUniqueName(const UnownedStringSlice& name) String CLikeSourceEmitter::generateName(IRInst* inst) { + // Handle `__exportDirectly` decoration before all else + if (inst->findDecoration()) + { + // If instruction has a NameHint, we naively emit it as a namespace + // This is automatically handled in `getNameforNameHint` when the + // `__exportDirectly` decoration is found, so we can just return it. + // TODO: This is a very hacky solution. + // + // Another option would be to have two separate decorations, one that + // handles this namespace, and a separate decoration for unmangled names. + if (auto nameHintDecoration = inst->findDecoration()) + { + return nameHintDecoration->getName(); + } + // Otherwise, we just want the instruction to not be mangled, which is + // similarly handled in `getMangledName`. + if (auto linkageDecoration = inst->findDecoration()) + { + return linkageDecoration->getMangledName(); + } + } + // If the instruction names something // that should be emitted as a target intrinsic, // then use that name instead. @@ -2901,6 +2923,13 @@ void CLikeSourceEmitter::emitStruct(IRStructType* structType) return; } + // If the selected `struct` type is externally defined + // then we also don't want to emit anything. + if (auto externLibDecoration = structType->findDecoration()) + { + return; + } + m_writer->emit("struct "); emitPostKeywordTypeAttributes(structType); diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index cb6c210be..e06aa8372 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -2709,26 +2709,43 @@ void CPPSourceEmitter::emitModuleImpl(IRModule* module, DiagnosticSink* sink) } } } + // Hardcode in (for now) an include for slang-gfx.h so that we can make use + // of the gfx namespace + // + // TODO: Aside from making sure this approach is viable, it would also be + // much better to allow this to be done by the programmer in the Slang file. + m_writer->emit("#include \"slang-gfx.h\"\n\n"); + + // Emit boilerplate that requires gfx. + // This is required by the wrapper, so that will be the next place to look + // as far as removing boilerplate goes. + m_writer->emit("gfx::IShaderProgram* loadShaderProgram(gfx::IDevice* _0, char* _1, char* _2);\n"); + m_writer->emit("gfx::ITransientResourceHeap* buildTransientHeap(gfx::IDevice* _0);\n"); + m_writer->emit("gfx::IPipelineState* buildPipelineState(gfx::IDevice* _0, gfx::IShaderProgram* _1);\n"); + m_writer->emit("void dispatchComputation(gfx::IDevice* _0, gfx::ITransientResourceHeap* _1, gfx::IPipelineState* _2, gfx::IResourceView* _3, uint32_t gridDimsX, uint32_t gridDimsY, uint32_t gridDimsZ);\n"); + m_writer->emit("gfx::IResourceView* createBufferView(gfx::IDevice* _0, gfx::IBufferResource* _1);\n"); + m_writer->emit("gfx::IBufferResource* unconvertBuffer(RWStructuredBuffer _0);\n\n"); + // Emit a wrapper function for calling the shader blob m_writer->emit("void "); m_writer->emit(entryPointName); - m_writer->emit("_wrapper(gfx_Device_0* device, Vector gridDims, \n"); + m_writer->emit("_wrapper(gfx::IDevice* device, Vector gridDims, \n"); m_writer->emit("\tRWStructuredBuffer buffer)\n{"); /* m_writer->emit("\n\tgfx_ShaderProgram_0* shaderProgram = loadShaderProgram_0(device, __"); m_writer->emit(entryPointName); m_writer->emit(", __"); m_writer->emit(entryPointName); m_writer->emit("Size);");*/ - m_writer->emit("\n\tgfx_ShaderProgram_0* shaderProgram = loadShaderProgram_0(device, \""); + m_writer->emit("\n\tgfx::IShaderProgram* shaderProgram = loadShaderProgram(device, \""); m_writer->emit(entryPointName); m_writer->emit("\", \""); m_writer->emit(moduleName); m_writer->emit("\");"); - m_writer->emit("\n\tgfx_TransientResourceHeap_0* transientHeap = buildTransientHeap_0(device);"); - m_writer->emit("\n\tgfx_PipelineState_0* pipelineState = "); - m_writer->emit("buildPipelineState_0(device, shaderProgram);"); - m_writer->emit("\n\tgfx_ResourceView_0* bufferView = createBufferView_0(device, unconvertBuffer_0(buffer));"); - m_writer->emit("\n\tdispatchComputation_0(device, transientHeap, pipelineState, "); + m_writer->emit("\n\tgfx::ITransientResourceHeap* transientHeap = buildTransientHeap(device);"); + m_writer->emit("\n\tgfx::IPipelineState* pipelineState = "); + m_writer->emit("buildPipelineState(device, shaderProgram);"); + m_writer->emit("\n\tgfx::IResourceView* bufferView = createBufferView(device, unconvertBuffer(buffer));"); + m_writer->emit("\n\tdispatchComputation(device, transientHeap, pipelineState, "); m_writer->emit("bufferView, gridDims.x, gridDims.y, gridDims.z);"); m_writer->emit("\n}\n"); } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 9fa5a2e9d..0fca118d1 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -553,6 +553,9 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(InstanceDecoration, instance, 1, 0) INST(NumThreadsDecoration, numThreads, 3, 0) + INST(__exportDirectly, __exportDirectly, 0, 0) + INST(__externLib, __externLib, 0, 0) + // Added to IRParam parameters to an entry point /* GeometryInputPrimitiveTypeDecoration */ INST(PointInputPrimitiveTypeDecoration, pointPrimitiveType, 0, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 7ef31d71a..9b50047de 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -269,6 +269,8 @@ IR_SIMPLE_DECORATION(PublicDecoration) IR_SIMPLE_DECORATION(KeepAliveDecoration) IR_SIMPLE_DECORATION(RequiresNVAPIDecoration) IR_SIMPLE_DECORATION(NoInlineDecoration) +IR_SIMPLE_DECORATION(__exportDirectly) +IR_SIMPLE_DECORATION(__externLib) struct IRNVAPIMagicDecoration : IRDecoration { @@ -2832,6 +2834,16 @@ public: { addDecoration(inst, kIROp_SequentialIDDecoration, getIntValue(getUIntType(), id)); } + + void addExportDirectlyDecoration(IRInst* value) + { + addDecoration(value, kIROp___exportDirectly); + } + + void addExternLibDecoration(IRInst* value) + { + addDecoration(value, kIROp___externLib); + } }; void addHoistableInst( diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index d4b069dca..b2a71a2e0 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -1034,7 +1034,7 @@ static void addLinkageDecoration( inst = outerGeneric; } - if(isImportedDecl(context, decl)) + if (isImportedDecl(context, decl)) { builder->addImportDecoration(inst, mangledName); } @@ -1047,6 +1047,14 @@ static void addLinkageDecoration( builder->addPublicDecoration(inst); builder->addKeepAliveDecoration(inst); } + if (decl->findModifier<__exportDirectly>()) + { + builder->addExportDirectlyDecoration(inst); + } + if (decl->findModifier<__externLib>()) + { + builder->addExternLibDecoration(inst); + } } static void addLinkageDecoration( @@ -1986,7 +1994,12 @@ static String getNameForNameHint( StringBuilder sb; sb.append(parentName); - sb.append("."); + if (decl->hasModifier<__exportDirectly>()) { + sb.append("::"); + } + else { + sb.append("."); + } sb.append(leafName->text); return sb.ProduceString(); diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp index b0568994f..acb561531 100644 --- a/source/slang/slang-mangle.cpp +++ b/source/slang/slang-mangle.cpp @@ -453,12 +453,20 @@ namespace Slang // forward to something else? E.g., what if we // are asked to mangle the name of a `typedef`? + auto decl = declRef.getDecl(); + + // Handle `__unmangled` modifier by simply emitting + // the given name. + if (decl->hasModifier()) + { + emit(context, decl->getName()->text); + return; + } + // We will start with a unique prefix to avoid // clashes with user-defined symbols: emitRaw(context, "_S"); - auto decl = declRef.getDecl(); - // Next we will add a bit of info to register // the *kind* of declaration we are dealing with. // -- cgit v1.2.3