diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-06-02 14:13:35 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-02 14:13:35 -0400 |
| commit | b39c99661b3ad482bbd419c24991ed325b5738a9 (patch) | |
| tree | 0f90fecdae10e704b2c1135c48ca5eeafa60b780 /examples/cpu-com-example | |
| parent | bc6bc56db51d06b92dc63ef9c9e0def6c9760c9e (diff) | |
COM interfaces with host callable (#2258)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Use TerminatedUnownedStringSlice for literals in output C++.
* Remove Escape/Unescape functions used in slang-token-reader.cpp
Add target type of 'host-cpp' etc to map to the target types.
* Fix some corner cases around string encoding.
* Added unit test for string escaping.
Fixed some assorted escaping bugs.
* Updated test output.
* Added decode test.
* Stop using hex output, to get around 'greedy' aspect. Use octal instead.
* Added HostHostCallable
Small changes to use ArtifactDesc/Info instead of large switches.
* Fix C++ emit to handle arbitrary function export.
* Add options handling for callable without an output being specified.
* Can compile with COM interface. Added example using com interface.
* Use the IR Ptr type instead of hack in C++ emit for interfaces.
* Fix issue with outputting the COM call when ptr is used.
* Fix crash issue on compilation failure.
Diffstat (limited to 'examples/cpu-com-example')
| -rw-r--r-- | examples/cpu-com-example/README.md | 8 | ||||
| -rw-r--r-- | examples/cpu-com-example/main.cpp | 135 | ||||
| -rw-r--r-- | examples/cpu-com-example/shader.slang | 21 |
3 files changed, 164 insertions, 0 deletions
diff --git a/examples/cpu-com-example/README.md b/examples/cpu-com-example/README.md new file mode 100644 index 000000000..a5e234d15 --- /dev/null +++ b/examples/cpu-com-example/README.md @@ -0,0 +1,8 @@ +Slang COM Example +================= + +The goal of this example is to demonstrate Slang generating CPU code that can be communicated with via Common Object Model (COM) style interfaces. + +The `shader.slang` file contains Slang code that uses COM interfaces. + +The `main.cpp` file contains the C++ application code, showing how to use the Slang API to load and compile the shader code and communicate via interfaces. diff --git a/examples/cpu-com-example/main.cpp b/examples/cpu-com-example/main.cpp new file mode 100644 index 000000000..2e9eeed79 --- /dev/null +++ b/examples/cpu-com-example/main.cpp @@ -0,0 +1,135 @@ +// main.cpp + +#include <stdio.h> + +#include <slang.h> + +#include <slang-com-ptr.h> +#include <slang-com-helper.h> + + +// This includes a useful small function for setting up the prelude (described more further below). +#include "../../source/core/slang-test-tool-util.h" + +// Slang namespace is used for elements support code (like core) which we use here +// for ComPtr<> and TestToolUtil +using namespace Slang; + +// For the moment we have to explicitly write the Slang COM interface in C++ code. It *MUST* match +// the interface in the slang source +// As it stands all interfaces need to derive from ISlangUnknown (or IUnknown). +class IDoThings : public ISlangUnknown +{ +public: + virtual int SLANG_MCALL doThing(int a, int b) = 0; + virtual int SLANG_MCALL calcHash(const char* in) = 0; +}; + +static int _calcHash(const char* in) +{ + int hash = 0; + for (; *in; ++in) + { + // A very poor hash function + hash = hash * 13 + *in; + } + return hash; +} + +class DoThings :public IDoThings +{ +public: + // We don't need queryInterface for this impl, or ref counting + virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE { return SLANG_E_NOT_IMPLEMENTED; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + + // IDoThings + virtual int SLANG_MCALL doThing(int a, int b) SLANG_OVERRIDE { return a + b + 1; } + virtual int SLANG_MCALL calcHash(const char* in) SLANG_OVERRIDE { return (int)_calcHash(in); } +}; + +static SlangResult _innerMain(int argc, char** argv) +{ + // Create the session + ComPtr<slang::IGlobalSession> slangSession; + slangSession.attach(spCreateSession(NULL)); + + // Set up the prelude + TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], slangSession); + + // Create a compile request + Slang::ComPtr<slang::ICompileRequest> request; + SLANG_RETURN_ON_FAIL(slangSession->createCompileRequest(request.writeRef())); + + // We want to compile to 'HOST_CALLABLE' here such that we can execute the Slang code. + // + // Note that it is possible to use HOST_HOST_CALLABLE, but this currently only works with 'regular' C++ compilers + // not with `slang-llvm`. + const int targetIndex = request->addCodeGenTarget(SLANG_SHADER_HOST_CALLABLE); + + // Set the target flag to indicate that we want to compile all into a library. + request->setTargetFlags(targetIndex, SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM); + + // Add the translation unit + const int translationUnitIndex = request->addTranslationUnit(SLANG_SOURCE_LANGUAGE_SLANG, nullptr); + + // Set the source file for the translation unit + request->addTranslationUnitSourceFile(translationUnitIndex, "shader.slang"); + + const SlangResult compileRes = request->compile(); + + // Even if there were no errors that forced compilation to fail, the + // compiler may have produced "diagnostic" output such as warnings. + // We will go ahead and print that output here. + // + if(auto diagnostics = request->getDiagnosticOutput()) + { + printf("%s", diagnostics); + } + + // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library + // it's just an interface to executable code). + ComPtr<ISlangSharedLibrary> sharedLibrary; + SLANG_RETURN_ON_FAIL(request->getTargetHostCallable(0, sharedLibrary.writeRef())); + + { + typedef const char* (*Func)(const char*); + Func func = (Func)sharedLibrary->findFuncByName("getString"); + + if (!func) + { + return SLANG_FAIL; + } + + String text = "Hello World!"; + String returnedText = func(text.getBuffer()); + + SLANG_ASSERT(text == returnedText); + } + { + typedef int (*Func)(const char* text, IDoThings* doThings); + + Func func = (Func)sharedLibrary->findFuncByName("calcHash"); + + if (!func) + { + return SLANG_FAIL; + } + + DoThings doThings; + + String text("Hello"); + + const int hash = func(text.getBuffer(), &doThings); + + SLANG_ASSERT(hash == _calcHash(text.getBuffer())); + } + + return SLANG_OK; +} + +int main(int argc, char** argv) +{ + return SLANG_SUCCEEDED(_innerMain(argc, argv)) ? 0 : -1; +} diff --git a/examples/cpu-com-example/shader.slang b/examples/cpu-com-example/shader.slang new file mode 100644 index 000000000..b0fe259be --- /dev/null +++ b/examples/cpu-com-example/shader.slang @@ -0,0 +1,21 @@ +// shader.slang + +// Example of using 'NativeString' + +public __extern_cpp NativeString getString(NativeString in) +{ + return in; +} + +[COM] +interface IDoThings +{ + int doThing(int a, int b); + int calcHash(NativeString in); +} + +public __extern_cpp int calcHash(NativeString text, IDoThings doThings) +{ + return doThings.calcHash(text); +} + |
