From b96465191eb8d261b9432526699478990e2e7132 Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 19 Jun 2025 22:24:56 -0500 Subject: [PATCH] dx12 present testing --- res/sh/common.hlsl | 2 +- res/sh/grid.hlsl | 106 ---------------- res/sh/material.hlsl | 18 +-- res/sh/mesh.hlsl | 42 ------- res/sh/sh_common.h | 3 +- res/sh/test.hlsl | 51 -------- src/app.c | 2 +- src/config.h | 2 +- src/gp.h | 4 +- src/gp_dx11.c | 18 +-- src/gp_dx12.c | 288 ++++++++++++++++++++++++++++++++----------- src/user.c | 2 +- 12 files changed, 241 insertions(+), 297 deletions(-) delete mode 100644 res/sh/grid.hlsl delete mode 100644 res/sh/mesh.hlsl delete mode 100644 res/sh/test.hlsl diff --git a/res/sh/common.hlsl b/res/sh/common.hlsl index 3ec27bdd..7a008d1e 100644 --- a/res/sh/common.hlsl +++ b/res/sh/common.hlsl @@ -7,7 +7,7 @@ #define NURI(i) NonUniformResourceIndex(i) #if !SH_CPU -# define INLINE +# define INLINE /* For intellisense */ #endif /* Linear color from normalized sRGB */ diff --git a/res/sh/grid.hlsl b/res/sh/grid.hlsl deleted file mode 100644 index 6106473b..00000000 --- a/res/sh/grid.hlsl +++ /dev/null @@ -1,106 +0,0 @@ -#include "shaders/common.hlsl" - -struct vs_instance { - float2x3 xf; - float line_thickness; - float line_spacing; - float2 offset; - uint bg0_srgb; - uint bg1_srgb; - uint line_srgb; - uint x_srgb; - uint y_srgb; -}; - -struct ps_input { - DESV(float4, screen_pos, SV_POSITION); - DECL(float, line_thickness); - DECL(float, line_spacing); - DECL(float2, offset); - DECL(float4, bg0_lin); - DECL(float4, bg1_lin); - DECL(float4, line_lin); - DECL(float4, x_lin); - DECL(float4, y_lin); -}; - -/* ========================== * - * Globals - * ========================== */ - -StructuredBuffer g_instance_buffer : register(t0); - -cbuffer constants : register(b0) -{ - float4x4 g_projection; - uint g_instance_offset; -}; - -/* ========================== * - * Vertex shader - * ========================== */ - -static const float2 G_quad_verts[4] = { - float2(-0.5f, -0.5f), - float2( 0.5f, -0.5f), - float2( 0.5f, 0.5f), - float2(-0.5f, 0.5f) -}; - -ps_input vs_main(uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID) -{ - vs_instance instance = g_instance_buffer[g_instance_offset + instance_id]; - float2 vert = G_quad_verts[vertex_id]; - float2 world_pos = mul(instance.xf, float3(vert, 1)).xy; - - ps_input output; - output.screen_pos = mul(g_projection, float4(world_pos, 0, 1)); - output.line_thickness = instance.line_thickness; - output.line_spacing = instance.line_spacing; - output.offset = instance.offset; - output.bg0_lin = linear_from_srgb32(instance.bg0_srgb); - output.bg1_lin = linear_from_srgb32(instance.bg1_srgb); - output.line_lin = linear_from_srgb32(instance.line_srgb); - output.x_lin = linear_from_srgb32(instance.x_srgb); - output.y_lin = linear_from_srgb32(instance.y_srgb); - - return output; -} - -/* ========================== * - * Pixel shader - * ========================== */ - -float4 ps_main(ps_input input) : SV_TARGET -{ - float2 grid_pos = input.screen_pos.xy + input.offset; - float half_thickness = input.line_thickness / 2; - float spacing = input.line_spacing; - - float4 color = input.bg0_lin; - - float2 v = abs(round(grid_pos / spacing) * spacing - grid_pos); - float dist = min(v.x, v.y); - - if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) { - color = input.x_lin; - } else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) { - color = input.y_lin; - } else if (dist < half_thickness) { - color = input.line_lin; - } else { - bool checker = false; - uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0); - uint cell_y = (uint)(abs(grid_pos.y) / spacing) + (grid_pos.y < 0); - if (cell_x % 2 == 0) { - checker = cell_y % 2 == 0; - } else { - checker = cell_y % 2 == 1; - } - if (checker) { - color = input.bg1_lin; - } - } - - return color; -} diff --git a/res/sh/material.hlsl b/res/sh/material.hlsl index 50a5f165..ae38f056 100644 --- a/res/sh/material.hlsl +++ b/res/sh/material.hlsl @@ -1,7 +1,7 @@ #include "sh/common.hlsl" /* ========================== * - * Root Signature + * Root signature * ========================== */ #define ROOTSIG \ @@ -24,13 +24,6 @@ SamplerState g_sampler : register(s0); * Vertex shader * ========================== */ -static const float2 g_quad_verts[4] = { - float2(-0.5f, -0.5f), - float2( 0.5f, -0.5f), - float2( 0.5f, 0.5f), - float2(-0.5f, 0.5f) -}; - struct vs_input { DECL(uint, SV_InstanceID); DECL(uint, SV_VertexID); @@ -45,8 +38,15 @@ struct vs_output { SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) { + static const float2 unit_quad_verts[4] = { + float2(-0.5f, -0.5f), + float2(0.5f, -0.5f), + float2(0.5f, 0.5f), + float2(-0.5f, 0.5f) + }; + struct sh_material_instance instance = g_instances[g_constants.instance_offset + input.SV_InstanceID]; - float2 vert = g_quad_verts[input.SV_VertexID]; + float2 vert = unit_quad_verts[input.SV_VertexID]; float2 world_pos = mul(instance.xf, float3(vert, 1)).xy; struct vs_output output; diff --git a/res/sh/mesh.hlsl b/res/sh/mesh.hlsl deleted file mode 100644 index 20ec6461..00000000 --- a/res/sh/mesh.hlsl +++ /dev/null @@ -1,42 +0,0 @@ -#include "shaders/common.hlsl" - -struct vs_input { - DECL(float4, pos); - DECL(float4, color_srgb); -}; - -struct ps_input { - DESV(float4, screen_pos, SV_POSITION); - DECL(float4, color_lin); -}; - -/* ========================== * - * Globals - * ========================== */ - -cbuffer constants : register(b0) -{ - float4x4 g_projection; -}; - -/* ========================== * - * Vertex shader - * ========================== */ - -ps_input vs_main(vs_input input) -{ - ps_input output; - output.screen_pos = mul(g_projection, float4(input.pos.xy, 0.f, 1.f)); - output.color_lin = linear_from_srgb(input.color_srgb); - - return output; -} - -/* ========================== * - * Pixel shader - * ========================== */ - -float4 ps_main(ps_input input) : SV_TARGET -{ - return input.color_lin; -} diff --git a/res/sh/sh_common.h b/res/sh/sh_common.h index 75a2e3c0..dd2d4e6b 100644 --- a/res/sh/sh_common.h +++ b/res/sh/sh_common.h @@ -6,8 +6,7 @@ #define SH_STRUCT(s) PACK(struct s) #define SH_DECL(t, n) struct CAT(sh_, t) n - -#define SH_ENTRY static /* For intellisense */ +#define SH_ENTRY(rootsig) static struct sh_uint { u32 v; }; INLINE struct sh_uint sh_uint_from_u32(u32 v) diff --git a/res/sh/test.hlsl b/res/sh/test.hlsl deleted file mode 100644 index 076735ca..00000000 --- a/res/sh/test.hlsl +++ /dev/null @@ -1,51 +0,0 @@ -#include "shaders/common.hlsl" - -struct vs_instance { - float2x3 xf; -}; - -struct ps_input { - DESV(float4, screen_pos, SV_POSITION); -}; - -/* ========================== * - * Globals - * ========================== */ - -StructuredBuffer g_instance_buffer : register(t0); - -cbuffer constants : register(b0) -{ - float4x4 g_projection; - uint g_instance_offset; -}; - -/* ========================== * - * Vertex shader - * ========================== */ - -static const float2 G_quad_verts[4] = { - float2(-0.5f, -0.5f), - float2( 0.5f, -0.5f), - float2( 0.5f, 0.5f), - float2(-0.5f, 0.5f) -}; - -ps_input vs_main(uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID) -{ - vs_instance instance = g_instance_buffer[g_instance_offset + instance_id]; - float2 vert = G_quad_verts[vertex_id]; - float2 world_pos = mul(instance.xf, float3(vert, 1)).xy; - ps_input output; - output.screen_pos = mul(g_projection, float4(world_pos, 0, 1)); - return output; -} - -/* ========================== * - * Pixel shader - * ========================== */ - -float4 ps_main(ps_input input) : SV_TARGET -{ - return float4(0, 0, 0, 0); -} diff --git a/src/app.c b/src/app.c index 3951b663..7434b16d 100644 --- a/src/app.c +++ b/src/app.c @@ -323,7 +323,7 @@ void app_entry_point(struct string args_str) struct host_startup_receipt host_sr = host_startup(&sock_sr); struct resource_startup_receipt resource_sr = resource_startup(); struct work_startup_receipt work_sr = work_startup(worker_count); - struct gp_startup_receipt gp_sr = gp_startup(&work_sr, window); + struct gp_startup_receipt gp_sr = gp_startup(&work_sr); struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup(&work_sr); struct ttf_startup_receipt ttf_sr = ttf_startup(); struct font_startup_receipt font_sr = font_startup(&work_sr, &gp_sr, &asset_cache_sr, &ttf_sr, &resource_sr); diff --git a/src/config.h b/src/config.h index 3b07856b..cf08c73b 100644 --- a/src/config.h +++ b/src/config.h @@ -96,4 +96,4 @@ #define AUDIO_ENABLED 0 #define VSYNC_ENABLED 0 -#define USER_FPS_LIMIT 300 +#define USER_FPS_LIMIT 30 diff --git a/src/gp.h b/src/gp.h index 06aa3665..4600a14c 100644 --- a/src/gp.h +++ b/src/gp.h @@ -9,7 +9,7 @@ struct work_startup_receipt; * ========================== */ struct gp_startup_receipt { i32 _; }; -struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struct sys_window *window); +struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr); /* ========================== * * Handle @@ -133,6 +133,6 @@ void gp_dispatch(struct gp_dispatch_params params); /* 1. Ensures the backbuffer is at size `backbuffer_resolution` * 2. Blits `texture` to the backbuffer using `texture_xf` (applied to centered unit square) * 3. Presents the backbuffer */ -void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync); +void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync); #endif diff --git a/src/gp_dx11.c b/src/gp_dx11.c index 379d6324..f95fb710 100644 --- a/src/gp_dx11.c +++ b/src/gp_dx11.c @@ -318,6 +318,7 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc /* Create D3D11 device & context */ { + __profscope(Create device); #if DX11_DEBUG u32 flags = D3D11_CREATE_DEVICE_DEBUG; #else @@ -362,6 +363,7 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc /* Create swap chain */ { + __profscope(Create swapchain); HWND hwnd = (HWND)sys_window_get_internal_handle(window); /* Get DXGI device from D3D11 device */ @@ -1966,18 +1968,16 @@ INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, s draw_texture(G.present_blit_flow, params); } - /* Clear textures */ + /* Clear texture */ gp_texture_clear(dst_texture_handle, RGBA32_F(0, 0, 0, 1)); /* 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; - gp_dispatch(params); - } + 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; + gp_dispatch(params); } void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) diff --git a/src/gp_dx12.c b/src/gp_dx12.c index 50f4a0a2..db50f9c5 100644 --- a/src/gp_dx12.c +++ b/src/gp_dx12.c @@ -14,6 +14,7 @@ #include "util.h" #include "rand.h" #include "sprite.h" +#include "gstat.h" /* Include common shader types */ #define SH_CPU 1 @@ -254,6 +255,9 @@ GLOBAL struct { /* Factory */ IDXGIFactory6 *factory; + /* Adapter */ + IDXGIAdapter1 *adapter; + /* Device */ ID3D12Device *device; @@ -273,6 +277,8 @@ GLOBAL struct { struct command_queue *cq_copy_background; /* Swapchain */ + HWND swapchain_hwnd; + struct v2i32 swapchain_resolution; u32 swapchain_frame_index; IDXGISwapChain3 *swapchain; struct dx12_resource *swapchain_resources[DX12_SWAPCHAIN_BUFFER_COUNT]; @@ -285,15 +291,13 @@ GLOBAL struct { INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gp_shutdown); INTERNAL void dx12_init_device(void); INTERNAL void dx12_init_objects(void); -INTERNAL void dx12_init_swapchain(struct sys_window *window); INTERNAL void dx12_init_pipelines(void); INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type); INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority); INTERNAL void command_queue_release(struct command_queue *cq); -INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff); INTERNAL void dx12_resource_release(struct dx12_resource *resource); -struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struct sys_window *window) +struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr) { __prof; (UNUSED)work_sr; @@ -317,13 +321,8 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc /* Initialize dx12 */ dx12_init_device(); dx12_init_objects(); - dx12_init_swapchain(window); dx12_init_pipelines(); - /* Init dummy buffers */ - /* TODO */ - - /* Register callbacks */ app_register_exit_callback(gp_shutdown); @@ -503,12 +502,12 @@ INTERNAL void dx12_init_device(void) /* Create device */ { + IDXGIAdapter1 *adapter = NULL; ID3D12Device *device = NULL; struct string error = LIT("Could not initialize GPU device."); struct string first_gpu_name = ZI; u32 adapter_index = 0; while (true) { - IDXGIAdapter1 *adapter = NULL; hr = IDXGIFactory6_EnumAdapterByGpuPreference(G.factory, adapter_index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, &IID_IDXGIAdapter1, (void **)&adapter); if (SUCCEEDED(hr)) { DXGI_ADAPTER_DESC1 desc; @@ -518,8 +517,6 @@ INTERNAL void dx12_init_device(void) } hr = D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device, (void **)&device); if (SUCCEEDED(hr)) { - IDXGIAdapter1_Release(adapter); - adapter = NULL; break; } ID3D12Device_Release(device); @@ -538,6 +535,7 @@ INTERNAL void dx12_init_device(void) } dx12_init_error(error); } + G.adapter = adapter; G.device = device; } @@ -597,63 +595,6 @@ INTERNAL void dx12_init_objects(void) G.cq_copy_background = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COPY, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL); } -/* ========================== * - * Dx12 swapchain initialization - * ========================== */ - -INTERNAL void dx12_init_swapchain(struct sys_window *window) -{ - HRESULT hr = 0; - - /* Create swapchain */ - { - HWND hwnd = (HWND)sys_window_get_internal_handle(window); - DXGI_SWAP_CHAIN_DESC1 desc = { - .Format = DX12_SWAPCHAIN_FORMAT, - .SampleDesc = { 1, 0 }, - .BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT, - .BufferCount = DX12_SWAPCHAIN_BUFFER_COUNT, - .Scaling = DXGI_SCALING_NONE, - .Flags = DX12_SWAPCHAIN_FLAGS, - .AlphaMode = DXGI_ALPHA_MODE_IGNORE, - .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD - }; - - /* Create swapchain1 */ - IDXGISwapChain1 *swapchain1 = NULL; - hr = IDXGIFactory2_CreateSwapChainForHwnd(G.factory, (IUnknown *)G.cq_direct->cq, hwnd, &desc, NULL, NULL, &swapchain1); - if (FAILED(hr)) { - dx12_init_error(LIT("Failed to create IDXGISwapChain1")); - } - - /* Upgrade to swapchain3 */ - hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&G.swapchain); - if (FAILED(hr)) { - dx12_init_error(LIT("Failed to create IDXGISwapChain3")); - } - - /* Disable Alt+Enter changing monitor resolution to match window size */ - IDXGIFactory_MakeWindowAssociation(G.factory, hwnd, DXGI_MWA_NO_ALT_ENTER); - - /* Get initial frame index */ - G.swapchain_frame_index = IDXGISwapChain3_GetCurrentBackBufferIndex(G.swapchain); - - IDXGISwapChain1_Release(swapchain1); - } - - /* Create swacphain RTVs */ - { - for (u32 i = 0; i < DX12_SWAPCHAIN_BUFFER_COUNT; ++i) { - ID3D12Resource *resource = NULL; - hr = IDXGISwapChain3_GetBuffer(G.swapchain, i, &IID_ID3D12Resource, (void **)&resource); - if (FAILED(hr)) { - dx12_init_error(LIT("Failed to get swapchain buffer")); - } - G.swapchain_resources[i] = dx12_resource_alloc_from_swapchain_buffer(resource); - } - } -} - /* ========================== * * Dx12 pipeline initialization * ========================== */ @@ -1069,6 +1010,7 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw) pso_desc.NumRenderTargets = 1; pso_desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; pso_desc.SampleDesc.Count = 1; + pso_desc.SampleDesc.Quality = 0; hr = ID3D12Device_CreateGraphicsPipelineState(G.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); if (FAILED(hr)) { error_str = LIT("Failed to create pipeline state object"); @@ -1187,6 +1129,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh) MEMZERO_STRUCT(d); d->heap = dh; d->handle = handle; + d->index = index; return d; } @@ -1366,7 +1309,7 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr return r; } -INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff) +INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff, struct v2i32 texture_size) { struct dx12_resource *r = NULL; { @@ -1384,8 +1327,10 @@ INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12R /* FIXME: Initialize dx12 resource struct here */ r->resource = buff; - r->rtv_descriptor = descriptor_alloc(G.rtv_heap); + r->texture_size = texture_size; + r->state = D3D12_RESOURCE_STATE_PRESENT; /* FIXME */ + ID3D12Device_CreateRenderTargetView(G.device, r->resource, NULL, r->rtv_descriptor->handle); return r; @@ -1396,6 +1341,11 @@ INTERNAL void dx12_resource_release(struct dx12_resource *t) (UNUSED)t; } +INTERNAL void dx12_resource_release_now(struct dx12_resource *t) +{ + (UNUSED)t; +} + INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandList *cl, struct dx12_resource *resource, enum D3D12_RESOURCE_STATES state) { enum D3D12_RESOURCE_STATES old_state = resource->state; @@ -1451,6 +1401,7 @@ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, stru desc.DepthOrArraySize = 1; desc.MipLevels = 1; desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; if (flags & GP_TEXTURE_FLAG_TARGETABLE) { desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; view_flags |= DX12_RESOURCE_VIEW_FLAG_RTV; @@ -1848,7 +1799,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl desc.DepthOrArraySize = 1; desc.MipLevels = 1; desc.SampleDesc.Count = 1; - + desc.SampleDesc.Quality = 0; D3D12_RESOURCE_STATES initial_state = D3D12_RESOURCE_STATE_GENERIC_READ; cb->resource = dx12_resource_alloc(heap_props, heap_flags, desc, initial_state, view_flags); @@ -1991,12 +1942,205 @@ void gp_dispatch(struct gp_dispatch_params params) arena_reset(flow->material_instances_arena); } +/* ========================== * + * Swapchain + * ========================== */ + /* ========================== * * Present * ========================== */ -void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) +#if 0 +#if GSTAT_ENABLED || PROFILING +INTERNAL void query_memory_info(void) { + HRESULT hr = 0; + IDXGIAdapter3 *dxgiAdapter3 = NULL; + struct DXGI_QUERY_VIDEO_MEMORY_INFO info = ZI; + if (SUCCEEDED(hr)) { + hr = IDXGIAdapter_QueryInterface(G.adapter, &IID_IDXGIAdapter3, (void **)&dxgiAdapter3); + ASSERT(SUCCEEDED(hr)); + } + if (SUCCEEDED(hr)) { + IDXGIAdapter3_QueryVideoMemoryInfo(dxgiAdapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info); + { + u64 vram = info.CurrentUsage; + u64 budget = info.Budget; + (UNUSED)vram; + (UNUSED)budget; +#if GSTAT_ENABLED + { + gstat_set(GSTAT_VRAM_USAGE, vram); + gstat_set(GSTAT_VRAM_BUDGET, budget); + } +#endif +#if PROFILING + { + LOCAL_PERSIST char *vram_plot_name = NULL; + LOCAL_PERSIST u64 prev_vram = 0; + if (!vram_plot_name) { + vram_plot_name = "Video memory usage"; + __prof_plot_init(vram_plot_name, __prof_plot_type_memory, 1, 1, 0); + } + if (vram != prev_vram) { + __prof_plot_i(vram_plot_name, vram); + } + prev_vram = vram; + } +#endif + } + } + if (dxgiAdapter3) { + IDXGIAdapter_Release(dxgiAdapter3); + } +} +#else +INTERNAL void query_memory_info(void) +{ +} +#endif +#endif + +INTERNAL struct dx12_resource *update_swapchain(struct sys_window *window, struct v2i32 resolution) +{ + __prof; + HWND hwnd = (HWND)sys_window_get_internal_handle(window); + b32 should_rebuild = !v2i32_eq(G.swapchain_resolution, resolution); + if (should_rebuild) { + HRESULT hr = 0; + + if (G.swapchain) { + ASSERT(hwnd == G.swapchain_hwnd); + /* Resize existing swapchain */ + /* FIXME: Fence */ + + /* Release resources */ + for (u32 i = 0; i < ARRAY_COUNT(G.swapchain_resources); ++i) { + struct dx12_resource *resource = G.swapchain_resources[i]; + dx12_resource_release_now(resource); + } + + /* Resize buffers */ + IDXGISwapChain_ResizeBuffers(G.swapchain, 0, resolution.x, resolution.y, DXGI_FORMAT_UNKNOWN, DX12_SWAPCHAIN_FLAGS); + } else { + /* Create swapchain1 */ + IDXGISwapChain1 *swapchain1 = NULL; + { + DXGI_SWAP_CHAIN_DESC1 desc = ZI; + desc.Format = DX12_SWAPCHAIN_FORMAT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.BufferCount = DX12_SWAPCHAIN_BUFFER_COUNT; + desc.Scaling = DXGI_SCALING_NONE; + desc.Flags = DX12_SWAPCHAIN_FLAGS; + desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + hr = IDXGIFactory2_CreateSwapChainForHwnd(G.factory, (IUnknown *)G.cq_direct->cq, hwnd, &desc, NULL, NULL, &swapchain1); + if (FAILED(hr)) { + dx12_init_error(LIT("Failed to create IDXGISwapChain1")); + } + } + + /* Upgrade to swapchain3 */ + hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&G.swapchain); + if (FAILED(hr)) { + dx12_init_error(LIT("Failed to create IDXGISwapChain3")); + } + + /* Disable Alt+Enter changing monitor resolution to match window size */ + IDXGIFactory_MakeWindowAssociation(G.factory, hwnd, DXGI_MWA_NO_ALT_ENTER); + + IDXGISwapChain1_Release(swapchain1); + G.swapchain_hwnd = hwnd; + } + + /* Allocate swapchain resources */ + for (u32 i = 0; i < ARRAY_COUNT(G.swapchain_resources); ++i) { + ID3D12Resource *resource = NULL; + hr = IDXGISwapChain3_GetBuffer(G.swapchain, i, &IID_ID3D12Resource, (void **)&resource); + if (FAILED(hr)) { + /* TODO: Don't panic */ + dx12_init_error(LIT("Failed to get swapchain buffer")); + } + G.swapchain_resources[i] = dx12_resource_alloc_from_swapchain_buffer(resource, resolution); + } + + G.swapchain_resolution = resolution; + } + + G.swapchain_frame_index = IDXGISwapChain3_GetCurrentBackBufferIndex(G.swapchain); + return G.swapchain_resources[G.swapchain_frame_index]; +} + +/* FIXME: Remove this */ +#include "draw.h" + +INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, struct xform src_xf) +{ + /* FIXME: Remove this */ + static struct gp_handle flow = ZI; + if (!flow.gen) { + flow = gp_flow_alloc(); + } +#if 0 + struct gp_handle dst_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, dst); + struct gp_handle src_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, src); +#endif + + /* 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(flow, params); + } + + /* FIXME: Clear backbuffer */ + + /* Render to backbuffer texture */ + struct gp_dispatch_params params = ZI; + params.flow = flow; + params.draw_target = dst_texture_handle; + params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->texture_size.x, dst->texture_size.y)); + params.draw_target_view = XFORM_IDENT; + gp_dispatch(params); +} + +void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) +{ + sys_sleep(0.1); + +#if 0 + /* FIXME: Remove this */ + static b32 bla = false; + static ID3D12Fence *fence = ZI; + static u64 fence_value = 0; + if (!bla) { + bla = true; + ID3D12Device_CreateFence(G.device, 0, 0, &IID_ID3D12Fence, (void **)&fence); + } + ++fence_value; + ID3D12CommandQueue_Signal(G.cq_direct->cq, fence, fence_value); + + HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); + ID3D12Fence_SetEventOnCompletion(fence, fence_value, event); + WaitForSingleObject(event, INFINITE); + CloseHandle(event); +#endif + + + struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution); + struct dx12_resource *texture_resource = handle_get_data(texture, DX12_HANDLE_KIND_RESOURCE); + + /* Blit */ + present_blit(backbuffer_resource, texture_resource, texture_xf); + + /* Present */ + HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0); + if (!SUCCEEDED(hr)) { + ASSERT(false); + } + (UNUSED)backbuffer_resolution; (UNUSED)texture; (UNUSED)texture_xf; diff --git a/src/user.c b/src/user.c index 4a01d181..7eb7030d 100644 --- a/src/user.c +++ b/src/user.c @@ -2093,7 +2093,7 @@ INTERNAL void user_update(void) } /* Present user texture */ - gp_present(backbuffer_resolution, G.user_texture, XFORM_TRS(.t = v2_mul(G.screen_size, 0.5), .s = G.user_size), VSYNC_ENABLED); + gp_present(G.window, backbuffer_resolution, G.user_texture, XFORM_TRS(.t = v2_mul(G.screen_size, 0.5), .s = G.user_size), VSYNC_ENABLED); } /* ========================== *