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{ 12static Slang ::Result loadProgram ( 13 rhi::IDevice * device , 14Slang ::ComPtr < rhi::IShaderProgram >& outShaderProgram , 15const char * shaderModuleName , 16const char * entryPointName , 17 slang::ProgramLayout *& slangReflection , 18const char * additionalModuleSource ) 19{ 20Slang ::ComPtr < slang::ISession > slangSession ; 21SLANG_RETURN_ON_FAIL (device -> getSlangSession (slangSession .writeRef ())); 22Slang ::ComPtr < slang::IBlob > diagnosticsBlob ; 23 slang::IModule * module = slangSession -> loadModule (shaderModuleName ,diagnosticsBlob .writeRef ()); 24diagnoseIfNeeded (diagnosticsBlob ); 25if (!module ) 26return SLANG_FAIL ; 27 28auto additionalModuleBlob = 29Slang ::UnownedRawBlob ::create (additionalModuleSource ,strlen (additionalModuleSource )); 30 slang::IModule * additionalModule = 31slangSession -> loadModuleFromSource ("linkedConstants" ,"path" ,additionalModuleBlob ); 32 33ComPtr < slang::IEntryPoint > computeEntryPoint ; 34SLANG_RETURN_ON_FAIL ( 35module -> findEntryPointByName (entryPointName ,computeEntryPoint .writeRef ())); 36 37Slang ::List < slang::IComponentType *> componentTypes ; 38componentTypes .add (module ); 39componentTypes .add (computeEntryPoint ); 40componentTypes .add (additionalModule ); 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 ; 52result = composedProgram -> link (linkedProgram .writeRef (),diagnosticsBlob .writeRef ()); 53diagnoseIfNeeded (diagnosticsBlob ); 54SLANG_RETURN_ON_FAIL (result ); 55 56composedProgram = linkedProgram ; 57slangReflection = composedProgram -> getLayout (); 58 59ShaderProgramDesc programDesc = {}; 60programDesc .slangGlobalScope = composedProgram .get (); 61 62auto shaderProgram = device -> createShaderProgram (programDesc ); 63 64outShaderProgram = shaderProgram ; 65return SLANG_OK ; 66} 67 68void linkTimeConstantTestImpl (IDevice * device ,UnitTestContext * context ) 69{ 70ComPtr < IShaderProgram > shaderProgram ; 71 slang::ProgramLayout * slangReflection ; 72GFX_CHECK_CALL_ABORT (loadProgram ( 73device , 74shaderProgram , 75"link-time-constant" , 76"computeMain" , 77slangReflection , 78R"( 79export static const bool turnOnFeature = true; 80export static const float constValue = 2.0; 81export static const uint numthread = 2; 82export static const int arraySize = 4; 83)" )); 84 85SlangUInt threadGroupSizes [3 ]; 86slangReflection -> findEntryPointByName ("computeMain" ) 87-> getComputeThreadGroupSize (3 ,threadGroupSizes ); 88SLANG_CHECK (threadGroupSizes [0 ]== 2 && threadGroupSizes [1 ]== 1 && threadGroupSizes [2 ]== 1 ); 89 90ComputePipelineDesc pipelineDesc = {}; 91pipelineDesc .program = shaderProgram .get (); 92ComPtr < IComputePipeline > pipelineState ; 93GFX_CHECK_CALL_ABORT (device -> createComputePipeline (pipelineDesc ,pipelineState .writeRef ())); 94 95const int numberCount = 4 ; 96float initialData []= {0.0f ,0.0f ,0.0f ,0.0f }; 97BufferDesc bufferDesc = {}; 98bufferDesc .size = numberCount * sizeof (float ); 99bufferDesc .format = rhi::Format ::Undefined ; 100bufferDesc .elementSize = sizeof (float ); 101bufferDesc .usage = BufferUsage ::ShaderResource |BufferUsage ::UnorderedAccess | 102BufferUsage ::CopyDestination |BufferUsage ::CopySource ; 103bufferDesc .defaultState = ResourceState ::UnorderedAccess ; 104bufferDesc .memoryType = MemoryType ::DeviceLocal ; 105 106ComPtr < IBuffer > numbersBuffer ; 107GFX_CHECK_CALL_ABORT ( 108device -> createBuffer (bufferDesc , (void * )initialData ,numbersBuffer .writeRef ())); 109 110// We have done all the set up work, now it is time to start recording a command buffer for 111// GPU execution. 112 { 113auto queue = device -> getQueue (QueueType ::Graphics ); 114auto commandEncoder = queue -> createCommandEncoder (); 115auto encoder = commandEncoder -> beginComputePass (); 116 117auto rootObject = encoder -> bindPipeline (pipelineState ); 118 119ShaderCursor entryPointCursor ( 120rootObject -> getEntryPoint (0 ));// get a cursor the the first entry-point. 121// Bind buffer to the entry point. 122entryPointCursor .getPath ("buffer" ).setBinding (numbersBuffer ); 123 124encoder -> dispatchCompute (1 ,1 ,1 ); 125encoder -> end (); 126queue -> submit (commandEncoder -> finish ()); 127queue -> waitOnHost (); 128 } 129 130compareComputeResult (device ,numbersBuffer , std::array {2.0f }); 131} 132 133SLANG_UNIT_TEST (linkTimeConstantD3D12 ) 134{ 135runTestImpl (linkTimeConstantTestImpl ,unitTestContext ,DeviceType ::D3D12 ); 136} 137 138SLANG_UNIT_TEST (linkTimeConstantVulkan ) 139{ 140runTestImpl (linkTimeConstantTestImpl ,unitTestContext ,DeviceType ::Vulkan ); 141} 142 143}// namespace gfx_test