yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
43d0c2100
master
1#include "core/slang-basic.h" 2#include "core/slang-blob.h" 3#include "gfx-test-util.h" 4#include "slang-rhi.h" 5#include "slang-rhi/shader-cursor.h" 6#include "unit-test/slang-unit-test.h" 7 8using namespace rhi ; 9 10namespace gfx_test 11{ 12// In this test, 13// we will run a compute shader that compiles to HLSL with a reference to the macro 14// "DOWNSTREAM_VALUE" that will be provided to dxc through slang's link-time compiler options. The 15// test verifies that `IComponentType2::linkWithOptions()` is able to produce a linked 16// IComponentType with additional compiler options. Here we will specify a DownstreamArg compiler 17// option to define the value of DOWNSTREAM_VALUE when running dxc. 18// 19static Slang ::Result loadProgram ( 20 rhi::IDevice * device , 21Slang ::ComPtr < rhi::IShaderProgram >& outShaderProgram , 22const char * shaderModuleName , 23const char * entryPointName , 24 slang::ProgramLayout *& slangReflection ) 25{ 26Slang ::ComPtr < slang::ISession > slangSession ; 27SLANG_RETURN_ON_FAIL (device -> getSlangSession (slangSession .writeRef ())); 28Slang ::ComPtr < slang::IBlob > diagnosticsBlob ; 29 slang::IModule * module = slangSession -> loadModule (shaderModuleName ,diagnosticsBlob .writeRef ()); 30diagnoseIfNeeded (diagnosticsBlob ); 31if (!module ) 32return SLANG_FAIL ; 33 34ComPtr < slang::IEntryPoint > computeEntryPoint ; 35SLANG_RETURN_ON_FAIL ( 36module -> findEntryPointByName (entryPointName ,computeEntryPoint .writeRef ())); 37 38Slang ::List < slang::IComponentType *> componentTypes ; 39componentTypes .add (module ); 40componentTypes .add (computeEntryPoint ); 41 42Slang ::ComPtr < slang::IComponentType > composedProgram ; 43SlangResult result = slangSession -> createCompositeComponentType ( 44componentTypes .getBuffer (), 45componentTypes .getCount (), 46composedProgram .writeRef (), 47diagnosticsBlob .writeRef ()); 48diagnoseIfNeeded (diagnosticsBlob ); 49SLANG_RETURN_ON_FAIL (result ); 50 51ComPtr < slang::IComponentType > linkedProgram ; 52 slang::CompilerOptionEntry entry ; 53entry .name = slang::CompilerOptionName ::DownstreamArgs ; 54entry .value .kind = slang::CompilerOptionValueKind ::String ; 55entry .value .stringValue0 = "dxc" ; 56entry .value .stringValue1 = "-DDOWNSTREAM_VALUE=4.0" ; 57result = composedProgram 58-> linkWithOptions (linkedProgram .writeRef (),1 ,& entry ,diagnosticsBlob .writeRef ()); 59diagnoseIfNeeded (diagnosticsBlob ); 60SLANG_RETURN_ON_FAIL (result ); 61 62composedProgram = linkedProgram ; 63slangReflection = composedProgram -> getLayout (); 64 65ShaderProgramDesc programDesc = {}; 66programDesc .slangGlobalScope = composedProgram .get (); 67 68auto shaderProgram = device -> createShaderProgram (programDesc ); 69 70outShaderProgram = shaderProgram ; 71return SLANG_OK ; 72} 73 74void linkTimeOptionTestImpl (IDevice * device ,UnitTestContext * context ) 75{ 76ComPtr < IShaderProgram > shaderProgram ; 77 slang::ProgramLayout * slangReflection ; 78GFX_CHECK_CALL_ABORT ( 79loadProgram (device ,shaderProgram ,"link-time-options" ,"computeMain" ,slangReflection )); 80 81ComputePipelineDesc pipelineDesc = {}; 82pipelineDesc .program = shaderProgram .get (); 83ComPtr < IComputePipeline > pipelineState ; 84GFX_CHECK_CALL_ABORT (device -> createComputePipeline (pipelineDesc ,pipelineState .writeRef ())); 85 86const int numberCount = 4 ; 87float initialData []= {0.0f ,0.0f ,0.0f ,0.0f }; 88BufferDesc bufferDesc = {}; 89bufferDesc .size = numberCount * sizeof (float ); 90bufferDesc .format = rhi::Format ::Undefined ; 91bufferDesc .elementSize = sizeof (float ); 92bufferDesc .usage = BufferUsage ::ShaderResource |BufferUsage ::UnorderedAccess | 93BufferUsage ::CopyDestination |BufferUsage ::CopySource ; 94bufferDesc .defaultState = ResourceState ::UnorderedAccess ; 95bufferDesc .memoryType = MemoryType ::DeviceLocal ; 96 97ComPtr < IBuffer > numbersBuffer ; 98GFX_CHECK_CALL_ABORT ( 99device -> createBuffer (bufferDesc , (void * )initialData ,numbersBuffer .writeRef ())); 100 101// We have done all the set up work, now it is time to start recording a command buffer for 102// GPU execution. 103 { 104auto queue = device -> getQueue (QueueType ::Graphics ); 105auto commandEncoder = queue -> createCommandEncoder (); 106auto computePassEncoder = commandEncoder -> beginComputePass (); 107 108auto rootObject = computePassEncoder -> bindPipeline (pipelineState ); 109 110ShaderCursor entryPointCursor ( 111rootObject -> getEntryPoint (0 ));// get a cursor the the first entry-point. 112// Bind buffer to the entry point. 113entryPointCursor .getPath ("buffer" ).setBinding (Binding (numbersBuffer )); 114 115computePassEncoder -> dispatchCompute (1 ,1 ,1 ); 116computePassEncoder -> end (); 117auto commandBuffer = commandEncoder -> finish (); 118queue -> submit (commandBuffer ); 119queue -> waitOnHost (); 120 } 121 122compareComputeResult (device ,numbersBuffer , std::array {4.0f }); 123} 124 125SLANG_UNIT_TEST (linkTimeOptionD3D12 ) 126{ 127runTestImpl (linkTimeOptionTestImpl ,unitTestContext ,DeviceType ::D3D12 ); 128} 129}// namespace gfx_test