From 3a7b7cdce3e409ae71b451306924f58edd1e68ee Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Thu, 8 Aug 2024 15:49:38 -0400 Subject: [PATCH] Update to SDL_gpu_shadercross.h --- mojoshader_sdlgpu.c | 4 +- ...gpu_spirvcross.h => SDL_gpu_shadercross.h} | 229 ++++++++++++++++-- 2 files changed, 215 insertions(+), 18 deletions(-) rename spirv/{SDL_gpu_spirvcross.h => SDL_gpu_shadercross.h} (55%) diff --git a/mojoshader_sdlgpu.c b/mojoshader_sdlgpu.c index 71b1422..7ac4088 100644 --- a/mojoshader_sdlgpu.c +++ b/mojoshader_sdlgpu.c @@ -14,8 +14,8 @@ #include -#define SDL_GPU_SPIRVCROSS_IMPLEMENTATION -#include "spirv/SDL_gpu_spirvcross.h" +#define SDL_GPU_SHADERCROSS_IMPLEMENTATION +#include "spirv/SDL_gpu_shadercross.h" /* Max entries for each register file type */ #define MAX_REG_FILE_F 8192 diff --git a/spirv/SDL_gpu_spirvcross.h b/spirv/SDL_gpu_shadercross.h similarity index 55% rename from spirv/SDL_gpu_spirvcross.h rename to spirv/SDL_gpu_shadercross.h index be5ac8c..e0b0a89 100644 --- a/spirv/SDL_gpu_spirvcross.h +++ b/spirv/SDL_gpu_shadercross.h @@ -1,17 +1,193 @@ -#ifndef SDL_GPU_SPIRVCROSS_H -#define SDL_GPU_SPIRVCROSS_H +#ifndef SDL_GPU_SHADERCROSS_H +#define SDL_GPU_SHADERCROSS_H #include +#ifndef SDL_GPU_SHADERCROSS_SPIRVCROSS +#define SDL_GPU_SHADERCROSS_SPIRVCROSS 1 +#endif + +#ifndef SDL_GPU_SHADERCROSS_HLSL +#define SDL_GPU_SHADERCROSS_HLSL 1 +#endif + +#if SDL_GPU_SHADERCROSS_SPIRVCROSS extern void *SDL_CompileFromSPIRV(SDL_GpuDevice *device, void *createInfo, SDL_bool isCompute); +#endif + +#if SDL_GPU_SHADERCROSS_HLSL +extern void *SDL_CompileFromHLSL(SDL_GpuDevice *device, + void *createInfo, + const char *hlslSource, + const char *shaderProfile); +#endif + +#endif /* SDL_GPU_SHADERCROSS_H */ + +#ifdef SDL_GPU_SHADERCROSS_IMPLEMENTATION + +#if SDL_GPU_SHADERCROSS_HLSL + +/* Win32 Type Definitions */ +typedef int HRESULT; +typedef const void *LPCVOID; +typedef size_t SIZE_T; +typedef const char *LPCSTR; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef void *LPVOID; +typedef void *REFIID; /* hack, unused */ +typedef void D3D_SHADER_MACRO; /* hack, unused */ +typedef void ID3DInclude; /* hack, unused */ + +/* Dynamic Library / Linking */ +#ifdef D3DCOMPILER_DLL +#undef D3DCOMPILER_DLL +#endif +#if defined(_WIN32) +#define D3DCOMPILER_DLL "d3dcompiler_47.dll" +#elif defined(__APPLE__) +#define D3DCOMPILER_DLL "libvkd3d-utils.1.dylib" +#else +#define D3DCOMPILER_DLL "libvkd3d-utils.so.1" +#endif + +/* __stdcall declaration, largely taken from vkd3d_windows.h */ +#ifndef _WIN32 +#ifdef __stdcall +#undef __stdcall +#endif +#ifdef __x86_64__ +#define __stdcall __attribute__((ms_abi)) +#else +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || defined(__APPLE__) +#define __stdcall __attribute__((__stdcall__)) __attribute__((__force_align_arg_pointer__)) +#else +#define __stdcall __attribute__((__stdcall__)) +#endif +#endif +#endif + +/* ID3DBlob definition, used by both D3DCompiler and DXCompiler */ +typedef struct ID3DBlob ID3DBlob; +typedef struct ID3DBlobVtbl +{ + HRESULT(__stdcall *QueryInterface) + (ID3DBlob *This, REFIID riid, void **ppvObject); + ULONG(__stdcall *AddRef) + (ID3DBlob *This); + ULONG(__stdcall *Release) + (ID3DBlob *This); + LPVOID(__stdcall *GetBufferPointer) + (ID3DBlob *This); + SIZE_T(__stdcall *GetBufferSize) + (ID3DBlob *This); +} ID3DBlobVtbl; +struct ID3DBlob +{ + const ID3DBlobVtbl *lpVtbl; +}; +#define ID3D10Blob ID3DBlob + +/* D3DCompiler */ +static void *d3dcompiler_dll = NULL; + +typedef HRESULT(__stdcall *pfn_D3DCompile)( + LPCVOID pSrcData, + SIZE_T SrcDataSize, + LPCSTR pSourceName, + const D3D_SHADER_MACRO *pDefines, + ID3DInclude *pInclude, + LPCSTR pEntrypoint, + LPCSTR pTarget, + UINT Flags1, + UINT Flags2, + ID3DBlob **ppCode, + ID3DBlob **ppErrorMsgs); + +static pfn_D3DCompile SDL_D3DCompile = NULL; + +void *SDL_CompileFromHLSL( + SDL_GpuDevice *device, + void *createInfo, + const char *hlslSource, + const char *shaderProfile) +{ + ID3DBlob *blob; + ID3DBlob *errorBlob; + HRESULT ret; + void *result; -#endif /* SDL_GPU_SPIRVCROSS_H */ + /* FIXME: d3dcompiler could probably be loaded in a better spot */ + if (d3dcompiler_dll == NULL) { + d3dcompiler_dll = SDL_LoadObject(D3DCOMPILER_DLL); + if (d3dcompiler_dll == NULL) { + return NULL; + } + } -#ifdef SDL_GPU_SPIRVCROSS_IMPLEMENTATION + if (SDL_D3DCompile == NULL) { + SDL_D3DCompile = (pfn_D3DCompile)SDL_LoadFunction(d3dcompiler_dll, "D3DCompile"); + if (SDL_D3DCompile == NULL) { + return NULL; + } + } + + ret = SDL_D3DCompile( + hlslSource, + SDL_strlen(hlslSource), + NULL, + NULL, + NULL, + ((SDL_GpuShaderCreateInfo *)createInfo)->entryPointName, + shaderProfile, + 0, + 0, + &blob, + &errorBlob); -#include "spirv_cross_c.h" + if (ret < 0) { + SDL_LogError( + SDL_LOG_CATEGORY_GPU, + "HLSL compilation failed: %s", + errorBlob->lpVtbl->GetBufferPointer(errorBlob)); + return NULL; + } + + if (shaderProfile[0] == 'c' && shaderProfile[1] == 's') { + SDL_GpuComputePipelineCreateInfo newCreateInfo; + newCreateInfo = *(SDL_GpuComputePipelineCreateInfo *)createInfo; + newCreateInfo.code = blob->lpVtbl->GetBufferPointer(blob); + newCreateInfo.codeSize = blob->lpVtbl->GetBufferSize(blob); + newCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC; + + result = SDL_GpuCreateComputePipeline(device, &newCreateInfo); + } else { + SDL_GpuShaderCreateInfo newCreateInfo; + newCreateInfo = *(SDL_GpuShaderCreateInfo *)createInfo; + newCreateInfo.code = blob->lpVtbl->GetBufferPointer(blob); + newCreateInfo.codeSize = blob->lpVtbl->GetBufferSize(blob); + newCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC; + + result = SDL_GpuCreateShader(device, &newCreateInfo); + } + + blob->lpVtbl->Release(blob); + + return result; +} + +#endif + +#if SDL_GPU_SHADERCROSS_SPIRVCROSS + +#if !SDL_GPU_SHADERCROSS_HLSL +#error SDL_GPU_SHADERCROSS_HLSL must be enabled for SDL_GPU_SHADERCROSS_SPIRVCROSS! +#endif + +#include #if defined(_WIN32) #define SPIRV_CROSS_DLL "spirv-cross-c-shared.dll" @@ -78,7 +254,7 @@ void *SDL_CompileFromSPIRV( case SDL_GPU_BACKEND_D3D11: case SDL_GPU_BACKEND_D3D12: backend = SPVC_BACKEND_HLSL; - format = SDL_GPU_SHADERFORMAT_HLSL; + format = SDL_GPU_SHADERFORMAT_DXBC; break; case SDL_GPU_BACKEND_METAL: backend = SPVC_BACKEND_MSL; @@ -184,23 +360,42 @@ void *SDL_CompileFromSPIRV( SDL_GpuComputePipelineCreateInfo newCreateInfo; newCreateInfo = *(SDL_GpuComputePipelineCreateInfo *)createInfo; newCreateInfo.format = format; - newCreateInfo.code = (const Uint8 *)translated_source; - newCreateInfo.codeSize = SDL_strlen(translated_source) + 1; newCreateInfo.entryPointName = cleansed_entrypoint; - /* Create the pipeline! */ - compiledResult = SDL_GpuCreateComputePipeline(device, &newCreateInfo); + if (backend == SPVC_BACKEND_HLSL) { + compiledResult = SDL_CompileFromHLSL( + device, + &newCreateInfo, + translated_source, + (shadermodel == 50) ? "cs_5_0" : "cs_5_1"); + } else { + newCreateInfo.code = (const Uint8 *)translated_source; + newCreateInfo.codeSize = SDL_strlen(translated_source) + 1; + compiledResult = SDL_GpuCreateComputePipeline(device, &newCreateInfo); + } } else { - SDL_GpuShaderCreateInfo newCreateInfo; newCreateInfo = *createInfo; newCreateInfo.format = format; - newCreateInfo.code = (const Uint8 *)translated_source; - newCreateInfo.codeSize = SDL_strlen(translated_source) + 1; newCreateInfo.entryPointName = cleansed_entrypoint; - /* Create the shader! */ - compiledResult = SDL_GpuCreateShader(device, &newCreateInfo); + if (backend == SPVC_BACKEND_HLSL) { + const char *profile; + if (newCreateInfo.stage == SDL_GPU_SHADERSTAGE_VERTEX) { + profile = (shadermodel == 50) ? "vs_5_0" : "vs_5_1"; + } else { + profile = (shadermodel == 50) ? "ps_5_0" : "ps_5_1"; + } + compiledResult = SDL_CompileFromHLSL( + device, + &newCreateInfo, + translated_source, + profile); + } else { + newCreateInfo.code = (const Uint8 *)translated_source; + newCreateInfo.codeSize = SDL_strlen(translated_source) + 1; + compiledResult = SDL_GpuCreateShader(device, &newCreateInfo); + } } /* Clean up */ @@ -209,4 +404,6 @@ void *SDL_CompileFromSPIRV( return compiledResult; } -#endif /* SDL_GPU_SPIRVCROSS_IMPLEMENTATION */ +#endif + +#endif /* SDL_GPU_SHADERCROSS_IMPLEMENTATION */