summaryrefslogtreecommitdiffstats
path: root/examples/cpu-com-example
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-06-02 14:13:35 -0400
committerGitHub <noreply@github.com>2022-06-02 14:13:35 -0400
commitb39c99661b3ad482bbd419c24991ed325b5738a9 (patch)
tree0f90fecdae10e704b2c1135c48ca5eeafa60b780 /examples/cpu-com-example
parentbc6bc56db51d06b92dc63ef9c9e0def6c9760c9e (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.md8
-rw-r--r--examples/cpu-com-example/main.cpp135
-rw-r--r--examples/cpu-com-example/shader.slang21
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);
+}
+