diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/cpu-hello-world/main.cpp | 2 | ||||
| -rw-r--r-- | examples/heterogeneous-hello-world/main.cpp | 273 | ||||
| -rw-r--r-- | examples/heterogeneous-hello-world/main.slang | 10 | ||||
| -rw-r--r-- | examples/heterogeneous-hello-world/shader.slang | 76 |
4 files changed, 11 insertions, 350 deletions
diff --git a/examples/cpu-hello-world/main.cpp b/examples/cpu-hello-world/main.cpp index cf8c57285..460b4698b 100644 --- a/examples/cpu-hello-world/main.cpp +++ b/examples/cpu-hello-world/main.cpp @@ -83,7 +83,7 @@ static SlangResult _innerMain(int argc, char** argv) // We would like to request a CPU code that can be executed directly on the host - // which is the 'SLANG_HOST_CALLABLE' target. // If we wanted a just a shared library/dll, we could have used SLANG_SHARED_LIBRARY. - int targetIndex = spAddCodeGenTarget(slangRequest, SLANG_HOST_CALLABLE); + int targetIndex = spAddCodeGenTarget(slangRequest, SLANG_SHADER_HOST_CALLABLE); // Set the target flag to indicate that we want to compile all the entrypoints in the // slang shader file into a library. diff --git a/examples/heterogeneous-hello-world/main.cpp b/examples/heterogeneous-hello-world/main.cpp deleted file mode 100644 index e711d4486..000000000 --- a/examples/heterogeneous-hello-world/main.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// main.cpp - -// This example uses the Slang gfx layer to target different APIs and execute -// both CPU and GPU code from a single Slang file (?) -// -#include <slang.h> -#include <slang-com-ptr.h> -using Slang::ComPtr; - -#include "slang-gfx.h" -#include "gfx-util/shader-cursor.h" -#include "source/core/slang-basic.h" -#include "../../prelude/slang-cpp-types.h" - -using namespace gfx; -using namespace Slang; - -// Creating global ref pointers to avoid dereferencing values -// -ComPtr<gfx::IDevice> gDevice; -ComPtr<gfx::IShaderProgram> gProgram; -ComPtr<gfx::IBufferResource> gBufferResource; -ComPtr<gfx::IResourceView> gResourceView; -ComPtr<gfx::ITransientResourceHeap> gTransientHeap; -ComPtr<gfx::IPipelineState> gPipelineState; -ComPtr<gfx::ICommandQueue> gQueue; - -// Boilerplate types to help the slang-generated file -// -bool executeComputation(); - -// 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. -// -// For convenience, we define a subroutine that will dump the information -// in a diagnostic blob if one is produced, and skip it otherwise. -// -void diagnoseIfNeeded(slang::IBlob *diagnosticsBlob) -{ - if (diagnosticsBlob != nullptr) - { - printf("%s", (const char *)diagnosticsBlob->getBufferPointer()); - } -} - -gfx::IDevice *createDevice() -{ - ComPtr<gfx::IDevice> device; - IDevice::Desc deviceDesc = {}; - // Changing device type would happen here. For example: - //deviceDesc.deviceType = DeviceType::CUDA; - SLANG_RETURN_NULL_ON_FAIL(gfxCreateDevice(&deviceDesc, gDevice.writeRef())); - return gDevice; -} - -// Loads the shader code defined in `shader.slang` for use by the `gfx` layer. -// -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. - // - ComPtr<slang::ISession> slangSession; - SLANG_RETURN_NULL_ON_FAIL(device->getSlangSession(slangSession.writeRef())); - - // 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 - // wrote: - // - // import MyStuff; - // - // In a Slang shader file. The compiler will use its search paths to try to locate - // `MyModule.slang`, then compile and load that file. If a matching module had - // already been loaded previously, that would be used directly. - // - ComPtr<slang::IBlob> diagnosticsBlob; - slang::IModule *module = slangSession->loadModule(moduleName, diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - if (!module) - return NULL; - - // Look up entry point - // - // char const *computeEntryPointName = entryPoint.getBuffer(); - ComPtr<slang::IEntryPoint> computeEntryPoint; - SLANG_RETURN_NULL_ON_FAIL( - 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`. - // - // A single Slang module could contain many different entry points (e.g., - // four vertex entry points, three fragment entry points, and two compute - // shaders), and before we try to generate output code for our target API - // we need to identify which entry points we plan to use together. - // - // Modules and entry points are both examples of *component types* in the - // Slang API. The API also provides a way to build a *composite* out of - // other pieces, and that is what we are going to do with our module - // and entry points. - // - Slang::List<slang::IComponentType *> componentTypes; - componentTypes.add(module); - componentTypes.add(computeEntryPoint); - - // Actually creating the composite component type is a single operation - // on the Slang session, but the operation could potentially fail if - // something about the composite was invalid (e.g., you are trying to - // combine multiple copies of the same module), so we need to deal - // with the possibility of diagnostic output. - // - ComPtr<slang::IComponentType> composedProgram; - SlangResult result = slangSession->createCompositeComponentType( - componentTypes.getBuffer(), - componentTypes.getCount(), - composedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_NULL_ON_FAIL(result); - - // At this point, `composedProgram` represents the shader program - // we want to run, and the compute shader there have been checked. - // We can create a `gfx::IShaderProgram` object from `composedProgram` - // so it may be used by the graphics layer. - gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = composedProgram.get(); - - gProgram = device->createProgram(programDesc); - - return gProgram; -} - -gfx::IBufferResource* createStructuredBuffer(gfx::IDevice* device, FixedArray<float, 4> initialData) -{ - // Create a structured buffer for storing computation data - // - const int numberCount = 4; - int structuredBufferSize = numberCount * sizeof(float); - - IBufferResource::Desc bufferDesc = {}; - bufferDesc.sizeInBytes = numberCount * sizeof(float); - bufferDesc.format = gfx::Format::Unknown; - bufferDesc.elementSize = sizeof(float); - bufferDesc.allowedStates = ResourceStateSet(ResourceState::ShaderResource, - ResourceState::UnorderedAccess, - ResourceState::CopyDestination, - ResourceState::CopySource); - bufferDesc.defaultState = ResourceState::UnorderedAccess; - bufferDesc.memoryType = MemoryType::DeviceLocal; - - SlangResult result = device->createBufferResource(bufferDesc, - (void *)&initialData, - gBufferResource.writeRef()); - SLANG_RETURN_NULL_ON_FAIL(result); - return gBufferResource; -} - -gfx::IResourceView *createBufferView( - gfx::IDevice *device, - gfx::IBufferResource *buffer) -{ - // Create a resource view for the structured buffer - // - gfx::IResourceView::Desc viewDesc = {}; - viewDesc.type = gfx::IResourceView::Type::UnorderedAccess; - viewDesc.format = gfx::Format::Unknown; - SLANG_RETURN_NULL_ON_FAIL(device->createBufferView(buffer, viewDesc, gResourceView.writeRef())); - return gResourceView; -} - -gfx::ITransientResourceHeap *buildTransientHeap(gfx::IDevice *device) -{ - ITransientResourceHeap::Desc transientHeapDesc = {}; - transientHeapDesc.constantBufferSize = 4096; - SLANG_RETURN_NULL_ON_FAIL( - device->createTransientResourceHeap(transientHeapDesc, gTransientHeap.writeRef())); - return gTransientHeap; -} - -gfx::IPipelineState *buildPipelineState( - gfx::IDevice *device, - gfx::IShaderProgram *shaderProgram) -{ - gfx::ComputePipelineStateDesc pipelineDesc = {}; - pipelineDesc.program = shaderProgram; - SLANG_RETURN_NULL_ON_FAIL( - device->createComputePipelineState(pipelineDesc, gPipelineState.writeRef())); - return gPipelineState; -} - -void printInitialValues(FixedArray<float, 4> initialArray, int length) -{ - printf("Before:\n"); - for (int i = 0; i < length; i++) - { - printf("%f, ", initialArray[i]); - } - printf("\n"); -} - -void dispatchComputation( - gfx::IDevice *device, - gfx::ITransientResourceHeap *transientHeap, - gfx::IPipelineState *pipelineState, - gfx::IResourceView *bufferView, - unsigned int gridDimsX, - unsigned int gridDimsY, - unsigned int gridDimsZ) -{ - ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics}; - gQueue = device->createCommandQueue(queueDesc); - - auto commandBuffer = transientHeap->createCommandBuffer(); - auto encoder = commandBuffer->encodeComputeCommands(); - - // First, obtain a root shader object from command encoder to start parameter binding. - auto rootObject = encoder->bindPipeline(pipelineState); - - gfx::ShaderCursor entryPointCursor( - rootObject->getEntryPoint(0)); // get a cursor the the first entry-point. - // Bind buffer view to the entry point. - entryPointCursor.getPath("ioBuffer").setResource(bufferView); - - encoder->dispatchCompute(gridDimsX, gridDimsY, gridDimsZ); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); -} - -bool printOutputValues( - gfx::IDevice *device, - gfx::IBufferResource *buffer, - int length) -{ - ComPtr<ISlangBlob> resultBlob; - SLANG_RETURN_FALSE_ON_FAIL(device->readBufferResource( - buffer, 0, length * sizeof(float), resultBlob.writeRef())); - auto result = reinterpret_cast<const float *>(resultBlob->getBufferPointer()); - printf("After: \n"); - for (int i = 0; i < length; i++) - { - printf("%f, ", result[i]); - } - printf("\n"); - return true; -} - -RWStructuredBuffer<float> convertBuffer(gfx::IBufferResource* _0) { - RWStructuredBuffer<float> result; - result.data = (float*)_0; - return result; -} - -gfx::IBufferResource *unconvertBuffer(RWStructuredBuffer<float> _0) -{ - return (gfx::IBufferResource *)(_0.data); -} - -int main() -{ - // We construct an instance of our example application - // `struct` type, and then walk through the lifecyle - // of the application. - - if (!(executeComputation())) - { - return -1; - } -} diff --git a/examples/heterogeneous-hello-world/main.slang b/examples/heterogeneous-hello-world/main.slang new file mode 100644 index 000000000..08b4b7f39 --- /dev/null +++ b/examples/heterogeneous-hello-world/main.slang @@ -0,0 +1,10 @@ +// main.slang + +__target_intrinsic(cpp, "printf(\"%s\", ($0).getBuffer())") +public void writeln(String text); + +public __extern_cpp int main() +{ + writeln("hello world"); + return 0; +}
\ No newline at end of file diff --git a/examples/heterogeneous-hello-world/shader.slang b/examples/heterogeneous-hello-world/shader.slang deleted file mode 100644 index d87370be1..000000000 --- a/examples/heterogeneous-hello-world/shader.slang +++ /dev/null @@ -1,76 +0,0 @@ -// shader.slang - -//TEST_INPUT:ubuffer(random(float, 4096, -1.0, 1.0), stride=4):name=ioBuffer -__unmangled __exportDirectly RWStructuredBuffer<float> convertBuffer(Ptr<gfx::IBufferResource> x); - -[shader("compute")] -[numthreads(4, 1, 1)] -void computeMain(uniform RWStructuredBuffer<float> ioBuffer, uint3 dispatchThreadID : SV_DispatchThreadID) -{ - uint tid = dispatchThreadID.x; - - float i = ioBuffer[tid]; - float o = i < 0.5 ? (i + i) : sqrt(i); - - ioBuffer[tid] = o; -} - - - -// Forward declarations of gfx types -// -namespace gfx { - __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 -// -__unmangled __exportDirectly Ptr<gfx::IDevice> createDevice(); -__unmangled __exportDirectly Ptr<gfx::IShaderProgram> loadShaderProgram( - Ptr<gfx::IDevice> device, - String entryPoint, - String module); -__unmangled __exportDirectly Ptr<gfx::IBufferResource> createStructuredBuffer( - Ptr<gfx::IDevice> device, - float[4] initialData); -__unmangled __exportDirectly Ptr<gfx::IResourceView> createBufferView( - Ptr<gfx::IDevice> device, - Ptr<gfx::IBufferResource> buffer); -__unmangled __exportDirectly Ptr<gfx::ITransientResourceHeap> buildTransientHeap( - Ptr<gfx::IDevice> device); -__unmangled __exportDirectly Ptr<gfx::IPipelineState> buildPipelineState( - Ptr<gfx::IDevice> device, - Ptr<gfx::IShaderProgram> shaderProgram); -__unmangled __exportDirectly void printInitialValues(float[4] initialArray, int length); -__unmangled __exportDirectly void dispatchComputation( - Ptr<gfx::IDevice> device, - Ptr<gfx::ITransientResourceHeap> transientHeap, - Ptr<gfx::IPipelineState> pipelineState, - Ptr<gfx::IResourceView> bufferView); -__unmangled __exportDirectly bool printOutputValues( - Ptr<gfx::IDevice> device, - Ptr<gfx::IBufferResource> buffer, - int length); - -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 }; - - // Declare functions - let device = createDevice(); - let structuredBuffer = createStructuredBuffer(device, initialArray); - // let bufferView = createBufferView(device, structuredBuffer); - __GPU_FOREACH(device, uint3(4, 1, 1), LAMBDA(uint3 dispatchThreadID) - { computeMain(convertBuffer(structuredBuffer), dispatchThreadID) ; }); - printInitialValues(initialArray, 4); - printOutputValues(device, structuredBuffer, 4); - - - return true; -} |
