Remove spirv-cross, take HLSL files as shader module input, update vertex format ABI

Caleb Cornett 2022-03-20 18:24:08 -04:00
parent f9f5e91001
commit 33751db045
6 changed files with 91 additions and 317 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "Vulkan-Headers"]
path = Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "SPIRV-Cross"]
path = SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross

View File

@ -79,7 +79,6 @@ target_include_directories(Refresh PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Vulkan-Headers/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Cross>
)
# MinGW builds should statically link libgcc
@ -93,23 +92,6 @@ set_target_properties(Refresh PROPERTIES OUTPUT_NAME "Refresh"
SOVERSION ${LIB_MAJOR_VERSION}
)
# Internal Dependencies
if (BUILD_D3D11)
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_CLI OFF CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_SHARED ON CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_STATIC OFF CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_ENABLE_C_API ON CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_ENABLE_HLSL ON CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_ENABLE_GLSL ON CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_ENABLE_REFLECT ON CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_ENABLE_MSL OFF CACHE "" INTERNAL FORCE)
set(SPIRV_CROSS_ENABLE_CPP OFF CACHE "" INTERNAL FORCE)
add_subdirectory(SPIRV-Cross EXCLUDE_FROM_ALL)
target_link_libraries(Refresh PUBLIC spirv-cross-c-shared)
endif()
# SDL2 Dependency
if (DEFINED SDL2_INCLUDE_DIRS AND DEFINED SDL2_LIBRARIES)
message(STATUS "using pre-defined SDL2 variables SDL2_INCLUDE_DIRS and SDL2_LIBRARIES")

@ -1 +0,0 @@
Subproject commit d5c3bd8b5e7db9e2d7fe809944b47b8f88e1c732

View File

@ -39,8 +39,6 @@
#include <SDL.h>
#include <SDL_syswm.h>
#include <spirv_cross_c.h>
/* Defines */
#define D3D11_DLL "d3d11.dll"
@ -129,7 +127,8 @@ static DXGI_FORMAT RefreshToD3D11_SurfaceFormat[] =
static DXGI_FORMAT RefreshToD3D11_VertexFormat[] =
{
DXGI_FORMAT_R32_FLOAT, /* SINGLE */
DXGI_FORMAT_R32_UINT, /* UINT */
DXGI_FORMAT_R32_FLOAT, /* FLOAT */
DXGI_FORMAT_R32G32_FLOAT, /* VECTOR2 */
DXGI_FORMAT_R32G32B32_FLOAT, /* VECTOR3 */
DXGI_FORMAT_R32G32B32A32_FLOAT, /* VECTOR4 */
@ -328,11 +327,10 @@ typedef struct D3D11CommandBufferPool
typedef struct D3D11ShaderModule
{
spvc_context context;
size_t numEntryPoints;
const spvc_entry_point *entryPoints;
ID3D11DeviceChild **shaders; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */
ID3D10Blob **blobs;
ID3D11DeviceChild *shader; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */
ID3D10Blob *blob;
char *shaderSource;
size_t shaderSourceLength;
} D3D11ShaderModule;
typedef struct D3D11GraphicsPipeline
@ -899,7 +897,8 @@ static uint32_t D3D11_INTERNAL_FindIndexOfVertexBinding(
static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout(
D3D11Renderer *renderer,
Refresh_VertexInputState inputState,
ID3D10Blob *shaderBlob
void *shaderBytes,
size_t shaderByteLength
) {
ID3D11InputLayout *result = NULL;
D3D11_INPUT_ELEMENT_DESC *elementDescs;
@ -942,8 +941,8 @@ static ID3D11InputLayout* D3D11_INTERNAL_FetchInputLayout(
renderer->device,
elementDescs,
inputState.vertexAttributeCount,
(void*) ID3D10Blob_GetBufferPointer(shaderBlob),
ID3D10Blob_GetBufferSize(shaderBlob),
shaderBytes,
shaderByteLength,
&result
);
if (FAILED(res))
@ -975,10 +974,11 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline(
) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData;
D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline*) SDL_malloc(sizeof(D3D11GraphicsPipeline));
D3D11ShaderModule* vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule;
D3D11ShaderModule* fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule;
int32_t vertexShaderIndex, fragmentShaderIndex;
D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule;
D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule;
ID3D10Blob *errorBlob;
int32_t i;
HRESULT res;
/* Color attachments */
pipeline->numColorAttachments = pipelineCreateInfo->attachmentInfo.colorAttachmentCount;
@ -1024,54 +1024,79 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline(
pipelineCreateInfo->rasterizerState
);
/* Vertex Shader + Input Layout */
vertexShaderIndex = -1;
for (i = 0; i < vertShaderModule->numEntryPoints; i += 1)
/* Vertex Shader */
if (vertShaderModule->shader == NULL)
{
if ( vertShaderModule->entryPoints[i].execution_model == SpvExecutionModelVertex &&
SDL_strcmp(vertShaderModule->entryPoints[i].name, pipelineCreateInfo->vertexShaderInfo.entryPointName) == 0 )
{
vertexShaderIndex = i;
break;
}
}
if (vertexShaderIndex == -1)
{
Refresh_LogError(
"Graphics pipeline creation failed! No entry point '%s' exists for the vertex shader!",
pipelineCreateInfo->vertexShaderInfo.entryPointName
res = renderer->D3DCompileFunc(
vertShaderModule->shaderSource,
vertShaderModule->shaderSourceLength,
NULL,
NULL,
NULL,
"main",
"vs_5_0",
0,
0,
&vertShaderModule->blob,
&errorBlob
);
if (FAILED(res))
{
Refresh_LogError("Vertex Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob));
return NULL;
}
res = ID3D11Device_CreateVertexShader(
renderer->device,
ID3D10Blob_GetBufferPointer(vertShaderModule->blob),
ID3D10Blob_GetBufferSize(vertShaderModule->blob),
NULL,
(ID3D11VertexShader**) &vertShaderModule->shader
);
ERROR_CHECK_RETURN("Could not create vertex shader", NULL);
}
pipeline->vertexShader = (ID3D11VertexShader*)vertShaderModule->shader;
/* Input Layout */
pipeline->inputLayout = D3D11_INTERNAL_FetchInputLayout(
renderer,
pipelineCreateInfo->vertexInputState,
vertShaderModule->blobs[vertexShaderIndex]
ID3D10Blob_GetBufferPointer(vertShaderModule->blob),
ID3D10Blob_GetBufferSize(vertShaderModule->blob)
);
pipeline->vertexShader = (ID3D11VertexShader*) vertShaderModule->shaders[vertexShaderIndex];
/* Fragment Shader */
fragmentShaderIndex = -1;
for (i = 0; i < fragShaderModule->numEntryPoints; i += 1)
if (fragShaderModule->shader == NULL)
{
if ( fragShaderModule->entryPoints[i].execution_model == SpvExecutionModelFragment &&
SDL_strcmp(fragShaderModule->entryPoints[i].name, pipelineCreateInfo->fragmentShaderInfo.entryPointName) == 0 )
{
fragmentShaderIndex = i;
break;
}
}
if (fragmentShaderIndex == -1)
{
Refresh_LogError(
"Graphics pipeline creation failed! No entry point '%s' exists for the fragment shader!",
pipelineCreateInfo->vertexShaderInfo.entryPointName
res = renderer->D3DCompileFunc(
fragShaderModule->shaderSource,
fragShaderModule->shaderSourceLength,
NULL,
NULL,
NULL,
"main",
"ps_5_0",
0,
0,
&fragShaderModule->blob,
&errorBlob
);
if (FAILED(res))
{
Refresh_LogError("Fragment Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob));
return NULL;
}
pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shaders[fragmentShaderIndex];
res = ID3D11Device_CreatePixelShader(
renderer->device,
ID3D10Blob_GetBufferPointer(fragShaderModule->blob),
ID3D10Blob_GetBufferSize(fragShaderModule->blob),
NULL,
(ID3D11PixelShader**) &fragShaderModule->shader
);
ERROR_CHECK_RETURN("Could not create pixel shader", NULL);
}
pipeline->fragmentShader = (ID3D11PixelShader*) fragShaderModule->shader;
/* FIXME: Need to create uniform buffers for the shaders */
@ -1090,199 +1115,14 @@ static Refresh_ShaderModule* D3D11_CreateShaderModule(
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo
) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData;
spvc_context context;
spvc_result result;
spvc_parsed_ir parsedIR;
spvc_compiler compiler;
const spvc_entry_point *entryPoints;
size_t numEntryPoints;
spvc_compiler_options compilerOptions;
char *hlslSource;
const char *shaderModel;
ID3DBlob **blobs;
ID3DBlob *errorBlob = NULL;
ID3D11DeviceChild **shaders;
D3D11ShaderModule *shaderModule;
uint32_t i;
HRESULT res;
/* Create the context */
result = spvc_context_create(&context);
if (result != SPVC_SUCCESS)
{
Refresh_LogError("Could not create SPIRV Cross context! Error: %X", result);
return NULL;
}
D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule));
shaderModule->shader = NULL; /* created when binding to a pipeline */
shaderModule->blob = NULL; /* created when binding to a pipeline */
shaderModule->shaderSourceLength = shaderModuleCreateInfo->codeSize;
shaderModule->shaderSource = (char*) SDL_malloc(shaderModule->shaderSourceLength);
SDL_memcpy(shaderModule->shaderSource, shaderModuleCreateInfo->byteCode, shaderModuleCreateInfo->codeSize);
/* Parse the SPIRV input */
result = spvc_context_parse_spirv(
context,
shaderModuleCreateInfo->byteCode,
shaderModuleCreateInfo->codeSize / sizeof(uint32_t), /* word count, not byte length */
&parsedIR
);
if (result != SPVC_SUCCESS)
{
Refresh_LogError("Could not parse SPIRV! Error: %X", result);
spvc_context_destroy(context); /* free all context-related memory */
return NULL;
}
/* Create the cross compiler */
result = spvc_context_create_compiler(
context,
SPVC_BACKEND_HLSL,
parsedIR,
SPVC_CAPTURE_MODE_TAKE_OWNERSHIP,
&compiler
);
if (result != SPVC_SUCCESS)
{
Refresh_LogError("Could not create SPIRV to HLSL cross compiler! Error: %X", result);
spvc_context_destroy(context); /* free all context-related memory */
return NULL;
}
/* Get entry points from the source bytecode */
result = spvc_compiler_get_entry_points(compiler, &entryPoints, &numEntryPoints);
if (result != SPVC_SUCCESS)
{
Refresh_LogError("Could not get SPIRV entry points! Error: %X", result);
spvc_context_destroy(context); /* free all context-related memory */
return NULL;
}
/* Set HLSL cross-compile options (target SM5.0) */
spvc_compiler_create_compiler_options(compiler, &compilerOptions);
spvc_compiler_options_set_uint(
compilerOptions,
SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL,
50 /* shader model 5.0 */
);
spvc_compiler_options_set_bool(
compilerOptions,
SPVC_COMPILER_OPTION_FLIP_VERTEX_Y,
SPVC_TRUE
);
spvc_compiler_install_compiler_options(compiler, compilerOptions);
/* Cross compile to HLSL */
result = spvc_compiler_compile(compiler, &hlslSource);
if (result != SPVC_SUCCESS)
{
Refresh_LogError("Could not cross-compile SPIRV to HLSL! Error: %X", result);
spvc_context_destroy(context); /* free all context-related memory */
return NULL;
}
/* Allocate memory for the D3D11 shader list */
shaders = (ID3D11DeviceChild**) SDL_malloc(numEntryPoints * sizeof(ID3D11DeviceChild*));
blobs = (ID3D10Blob**) SDL_malloc(numEntryPoints * sizeof(ID3D10Blob*));
/* Compile each HLSL entry point into a D3D shader */
for (i = 0; i < numEntryPoints; i += 1)
{
/* Determine the exact shader model to use */
switch (entryPoints[i].execution_model)
{
case SpvExecutionModelVertex:
shaderModel = "vs_5_0";
break;
case SpvExecutionModelFragment:
shaderModel = "ps_5_0";
break;
case SpvExecutionModelGLCompute:
shaderModel = "cs_5_0";
break;
default:
Refresh_LogError(
"Attempting to compile a shader with an unknown execution model: %X",
entryPoints[i].execution_model
);
spvc_context_destroy(context); /* free all context-related memory */
SDL_free(shaders);
return NULL;
}
/* Compile the shader blob */
res = renderer->D3DCompileFunc(
hlslSource,
SDL_strlen(hlslSource),
NULL,
NULL,
NULL,
entryPoints[i].name,
shaderModel,
0,
0,
&blobs[i],
&errorBlob
);
if (FAILED(res))
{
Refresh_LogError(
"D3DCompile failed on HLSL shader with entry point '%s'! Error: %X\nCompiler error message: %s",
entryPoints[i].name,
res,
errorBlob ? (const char*) ID3D10Blob_GetBufferPointer(errorBlob) : "<none>"
);
spvc_context_destroy(context); /* free all context-related memory */
SDL_free(shaders);
return NULL;
}
/* Create the shader from the blob */
switch (entryPoints[i].execution_model)
{
case SpvExecutionModelVertex:
res = ID3D11Device_CreateVertexShader(
renderer->device,
ID3D10Blob_GetBufferPointer(blobs[i]),
ID3D10Blob_GetBufferSize(blobs[i]),
NULL,
(ID3D11VertexShader**) &shaders[i]
);
break;
case SpvExecutionModelFragment:
res = ID3D11Device_CreatePixelShader(
renderer->device,
ID3D10Blob_GetBufferPointer(blobs[i]),
ID3D10Blob_GetBufferSize(blobs[i]),
NULL,
(ID3D11PixelShader**) &shaders[i]
);
break;
case SpvExecutionModelGLCompute:
res = ID3D11Device_CreateComputeShader(
renderer->device,
ID3D10Blob_GetBufferPointer(blobs[i]),
ID3D10Blob_GetBufferSize(blobs[i]),
NULL,
(ID3D11ComputeShader**) &shaders[i]
);
break;
}
if (FAILED(res))
{
Refresh_LogError("D3D11 shader creation failed! Error code: %X", res);
spvc_context_destroy(context); /* free all context-related memory */
SDL_free(shaders);
return NULL;
}
}
/* Create the final shader module object to return */
shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule));
shaderModule->context = context;
shaderModule->entryPoints = entryPoints;
shaderModule->numEntryPoints = numEntryPoints;
shaderModule->shaders = shaders;
shaderModule->blobs = blobs;
return (Refresh_ShaderModule*) shaderModule;
}
@ -1514,21 +1354,10 @@ static void D3D11_QueueDestroyShaderModule(
Refresh_ShaderModule* shaderModule
) {
D3D11ShaderModule *d3dShaderModule = (D3D11ShaderModule*) shaderModule;
uint32_t i;
/* Release the D3D11 shader objects and free the arrays */
for (i = 0; i < d3dShaderModule->numEntryPoints; i += 1)
{
ID3D11DeviceChild_Release(d3dShaderModule->shaders[i]);
ID3D10Blob_Release(d3dShaderModule->blobs[i]);
}
SDL_free(d3dShaderModule->shaders);
SDL_free(d3dShaderModule->blobs);
/* Destroy the SPIRV-Cross context.
* This should destroy the entryPoints list as well.
*/
spvc_context_destroy(d3dShaderModule->context);
ID3D11DeviceChild_Release(d3dShaderModule->shader);
ID3D10Blob_Release(d3dShaderModule->blob);
SDL_free(d3dShaderModule->shaderSource);
SDL_free(d3dShaderModule);
}
static void D3D11_QueueDestroyComputePipeline(

View File

@ -61,8 +61,9 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>REFRESH_DRIVER_D3D11;REFRESH_DRIVER_VULKAN;SPIRV_CROSS_C_API_GLSL;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_REFLECT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\SPIRV-Cross;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>REFRESH_DRIVER_D3D11;REFRESH_DRIVER_VULKAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
@ -73,10 +74,11 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>REFRESH_DRIVER_D3D11;REFRESH_DRIVER_VULKAN;SPIRV_CROSS_C_API_GLSL;SPIRV_CROSS_C_API_HLSL;SPIRV_CROSS_C_API_REFLECT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>REFRESH_DRIVER_D3D11;REFRESH_DRIVER_VULKAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\SPIRV-Cross;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -85,14 +87,6 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\SPIRV-Cross\spirv_cfg.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_cross.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_cross_c.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_cross_parsed_ir.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_glsl.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_hlsl.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_parser.cpp" />
<ClCompile Include="..\SPIRV-Cross\spirv_reflect.cpp" />
<ClCompile Include="..\src\Refresh.c" />
<ClCompile Include="..\src\Refresh_Driver_D3D11.c" />
<ClCompile Include="..\src\Refresh_Driver_Vulkan.c" />

View File

@ -13,30 +13,6 @@
<ClCompile Include="..\src\Refresh_Driver_D3D11.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_cfg.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_cross.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_cross_c.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_cross_parsed_ir.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_glsl.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_hlsl.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_parser.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
<ClCompile Include="..\SPIRV-Cross\spirv_reflect.cpp">
<Filter>Source Files\spirv-cross</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\Refresh.h">
@ -62,8 +38,5 @@
<Filter Include="Source Files">
<UniqueIdentifier>{B2BA146C-CAA1-30BE-B7A9-F8D02673EA0C}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\spirv-cross">
<UniqueIdentifier>{4764626f-fd8b-4a1c-8c20-fd92a1f3cb4b}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>