yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1// cuda-command-queue.cpp 2#include "cuda-command-queue.h" 3 4#include "cuda-buffer.h" 5#include "cuda-command-buffer.h" 6#include "cuda-query.h" 7#include "cuda-shader-object-layout.h" 8 9namespace gfx 10{ 11#ifdef GFX_ENABLE_CUDA 12using namespace Slang ; 13 14namespace cuda 15{ 16 17ICommandQueue * CommandQueueImpl ::getInterface (const Guid & guid ) 18{ 19if (guid == GfxGUID ::IID_ISlangUnknown || guid == GfxGUID ::IID_ICommandQueue ) 20return static_cast < ICommandQueue *> (this ); 21return nullptr ; 22} 23 24void CommandQueueImpl ::init (DeviceImpl * inRenderer ) 25{ 26renderer = inRenderer ; 27m_desc .type = ICommandQueue ::QueueType ::Graphics ; 28cuStreamCreate (& stream ,0 ); 29} 30CommandQueueImpl ::~CommandQueueImpl () 31{ 32cuStreamSynchronize (stream ); 33cuStreamDestroy (stream ); 34currentPipeline = nullptr ; 35currentRootObject = nullptr ; 36} 37 38SLANG_NO_THROW void SLANG_MCALL CommandQueueImpl ::executeCommandBuffers ( 39GfxCount count , 40ICommandBuffer * const * commandBuffers , 41IFence * fence , 42uint64_t valueToSignal ) 43{ 44SLANG_UNUSED (valueToSignal ); 45// TODO: implement fence. 46assert (fence == nullptr ); 47for (GfxIndex i = 0 ;i < count ;i ++ ) 48 { 49execute (static_cast < CommandBufferImpl *> (commandBuffers [i ])); 50 } 51} 52 53SLANG_NO_THROW void SLANG_MCALL CommandQueueImpl ::waitOnHost () 54{ 55auto resultCode = cuStreamSynchronize (stream ); 56if (resultCode != CUDA_SUCCESS ) 57SLANG_CUDA_HANDLE_ERROR (resultCode ); 58} 59 60SLANG_NO_THROW Result SLANG_MCALL CommandQueueImpl ::waitForFenceValuesOnDevice ( 61GfxCount fenceCount , 62IFence ** fences , 63uint64_t * waitValues ) 64{ 65return SLANG_FAIL ; 66} 67 68SLANG_NO_THROW Result SLANG_MCALL CommandQueueImpl ::getNativeHandle (InteropHandle * outHandle ) 69{ 70return SLANG_FAIL ; 71} 72 73void CommandQueueImpl ::setPipelineState (IPipelineState * state ) 74{ 75currentPipeline = dynamic_cast < ComputePipelineStateImpl *> (state ); 76} 77 78Result CommandQueueImpl ::bindRootShaderObject (IShaderObject * object ) 79{ 80currentRootObject = dynamic_cast < RootShaderObjectImpl *> (object ); 81if (currentRootObject ) 82return SLANG_OK ; 83return SLANG_E_INVALID_ARG ; 84} 85 86void CommandQueueImpl ::dispatchCompute (int x ,int y ,int z ) 87{ 88// Specialize the compute kernel based on the shader object bindings. 89RefPtr < PipelineStateBase > newPipeline ; 90renderer -> maybeSpecializePipeline (currentPipeline ,currentRootObject ,newPipeline ); 91currentPipeline = static_cast < ComputePipelineStateImpl *> (newPipeline .Ptr ()); 92 93// Find out thread group size from program reflection. 94auto & kernelName = currentPipeline -> shaderProgram -> kernelName ; 95auto programLayout = static_cast < RootShaderObjectLayoutImpl *> (currentRootObject -> getLayout ()); 96int kernelId = programLayout -> getKernelIndex (kernelName .getUnownedSlice ()); 97SLANG_ASSERT (kernelId != -1 ); 98UInt threadGroupSize [3 ]; 99programLayout -> getKernelThreadGroupSize (kernelId ,threadGroupSize ); 100 101// Copy global parameter data to the `SLANG_globalParams` symbol. 102 { 103CUdeviceptr globalParamsSymbol = 0 ; 104size_t globalParamsSymbolSize = 0 ; 105cuModuleGetGlobal ( 106& globalParamsSymbol , 107& globalParamsSymbolSize , 108currentPipeline -> shaderProgram -> cudaModule , 109"SLANG_globalParams" ); 110 111CUdeviceptr globalParamsCUDAData = (CUdeviceptr )currentRootObject -> getBuffer (); 112cuMemcpyAsync ( 113 (CUdeviceptr )globalParamsSymbol , 114 (CUdeviceptr )globalParamsCUDAData , 115globalParamsSymbolSize , 1160 ); 117 } 118// 119// The argument data for the entry-point parameters are already 120// stored in host memory in a CUDAEntryPointShaderObject, as expected by cuLaunchKernel. 121// 122auto entryPointBuffer = currentRootObject -> entryPointObjects [kernelId ]-> getBuffer (); 123auto entryPointDataSize = currentRootObject -> entryPointObjects [kernelId ]-> getBufferSize (); 124 125void * extraOptions []= { 126CU_LAUNCH_PARAM_BUFFER_POINTER , 127entryPointBuffer , 128CU_LAUNCH_PARAM_BUFFER_SIZE , 129& entryPointDataSize , 130CU_LAUNCH_PARAM_END , 131 }; 132 133// Once we have all the necessary data extracted and/or 134// set up, we can launch the kernel and see what happens. 135// 136auto cudaLaunchResult = cuLaunchKernel ( 137currentPipeline -> shaderProgram -> cudaKernel , 138x , 139y , 140z , 141int (threadGroupSize [0 ]), 142int (threadGroupSize [1 ]), 143int (threadGroupSize [2 ]), 1440 , 145stream , 146nullptr , 147extraOptions ); 148 149SLANG_ASSERT (cudaLaunchResult == CUDA_SUCCESS ); 150} 151 152void CommandQueueImpl ::copyBuffer ( 153IBufferResource * dst , 154size_t dstOffset , 155IBufferResource * src , 156size_t srcOffset , 157size_t size ) 158{ 159auto dstImpl = static_cast < BufferResourceImpl *> (dst ); 160auto srcImpl = static_cast < BufferResourceImpl *> (src ); 161cuMemcpy ( 162 (CUdeviceptr )((uint8_t * )dstImpl -> m_cudaMemory + dstOffset ), 163 (CUdeviceptr )((uint8_t * )srcImpl -> m_cudaMemory + srcOffset ), 164size ); 165} 166 167void CommandQueueImpl ::uploadBufferData ( 168IBufferResource * dst , 169size_t offset , 170size_t size , 171void * data ) 172{ 173auto dstImpl = static_cast < BufferResourceImpl *> (dst ); 174cuMemcpy ((CUdeviceptr )((uint8_t * )dstImpl -> m_cudaMemory + offset ), (CUdeviceptr )data ,size ); 175} 176 177void CommandQueueImpl ::writeTimestamp (IQueryPool * pool ,SlangInt index ) 178{ 179auto poolImpl = static_cast < QueryPoolImpl *> (pool ); 180cuEventRecord (poolImpl -> m_events [index ],stream ); 181} 182 183void CommandQueueImpl ::execute (CommandBufferImpl * commandBuffer ) 184{ 185for (auto & cmd :commandBuffer -> m_commands ) 186 { 187switch (cmd .name ) 188 { 189case CommandName ::SetPipelineState : 190setPipelineState (commandBuffer -> getObject < PipelineStateBase > (cmd .operands [0 ])); 191break ; 192case CommandName ::BindRootShaderObject : 193bindRootShaderObject (commandBuffer -> getObject < ShaderObjectBase > (cmd .operands [0 ])); 194break ; 195case CommandName ::DispatchCompute : 196dispatchCompute (int (cmd .operands [0 ]),int (cmd .operands [1 ]),int (cmd .operands [2 ])); 197break ; 198case CommandName ::CopyBuffer : 199copyBuffer ( 200commandBuffer -> getObject < BufferResource > (cmd .operands [0 ]), 201cmd .operands [1 ], 202commandBuffer -> getObject < BufferResource > (cmd .operands [2 ]), 203cmd .operands [3 ], 204cmd .operands [4 ]); 205break ; 206case CommandName ::UploadBufferData : 207uploadBufferData ( 208commandBuffer -> getObject < BufferResource > (cmd .operands [0 ]), 209cmd .operands [1 ], 210cmd .operands [2 ], 211commandBuffer -> getData < uint8_t > (cmd .operands [3 ])); 212break ; 213case CommandName ::WriteTimestamp : 214writeTimestamp ( 215commandBuffer -> getObject < QueryPoolBase > (cmd .operands [0 ]), 216 (SlangInt )cmd .operands [1 ]); 217 } 218 } 219} 220 221}// namespace cuda 222#endif 223}// namespace gfx