Add shader type to the .refresh shader bytecode format

d3d11
Caleb Cornett 2024-02-11 00:07:01 -06:00 committed by cosmonaut
parent c497402f1d
commit 7274173b44
6 changed files with 134 additions and 130 deletions

View File

@ -194,6 +194,17 @@ partial class Program
// Magic // Magic
writer.Write(new char[] { 'R', 'F', 'S', 'H'}); writer.Write(new char[] { 'R', 'F', 'S', 'H'});
// Type
uint shaderTypeIndex;
switch (shaderType)
{
default:
case ".vert": shaderTypeIndex = 0; break;
case ".frag": shaderTypeIndex = 1; break;
case ".comp": shaderTypeIndex = 2; break;
}
writer.Write(shaderTypeIndex);
if (data.vulkan) if (data.vulkan)
{ {
string inputPath = Path.Combine(tempDir, $"{shaderName}.spv"); string inputPath = Path.Combine(tempDir, $"{shaderName}.spv");

View File

@ -242,7 +242,7 @@ Refresh_ShaderModule* Refresh_CreateShaderModule(
Refresh_Device *device, Refresh_Device *device,
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo
) { ) {
Refresh_ShaderModuleCreateInfo driverSpecificCreateInfo = { 0, NULL }; Refresh_Driver_ShaderModuleCreateInfo driverSpecificCreateInfo = { 0, NULL, 0 };
uint8_t *bytes; uint8_t *bytes;
uint32_t i, size; uint32_t i, size;
@ -252,12 +252,24 @@ Refresh_ShaderModule* Refresh_CreateShaderModule(
bytes = (uint8_t*) shaderModuleCreateInfo->byteCode; bytes = (uint8_t*) shaderModuleCreateInfo->byteCode;
if (bytes[0] != 'R' || bytes[1] != 'F' || bytes[2] != 'S' || bytes[3] != 'H') if (bytes[0] != 'R' || bytes[1] != 'F' || bytes[2] != 'S' || bytes[3] != 'H')
{ {
Refresh_LogError("Cannot parse malformed Refresh shader blob!"); Refresh_LogError("Cannot parse malformed Refresh shader blob: Incorrect magic number");
return NULL;
}
/* get the type of shader */
driverSpecificCreateInfo.type = (Refresh_Driver_ShaderType) *((uint32_t*) &bytes[4]);
if ( driverSpecificCreateInfo.type < 0 ||
driverSpecificCreateInfo.type > REFRESH_DRIVER_SHADERTYPE_COMPUTE )
{
Refresh_LogError(
"Cannot parse malformed Refresh shader blob: Unknown shader type (%d)",
driverSpecificCreateInfo.type
);
return NULL; return NULL;
} }
/* find the code for the selected backend */ /* find the code for the selected backend */
i = 4; i = 8;
while (i < shaderModuleCreateInfo->codeSize) while (i < shaderModuleCreateInfo->codeSize)
{ {
size = *((uint32_t*) &bytes[i + 1]); size = *((uint32_t*) &bytes[i + 1]);
@ -1074,9 +1086,7 @@ int Refresh_QueryFence(
Refresh_Device *device, Refresh_Device *device,
Refresh_Fence *fence Refresh_Fence *fence
) { ) {
if (device == NULL) { if (device == NULL) { return 0; }
return 0;
}
return device->QueryFence( return device->QueryFence(
device->driverData, device->driverData,

View File

@ -211,6 +211,22 @@ static inline int32_t BytesPerImage(
#define MAX_COLOR_TARGET_BINDINGS 4 #define MAX_COLOR_TARGET_BINDINGS 4
#define MAX_PRESENT_COUNT 16 #define MAX_PRESENT_COUNT 16
/* Internal Shader Module Create Info */
typedef enum Refresh_Driver_ShaderType
{
REFRESH_DRIVER_SHADERTYPE_VERTEX,
REFRESH_DRIVER_SHADERTYPE_FRAGMENT,
REFRESH_DRIVER_SHADERTYPE_COMPUTE
} Refresh_Driver_ShaderType;
typedef struct Refresh_Driver_ShaderModuleCreateInfo
{
size_t codeSize;
const uint32_t* byteCode;
Refresh_Driver_ShaderType type;
} Refresh_Driver_ShaderModuleCreateInfo;
/* Refresh_Device Definition */ /* Refresh_Device Definition */
typedef struct Refresh_Renderer Refresh_Renderer; typedef struct Refresh_Renderer Refresh_Renderer;
@ -240,7 +256,7 @@ struct Refresh_Device
Refresh_ShaderModule* (*CreateShaderModule)( Refresh_ShaderModule* (*CreateShaderModule)(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo
); );
Refresh_Texture* (*CreateTexture)( Refresh_Texture* (*CreateTexture)(

View File

@ -397,8 +397,6 @@ typedef struct D3D11ShaderModule
{ {
ID3D11DeviceChild *shader; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */ ID3D11DeviceChild *shader; /* ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader */
ID3D10Blob *blob; ID3D10Blob *blob;
char *shaderSource;
size_t shaderSourceLength;
} D3D11ShaderModule; } D3D11ShaderModule;
typedef struct D3D11GraphicsPipeline typedef struct D3D11GraphicsPipeline
@ -1183,44 +1181,8 @@ static Refresh_ComputePipeline* D3D11_CreateComputePipeline(
) { ) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11Renderer *renderer = (D3D11Renderer*) driverData;
D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule; D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) computeShaderInfo->shaderModule;
ID3D10Blob *errorBlob;
D3D11ComputePipeline *pipeline;
HRESULT res;
/* First, compile the shader since we didn't do that when creating the shader module */ D3D11ComputePipeline *pipeline = SDL_malloc(sizeof(D3D11ComputePipeline));
if (shaderModule->shader == NULL)
{
res = renderer->D3DCompileFunc(
shaderModule->shaderSource,
shaderModule->shaderSourceLength,
NULL,
NULL,
NULL,
"main",
"cs_5_0",
0,
0,
&shaderModule->blob,
&errorBlob
);
if (FAILED(res))
{
Refresh_LogError("Compute Shader Compile Error: %s", ID3D10Blob_GetBufferPointer(errorBlob));
return NULL;
}
res = ID3D11Device_CreateComputeShader(
renderer->device,
ID3D10Blob_GetBufferPointer(shaderModule->blob),
ID3D10Blob_GetBufferSize(shaderModule->blob),
NULL,
(ID3D11ComputeShader**) &shaderModule->shader
);
ERROR_CHECK_RETURN("Could not create compute shader", NULL);
}
/* Allocate and set up the pipeline */
pipeline = SDL_malloc(sizeof(D3D11ComputePipeline));
pipeline->numTextures = computeShaderInfo->imageBindingCount; pipeline->numTextures = computeShaderInfo->imageBindingCount;
pipeline->numBuffers = computeShaderInfo->bufferBindingCount; pipeline->numBuffers = computeShaderInfo->bufferBindingCount;
pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader; pipeline->computeShader = (ID3D11ComputeShader*) shaderModule->shader;
@ -1239,75 +1201,8 @@ static Refresh_GraphicsPipeline* D3D11_CreateGraphicsPipeline(
D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11Renderer *renderer = (D3D11Renderer*) driverData;
D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule; D3D11ShaderModule *vertShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule;
D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule; D3D11ShaderModule *fragShaderModule = (D3D11ShaderModule*) pipelineCreateInfo->fragmentShaderInfo.shaderModule;
ID3D10Blob *errorBlob;
D3D11GraphicsPipeline *pipeline;
HRESULT res;
/* First, compile the shaders since we didn't do that when creating the shader modules */ D3D11GraphicsPipeline *pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline));
if (vertShaderModule->shader == NULL)
{
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);
}
if (fragShaderModule->shader == NULL)
{
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;
}
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);
}
/* Allocate and set up the pipeline */
pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline));
/* Blend */ /* Blend */
@ -1454,23 +1349,96 @@ static Refresh_Sampler* D3D11_CreateSampler(
static Refresh_ShaderModule* D3D11_CreateShaderModule( static Refresh_ShaderModule* D3D11_CreateShaderModule(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo
) { ) {
D3D11Renderer *renderer = (D3D11Renderer*) driverData; D3D11Renderer *renderer = (D3D11Renderer*) driverData;
D3D11ShaderModule *shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule)); D3D11ShaderModule* shaderModule;
Refresh_Driver_ShaderType shaderType = shaderModuleCreateInfo->type;
const char *profileNames[] = { "vs_5_0", "ps_5_0", "cs_5_0" };
ID3D10Blob *blob, *errorBlob;
ID3D11DeviceChild *shader = NULL;
HRESULT res;
/* We don't know whether this is a vertex, fragment, or compute shader, /* Compile HLSL to DXBC */
* so wait to compile until we bind to a pipeline... res = renderer->D3DCompileFunc(
* shaderModuleCreateInfo->byteCode,
* FIXME: Could we store a flag in the shaderc output to mark if a shader is vertex/fragment/compute? shaderModuleCreateInfo->codeSize,
* Then we could compile on shader module creation instead of at bind time. NULL,
*/ NULL,
shaderModule->shader = NULL; NULL,
shaderModule->blob = NULL; "main", /* API FIXME: Intentionally ignoring entryPointName because it MUST be "main" anyway */
profileNames[shaderType],
0,
0,
&blob,
&errorBlob
);
if (FAILED(res))
{
Refresh_LogError(
"D3DCompile Error (%s): %s",
profileNames[shaderType],
ID3D10Blob_GetBufferPointer(errorBlob)
);
ID3D10Blob_Release(errorBlob);
return NULL;
}
shaderModule->shaderSourceLength = shaderModuleCreateInfo->codeSize; /* Actually create the shader */
shaderModule->shaderSource = (char*) SDL_malloc(shaderModule->shaderSourceLength); if (shaderType == REFRESH_DRIVER_SHADERTYPE_VERTEX)
SDL_memcpy(shaderModule->shaderSource, shaderModuleCreateInfo->byteCode, shaderModuleCreateInfo->codeSize); {
res = ID3D11Device_CreateVertexShader(
renderer->device,
ID3D10Blob_GetBufferPointer(blob),
ID3D10Blob_GetBufferSize(blob),
NULL,
(ID3D11VertexShader**) &shader
);
if (FAILED(res))
{
D3D11_INTERNAL_LogError(renderer->device, "Could not compile vertex shader", res);
ID3D10Blob_Release(blob);
return NULL;
}
}
else if (shaderType == REFRESH_DRIVER_SHADERTYPE_FRAGMENT)
{
res = ID3D11Device_CreatePixelShader(
renderer->device,
ID3D10Blob_GetBufferPointer(blob),
ID3D10Blob_GetBufferSize(blob),
NULL,
(ID3D11PixelShader**) &shader
);
if (FAILED(res))
{
D3D11_INTERNAL_LogError(renderer->device, "Could not compile pixel shader", res);
ID3D10Blob_Release(blob);
return NULL;
}
}
else if (shaderType == REFRESH_DRIVER_SHADERTYPE_COMPUTE)
{
res = ID3D11Device_CreateComputeShader(
renderer->device,
ID3D10Blob_GetBufferPointer(blob),
ID3D10Blob_GetBufferSize(blob),
NULL,
(ID3D11ComputeShader**) &shader
);
if (FAILED(res))
{
D3D11_INTERNAL_LogError(renderer->device, "Could not compile compute shader", res);
ID3D10Blob_Release(blob);
return NULL;
}
}
/* Allocate and set up the shader module */
shaderModule = (D3D11ShaderModule*) SDL_malloc(sizeof(D3D11ShaderModule));
shaderModule->shader = shader;
shaderModule->blob = blob;
return (Refresh_ShaderModule*) shaderModule; return (Refresh_ShaderModule*) shaderModule;
} }
@ -2440,7 +2408,6 @@ static void D3D11_QueueDestroyShaderModule(
ID3D10Blob_Release(d3dShaderModule->blob); ID3D10Blob_Release(d3dShaderModule->blob);
} }
SDL_free(d3dShaderModule->shaderSource);
SDL_free(d3dShaderModule); SDL_free(d3dShaderModule);
} }

View File

@ -318,7 +318,7 @@ static Refresh_Sampler* TEMPLATE_CreateSampler(
static Refresh_ShaderModule* TEMPLATE_CreateShaderModule( static Refresh_ShaderModule* TEMPLATE_CreateShaderModule(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo
) { ) {
NOT_IMPLEMENTED NOT_IMPLEMENTED
} }

View File

@ -6670,7 +6670,7 @@ static Refresh_Sampler* VULKAN_CreateSampler(
static Refresh_ShaderModule* VULKAN_CreateShaderModule( static Refresh_ShaderModule* VULKAN_CreateShaderModule(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_ShaderModuleCreateInfo *shaderModuleCreateInfo Refresh_Driver_ShaderModuleCreateInfo *shaderModuleCreateInfo
) { ) {
VulkanShaderModule *vulkanShaderModule = SDL_malloc(sizeof(VulkanShaderModule)); VulkanShaderModule *vulkanShaderModule = SDL_malloc(sizeof(VulkanShaderModule));
VkResult vulkanResult; VkResult vulkanResult;