diff --git a/src/common.h b/src/common.h index 22aeeb2e..02008e6d 100644 --- a/src/common.h +++ b/src/common.h @@ -656,14 +656,14 @@ INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? #include "prof_tracy.h" -#define PROF_THREAD_GROUP_RUNNERS -8000 -#define PROF_THREAD_GROUP_FIBERS -7000 -#define PROF_THREAD_GROUP_WORKERS -6000 -#define PROF_THREAD_GROUP_IO -5 -#define PROF_THREAD_GROUP_WINDOW -4 -#define PROF_THREAD_GROUP_EVICTORS -3 -#define PROF_THREAD_GROUP_APP -2 -#define PROF_THREAD_GROUP_MAIN -1 +#define PROF_THREAD_GROUP_RUNNERS -8000000 +#define PROF_THREAD_GROUP_FIBERS -7000000 +#define PROF_THREAD_GROUP_WORKERS -6000000 +#define PROF_THREAD_GROUP_IO -5000000 +#define PROF_THREAD_GROUP_WINDOW -4000000 +#define PROF_THREAD_GROUP_EVICTORS -3000000 +#define PROF_THREAD_GROUP_APP -2000000 +#define PROF_THREAD_GROUP_MAIN -1000000 #ifdef __cplusplus } diff --git a/src/gp_dx11.c b/src/gp_dx11.c deleted file mode 100644 index 915b960b..00000000 --- a/src/gp_dx11.c +++ /dev/null @@ -1,2104 +0,0 @@ -#if !DX12_TEST - -#include "gp.h" -#include "resource.h" -#include "sys.h" -#include "memory.h" -#include "arena.h" -#include "scratch.h" -#include "string.h" -#include "math.h" -#include "inc.h" -#include "sprite.h" -#include "log.h" -#include "gstat.h" - -#pragma warning(push, 0) -# define UNICODE -# define COBJMACROS -# include -# include -# include -# include -# include -#pragma warning(pop) - -#pragma comment(lib, "d3d11") -#pragma comment(lib, "dxgi") -#pragma comment(lib, "dxguid") -#pragma comment(lib, "d3dcompiler") - -/* FIXME: Enable this and resolve unreleased references */ -#if RTC -# define DX11_DEBUG 0 -# define DX11_SHADER_DEBUG 1 -#else -# define DX11_DEBUG 0 -# define DX11_SHADER_DEBUG 0 -#endif - -#define DX11_BACKBUFFER_RECREATION_DELAY (1.0 / 30.0) - -#define DX11_WAIT_FRAME_LATENCY 1 -#define DX11_ALLOW_TEARING 1 - -#define DX11_SWAPCHAIN_FLAGS ((DX11_ALLOW_TEARING * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | (DX11_WAIT_FRAME_LATENCY * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) - -#define DX11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM) -#define DX11_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) - - - - - - - - - - -/* FIXME: Remove this */ -#include "draw.h" - - - - - - - -enum dx11_shader_kind { - DX11_SHADER_KIND_NONE, - DX11_SHADER_KIND_MESH, - DX11_SHADER_KIND_TEXTURE, - DX11_SHADER_KIND_GRID, - DX11_SHADER_KIND_TEST, - - NUM_DX11_SHADER_KINDS -}; - -enum dx11_handle_kind { - DX11_HANDLE_KIND_NONE, - DX11_HANDLE_KIND_TEXTURE, - DX11_HANDLE_KIND_FLOW, - - NUM_DX11_HANDLE_KINDS -}; - -struct dx11_handle_header { - enum dx11_handle_kind kind; -}; - -struct dx11_shader { - enum dx11_shader_kind kind; - b32 valid; /* Is this shader allocated */ - ID3D11InputLayout *input_layout; - ID3D11VertexShader *vs; - ID3D11PixelShader *ps; -}; - -struct dx11_buffer { - D3D11_BUFFER_DESC desc; - - /* Cpu buffer */ - struct arena *cpu_buffer_arena; - u8 *cpu_buffer; - - /* Gpu buffer */ - ID3D11ShaderResourceView *srv; - ID3D11Buffer *gpu_buffer; - u64 gpu_buffer_pos; - u64 gpu_buffer_capacity; - - struct dx11_buffer *next_free; -}; - -struct dx11_cmd_buffers { - union { - struct { - struct dx11_buffer *vertex_buffer; - struct dx11_buffer *index_buffer; - } mesh; - struct { - struct dx11_buffer *instance_buffer; - } texture; - struct { - struct dx11_buffer *instance_buffer; - } grid; - }; -}; - -struct dx11_cmd { - enum gp_cmd_kind kind; - b32 is_grid; - union { - struct { - struct xform xf; - } view; - struct { - u32 vertex_offset; - u32 vertex_count; - u32 index_offset; - u32 index_count; - } mesh; - struct { - struct gp_handle texture; /* Overrides sprite if set */ - struct sprite_tag sprite; - u32 instance_offset; - u32 instance_count; - } texture; - struct { - u32 instance_offset; - u32 instance_count; - } grid; - struct { - u32 instance_offset; - u32 instance_count; - } test; - }; - - struct dx11_cmd *next; -}; - -struct dx11_flow { - struct dx11_handle_header header; - - /* Commands w/ data still in cpu memory */ - struct arena *cpu_cmds_arena; - struct dx11_cmd *cpu_first_cmd; - struct dx11_cmd *cpu_last_cmd; - - /* Commands w/ buffer data submitted to video memory */ - struct arena *gp_cmds_arena; - struct dx11_cmd *gpu_first_cmd; - struct dx11_cmd *gpu_last_cmd; - - struct { - struct { - struct dx11_buffer *vertex_buffer; - struct dx11_buffer *index_buffer; - } mesh; - struct { - struct dx11_buffer *instance_buffer; - } texture; - struct { - struct dx11_buffer *instance_buffer; - } grid; - struct { - struct dx11_buffer *instance_buffer; - } test; - } cmd_buffers; - - struct dx11_buffer *constant_buffer; - - struct dx11_flow *next_free; -}; - -struct dx11_texture { - struct dx11_handle_header header; - - ID3D11Texture2D *texture; - ID3D11ShaderResourceView *srv; - ID3D11RenderTargetView *rtv; - struct v2i32 size; - struct dx11_texture *next_free; -}; - -/* ========================== * - * Global state - * ========================== */ - -struct dx11_shader_desc { - enum dx11_shader_kind kind; - char *name_cstr; - D3D11_INPUT_ELEMENT_DESC input_layout_desc[64]; /* NULL terminated array */ - - /* Internal */ -#if RESOURCE_RELOADING - struct arena *includes_arena; - struct sys_mutex *includes_mutex; - struct dict *includes_dict; - struct atomic_i32 is_dirty; -#endif -}; - -GLOBAL struct { - struct arena *arena; - -#if PROFILING_D3D - __prof_dx11_ctx(profiling_ctx); -#endif - - ID3D11Device *dev; - - ID3D11DeviceContext *devcon; - - IDXGISwapChain2 *swapchain; - HANDLE swapchain_waitable; - struct dx11_texture backbuffer_texture; - i64 last_backbuffer_resize_ns; - - ID3D11BlendState *blend_state; - ID3D11RasterizerState *rasterizer_state; - ID3D11DepthStencilState *depth_stencil_state; - ID3D11SamplerState *sampler_state; - - /* Buffer pool */ - struct sys_mutex *buffers_mutex; - struct arena *buffers_arena; - struct dx11_buffer *first_free_buffer; - - /* Flow pool */ - struct sys_mutex *flows_mutex; - struct arena *flows_arena; - struct dx11_flow *first_free_flow; - - /* Dispatch state pool */ - struct sys_mutex *dispatch_states_mutex; - struct arena *dispatch_states_arena; - struct dx11_dispatch_state *first_free_dispatch_state; - - /* Texture pool */ - struct sys_mutex *textures_mutex; - struct arena *textures_arena; - struct dx11_texture *first_free_texture; - - /* Shaders */ - struct dx11_shader shaders[NUM_DX11_SHADER_KINDS]; - struct dx11_shader_desc shader_info[NUM_DX11_SHADER_KINDS]; - - /* Dummy buffers */ - struct dx11_buffer *dummy_vertex_buffer; - struct dx11_buffer *quad_index_buffer; - - /* Blit flow */ - struct gp_handle present_blit_flow; - -} G = ZI, DEBUG_ALIAS(G, G_gp_dx11); - -/* ========================== * - * Startup - * ========================== */ - -INTERNAL void init_shader_table(void); -INTERNAL void reload_shader(struct dx11_shader *shader, struct dx11_shader_desc *desc); -INTERNAL struct dx11_buffer *dx11_buffer_alloc(struct D3D11_BUFFER_DESC desc, D3D11_SUBRESOURCE_DATA *initial_data); - -#if RESOURCE_RELOADING -INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name); -#endif - -struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr) -{ - __prof; - (UNUSED)work_sr; - - G.arena = arena_alloc(GIGABYTE(64)); - - /* Initialize buffers pool */ - G.buffers_mutex = sys_mutex_alloc(); - G.buffers_arena = arena_alloc(GIGABYTE(64)); - - /* Initialize flows pool */ - G.flows_mutex = sys_mutex_alloc(); - G.flows_arena = arena_alloc(GIGABYTE(64)); - - /* Initialize dispatch state pool */ - G.dispatch_states_mutex = sys_mutex_alloc(); - G.dispatch_states_arena = arena_alloc(GIGABYTE(64)); - - /* Initialize texture pool */ - G.textures_mutex = sys_mutex_alloc(); - G.textures_arena = arena_alloc(GIGABYTE(64)); - - /* Initialize shader table */ - init_shader_table(); - - HRESULT hr; - ID3D11Device *device = NULL; - ID3D11DeviceContext *context = NULL; - - /* Create D3D11 device & context */ - { - __profscope(Create device); -#if DX11_DEBUG - u32 flags = D3D11_CREATE_DEVICE_DEBUG; -#else - u32 flags = 0; -#endif - D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; - hr = D3D11CreateDevice( - NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - flags, - levels, - countof(levels), - D3D11_SDK_VERSION, - &device, - NULL, - &context - ); - ASSERT(SUCCEEDED(hr)); - } - -#if DX11_DEBUG - /* D3D11 Debug break */ - { - ID3D11InfoQueue *info; - ID3D11Device_QueryInterface(device, &IID_ID3D11InfoQueue, (void **)&info); - ID3D11InfoQueue_SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_CORRUPTION, TRUE); - ID3D11InfoQueue_SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_ERROR, TRUE); - ID3D11InfoQueue_Release(info); - } - - /* DXGI Debug break */ - { - IDXGIInfoQueue *dxgi_info; - hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgi_info); - ASSERT(SUCCEEDED(hr)); - IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE); - IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE); - IDXGIInfoQueue_Release(dxgi_info); - } -#endif - - if (!SUCCEEDED(hr) || !device || !context) { - /* Gpu initialization failure */ - /* TODO: Better message */ - sys_panic(LIT("Failed to initialize DirectX 11")); - } - G.dev = device; - G.devcon = context; - - struct string prof_ctx_name = LIT("D3d11 Context"); - (UNUSED)prof_ctx_name; - __prof_dx11_ctx_alloc(G.profiling_ctx, G.dev, G.devcon, prof_ctx_name.text, prof_ctx_name.len); - - /* Create the blend state */ - { - __profscope(create_blend_state); - const f32 blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - - /* TODO: Actually go over these (just want alpha blending/transparency) */ - D3D11_BLEND_DESC desc = { - .AlphaToCoverageEnable = false, - .RenderTarget[0].BlendEnable = true, - .RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA, - .RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA, - .RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD, - .RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE, - .RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA, - .RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD, - .RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL - }; - - /* FIXME: Free this? */ - ID3D11Device_CreateBlendState(G.dev, &desc, &G.blend_state); - ID3D11DeviceContext_OMSetBlendState(G.devcon, G.blend_state, blend_factor, 0xffffffff); - } - - /* Create depth-stencil State */ - - { - __profscope(create_depth_stencil_state); - /* TODO: Actually go over these (copied from elsewhere) */ - D3D11_DEPTH_STENCIL_DESC desc = ZI; - desc.DepthEnable = false; - desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - desc.DepthFunc = D3D11_COMPARISON_ALWAYS; - desc.StencilEnable = false; - desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - desc.BackFace = desc.FrontFace; - /* FIXME: Free this? */ - ID3D11Device_CreateDepthStencilState(G.dev, &desc, &G.depth_stencil_state); - ID3D11DeviceContext_OMSetDepthStencilState(G.devcon, G.depth_stencil_state, 0); - } - - /* Create the rasterizer state */ - { - __profscope(create_rasterizer_state); - D3D11_RASTERIZER_DESC desc = { - .FillMode = D3D11_FILL_SOLID, - .CullMode = D3D11_CULL_NONE, - //.ScissorEnable = true, - .DepthClipEnable = true - }; - /* FIXME: Free this? */ - ID3D11Device_CreateRasterizerState(G.dev, &desc, &G.rasterizer_state); - ID3D11DeviceContext_RSSetState(G.devcon, G.rasterizer_state); - } - - /* Create the sampler state */ - { - __profscope(create_sampler_state); - D3D11_SAMPLER_DESC desc = { - //.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR, - .Filter = D3D11_FILTER_MIN_MAG_MIP_POINT, - .AddressU = D3D11_TEXTURE_ADDRESS_CLAMP, - .AddressV = D3D11_TEXTURE_ADDRESS_CLAMP, - .AddressW = D3D11_TEXTURE_ADDRESS_CLAMP, - .MaxAnisotropy = 1, - //.ComparisonFunc = D3D11_COMPARISON_ALWAYS, - .MaxLOD = D3D11_FLOAT32_MAX - }; - /* FIXME: Free this? */ - ID3D11Device_CreateSamplerState(G.dev, &desc, &G.sampler_state); - ID3D11DeviceContext_PSSetSamplers(G.devcon, 0, 1, &G.sampler_state); - } - - /* Init shaders */ - logf_info("Compiling shaders"); - for (u32 i = DX11_SHADER_KIND_NONE + 1; i < NUM_DX11_SHADER_KINDS; ++i) { - struct dx11_shader *shader = &G.shaders[i]; - struct dx11_shader_desc *desc = &G.shader_info[i]; - reload_shader(shader, desc); - } - logf_info("Finished compiling shaders"); - - /* Init dummy buffers */ - { - /* Dummy vertex buffer */ - u8 dummy_data[16] = ZI; - D3D11_BUFFER_DESC vdesc = ZI; - vdesc.Usage = D3D11_USAGE_IMMUTABLE; - vdesc.ByteWidth = sizeof(dummy_data); - vdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - D3D11_SUBRESOURCE_DATA dummy_data_subres = ZI; - dummy_data_subres.pSysMem = dummy_data; - G.dummy_vertex_buffer = dx11_buffer_alloc(vdesc, &dummy_data_subres); - - /* Quad index buffer */ - LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; - D3D11_BUFFER_DESC idesc = ZI; - idesc.Usage = D3D11_USAGE_IMMUTABLE; - idesc.ByteWidth = sizeof(quad_indices); - idesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - D3D11_SUBRESOURCE_DATA idata = ZI; - idata.pSysMem = quad_indices; - G.quad_index_buffer = dx11_buffer_alloc(idesc, &idata); - } - - /* Setup file change callbacks */ -#if RESOURCE_RELOADING - resource_register_watch_callback(shader_resource_watch_callback); -#endif - - G.present_blit_flow = gp_flow_alloc(); - - return (struct gp_startup_receipt) { 0 }; -} - -/* ========================== * - * Util - * ========================== */ - - /* Calculate the view projection matrix */ -INLINE struct mat4x4 calculate_vp(struct xform view, f32 viewport_width, f32 viewport_height) -{ - struct mat4x4 projection = mat4x4_from_ortho(0.0, viewport_width, viewport_height, 0.0, -1.0, 1.0); - struct mat4x4 view4x4 = mat4x4_from_xform(view); - return mat4x4_mul(projection, view4x4); -} - -/* ========================== * - * Handle - * ========================== */ - -INTERNAL void dx11_texture_release(struct dx11_texture *t); - -void gp_release(struct gp_handle handle) -{ - struct dx11_handle_header *header = (struct dx11_handle_header *)handle.v; - switch (header->kind) { - default: break; - - case DX11_HANDLE_KIND_TEXTURE: - { - dx11_texture_release((struct dx11_texture *)header); - } break; - - case DX11_HANDLE_KIND_FLOW: - { - /* TODO */ - ASSERT(false); - } break; - } -} - -/* ========================== * - * Mesh shader structs - * ========================== */ - -PACK(struct dx11_mesh_uniform { - struct mat4x4 vp; -}); - -PACK(struct dx11_mesh_vertex { - struct v2 pos; - u32 color_srgb; -}); - -/* ========================== * - * Texture shader structs - * ========================== */ - -PACK(struct dx11_texture_uniform { - struct mat4x4 vp; - u32 instance_offset; -}); - -PACK(struct dx11_texture_instance { - struct xform xf; - struct v2 uv0; - struct v2 uv1; - u32 tint_srgb; - f32 emittance; -}); - -/* ========================== * - * Grid shader structs - * ========================== */ - -PACK(struct dx11_grid_uniform { - struct mat4x4 vp; - u32 instance_offset; -}); - -PACK(struct dx11_grid_instance { - struct xform xf; - f32 line_thickness; - f32 line_spacing; - struct v2 offset; - u32 bg0_srgb; - u32 bg1_srgb; - u32 line_srgb; - u32 x_srgb; - u32 y_srgb; -}); - -/* ========================== * - * Test shader structs - * ========================== */ - -PACK(struct dx11_test_uniform { - struct mat4x4 vp; - u32 instance_offset; -}); - -PACK(struct dx11_test_instance { - struct xform xf; -}); - -/* ========================== * - * Shader table - * ========================== */ - -INTERNAL void init_shader_table(void) -{ - MEMZERO_ARRAY(G.shader_info); - - /* Mesh shader layout */ - G.shader_info[DX11_SHADER_KIND_MESH] = (struct dx11_shader_desc) { - .kind = DX11_SHADER_KIND_MESH, - .name_cstr = "shaders_dx11/mesh.hlsl", - .input_layout_desc = { - { "pos", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "color_srgb", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } - } - }; - - /* Texture shader layout */ - G.shader_info[DX11_SHADER_KIND_TEXTURE] = (struct dx11_shader_desc) { - .kind = DX11_SHADER_KIND_TEXTURE, - .name_cstr = "shaders_dx11/texture.hlsl" - }; - - /* Grid shader layout */ - G.shader_info[DX11_SHADER_KIND_GRID] = (struct dx11_shader_desc) { - .kind = DX11_SHADER_KIND_GRID, - .name_cstr = "shaders_dx11/grid.hlsl" - }; - - /* Test shader layout */ - G.shader_info[DX11_SHADER_KIND_TEST] = (struct dx11_shader_desc) { - .kind = DX11_SHADER_KIND_TEST, - .name_cstr = "shaders_dx11/test.hlsl" - }; - -#if RESOURCE_RELOADING - for (u64 i = 0; i < countof(G.shader_info); ++i) { - struct dx11_shader_desc *desc = &G.shader_info[i]; - desc->includes_arena = arena_alloc(MEGABYTE(8)); - desc->includes_mutex = sys_mutex_alloc(); - desc->includes_dict = dict_init(desc->includes_arena, 64); - } -#endif -} - -/* ========================== * - * Shader dirty check - * ========================== */ - -#if RESOURCE_RELOADING -INTERNAL void shader_add_include(struct dx11_shader_desc *desc, struct string include_name_src) -{ - __prof; - u64 hash = hash_fnv64(HASH_FNV64_BASIS, include_name_src); - struct dict *dict = desc->includes_dict; - struct sys_lock lock = sys_mutex_lock_e(desc->includes_mutex); - { - dict_set(desc->includes_arena, dict, hash, 1); - } - sys_mutex_unlock(&lock); -} - -INTERNAL void shader_reset_includes(struct dx11_shader_desc *desc) -{ - __prof; - struct dict *dict = desc->includes_dict; - struct sys_lock lock = sys_mutex_lock_e(desc->includes_mutex); - { - dict_reset(dict); - } - sys_mutex_unlock(&lock); -} - -INTERNAL b32 shader_set_dirty(struct string name) -{ - __prof; - b32 caused_dirty = false; - for (u64 i = 0; i < NUM_DX11_SHADER_KINDS; ++i) { - struct dx11_shader_desc *desc = &G.shader_info[i]; - struct string desc_name = string_from_cstr_no_limit(desc->name_cstr); - if (string_eq(desc_name, name)) { - atomic_i32_fetch_set(&desc->is_dirty, 1); - caused_dirty = true; - } else { - struct dict *includes_dict = desc->includes_dict; - u64 hash = hash_fnv64(HASH_FNV64_BASIS, name); - struct sys_lock lock = sys_mutex_lock_e(desc->includes_mutex); - { - if (dict_get(includes_dict, hash) != 0) { - atomic_i32_fetch_set(&desc->is_dirty, 1); - caused_dirty = true; - } - } - sys_mutex_unlock(&lock); - } - } - return caused_dirty; -} - -INTERNAL b32 shader_unset_dirty(struct dx11_shader_desc *desc) -{ - return atomic_i32_fetch_test_set(&desc->is_dirty, 1, 0) == 1; -} -#endif - -/* ========================== * - * Shader include handler - * ========================== */ - -struct dx11_include_handler { - ID3DInclude d3d_handler; - ID3DIncludeVtbl vtbl; - struct dx11_shader *shader; - struct string error; - b32 has_open_resource; - struct resource res; -}; - -INTERNAL HRESULT dx11_include_open(ID3DInclude *d3d_handler, D3D_INCLUDE_TYPE include_type, LPCSTR name_cstr, LPCVOID parent_data, LPCVOID *data_out, UINT *data_len_out) -{ - __prof; - (UNUSED)include_type; - (UNUSED)parent_data; - HRESULT result = E_FAIL; - struct dx11_include_handler *handler = (struct dx11_include_handler *)d3d_handler; - struct string name = string_from_cstr_no_limit((char *)name_cstr); - - if (handler->has_open_resource) { - sys_panic(LIT("Dx11 include handler somehow already has a resource open")); - } - - struct resource res = resource_open(name); - if (resource_exists(&res)) { - handler->res = res; - handler->has_open_resource = true; - struct string data = resource_get_data(&res); - *data_out = data.text; - *data_len_out = data.len; - result = S_OK; - } - -#if RESOURCE_RELOADING - shader_add_include(&G.shader_info[handler->shader->kind], name); -#endif - - return result; -} - -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(struct dx11_shader *shader) -{ - struct dx11_include_handler handler = ZI; - handler.d3d_handler.lpVtbl = &handler.vtbl; - handler.vtbl.Open = dx11_include_open; - handler.vtbl.Close = dx11_include_close; - handler.shader = shader; - 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); - } -} - -/* ========================== * - * Shader compilation - * ========================== */ - - /* TODO: Multithread shader compilation */ - -/* If shader compilation fails, then function returns error string 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 arena_temp scratch = scratch_begin(arena); - struct string error_str = ZI; - i64 start_ns = sys_time_ns(); - - struct string shader_name = string_from_cstr_no_limit(shader_desc->name_cstr); - - shader->kind = shader_desc->kind; -#if RESOURCE_RELOADING - shader_reset_includes(shader_desc); -#endif - - struct dx11_include_handler include_handler = dx11_include_handler_alloc(shader); - - u32 flags = 0; -#if DX11_SHADER_DEBUG - flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_ENABLE_STRICTNESS; -#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(shader_name)); - /* Compile shader */ - /* TODO: pre-compile shaders w/ FXC? */ - struct string friendly_name = string_cat(scratch.arena, LIT("res/"), shader_name); - char *friendly_name_cstr = cstr_from_string(scratch.arena, friendly_name); - HRESULT hr = D3DCompile(shader_src.text, shader_src.len, friendly_name_cstr, NULL, (ID3DInclude *)&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, friendly_name_cstr, NULL, (ID3DInclude *)&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 < countof(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 */ - if (elem_count > 0) { - HRESULT hr = ID3D11Device_CreateInputLayout(G.dev, shader_desc->input_layout_desc, elem_count, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), &shader->input_layout); - if (!SUCCEEDED(hr)) { - success = false; - error_str = LIT("Failed to create input layout"); - } - } - } else { - success = false; - } - - if (!success || error_blob) { - if (error_str.len <= 0) { - 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) { - if (include_handler.error.len > 0) { - error_str = string_format(arena, LIT("%F %F"), FMT_STR(error_blob_str), FMT_STR(include_handler.error)); - } else { - error_str = string_copy(arena, error_blob_str); - } - } - } - } - - if (success) { - logf_success("Finished compiling shader \"%F\" in %F seconds", FMT_STR(shader_name), FMT_FLOAT(SECONDS_FROM_NS(sys_time_ns() - start_ns))); - } - - 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(&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 arena_temp scratch = scratch_begin_no_conflict(); - { - struct string name = string_from_cstr_no_limit(desc->name_cstr); - struct string error_msg = ZI; - struct resource src_res = resource_open(name); - { - if (resource_exists(&src_res)) { - 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); - } - } else { - error_msg = string_format(scratch.arena, LIT("Could not find shader \"%F\""), FMT_STR(name)); - } - } - resource_close(&src_res); - if (error_msg.len != 0) { - log_error(error_msg); - if (!old_shader->valid) { - /* If shader failed to load and no previous shader exists, show message box in case in game console can't be rendered */ - sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, error_msg); - } - } - } - scratch_end(scratch); -} - -#if RESOURCE_RELOADING -INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name) -{ - if (shader_set_dirty(name)) { - logf_debug("Shader source file \"%F\" has changed", FMT_STR(name)); - } -} -#endif - -/* ========================== * - * Texture - * ========================== */ - -INTERNAL enum DXGI_FORMAT dx11_format_from_gp_format(enum gp_texture_format gp_format) -{ - LOCAL_PERSIST const enum DXGI_FORMAT dx11_formats[NUM_GP_TEXTURE_FORMATS] = { - [GP_TEXTURE_FORMAT_R8G8B8A8_UNORM] = DXGI_FORMAT_R8G8B8A8_UNORM, - [GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB - }; - enum DXGI_FORMAT res = DXGI_FORMAT_UNKNOWN; - if ((u32)gp_format < countof(dx11_formats)) { - res = dx11_formats[gp_format]; - } - return res; -} - -INTERNAL u32 pixel_size_from_dx11_format(enum DXGI_FORMAT dx11_format) -{ - LOCAL_PERSIST const u32 pixel_sizes[] = { - [DXGI_FORMAT_R8G8B8A8_UNORM] = 4, - [DXGI_FORMAT_R8G8B8A8_UNORM_SRGB] = 4 - }; - u32 res = 0; - if ((u32)dx11_format < countof(pixel_sizes)) { - res = pixel_sizes[dx11_format]; - } - return res; -} - -INTERNAL struct dx11_texture *dx11_texture_alloc(enum DXGI_FORMAT format, u32 flags, struct v2i32 size, void *initial_data) -{ - struct dx11_texture *t = NULL; - { - struct sys_lock lock = sys_mutex_lock_e(G.textures_mutex); - if (G.first_free_texture) { - t = G.first_free_texture; - G.first_free_texture = t->next_free; - } else { - t = arena_push_no_zero(G.textures_arena, struct dx11_texture); - } - sys_mutex_unlock(&lock); - } - MEMZERO_STRUCT(t); - t->header.kind = DX11_HANDLE_KIND_TEXTURE; - - D3D11_TEXTURE2D_DESC desc = ZI; - desc.Width = max_i32(size.x, 1); - desc.Height = max_i32(size.y, 1); - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.BindFlags = flags; - desc.Format = format; - - /* Create texture */ - ID3D11Texture2D *texture = NULL; - if (initial_data) { - u32 pixel_size = pixel_size_from_dx11_format(format); - D3D11_SUBRESOURCE_DATA subresource_data = { .pSysMem = initial_data, .SysMemPitch = size.x * pixel_size, .SysMemSlicePitch = 0 }; - ID3D11Device_CreateTexture2D(G.dev, &desc, &subresource_data, &texture); - } else { - ID3D11Device_CreateTexture2D(G.dev, &desc, NULL, &texture); - } - ASSERT(texture != NULL); - t->texture = texture; - - /* Create SRV */ - if (t->texture && (flags & D3D11_BIND_SHADER_RESOURCE)) { - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = ZI; - srv_desc.Format = desc.Format; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srv_desc.Texture2D.MipLevels = desc.MipLevels; - ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)texture, &srv_desc, &t->srv); - } - - /* Create RTV */ - if (t->texture && (flags & D3D11_BIND_RENDER_TARGET)) { - ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &t->rtv); - } - - t->size = size; - return t; -} - -INTERNAL void dx11_texture_release(struct dx11_texture *t) -{ - { - struct sys_lock lock = sys_mutex_lock_e(G.textures_mutex); - t->next_free = G.first_free_texture; - G.first_free_texture = t; - sys_mutex_unlock(&lock); - } - if (t->rtv) { - ID3D11RenderTargetView_Release(t->rtv); - } - if (t->srv) { - ID3D11ShaderResourceView_Release(t->srv); - } - if (t->texture) { - ID3D11Texture2D_Release(t->texture); - } -} - -struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data) -{ - __prof; - struct gp_handle res = ZI; - - /* Convert format to dx11 format */ - enum DXGI_FORMAT dx11_format = dx11_format_from_gp_format(format); - if (dx11_format == DXGI_FORMAT_UNKNOWN) { - /* Unknown format */ - ASSERT(false); - sys_panic(LIT("Unknown dx11 texture format during texture allocation")); - } - - /* Convert flags to dx11 flags */ - u32 dx11_flags = D3D11_BIND_SHADER_RESOURCE; - if (flags & GP_TEXTURE_FLAG_TARGETABLE) { - dx11_flags |= D3D11_BIND_RENDER_TARGET; - } - - struct dx11_texture *t = dx11_texture_alloc(dx11_format, dx11_flags, size, initial_data); - res.v = (u64)t; - return res; -} - -struct v2i32 gp_texture_get_size(struct gp_handle texture) -{ - return ((struct dx11_texture *)texture.v)->size; -} - -/* ========================== * - * Dx11 buffer - * ========================== */ - - /* TODO: Buffer caching based on size */ - - /* NOTE: If initial_data is not provided, then ByteWidth will be ignored (set dynamically when buffer grows) */ -INTERNAL struct dx11_buffer *dx11_buffer_alloc(struct D3D11_BUFFER_DESC desc, D3D11_SUBRESOURCE_DATA *initial_data) -{ - __prof; - struct dx11_buffer *buffer = NULL; - { - struct arena *cpu_buffer_arena = NULL; - { - struct sys_lock lock = sys_mutex_lock_e(G.buffers_mutex); - if (G.first_free_buffer) { - buffer = G.first_free_buffer; - G.first_free_buffer = buffer->next_free; - cpu_buffer_arena = buffer->cpu_buffer_arena; - } else { - buffer = arena_push_no_zero(G.buffers_arena, struct dx11_buffer); - } - sys_mutex_unlock(&lock); - } - MEMZERO_STRUCT(buffer); - if (!cpu_buffer_arena) { - cpu_buffer_arena = arena_alloc(GIGABYTE(64)); - } - buffer->cpu_buffer_arena = cpu_buffer_arena; - } - buffer->desc = desc; - buffer->cpu_buffer = arena_push_dry(buffer->cpu_buffer_arena, u8); - - if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) { - ASSERT(desc.StructureByteStride != 0); /* Must provide stride for shader resource buffers */ - } - - if (initial_data) { - ASSERT(desc.ByteWidth > 0); /* Must provide size of subresource in desc */ - buffer->gpu_buffer_capacity = desc.ByteWidth; - ID3D11Device_CreateBuffer(G.dev, &buffer->desc, initial_data, &buffer->gpu_buffer); - - /* Create SRV */ - if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) { - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = ZI; - srv_desc.Format = DXGI_FORMAT_UNKNOWN; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - srv_desc.Buffer.NumElements = buffer->gpu_buffer_capacity / buffer->desc.StructureByteStride; - ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)buffer->gpu_buffer, &srv_desc, &buffer->srv); - } - } - - return buffer; -} - -/* TODO */ -#if 0 -INTERNAL void dx11_buffer_release(struct dx11_buffer *buffer) -{ - (UNUSED)buffer; - ASSERT(false); -} -#endif - -INTERNAL void *dx11_buffer_push(struct dx11_buffer *buffer, u64 size) -{ - void *data = arena_push_array_no_zero(buffer->cpu_buffer_arena, u8, size); - return data; -} - -INTERNAL void dx11_buffer_submit(struct dx11_buffer *buffer) -{ - __prof; - - /* Grow GPU buffer if necessary */ - u64 cpu_data_size = buffer->cpu_buffer_arena->pos; - if (cpu_data_size > buffer->gpu_buffer_capacity) { - - if (buffer->srv) { - ID3D11ShaderResourceView_Release(buffer->srv); - } - if (buffer->gpu_buffer) { - ID3D11Buffer_Release(buffer->gpu_buffer); - } - - /* Create buffer */ - /* FIXME: Cap to prevent infinite loop */ - u64 new_capacity = buffer->gpu_buffer_capacity * 2; - if (new_capacity == 0) { - if (buffer->desc.StructureByteStride != 0) { - new_capacity = buffer->desc.StructureByteStride; - } else { - new_capacity = KILOBYTE(64); - } - } - while (new_capacity < cpu_data_size) { - new_capacity *= 2; - } - buffer->desc.ByteWidth = new_capacity; - buffer->gpu_buffer_capacity = new_capacity; - ID3D11Device_CreateBuffer(G.dev, &buffer->desc, NULL, &buffer->gpu_buffer); - - /* Create SRV */ - if (buffer->desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) { - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = ZI; - srv_desc.Format = DXGI_FORMAT_UNKNOWN; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - srv_desc.Buffer.NumElements = new_capacity / buffer->desc.StructureByteStride; - ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)buffer->gpu_buffer, &srv_desc, &buffer->srv); - } - } - - /* Upload cpu data */ - if (buffer->gpu_buffer) { - D3D11_MAPPED_SUBRESOURCE subres; - ID3D11DeviceContext_Map(G.devcon, (ID3D11Resource *)buffer->gpu_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subres); - MEMCPY(subres.pData, buffer->cpu_buffer, cpu_data_size); - ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)buffer->gpu_buffer, 0); - } - - /* Reset cpu data */ - arena_reset(buffer->cpu_buffer_arena); -} - -/* ========================== * - * Flow - * ========================== */ - -struct gp_handle gp_flow_alloc(void) -{ - __prof; - struct dx11_flow *flow = NULL; - { - struct arena *cpu_cmds_arena = NULL; - struct arena *gp_cmds_arena = NULL; - { - struct sys_lock lock = sys_mutex_lock_e(G.flows_mutex); - if (G.first_free_flow) { - flow = G.first_free_flow; - G.first_free_flow = flow->next_free; - cpu_cmds_arena = flow->cpu_cmds_arena; - gp_cmds_arena = flow->gp_cmds_arena; - } else { - flow = arena_push_no_zero(G.flows_arena, struct dx11_flow); - } - sys_mutex_unlock(&lock); - } - MEMZERO_STRUCT(flow); - if (!cpu_cmds_arena) { - cpu_cmds_arena = arena_alloc(GIGABYTE(64)); - } - if (!gp_cmds_arena) { - gp_cmds_arena = arena_alloc(GIGABYTE(64)); - } - flow->cpu_cmds_arena = cpu_cmds_arena; - flow->gp_cmds_arena = gp_cmds_arena; - arena_reset(flow->cpu_cmds_arena); - arena_reset(flow->gp_cmds_arena); - } - flow->header.kind = DX11_HANDLE_KIND_FLOW; - - /* Desc template */ - const D3D11_BUFFER_DESC structured_buffer_desc = { - .Usage = D3D11_USAGE_DYNAMIC, - .BindFlags = D3D11_BIND_SHADER_RESOURCE, - .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE, - .MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED - }; - - /* Allocate buffers */ - { - /* Mesh buffers */ - { - D3D11_BUFFER_DESC vdesc = ZI; - vdesc.Usage = D3D11_USAGE_DYNAMIC; - vdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - - /* Quad index buffer */ - D3D11_BUFFER_DESC idesc = ZI; - idesc.Usage = D3D11_USAGE_DYNAMIC; - idesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - idesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - - flow->cmd_buffers.mesh.vertex_buffer = dx11_buffer_alloc(vdesc, NULL); - flow->cmd_buffers.mesh.index_buffer = dx11_buffer_alloc(idesc, NULL); - } - - /* Texture buffers */ - { - struct D3D11_BUFFER_DESC desc = structured_buffer_desc; - desc.StructureByteStride = sizeof(struct dx11_texture_instance); - flow->cmd_buffers.texture.instance_buffer = dx11_buffer_alloc(desc, NULL); - } - - /* Grid buffers */ - { - struct D3D11_BUFFER_DESC desc = structured_buffer_desc; - desc.StructureByteStride = sizeof(struct dx11_grid_instance); - flow->cmd_buffers.grid.instance_buffer = dx11_buffer_alloc(desc, NULL); - } - - /* Test buffers */ - { - struct D3D11_BUFFER_DESC desc = structured_buffer_desc; - desc.StructureByteStride = sizeof(struct dx11_test_instance); - flow->cmd_buffers.test.instance_buffer = dx11_buffer_alloc(desc, NULL); - } - } - - struct gp_handle res = ZI; - res.v = (u64)flow; - return res; -} - -void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params) -{ - __prof; - struct dx11_flow *flow = (struct dx11_flow *)gp_flow.v; - - switch (params.kind) { - default: - { - /* Unknown cmd kind */ - ASSERT(false); - } break; - - case GP_CMD_KIND_DRAW_SHAPE: - { - struct dx11_cmd *cmd = flow->cpu_last_cmd; - if (cmd && cmd->kind != params.kind) { - /* Cannot batch */ - cmd = NULL; - } - - /* Start new cmd */ - if (!cmd) { - /* TODO: Better count method */ - cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); - cmd->kind = params.kind; - cmd->mesh.vertex_offset = (flow->cmd_buffers.mesh.vertex_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_mesh_vertex)); - cmd->mesh.index_offset = (flow->cmd_buffers.mesh.index_buffer->cpu_buffer_arena->pos / sizeof(u32)); - if (flow->cpu_last_cmd) { - flow->cpu_last_cmd->next = cmd; - } else { - flow->cpu_first_cmd = cmd; - } - flow->cpu_last_cmd = cmd; - } - - /* Push vertices */ - u64 vertex_count = params.mesh.vertices.count; - u64 start_index = cmd->mesh.vertex_count; - cmd->mesh.vertex_count += vertex_count; - struct dx11_mesh_vertex *verts = dx11_buffer_push(flow->cmd_buffers.mesh.vertex_buffer, sizeof(struct dx11_mesh_vertex) * vertex_count); - for (u64 i = 0; i < vertex_count; ++i) { - struct dx11_mesh_vertex *vert = &verts[i]; - vert->pos = params.mesh.vertices.points[i]; - vert->color_srgb = params.mesh.color; - } - - /* Push indices */ - u64 index_count = params.mesh.indices.count; - u32 *indices = dx11_buffer_push(flow->cmd_buffers.mesh.index_buffer, sizeof(u32) * index_count); - cmd->mesh.index_count += index_count; - for (u64 i = 0; i < index_count; ++i) { - indices[i] = start_index + params.mesh.indices.indices[i]; - } - } break; - - case GP_CMD_KIND_DRAW_TEXTURE: - { - if (params.texture.grid) { - struct dx11_cmd *cmd = flow->cpu_last_cmd; - if (cmd && (cmd->kind != params.kind || !cmd->is_grid)) { - /* Cannot batch */ - cmd = NULL; - } - - /* Start new cmd */ - if (!cmd) { - /* TODO: Better count method */ - cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); - cmd->kind = params.kind; - cmd->is_grid = true; - cmd->grid.instance_offset = (flow->cmd_buffers.grid.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_grid_instance)); - if (flow->cpu_last_cmd) { - flow->cpu_last_cmd->next = cmd; - } else { - flow->cpu_first_cmd = cmd; - } - flow->cpu_last_cmd = cmd; - } - - /* Push instance data */ - ++cmd->grid.instance_count; - struct dx11_grid_instance *instance = dx11_buffer_push(flow->cmd_buffers.grid.instance_buffer, sizeof(struct dx11_grid_instance)); - instance->xf = params.texture.xf; - instance->line_thickness = params.texture.grid->line_thickness; - instance->line_spacing = params.texture.grid->line_spacing; - instance->offset = params.texture.grid->offset; - instance->bg0_srgb = params.texture.grid->bg0_color; - instance->bg1_srgb = params.texture.grid->bg1_color; - instance->line_srgb = params.texture.grid->line_color; - instance->x_srgb = params.texture.grid->x_color; - instance->y_srgb = params.texture.grid->y_color; - } else { - struct dx11_cmd *cmd = flow->cpu_last_cmd; - if (cmd && - ((cmd->kind != params.kind) || - (cmd->texture.sprite.hash != params.texture.sprite.hash) || - (cmd->texture.texture.v != params.texture.texture.v) || - (cmd->is_grid))) { - /* Cannot batch */ - cmd = NULL; - } - - /* Start new cmd */ - if (!cmd) { - /* TODO: Better count method */ - cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); - cmd->kind = params.kind; - cmd->texture.sprite = params.texture.sprite; - cmd->texture.texture = params.texture.texture; - cmd->texture.instance_offset = (flow->cmd_buffers.texture.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_texture_instance)); - if (flow->cpu_last_cmd) { - flow->cpu_last_cmd->next = cmd; - } else { - flow->cpu_first_cmd = cmd; - } - flow->cpu_last_cmd = cmd; - } - - /* Push instance data */ - ++cmd->texture.instance_count; - struct dx11_texture_instance *instance = dx11_buffer_push(flow->cmd_buffers.texture.instance_buffer, sizeof(struct dx11_texture_instance)); - instance->xf = params.texture.xf; - instance->uv0 = params.texture.clip.p0; - instance->uv1 = params.texture.clip.p1; - instance->tint_srgb = params.texture.tint; - instance->emittance = params.texture.emittance; - } - } break; - - case GP_CMD_KIND_TEST: - { - struct dx11_cmd *cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd); - cmd->kind = params.kind; - cmd->test.instance_offset = (flow->cmd_buffers.test.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_test_instance)); - if (flow->cpu_last_cmd) { - flow->cpu_last_cmd->next = cmd; - } else { - flow->cpu_first_cmd = cmd; - } - flow->cpu_last_cmd = cmd; - - /* Push instance data */ - ++cmd->test.instance_count; - struct dx11_test_instance *instance = dx11_buffer_push(flow->cmd_buffers.test.instance_buffer, sizeof(struct dx11_test_instance)); - instance->xf = params.test.xf; - } break; - } -} - -/* ========================== * - * Dispatch - * ========================== */ - -enum dx11_unbind_flags { - DX11_UNBIND_NONE = 0, - DX11_UNBIND_VS = (1 << 0), - DX11_UNBIND_PS = (1 << 1), - DX11_UNBIND_IA = (1 << 2), - DX11_UNBIND_CBUFF = (1 << 3), - DX11_UNBIND_VBUFF = (1 << 4), - DX11_UNBIND_IBUFF = (1 << 5), - DX11_UNBIND_SRV = (1 << 6), - DX11_UNBIND_RTV = (1 << 7) -}; - -INTERNAL void dx11_unbind(u32 flags) -{ - __prof; - ID3D11RenderTargetView *null_rtvs[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - ID3D11ShaderResourceView *null_srvs[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - ID3D11Buffer *null_buffers[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - ID3D11InputLayout *null_ia = NULL; - ID3D11VertexShader *null_vs = NULL; - ID3D11PixelShader *null_ps = NULL; - u32 zero = 0; - - if (flags & DX11_UNBIND_RTV) { - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 8, null_rtvs, NULL); - } - - if (flags & DX11_UNBIND_SRV) { - if (flags & DX11_UNBIND_VS) { - ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 8, null_srvs); - } - if (flags & DX11_UNBIND_PS) { - ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 8, null_srvs); - } - } - - if (flags & DX11_UNBIND_VBUFF) { - ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, null_buffers, &zero, &zero); - } - - if (flags & DX11_UNBIND_IBUFF) { - ID3D11DeviceContext_IASetIndexBuffer(G.devcon, null_buffers[0], DXGI_FORMAT_R16_UINT, zero); - } - - if (flags & DX11_UNBIND_IA) { - ID3D11DeviceContext_IASetInputLayout(G.devcon, null_ia); - } - - if (flags & DX11_UNBIND_CBUFF) { - if (flags & DX11_UNBIND_VS) { - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 8, null_buffers); - } - if (flags & DX11_UNBIND_PS) { - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 8, null_buffers); - } - } - - if (flags & DX11_UNBIND_VS) { - ID3D11DeviceContext_VSSetShader(G.devcon, null_vs, 0, 0); - } - - if (flags & DX11_UNBIND_PS) { - ID3D11DeviceContext_PSSetShader(G.devcon, null_ps, 0, 0); - } -} - -/* TODO: Lock resources during dispatch */ -void gp_dispatch(struct gp_dispatch_params params) -{ - __prof; - __profscope_dx11(G.profiling_ctx, Dispatch, RGB32_F(0.5, 0.2, 0.2)); - struct dx11_flow *flow = (struct dx11_flow *)params.flow.v; - - /* Swap cmd lists */ - struct arena *swp_arena = flow->gp_cmds_arena; - flow->gp_cmds_arena = flow->cpu_cmds_arena; - flow->gpu_first_cmd = flow->cpu_first_cmd; - flow->gpu_last_cmd = flow->cpu_last_cmd; - - /* Reset cpu cmd list */ - flow->cpu_cmds_arena = swp_arena; - flow->cpu_first_cmd = NULL; - flow->cpu_last_cmd = NULL; - arena_reset(flow->cpu_cmds_arena); - - /* Submit cmd data */ - { - __profscope(Submit buffers); - - /* Submit mesh buffers */ - dx11_buffer_submit(flow->cmd_buffers.mesh.vertex_buffer); - dx11_buffer_submit(flow->cmd_buffers.mesh.index_buffer); - - /* Submit texture buffers */ - dx11_buffer_submit(flow->cmd_buffers.texture.instance_buffer); - - /* Submit grid buffers */ - dx11_buffer_submit(flow->cmd_buffers.grid.instance_buffer); - - /* Submit test buffers */ - dx11_buffer_submit(flow->cmd_buffers.test.instance_buffer); - } - - struct sprite_scope *sprite_scope = sprite_scope_begin(); - - struct rect viewport = params.draw_target_viewport; - - /* Set viewport */ - D3D11_VIEWPORT d3d11_viewport = ZI; - d3d11_viewport.Width = viewport.width; - d3d11_viewport.Height = viewport.height; - d3d11_viewport.MinDepth = 0.0f; - d3d11_viewport.MaxDepth = 1.0f; - d3d11_viewport.TopLeftX = viewport.x; - d3d11_viewport.TopLeftY = viewport.y; - ID3D11DeviceContext_RSSetViewports(G.devcon, 1, &d3d11_viewport); - - struct dx11_texture *final_tex = (struct dx11_texture *)params.draw_target.v; - - /* Allocate constant buffer */ - struct dx11_buffer *constant_buffer = flow->constant_buffer; - if (!constant_buffer) { - const D3D11_BUFFER_DESC desc = { - .Usage = D3D11_USAGE_DYNAMIC, - .BindFlags = D3D11_BIND_CONSTANT_BUFFER, - .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE - }; - constant_buffer = dx11_buffer_alloc(desc, NULL); - flow->constant_buffer = constant_buffer; - } - - /* Clear target */ - if (params.clear_target) { - u32 clear_color = 0; - if (final_tex->rtv) { - __profscope_dx11(G.profiling_ctx, Clear, RGB32_F(0.5, 0.1, 0.1)); - f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f; - f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f; - f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f; - f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f; - f32 fill[4] = { r, g, b, a }; - ID3D11DeviceContext_ClearRenderTargetView(G.devcon, final_tex->rtv, fill); - } - } - - /* Regular pass */ - struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, viewport.width, viewport.height); - { - __profscope(Regular pass); - __profscope_dx11(G.profiling_ctx, Regular pass, RGB32_F(0.2, 0.5, 0.5)); - for (struct dx11_cmd *cmd = flow->gpu_first_cmd; cmd; cmd = cmd->next) { - enum gp_cmd_kind cmd_kind = cmd->kind; - - switch (cmd_kind) { - default: - { - /* Unknown cmd kind */ - ASSERT(false); - } break; - - case GP_CMD_KIND_DRAW_SHAPE: - { - __profscope(Draw mesh); - __profscope_dx11(G.profiling_ctx, Draw mesh, RGB32_F(0.5, 0.2, 0.2)); - struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_MESH]; - if (shader->valid) { - struct dx11_buffer *vertex_buffer = flow->cmd_buffers.mesh.vertex_buffer; - struct dx11_buffer *index_buffer = flow->cmd_buffers.mesh.index_buffer; - - u32 vertex_offset = cmd->mesh.vertex_offset; - u32 index_offset = cmd->mesh.index_offset; - u32 index_count = cmd->mesh.index_count; - - /* Bind shader */ - ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); - ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); - ID3D11DeviceContext_IASetInputLayout(G.devcon, shader->input_layout); - - /* Fill & bind constant buffer */ - { - struct dx11_mesh_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_mesh_uniform)); - uniform->vp = vp_matrix; - dx11_buffer_submit(constant_buffer); - } - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - - /* Bind vertex buffer */ - u32 zero = 0; - u32 stride = sizeof(struct dx11_mesh_vertex); - ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &vertex_buffer->gpu_buffer, &stride, &zero); - ID3D11DeviceContext_IASetIndexBuffer(G.devcon, index_buffer->gpu_buffer, DXGI_FORMAT_R32_UINT, zero); - - /* Bind RTVs */ - ID3D11RenderTargetView *rtvs[] = { final_tex->rtv }; - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, countof(rtvs), rtvs, NULL); - - /* Draw */ - ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset); - - /* Unbind */ - dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_IA | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_RTV); - } - } break; - - case GP_CMD_KIND_DRAW_TEXTURE: - { - if (cmd->is_grid) { - __profscope(Draw grid); - __profscope_dx11(G.profiling_ctx, Draw grid, RGB32_F(0.2, 0.2, 0.5)); - struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID]; - if (shader->valid) { - struct dx11_buffer *instance_buffer = flow->cmd_buffers.grid.instance_buffer; - u32 instance_offset = cmd->grid.instance_offset; - u32 instance_count = cmd->grid.instance_count; - - /* Bind shader */ - ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); - ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); - - /* Fill & bind constant buffer */ - { - struct dx11_grid_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_grid_uniform)); - uniform->vp = vp_matrix; - uniform->instance_offset = instance_offset; - dx11_buffer_submit(constant_buffer); - } - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - - /* Bind dummy vertex buffer */ - u32 zero = 0; - ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero); - ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero); - - /* Bind SRVs */ - ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv }; - ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, countof(srvs), srvs); - ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, countof(srvs), srvs); - - /* Bind RTVs */ - ID3D11RenderTargetView *rtvs[] = { final_tex->rtv }; - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, countof(rtvs), rtvs, NULL); - - /* Draw */ - ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0); - - /* Unbind */ - dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); - } - } else { - __profscope(Draw texture); - __profscope_dx11(G.profiling_ctx, Draw texture, RGB32_F(0.2, 0.5, 0.2)); - struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE]; - if (shader->valid) { - struct dx11_texture *texture = NULL; - if (cmd->texture.texture.v) { - /* Load texture if handle is set */ - texture = (struct dx11_texture *)cmd->texture.texture.v; - } else if (cmd->texture.sprite.hash) { - /* Otherwise load sprite */ - struct sprite_texture *sprite_texture = sprite_texture_from_tag_async(sprite_scope, cmd->texture.sprite); - if (sprite_texture->loaded) { - texture = (struct dx11_texture *)sprite_texture->texture.v; - } - } - - if (texture && texture->srv) { - struct dx11_buffer *instance_buffer = flow->cmd_buffers.texture.instance_buffer; - u32 instance_offset = cmd->texture.instance_offset; - u32 instance_count = cmd->texture.instance_count; - - /* Bind shader */ - ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); - ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); - - /* Fill & bind constant buffer */ - { - struct dx11_texture_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_texture_uniform)); - uniform->vp = vp_matrix; - uniform->instance_offset = instance_offset; - dx11_buffer_submit(constant_buffer); - } - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - - /* Bind dummy vertex buffer */ - u32 zero = 0; - ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero); - ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero); - - /* Bind SRVs */ - ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv, texture->srv }; - ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, countof(srvs), srvs); - ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, countof(srvs), srvs); - - /* Bind RTVs */ - ID3D11RenderTargetView *rtvs[] = { final_tex->rtv }; - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, countof(rtvs), rtvs, NULL); - - /* Draw */ - ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0); - - /* Unbind */ - dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); - } - } - } - } break; - - case GP_CMD_KIND_TEST: - { - __profscope(Test); - __profscope_dx11(G.profiling_ctx, Test, RGB32_F(1, 0.2, 1)); - struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEST]; - if (shader->valid) { - struct dx11_buffer *instance_buffer = flow->cmd_buffers.test.instance_buffer; - u32 instance_offset = cmd->test.instance_offset; - u32 instance_count = cmd->test.instance_count; - - /* Bind shader */ - ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); - ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); - - /* Fill & bind constant buffer */ - { - struct dx11_test_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_test_uniform)); - uniform->vp = vp_matrix; - uniform->instance_offset = instance_offset; - dx11_buffer_submit(constant_buffer); - } - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer); - - /* Bind dummy vertex buffer */ - u32 zero = 0; - ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero); - ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero); - - /* Bind SRVs */ - ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv }; - ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, countof(srvs), srvs); - ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, countof(srvs), srvs); - - /* Bind RTVs */ - ID3D11RenderTargetView *rtvs[] = { final_tex->rtv }; - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, countof(rtvs), rtvs, NULL); - - /* Draw */ - ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0); - - /* Unbind */ - dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); - } - } break; - } - } - } - - sprite_scope_end(sprite_scope); -} - -/* ========================== * - * Memory info - * ========================== */ - -struct gp_memory_info gp_query_memory_info(void) -{ - return (struct gp_memory_info) { 0 }; -} - -/* ========================== * - * Present - * ========================== */ - -INTERNAL void capture_image_for_profiler(void); - -INTERNAL void present_resize(struct v2i32 size) -{ - __prof; - /* Delay backbuffer recreation so that we don't recreate it too quickly. - * It seems that doing this without a delay too often will cause windows - * to eventually just display a blackscreen rather than the backbuffer - * (e.g. when resizing for more than a few seconds). */ - i64 now_ns = sys_time_ns(); - if (G.last_backbuffer_resize_ns != 0) { - i64 next_resize_ns = G.last_backbuffer_resize_ns + NS_FROM_SECONDS(DX11_BACKBUFFER_RECREATION_DELAY); - if (now_ns < next_resize_ns) { - sys_sleep_precise(SECONDS_FROM_NS(next_resize_ns - now_ns)); - now_ns = sys_time_ns(); - } - } - G.last_backbuffer_resize_ns = now_ns; - - /* Release */ - if (G.backbuffer_texture.texture != 0) { - ID3D11RenderTargetView_Release(G.backbuffer_texture.rtv); - ID3D11Texture2D_Release(G.backbuffer_texture.texture); - } - - /* Resize */ - IDXGISwapChain_ResizeBuffers(G.swapchain, 0, size.x, size.y, DXGI_FORMAT_UNKNOWN, DX11_SWAPCHAIN_FLAGS); - IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&G.backbuffer_texture.texture); - G.backbuffer_texture.size = size; - - /* Create rtv */ - D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = ZI; - rtv_desc.Format = DX11_SWAPCHAIN_RTV_FORMAT; - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)G.backbuffer_texture.texture, &rtv_desc, &G.backbuffer_texture.rtv); -} - -INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, struct xform src_xf) -{ - __prof; - __profscope_dx11(G.profiling_ctx, Blit, RGB32_F(0.3, 0.1, 0.1)); - struct gp_handle src_texture_handle = { .v = (u64)src }; - struct gp_handle dst_texture_handle = { .v = (u64)dst }; - - /* Draw texture to backbuffer texture */ - /* TODO: Specialized blit shader */ - { - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = src_xf, .texture = src_texture_handle); - draw_texture(G.present_blit_flow, params); - } - - /* Render to backbuffer texture */ - struct gp_dispatch_params params = ZI; - params.flow = G.present_blit_flow; - params.draw_target = dst_texture_handle; - params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->size.x, dst->size.y)); - params.draw_target_view = XFORM_IDENT; - params.clear_target = true; - gp_dispatch(params); -} - -INTERNAL void present_init_swapchain(struct sys_window *window) -{ - - /* Create swap chain */ - { - __profscope(Create swapchain); - HWND hwnd = (HWND)sys_window_get_internal_handle(window); - - /* Get DXGI device from D3D11 device */ - IDXGIDevice *dxgiDevice; - HRESULT hr = ID3D11Device_QueryInterface(G.dev, &IID_IDXGIDevice, (void **)&dxgiDevice); - ASSERT(SUCCEEDED(hr)); - - /* Get DXGI adapter from DXGI device */ - IDXGIAdapter *dxgiAdapter; - hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter); - ASSERT(SUCCEEDED(hr)); - - /* Get DXGI factory from DXGI adapter */ - IDXGIFactory2 *factory; - hr = IDXGIAdapter_GetParent(dxgiAdapter, &IID_IDXGIFactory2, (void **)&factory); - ASSERT(SUCCEEDED(hr)); - - DXGI_SWAP_CHAIN_DESC1 desc = { - .Format = DX11_SWAPCHAIN_FORMAT, - .SampleDesc = { 1, 0 }, - .BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT, - .BufferCount = 3, - .Scaling = DXGI_SCALING_NONE, - .Flags = DX11_SWAPCHAIN_FLAGS, - .AlphaMode = DXGI_ALPHA_MODE_IGNORE, - .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD - }; - - IDXGISwapChain1 *swapchain1 = NULL; - hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)G.dev, hwnd, &desc, NULL, NULL, &swapchain1); - ASSERT(SUCCEEDED(hr)); - - if (SUCCEEDED(hr)) { - IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void **)&G.swapchain); - } - - /* Disable Alt+Enter changing monitor resolution to match window size */ - IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER); - - IDXGISwapChain1_Release(swapchain1); - IDXGIFactory2_Release(factory); - IDXGIAdapter_Release(dxgiAdapter); - IDXGIDevice_Release(dxgiDevice); - } - - /* Create the swapchain waitable object */ -#if DX11_WAIT_FRAME_LATENCY - if (G.swapchain != NULL) { - IDXGISwapChain2_SetMaximumFrameLatency(G.swapchain, 1); - G.swapchain_waitable = IDXGISwapChain2_GetFrameLatencyWaitableObject(G.swapchain); - ASSERT(G.swapchain_waitable != NULL); - } -#endif -} - -void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) -{ - __prof; - - /* Reload dirty shaders */ -#if RESOURCE_RELOADING - for (u64 i = DX11_SHADER_KIND_NONE + 1; i < NUM_DX11_SHADER_KINDS; ++i) { - struct dx11_shader_desc *desc = &G.shader_info[i]; - if (shader_unset_dirty(desc)) { - reload_shader(&G.shaders[i], desc); - } - } -#endif - - if (!G.swapchain) { - present_init_swapchain(window); - } - - /* Wait */ - i32 flags = 0; - if (vsync) { - if (G.swapchain_waitable != NULL) { - __profscope(Present wait); - WaitForSingleObjectEx(G.swapchain_waitable, 1000, TRUE); - } - } else { -#if DX11_ALLOW_TEARING - flags = DXGI_PRESENT_ALLOW_TEARING; -#endif - } - - /* Resize backbuffer */ - if (!v2i32_eq(G.backbuffer_texture.size, backbuffer_resolution)) { - present_resize(backbuffer_resolution); - } - - /* Blit to backbuffer */ - present_blit(&G.backbuffer_texture, (struct dx11_texture *)texture.v, texture_xf); - - /* Present */ - capture_image_for_profiler(); - { - __profscope(Present); - IDXGISwapChain2_Present(G.swapchain, vsync, flags); - __prof_dx11_collect(G.profiling_ctx); - __profframe(0); - } -} - -/* ========================== * - * Profiling frame capture - * ========================== */ - - /* FIXME: enable this */ -#if PROFILING_CAPTURE_FRAME_IMAGE - -#define CAP_WIDTH 320 -#define CAP_HEIGHT 180 - -struct prof_cap { - ID3D11Texture2D *texture; - struct v2 size; -}; - -INTERNAL void capture_image_for_profiler(void) -{ - __prof; - - /* A rolling window of staging textures is used. This is because trying to - * map a texture immediately after copying the resource will cause the map - * to hang while it waits for the copy to finish. - * - * At the time of writing this code, 5 textures seems to be the sweet spot - * for performance. - */ - static struct prof_cap staging_caps[5] = ZI; - static u32 cap_index = 0; - static b32 ready_to_read = false; - - ID3D11Texture2D *backbuffer = NULL; - IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer); - - struct prof_cap *write_cap = &staging_caps[cap_index]; - MEMZERO_STRUCT(write_cap); - { - D3D11_TEXTURE2D_DESC staging_desc; - ID3D11Texture2D_GetDesc(backbuffer, &staging_desc); - staging_desc.Usage = D3D11_USAGE_STAGING; - staging_desc.BindFlags = 0; - staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - write_cap->size = V2(staging_desc.Width, staging_desc.Height); - ID3D11Device_CreateTexture2D(G.dev, &staging_desc, NULL, &write_cap->texture); - } - - ID3D11DeviceContext_CopyResource(G.devcon, (ID3D11Resource *)write_cap->texture, (ID3D11Resource *)backbuffer); - ID3D11Texture2D_Release(backbuffer); - - ++cap_index; - if (cap_index >= countof(staging_caps)) { - cap_index = 0; - ready_to_read = true; - } - - if (ready_to_read) { - struct prof_cap *read_cap = &staging_caps[cap_index]; - { - D3D11_MAPPED_SUBRESOURCE res; - ID3D11DeviceContext_Map(G.devcon, (ID3D11Resource *)read_cap->texture, 0, D3D11_MAP_READ, 0, &res); - u32 final_width = CAP_WIDTH; - u32 final_height = CAP_HEIGHT; - f32 width_frequency = (f32)read_cap->size.x / (f32)final_width; - f32 height_frequency = (f32)read_cap->size.y / (f32)final_height; - { - struct arena_temp scratch = scratch_begin_no_conflict(); - - u32 *source = res.pData; - u32 *dest = arena_push_array_no_zero(scratch.arena, u32, final_width * final_height); - u32 pitch = res.RowPitch / 4; - for (u32 y = 0; y < final_height; ++y) { - for (u32 x = 0; x < final_width; ++x) { - u32 *pixel = &dest[x + (y * final_width)]; - u64 source_x = (u64)(width_frequency * (f32)x); - u64 source_y = (u64)(height_frequency * (f32)y); - *pixel = source[source_x + (source_y * pitch)]; - } - } - - { - __profscope(prof_frame_image); - __profframeimage(dest, (u16)final_width, (u16)final_height, countof(staging_caps) - 1, false); - } - - scratch_end(scratch); - } - ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)read_cap->texture, 0); - } - ID3D11Texture2D_Release(read_cap->texture); - } -} -#else - -INTERNAL void capture_image_for_profiler(void) -{ -} - -#endif - - -#endif diff --git a/src/prof_tracy.h b/src/prof_tracy.h index 6be530cb..125ce687 100644 --- a/src/prof_tracy.h +++ b/src/prof_tracy.h @@ -7,10 +7,10 @@ #if PROFILING -#define PROFILING_SYSTEM_TRACE 0 +#define PROFILING_SYSTEM_TRACE 1 #define PROFILING_CAPTURE_FRAME_IMAGE 0 #define PROFILING_LOCKS 0 -#define PROFILING_D3D 0 +#define PROFILING_D3D 1 #define PROFILING_FILE_WSTR L".tracy" #define PROFILING_CMD_WSTR L"cmd /C start \"\" /wait tracy-capture.exe -o .tracy -a 127.0.0.1 && start \"\" tracy-profiler.exe .tracy" diff --git a/src/sys_win32.c b/src/sys_win32.c index 2951da89..c1a1b1a0 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -530,9 +530,9 @@ INTERNAL SYS_THREAD_DEF(runner_entry, runner_ctx_arg) } } - /* Run job */ + /* Execute fiber */ if (job_func) { - __profscope(Run job); + __profscope(Execute fiber); struct fiber *fiber = fiber_alloc(FIBER_KIND_JOB_RUNNER); fiber->job_func = job_func; fiber->job_sig = job_sig;