shader include handler
This commit is contained in:
parent
7c1eae3b8c
commit
a1fcf2ce08
4
res/shaders/common.hlsl
Normal file
4
res/shaders/common.hlsl
Normal file
@ -0,0 +1,4 @@
|
||||
float4 linear_from_srgb(float4 srgb)
|
||||
{
|
||||
return float4(pow(srgb.rgb, 2.2), srgb.a);
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
#include "res/shaders/common.hlsl"
|
||||
|
||||
struct vs_input {
|
||||
float4 pos : POSITION;
|
||||
float line_thickness : THICKNESS;
|
||||
@ -27,11 +29,6 @@ cbuffer vs_constants : register(b0)
|
||||
float4x4 projection;
|
||||
};
|
||||
|
||||
float4 linear_from_srgb(float4 srgb)
|
||||
{
|
||||
return float4(pow(srgb.rgb, 2.2), srgb.a);
|
||||
}
|
||||
|
||||
ps_input vs_main(vs_input input)
|
||||
{
|
||||
ps_input output;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#include "res/shaders/common.hlsl"
|
||||
|
||||
struct {
|
||||
SamplerState sampler0;
|
||||
Texture2D texture0;
|
||||
@ -20,11 +22,6 @@ struct ps_input {
|
||||
float4 tint_lin : COLOR;
|
||||
};
|
||||
|
||||
float4 linear_from_srgb(float4 srgb)
|
||||
{
|
||||
return float4(pow(srgb.rgb, 2.2), srgb.a);
|
||||
}
|
||||
|
||||
ps_input vs_main(vs_input input)
|
||||
{
|
||||
ps_input output;
|
||||
|
||||
@ -32,12 +32,12 @@
|
||||
/* FIXME: Enable this and resolve unreleased references */
|
||||
#if RTC
|
||||
# define D3D11_DEBUG 0
|
||||
# define D3D11_SHADER_DEBUG 1
|
||||
#else
|
||||
# define D3D11_DEBUG 0
|
||||
# define D3D11_SHADER_DEBUG 0
|
||||
#endif
|
||||
|
||||
#define D3D11_SHADER_DEBUG RTC
|
||||
|
||||
#define D3D11_SWAPCHAIN_FLAGS (DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)
|
||||
|
||||
#define D3D11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM)
|
||||
@ -209,206 +209,14 @@ INTERNAL void send_constant_buffer_data(ID3D11Buffer *buffer, struct mat4x4 vp)
|
||||
ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)buffer, 0);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Shader
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void init_shader_table(void)
|
||||
{
|
||||
MEMZERO_ARRAY(G.shader_info);
|
||||
|
||||
/* Triangle shader layout */
|
||||
G.shader_info[SHADER_TRIANGLE] = (struct dx11_shader_desc) {
|
||||
.kind = SHADER_TRIANGLE,
|
||||
.name_cstr = "res/shaders/triangle.hlsl",
|
||||
.vertex_size = sizeof(struct triangle_shader_vertex),
|
||||
.input_layout_desc = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
/* Grid shader layout */
|
||||
G.shader_info[SHADER_GRID] = (struct dx11_shader_desc) {
|
||||
.kind = SHADER_GRID,
|
||||
.name_cstr = "res/shaders/grid.hlsl",
|
||||
.vertex_size = sizeof(struct grid_shader_vertex),
|
||||
.input_layout_desc = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "THICKNESS", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "SPACING", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "OFFSET", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 3, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 4, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
G.shader_info_lookup = dict_init(&G.arena, SHADER_INFO_LOOKUP_BINS);
|
||||
for (u64 i = SHADER_NONE + 1; i < ARRAY_COUNT(G.shader_info); ++i) {
|
||||
struct dx11_shader_desc *desc = &G.shader_info[i];
|
||||
struct string name = string_from_cstr_no_limit(desc->name_cstr);
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
dict_set(&G.arena, &G.shader_info_lookup, hash, desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* If shader compilation fails, then error string is returned allocated on `arena` */
|
||||
INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *shader, struct dx11_shader_desc *shader_desc, struct resource *src_res)
|
||||
{
|
||||
__prof;
|
||||
struct temp_arena scratch = scratch_begin(arena);
|
||||
struct string error_str = ZI;
|
||||
|
||||
shader->kind = shader_desc->kind;
|
||||
shader->vertex_size = shader_desc->vertex_size;
|
||||
|
||||
u32 flags = D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
|
||||
#if D3D11_SHADER_DEBUG
|
||||
flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS;
|
||||
#else
|
||||
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
|
||||
/* Compile shader */
|
||||
ID3DBlob *vs_blob = NULL;
|
||||
ID3DBlob *ps_blob = NULL;
|
||||
ID3DBlob *error_blob = NULL;
|
||||
b32 success = false;
|
||||
{
|
||||
struct string shader_src = resource_get_data(src_res);
|
||||
logf_info("Compiling shader \"%F\"", FMT_STR(resource_get_name(src_res)));
|
||||
/* Compile shader */
|
||||
/* TODO: pre-compile shaders w/ FXC? */
|
||||
HRESULT hr = D3DCompile(shader_src.text, shader_src.len, NULL, NULL, NULL, "vs_main", "vs_5_0", flags, 0, &vs_blob, &error_blob);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ID3D11Device_CreateVertexShader(G.dev, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), NULL, &shader->vs);
|
||||
hr = D3DCompile(shader_src.text, shader_src.len, NULL, NULL, NULL, "ps_main", "ps_5_0", flags, 0, &ps_blob, &error_blob);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ID3D11Device_CreatePixelShader(G.dev, ID3D10Blob_GetBufferPointer(ps_blob), ID3D10Blob_GetBufferSize(ps_blob), NULL, &shader->ps);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success && !error_blob) {
|
||||
/* Get number of device layout elements from NULL terminated array */
|
||||
u32 elem_count = 0;
|
||||
for (; elem_count < ARRAY_COUNT(shader_desc->input_layout_desc); ++elem_count) {
|
||||
const D3D11_INPUT_ELEMENT_DESC *d = &shader_desc->input_layout_desc[elem_count];
|
||||
if (d->SemanticName == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create device layout */
|
||||
ID3D11Device_CreateInputLayout(G.dev, shader_desc->input_layout_desc, elem_count, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), &shader->input_layout);
|
||||
} else {
|
||||
error_str = LIT("Unknown error");
|
||||
if (error_blob) {
|
||||
u64 error_blob_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
||||
char *error_blob_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
||||
struct string error_blob_str = string_copy(arena, string_from_cstr(error_blob_cstr, error_blob_cstr_len));
|
||||
if (string_ends_with(error_blob_str, LIT("\n"))) {
|
||||
/* Remove trailing newline */
|
||||
error_blob_str.len -= 1;
|
||||
}
|
||||
if (error_blob_str.len > 0) {
|
||||
error_str = error_blob_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vs_blob) {
|
||||
ID3D10Blob_Release(vs_blob);
|
||||
}
|
||||
if (ps_blob) {
|
||||
ID3D10Blob_Release(ps_blob);
|
||||
}
|
||||
if (error_blob) {
|
||||
ID3D10Blob_Release(error_blob);
|
||||
}
|
||||
|
||||
shader->valid = true;
|
||||
|
||||
scratch_end(scratch);
|
||||
return error_str;
|
||||
}
|
||||
|
||||
INTERNAL void shader_release(struct dx11_shader *shader)
|
||||
{
|
||||
__prof;
|
||||
if (shader->vs) {
|
||||
ID3D11VertexShader_Release(shader->vs);
|
||||
}
|
||||
if (shader->ps) {
|
||||
ID3D11PixelShader_Release(shader->ps);
|
||||
}
|
||||
if (shader->input_layout) {
|
||||
ID3D11InputLayout_Release(shader->input_layout);
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_desc *desc)
|
||||
{
|
||||
__prof;
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
{
|
||||
struct string name = string_from_cstr_no_limit(desc->name_cstr);
|
||||
struct string error_msg = ZI;
|
||||
if (resource_exists(name)) {
|
||||
struct resource src_res = resource_open(name);
|
||||
{
|
||||
struct dx11_shader new_shader = ZI;
|
||||
struct string comp_error = shader_alloc(scratch.arena, &new_shader, desc, &src_res);
|
||||
if (comp_error.len == 0) {
|
||||
if (old_shader->valid) {
|
||||
shader_release(old_shader);
|
||||
}
|
||||
*old_shader = new_shader;
|
||||
} else {
|
||||
error_msg = string_format(scratch.arena,
|
||||
LIT("Failed to compile shader \"%F\":\n%F"),
|
||||
FMT_STR(name),
|
||||
FMT_STR(comp_error));
|
||||
shader_release(&new_shader);
|
||||
}
|
||||
}
|
||||
resource_close(&src_res);
|
||||
} else {
|
||||
error_msg = string_format(scratch.arena, LIT("Could not find shader \"%F\""), FMT_STR(name));
|
||||
}
|
||||
if (error_msg.len != 0) {
|
||||
if (old_shader->valid) {
|
||||
/* If shader failed to load but a working shader already exists, just error rather than panicking */
|
||||
log_error(error_msg);
|
||||
} else {
|
||||
sys_panic(error_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name)
|
||||
{
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
struct dx11_shader_desc *desc = (struct dx11_shader_desc *)dict_get(&G.shader_info_lookup, hash);
|
||||
if (desc) {
|
||||
logf_info("Shader source file \"%F\" has changed", FMT_STR(name));
|
||||
atomic_i32_eval_exchange(&desc->should_reload, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void init_shader_table(void);
|
||||
INTERNAL void reload_shader(struct dx11_shader *shader, struct dx11_shader_desc *desc);
|
||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name);
|
||||
|
||||
struct renderer_startup_receipt renderer_startup(struct sys_window *window)
|
||||
{
|
||||
__profscope(initializing_d3d11);
|
||||
@ -632,6 +440,284 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window)
|
||||
return (struct renderer_startup_receipt) { 0 };
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Shader table
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void init_shader_table(void)
|
||||
{
|
||||
MEMZERO_ARRAY(G.shader_info);
|
||||
|
||||
/* Triangle shader layout */
|
||||
G.shader_info[SHADER_TRIANGLE] = (struct dx11_shader_desc) {
|
||||
.kind = SHADER_TRIANGLE,
|
||||
.name_cstr = "res/shaders/triangle.hlsl",
|
||||
.vertex_size = sizeof(struct triangle_shader_vertex),
|
||||
.input_layout_desc = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
/* Grid shader layout */
|
||||
G.shader_info[SHADER_GRID] = (struct dx11_shader_desc) {
|
||||
.kind = SHADER_GRID,
|
||||
.name_cstr = "res/shaders/grid.hlsl",
|
||||
.vertex_size = sizeof(struct grid_shader_vertex),
|
||||
.input_layout_desc = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "THICKNESS", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "SPACING", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "OFFSET", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 3, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 4, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
G.shader_info_lookup = dict_init(&G.arena, SHADER_INFO_LOOKUP_BINS);
|
||||
for (u64 i = SHADER_NONE + 1; i < ARRAY_COUNT(G.shader_info); ++i) {
|
||||
struct dx11_shader_desc *desc = &G.shader_info[i];
|
||||
struct string name = string_from_cstr_no_limit(desc->name_cstr);
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
dict_set(&G.arena, &G.shader_info_lookup, hash, desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Shader compilation
|
||||
* ========================== */
|
||||
|
||||
/* TODO: Multithread shader compilation */
|
||||
|
||||
#define DX11_MAX_INCLUDES 64
|
||||
|
||||
struct dx11_include_handler {
|
||||
ID3DInclude d3d_handler;
|
||||
ID3DIncludeVtbl vtbl;
|
||||
struct string error;
|
||||
b32 has_open_resource;
|
||||
struct resource res;
|
||||
};
|
||||
|
||||
INTERNAL HRESULT dx11_include_open(ID3DInclude *d3d_handler, D3D_INCLUDE_TYPE include_type, LPCSTR path_cstr, LPCVOID parent_data, LPCVOID *data_out, UINT *data_len_out)
|
||||
{
|
||||
__prof;
|
||||
(UNUSED)include_type;
|
||||
(UNUSED)parent_data;
|
||||
struct dx11_include_handler *handler = (struct dx11_include_handler *)d3d_handler;
|
||||
|
||||
if (handler->has_open_resource) {
|
||||
sys_panic(LIT("D3d include handler somehow already has a resource open"));
|
||||
}
|
||||
|
||||
struct string path = string_from_cstr_no_limit((char *)path_cstr);
|
||||
if (resource_exists(path)) {
|
||||
handler->has_open_resource = true;
|
||||
struct resource *res = &handler->res;
|
||||
*res = resource_open(path);
|
||||
struct string data = resource_get_data(res);
|
||||
*data_out = data.text;
|
||||
*data_len_out = data.len;
|
||||
return S_OK;
|
||||
} else {
|
||||
handler->error = LIT("Resource not found.");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
INTERNAL HRESULT dx11_include_close(ID3DInclude *d3d_handler, LPCVOID data)
|
||||
{
|
||||
__prof;
|
||||
(UNUSED)data;
|
||||
struct dx11_include_handler *handler = (struct dx11_include_handler *)d3d_handler;
|
||||
if (handler->has_open_resource) {
|
||||
resource_close(&handler->res);
|
||||
handler->has_open_resource = false;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
INTERNAL struct dx11_include_handler dx11_include_handler_alloc(void)
|
||||
{
|
||||
struct dx11_include_handler handler = ZI;
|
||||
handler.d3d_handler.lpVtbl = &handler.vtbl;
|
||||
handler.vtbl.Open = dx11_include_open;
|
||||
handler.vtbl.Close = dx11_include_close;
|
||||
return handler;
|
||||
}
|
||||
|
||||
INTERNAL void dx11_include_handler_release(struct dx11_include_handler *handler)
|
||||
{
|
||||
if (handler->has_open_resource) {
|
||||
ASSERT(false); /* Resource should have been closed by handler by now */
|
||||
resource_close(&handler->res);
|
||||
}
|
||||
}
|
||||
|
||||
/* If shader compilation fails, then error string is returned allocated on `arena` */
|
||||
INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *shader, struct dx11_shader_desc *shader_desc, struct resource *src_res)
|
||||
{
|
||||
__prof;
|
||||
struct temp_arena scratch = scratch_begin(arena);
|
||||
struct dx11_include_handler vs_include_handler = dx11_include_handler_alloc();
|
||||
struct dx11_include_handler ps_include_handler = dx11_include_handler_alloc();
|
||||
struct string error_str = ZI;
|
||||
|
||||
shader->kind = shader_desc->kind;
|
||||
shader->vertex_size = shader_desc->vertex_size;
|
||||
|
||||
u32 flags = D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
|
||||
#if D3D11_SHADER_DEBUG
|
||||
flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS;
|
||||
#else
|
||||
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
|
||||
/* Compile shader */
|
||||
ID3DBlob *vs_blob = NULL;
|
||||
ID3DBlob *ps_blob = NULL;
|
||||
ID3DBlob *error_blob = NULL;
|
||||
b32 success = false;
|
||||
{
|
||||
struct string shader_src = resource_get_data(src_res);
|
||||
logf_info("Compiling shader \"%F\"", FMT_STR(resource_get_name(src_res)));
|
||||
/* Compile shader */
|
||||
/* TODO: pre-compile shaders w/ FXC? */
|
||||
HRESULT hr = D3DCompile(shader_src.text, shader_src.len, NULL, NULL, (ID3DInclude *)&vs_include_handler, "vs_main", "vs_5_0", flags, 0, &vs_blob, &error_blob);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ID3D11Device_CreateVertexShader(G.dev, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), NULL, &shader->vs);
|
||||
hr = D3DCompile(shader_src.text, shader_src.len, NULL, NULL, (ID3DInclude *)&ps_include_handler, "ps_main", "ps_5_0", flags, 0, &ps_blob, &error_blob);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ID3D11Device_CreatePixelShader(G.dev, ID3D10Blob_GetBufferPointer(ps_blob), ID3D10Blob_GetBufferSize(ps_blob), NULL, &shader->ps);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success && !error_blob) {
|
||||
/* Get number of device layout elements from NULL terminated array */
|
||||
u32 elem_count = 0;
|
||||
for (; elem_count < ARRAY_COUNT(shader_desc->input_layout_desc); ++elem_count) {
|
||||
const D3D11_INPUT_ELEMENT_DESC *d = &shader_desc->input_layout_desc[elem_count];
|
||||
if (d->SemanticName == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create device layout */
|
||||
ID3D11Device_CreateInputLayout(G.dev, shader_desc->input_layout_desc, elem_count, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), &shader->input_layout);
|
||||
} else {
|
||||
error_str = LIT("Unknown error");
|
||||
if (error_blob) {
|
||||
u64 error_blob_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
||||
char *error_blob_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
||||
struct string error_blob_str = string_copy(scratch.arena, string_from_cstr(error_blob_cstr, error_blob_cstr_len));
|
||||
if (string_ends_with(error_blob_str, LIT("\n"))) {
|
||||
/* Remove trailing newline */
|
||||
error_blob_str.len -= 1;
|
||||
}
|
||||
if (error_blob_str.len > 0) {
|
||||
struct string include_error = vs_include_handler.error.len > 0 ? vs_include_handler.error : ps_include_handler.error;
|
||||
if (include_error.len > 0) {
|
||||
error_str = string_format(arena, LIT("%F %F"), FMT_STR(error_blob_str), FMT_STR(include_error));
|
||||
} else {
|
||||
error_str = string_copy(arena, error_blob_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vs_blob) {
|
||||
ID3D10Blob_Release(vs_blob);
|
||||
}
|
||||
if (ps_blob) {
|
||||
ID3D10Blob_Release(ps_blob);
|
||||
}
|
||||
if (error_blob) {
|
||||
ID3D10Blob_Release(error_blob);
|
||||
}
|
||||
|
||||
shader->valid = true;
|
||||
|
||||
dx11_include_handler_release(&ps_include_handler);
|
||||
dx11_include_handler_release(&vs_include_handler);
|
||||
scratch_end(scratch);
|
||||
return error_str;
|
||||
}
|
||||
|
||||
INTERNAL void shader_release(struct dx11_shader *shader)
|
||||
{
|
||||
__prof;
|
||||
if (shader->vs) {
|
||||
ID3D11VertexShader_Release(shader->vs);
|
||||
}
|
||||
if (shader->ps) {
|
||||
ID3D11PixelShader_Release(shader->ps);
|
||||
}
|
||||
if (shader->input_layout) {
|
||||
ID3D11InputLayout_Release(shader->input_layout);
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_desc *desc)
|
||||
{
|
||||
__prof;
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
{
|
||||
struct string name = string_from_cstr_no_limit(desc->name_cstr);
|
||||
struct string error_msg = ZI;
|
||||
if (resource_exists(name)) {
|
||||
struct resource src_res = resource_open(name);
|
||||
{
|
||||
struct dx11_shader new_shader = ZI;
|
||||
struct string comp_error = shader_alloc(scratch.arena, &new_shader, desc, &src_res);
|
||||
if (comp_error.len == 0) {
|
||||
if (old_shader->valid) {
|
||||
shader_release(old_shader);
|
||||
}
|
||||
*old_shader = new_shader;
|
||||
} else {
|
||||
error_msg = string_format(scratch.arena,
|
||||
LIT("Failed to compile shader \"%F\":\n\n%F"),
|
||||
FMT_STR(name),
|
||||
FMT_STR(comp_error));
|
||||
shader_release(&new_shader);
|
||||
}
|
||||
}
|
||||
resource_close(&src_res);
|
||||
} else {
|
||||
error_msg = string_format(scratch.arena, LIT("Could not find shader \"%F\""), FMT_STR(name));
|
||||
}
|
||||
if (error_msg.len != 0) {
|
||||
if (old_shader->valid) {
|
||||
/* If shader failed to load but a working shader already exists, just error rather than panicking */
|
||||
log_error(error_msg);
|
||||
} else {
|
||||
sys_panic(error_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#if RESOURCE_RELOADING
|
||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name)
|
||||
{
|
||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||
struct dx11_shader_desc *desc = (struct dx11_shader_desc *)dict_get(&G.shader_info_lookup, hash);
|
||||
if (desc) {
|
||||
logf_info("Shader source file \"%F\" has changed", FMT_STR(name));
|
||||
atomic_i32_eval_exchange(&desc->should_reload, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Render
|
||||
* ========================== */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user