yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
1681bc67f
master
1#include "gfx-test-util.h" 2 3#include "slang-com-ptr.h" 4#include "unit-test/slang-unit-test.h" 5 6#define GFX_ENABLE_RENDERDOC_INTEGRATION 0 7#define GFX_ENABLE_SPIRV_DEBUG 0 8#if GFX_ENABLE_RENDERDOC_INTEGRATION 9#include "external/renderdoc_app.h" 10 11#include <windows.h> 12#endif 13 14using Slang ::ComPtr ; 15 16namespace gfx_test 17{ 18 19void diagnoseIfNeeded (slang::IBlob * diagnosticsBlob ) 20{ 21if (diagnosticsBlob != nullptr ) 22 { 23getTestReporter ()-> message ( 24TestMessageType ::Info , 25 (const char * )diagnosticsBlob -> getBufferPointer ()); 26 } 27} 28 29Result loadComputeProgram ( 30IDevice * device , 31ComPtr < IShaderProgram >& outShaderProgram , 32const char * shaderModuleName , 33const char * entryPointName , 34 slang::ProgramLayout *& slangReflection ) 35{ 36ComPtr < slang::ISession > slangSession ; 37SLANG_RETURN_ON_FAIL (device -> getSlangSession (slangSession .writeRef ())); 38ComPtr < slang::IBlob > diagnosticsBlob ; 39 slang::IModule * module = slangSession -> loadModule (shaderModuleName ,diagnosticsBlob .writeRef ()); 40diagnoseIfNeeded (diagnosticsBlob ); 41if (!module ) 42return SLANG_FAIL ; 43 44ComPtr < slang::IEntryPoint > computeEntryPoint ; 45SLANG_RETURN_ON_FAIL ( 46module -> findEntryPointByName (entryPointName ,computeEntryPoint .writeRef ())); 47 48 std::vector < slang::IComponentType *> componentTypes ; 49componentTypes .push_back (module ); 50componentTypes .push_back (computeEntryPoint ); 51 52ComPtr < slang::IComponentType > composedProgram ; 53Result result = slangSession -> createCompositeComponentType ( 54componentTypes .data (), 55componentTypes .size (), 56composedProgram .writeRef (), 57diagnosticsBlob .writeRef ()); 58diagnoseIfNeeded (diagnosticsBlob ); 59SLANG_RETURN_ON_FAIL (result ); 60 61ComPtr < slang::IComponentType > linkedProgram ; 62result = composedProgram -> link (linkedProgram .writeRef (),diagnosticsBlob .writeRef ()); 63diagnoseIfNeeded (diagnosticsBlob ); 64SLANG_RETURN_ON_FAIL (result ); 65 66slangReflection = linkedProgram -> getLayout (); 67outShaderProgram = device -> createShaderProgram (linkedProgram ,diagnosticsBlob .writeRef ()); 68diagnoseIfNeeded (diagnosticsBlob ); 69return outShaderProgram ?SLANG_OK :SLANG_FAIL ; 70} 71 72Result loadComputeProgram ( 73IDevice * device , 74 slang::ISession * slangSession , 75ComPtr < IShaderProgram >& outShaderProgram , 76const char * shaderModuleName , 77const char * entryPointName , 78 slang::ProgramLayout *& slangReflection ) 79{ 80ComPtr < slang::IBlob > diagnosticsBlob ; 81 slang::IModule * module = slangSession -> loadModule (shaderModuleName ,diagnosticsBlob .writeRef ()); 82diagnoseIfNeeded (diagnosticsBlob ); 83if (!module ) 84return SLANG_FAIL ; 85 86ComPtr < slang::IEntryPoint > computeEntryPoint ; 87SLANG_RETURN_ON_FAIL ( 88module -> findEntryPointByName (entryPointName ,computeEntryPoint .writeRef ())); 89 90 std::vector < slang::IComponentType *> componentTypes ; 91componentTypes .push_back (module ); 92componentTypes .push_back (computeEntryPoint ); 93 94ComPtr < slang::IComponentType > composedProgram ; 95Result result = slangSession -> createCompositeComponentType ( 96componentTypes .data (), 97componentTypes .size (), 98composedProgram .writeRef (), 99diagnosticsBlob .writeRef ()); 100diagnoseIfNeeded (diagnosticsBlob ); 101SLANG_RETURN_ON_FAIL (result ); 102 103ComPtr < slang::IComponentType > linkedProgram ; 104result = composedProgram -> link (linkedProgram .writeRef (),diagnosticsBlob .writeRef ()); 105diagnoseIfNeeded (diagnosticsBlob ); 106SLANG_RETURN_ON_FAIL (result ); 107 108slangReflection = linkedProgram -> getLayout (); 109outShaderProgram = device -> createShaderProgram (linkedProgram ,diagnosticsBlob .writeRef ()); 110diagnoseIfNeeded (diagnosticsBlob ); 111return outShaderProgram ?SLANG_OK :SLANG_FAIL ; 112} 113 114Result loadComputeProgramFromSource ( 115IDevice * device , 116ComPtr < IShaderProgram >& outShaderProgram , 117 std::string_view source ) 118{ 119auto slangSession = device -> getSlangSession (); 120 slang::IModule * module = nullptr ; 121ComPtr < slang::IBlob > diagnosticsBlob ; 122size_t hash = std::hash < std::string_view > ()(source ); 123 std::string moduleName = "source_module_" + std::to_string (hash ); 124auto srcBlob = Slang ::UnownedRawBlob ::create (source .data (),source .size ()); 125module = slangSession -> loadModuleFromSource ( 126moduleName .data (), 127moduleName .data (), 128srcBlob , 129diagnosticsBlob .writeRef ()); 130diagnoseIfNeeded (diagnosticsBlob ); 131if (!module ) 132return SLANG_FAIL ; 133 134 std::vector < ComPtr < slang::IComponentType >> componentTypes ; 135componentTypes .push_back (ComPtr < slang::IComponentType > (module )); 136 137for (SlangInt32 i = 0 ;i < module -> getDefinedEntryPointCount ();i ++ ) 138 { 139ComPtr < slang::IEntryPoint > entryPoint ; 140SLANG_RETURN_ON_FAIL (module -> getDefinedEntryPoint (i ,entryPoint .writeRef ())); 141componentTypes .push_back (ComPtr < slang::IComponentType > (entryPoint .get ())); 142 } 143 144 std::vector < slang::IComponentType *> rawComponentTypes ; 145for (auto & compType :componentTypes ) 146rawComponentTypes .push_back (compType .get ()); 147 148ComPtr < slang::IComponentType > linkedProgram ; 149Result result = slangSession -> createCompositeComponentType ( 150rawComponentTypes .data (), 151rawComponentTypes .size (), 152linkedProgram .writeRef (), 153diagnosticsBlob .writeRef ()); 154diagnoseIfNeeded (diagnosticsBlob ); 155SLANG_RETURN_ON_FAIL (result ); 156 157outShaderProgram = device -> createShaderProgram (linkedProgram ,diagnosticsBlob .writeRef ()); 158diagnoseIfNeeded (diagnosticsBlob ); 159return outShaderProgram ?SLANG_OK :SLANG_FAIL ; 160} 161 162Result loadGraphicsProgram ( 163IDevice * device , 164ComPtr < IShaderProgram >& outShaderProgram , 165const char * shaderModuleName , 166const char * vertexEntryPointName , 167const char * fragmentEntryPointName , 168 slang::ProgramLayout *& slangReflection ) 169{ 170ComPtr < slang::ISession > slangSession ; 171SLANG_RETURN_ON_FAIL (device -> getSlangSession (slangSession .writeRef ())); 172ComPtr < slang::IBlob > diagnosticsBlob ; 173 slang::IModule * module = slangSession -> loadModule (shaderModuleName ,diagnosticsBlob .writeRef ()); 174diagnoseIfNeeded (diagnosticsBlob ); 175if (!module ) 176return SLANG_FAIL ; 177 178ComPtr < slang::IEntryPoint > vertexEntryPoint ; 179SLANG_RETURN_ON_FAIL ( 180module -> findEntryPointByName (vertexEntryPointName ,vertexEntryPoint .writeRef ())); 181 182ComPtr < slang::IEntryPoint > fragmentEntryPoint ; 183SLANG_RETURN_ON_FAIL ( 184module -> findEntryPointByName (fragmentEntryPointName ,fragmentEntryPoint .writeRef ())); 185 186 std::vector < slang::IComponentType *> componentTypes ; 187componentTypes .push_back (module ); 188componentTypes .push_back (vertexEntryPoint ); 189componentTypes .push_back (fragmentEntryPoint ); 190 191ComPtr < slang::IComponentType > composedProgram ; 192Result result = slangSession -> createCompositeComponentType ( 193componentTypes .data (), 194componentTypes .size (), 195composedProgram .writeRef (), 196diagnosticsBlob .writeRef ()); 197diagnoseIfNeeded (diagnosticsBlob ); 198SLANG_RETURN_ON_FAIL (result ); 199 200ComPtr < slang::IComponentType > linkedProgram ; 201result = composedProgram -> link (linkedProgram .writeRef (),diagnosticsBlob .writeRef ()); 202diagnoseIfNeeded (diagnosticsBlob ); 203SLANG_RETURN_ON_FAIL (result ); 204 205slangReflection = linkedProgram -> getLayout (); 206outShaderProgram = device -> createShaderProgram (linkedProgram ,diagnosticsBlob .writeRef ()); 207diagnoseIfNeeded (diagnosticsBlob ); 208return outShaderProgram ?SLANG_OK :SLANG_FAIL ; 209} 210 211Slang ::ComPtr < IDevice > createTestingDevice ( 212UnitTestContext * context , 213DeviceType deviceType , 214Slang ::List < const char *> additionalSearchPaths ) 215{ 216Slang ::ComPtr < IDevice > device ; 217DeviceDesc deviceDesc = {}; 218deviceDesc .deviceType = deviceType ; 219 220deviceDesc .slang .slangGlobalSession = context -> slangGlobalSession ; 221Slang ::List < const char *> searchPaths = getSlangSearchPaths (); 222searchPaths .addRange (additionalSearchPaths ); 223deviceDesc .slang .searchPaths = searchPaths .getBuffer (); 224deviceDesc .slang .searchPathCount = searchPaths .getCount (); 225 226 std::vector < slang::PreprocessorMacroDesc > preprocessorMacros ; 227 std::vector < slang::CompilerOptionEntry > compilerOptions ; 228 229 slang::CompilerOptionEntry emitSpirvDirectlyEntry ; 230emitSpirvDirectlyEntry .name = slang::CompilerOptionName ::EmitSpirvDirectly ; 231emitSpirvDirectlyEntry .value .intValue0 = 1 ; 232compilerOptions .push_back (emitSpirvDirectlyEntry ); 233#if DEBUG_SPIRV 234 slang::CompilerOptionEntry debugLevelCompilerOptionEntry = {}; 235debugLevelCompilerOptionEntry .name = slang::CompilerOptionName ::DebugInformation ; 236debugLevelCompilerOptionEntry .value .intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD ; 237compilerOptions .push_back (debugLevelCompilerOptionEntry ); 238#endif 239#if DUMP_INTERMEDIATES 240 slang::CompilerOptionEntry dumpIntermediatesOptionEntry = {}; 241dumpIntermediatesOptionEntry .name = slang::CompilerOptionName ::DumpIntermediates ; 242dumpIntermediatesOptionEntry .value .intValue0 = 1 ; 243compilerOptions .push_back (dumpIntermediatesOptionEntry ); 244#endif 245 246deviceDesc .slang .preprocessorMacros = preprocessorMacros .data (); 247deviceDesc .slang .preprocessorMacroCount = preprocessorMacros .size (); 248deviceDesc .slang .compilerOptionEntries = compilerOptions .data (); 249deviceDesc .slang .compilerOptionEntryCount = compilerOptions .size (); 250 251if (context -> enableDebugLayers ) 252 { 253deviceDesc .enableValidation = context -> enableDebugLayers ; 254deviceDesc .debugCallback = context -> debugCallback ; 255getRHI ()-> enableDebugLayers (); 256 } 257 258D3D12DeviceExtendedDesc extDesc = {}; 259if (deviceType == DeviceType ::D3D12 ) 260 { 261extDesc .rootParameterShaderAttributeName = "root" ; 262deviceDesc .next = & extDesc ; 263 } 264 265auto createDeviceResult = getRHI ()-> createDevice (deviceDesc ,device .writeRef ()); 266if (SLANG_FAILED (createDeviceResult )) 267 { 268SLANG_IGNORE_TEST 269 } 270return device ; 271} 272 273Slang ::List < const char *> getSlangSearchPaths () 274{ 275Slang ::List < const char *> searchPaths ; 276searchPaths .add ("" ); 277searchPaths .add ("../../tools/gfx-unit-test" ); 278searchPaths .add ("tools/gfx-unit-test" ); 279return searchPaths ; 280} 281 282#if GFX_ENABLE_RENDERDOC_INTEGRATION 283RENDERDOC_API_1_1_2 * rdoc_api = NULL ; 284void initializeRenderDoc () 285{ 286if (HMODULE mod = GetModuleHandleA ("renderdoc.dll" )) 287 { 288pRENDERDOC_GetAPI RENDERDOC_GetAPI = 289 (pRENDERDOC_GetAPI )GetProcAddress (mod ,"RENDERDOC_GetAPI" ); 290int ret = RENDERDOC_GetAPI (eRENDERDOC_API_Version_1_1_2 , (void ** )& rdoc_api ); 291assert (ret == 1 ); 292 } 293} 294void renderDocBeginFrame () 295{ 296if (!rdoc_api ) 297initializeRenderDoc (); 298if (rdoc_api ) 299rdoc_api -> StartFrameCapture (nullptr ,nullptr ); 300} 301void renderDocEndFrame () 302{ 303if (rdoc_api ) 304rdoc_api -> EndFrameCapture (nullptr ,nullptr ); 305_fgetchar (); 306} 307#else 308void initializeRenderDoc () {} 309void renderDocBeginFrame () {} 310void renderDocEndFrame () {} 311#endif 312}// namespace gfx_test