yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
13dd01489
master
1#include "test-base.h" 2 3#ifdef _WIN32 4// clang-format off 5// include ordering sensitive 6# include <windows.h> 7# include <shellapi.h> 8# include <io.h> 9# include <fcntl.h> 10// clang-format on 11#include <iostream> 12#include <string> 13#endif 14 15static rhi::DeviceType parseApiString (const char * apiStr ) 16{ 17static const struct 18 { 19const char * name ; 20 rhi::DeviceType type ; 21 }apiTable []= { 22#ifdef _WIN32 23 {"d3d11" , rhi::DeviceType ::D3D11 }, 24 {"d3d12" , rhi::DeviceType ::D3D12 }, 25#endif 26 {"vulkan" , rhi::DeviceType ::Vulkan }, 27#ifdef __APPLE__ 28 {"metal" , rhi::DeviceType ::Metal }, 29#endif 30 {"cpu" , rhi::DeviceType ::CPU }, 31 {"cuda" , rhi::DeviceType ::CUDA }, 32 {"webgpu" , rhi::DeviceType ::WGPU }}; 33 34for (auto & api :apiTable ) 35 { 36if (strcmp (apiStr ,api .name )== 0 ) 37 { 38return api .type ; 39 } 40 } 41return rhi::DeviceType ::Default ;// Invalid/unknown 42} 43 44#ifdef _WIN32 45static std::string wstringToString (const std::wstring & wstr ) 46{ 47char buffer [256 ]; 48wcstombs (buffer ,wstr .c_str (),sizeof (buffer )); 49return std::string (buffer ); 50} 51#endif 52 53// Simple output function that works for both console and WIN32 apps 54static void printOutput (const char * text ) 55{ 56printf ("%s" ,text ); 57#ifdef _WIN32 58OutputDebugStringA (text ); 59#endif 60} 61 62#ifdef _WIN32 63// For WIN32 apps, allocate a console window to show help text 64static bool ensureConsoleVisible () 65{ 66// Check if we already have a console (running from cmd.exe or already allocated) 67if (GetConsoleWindow ()!= NULL ) 68 { 69// We already have a console, just use it 70return false;// No new window created 71 } 72 73// Check if stdout is connected to a console or redirected 74HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE ); 75if (hStdOut != INVALID_HANDLE_VALUE ) 76 { 77DWORD fileType = GetFileType (hStdOut ); 78switch (fileType ) 79 { 80case FILE_TYPE_CHAR :// Console 81case FILE_TYPE_DISK :// File redirection 82case FILE_TYPE_PIPE :// Pipe redirection 83// Output goes to console or is redirected, don't create a console 84return false; 85 } 86// FILE_TYPE_UNKNOWN or other cases: proceed to create console 87 } 88 89// No console exists and output isn't redirected, so allocate a new one 90if (AllocConsole ()) 91 { 92// Redirect stdout to the console 93freopen_s ((FILE ** )stdout ,"CONOUT$" ,"w" ,stdout ); 94freopen_s ((FILE ** )stderr ,"CONOUT$" ,"w" ,stderr ); 95freopen_s ((FILE ** )stdin ,"CONIN$" ,"r" ,stdin ); 96 97// Make sure cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 98// point to console as well 99 std::ios::sync_with_stdio (true); 100 101// Set console title 102SetConsoleTitleA ("Triangle Example - Help" ); 103return true;// New window was created 104 } 105 106return false;// Failed to create console 107} 108#endif 109 110int TestBase ::parseOption (int argc ,char ** argv ) 111{ 112// Parse command line arguments for help, API selection, and test mode 113#ifdef _WIN32 114wchar_t ** szArglist ; 115szArglist = CommandLineToArgvW (GetCommandLineW (),& argc ); 116#endif 117 118for (int i = 0 ;i < argc ;i ++ ) 119 { 120#ifdef _WIN32 121 std::string arg = wstringToString (szArglist [i ]); 122#else 123 std::string arg = argv [i ]; 124#endif 125 126if (arg == "--test-mode" || arg == "-test-mode" ) 127 { 128m_isTestMode = true; 129 } 130else if (arg == "-h" || arg == "--help" ) 131 { 132m_showHelp = true; 133 } 134else if ((arg == "-api" || arg == "--api" )&& i + 1 < argc ) 135 { 136i ++ ;// Move to the next argument which should be the API name 137#ifdef _WIN32 138 std::string apiStr = wstringToString (szArglist [i ]); 139#else 140 std::string apiStr = argv [i ]; 141#endif 142 143 rhi::DeviceType newType = parseApiString (apiStr .c_str ()); 144if (newType != rhi::DeviceType ::Default ) 145 { 146m_deviceType = newType ; 147 } 148else 149 { 150#ifdef _WIN32 151// For WIN32 apps, ensure we have a visible console window for errors too 152ensureConsoleVisible (); 153#endif 154 std::string errorMsg = "Unknown API: " + apiStr + "\n" ; 155printOutput (errorMsg .c_str ()); 156m_showHelp = true; 157 } 158 } 159 } 160 161#ifdef _WIN32 162LocalFree (szArglist ); 163#endif 164 165return 0 ; 166} 167 168void TestBase ::printEntrypointHashes ( 169int entryPointCount , 170int targetCount , 171ComPtr < slang::IComponentType >& composedProgram ) 172{ 173for (int targetIndex = 0 ;targetIndex < targetCount ;targetIndex ++ ) 174 { 175for (int entryPointIndex = 0 ;entryPointIndex < entryPointCount ;entryPointIndex ++ ) 176 { 177ComPtr < slang::IBlob > entryPointHashBlob ; 178composedProgram -> getEntryPointHash ( 179entryPointIndex , 180targetIndex , 181entryPointHashBlob .writeRef ()); 182 183Slang ::StringBuilder strBuilder ; 184strBuilder <<"callIdx: " <<m_globalCounter <<", entrypoint: " <<entryPointIndex 185 <<", target: " <<targetIndex <<", hash: " ; 186m_globalCounter ++ ; 187 188uint8_t * buffer = (uint8_t * )entryPointHashBlob -> getBufferPointer (); 189for (size_t i = 0 ;i < entryPointHashBlob -> getBufferSize ();i ++ ) 190 { 191strBuilder <<Slang ::StringUtil ::makeStringWithFormat ("%.2X" ,buffer [i ]); 192 } 193fprintf (stdout ,"%s\n" ,strBuilder .begin ()); 194 } 195 } 196} 197 198void TestBase ::printUsage (const char * programName )const 199{ 200#ifdef _WIN32 201// For WIN32 apps, ensure we have a visible console window 202bool createdNewWindow = ensureConsoleVisible (); 203#endif 204 205// Use printOutput to ensure output appears in both console and debug output (for WIN32 apps) 206 std::string usage = "Usage: " + std::string (programName )+ " [options]\n\n" ; 207printOutput (usage .c_str ()); 208printOutput ("Options:\n" ); 209printOutput (" -h, --help Show this help message\n" ); 210printOutput (" -api (" ); 211#ifdef _WIN32 212printOutput ("d3d11|d3d12|" ); 213#endif 214printOutput ("vulkan" ); 215#ifdef __APPLE__ 216printOutput ("|metal" ); 217#endif 218printOutput ("|cpu|cuda|webgpu)\n" ); 219#ifdef _WIN32 220printOutput (" Use a given rendering API (Default: d3d12)\n" ); 221#elif defined(__APPLE__ ) 222printOutput (" Use a given rendering API (Default: metal)\n" ); 223#else 224printOutput (" Use a given rendering API (Default: vulkan)\n" ); 225#endif 226printOutput (" -test-mode Print hash values of compiled shader entry points " 227"and skip rendering\n" ); 228printOutput ("\n" ); 229printOutput ("Supported APIs:\n" ); 230#ifdef _WIN32 231printOutput (" d3d11 - Direct3D 11\n" ); 232printOutput (" d3d12 - Direct3D 12\n" ); 233#endif 234printOutput (" vulkan - Vulkan\n" ); 235#ifdef __APPLE__ 236printOutput (" metal - Metal (macOS/iOS)\n" ); 237#endif 238printOutput (" cpu - CPU execution\n" ); 239printOutput (" cuda - CUDA\n" ); 240printOutput (" webgpu - WebGPU\n" ); 241 242#ifdef _WIN32 243// For WIN32 apps, only prompt if we created a new console window 244if (createdNewWindow ) 245 { 246printOutput ("\nPress Enter to continue or close this window...\n" ); 247getchar ();// Wait for user input 248 } 249#endif 250}