push & process commands separately

This commit is contained in:
jacob 2025-06-25 20:25:08 -05:00
parent e503fc9bdf
commit 9e0696d183
8 changed files with 417 additions and 276 deletions

View File

@ -33,7 +33,6 @@ struct vs_input {
};
struct vs_output {
nointerpolation DECLS(uint, flags);
nointerpolation DECLS(int, tex_nurid);
nointerpolation DECLS(int, grid_id);
DECLS(float2, uv);
@ -56,7 +55,6 @@ SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
struct vs_output output;
output.SV_Position = mul(g_constants.projection, float4(world_pos, 0, 1));
output.flags = instance.flags;
output.tex_nurid = instance.tex_nurid;
output.grid_id = instance.grid_id;
output.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));

View File

@ -73,15 +73,12 @@ SH_ASSERT_32BIT(struct sh_blit_constants, 18); /* Expected 32bit root constant
* Material shader structures
* ========================== */
#define SH_MATERIAL_FLAG_NONE (0)
SH_STRUCT(sh_material_constants {
SH_DECL(float4x4, projection);
});
SH_ASSERT_32BIT(struct sh_material_constants, 16); /* Expected 32bit root constant size in shader */
SH_STRUCT(sh_material_instance {
SH_DECL(uint, flags);
SH_DECL(int, tex_nurid);
SH_DECL(int, grid_id);
SH_DECL(float2x3, xf);

View File

@ -28,7 +28,7 @@ struct draw_startup_receipt draw_startup(struct gp_startup_receipt *gp_sr,
* Texture
* ========================== */
void draw_texture(struct gp_handle flow, struct draw_texture_params params)
void draw_texture(struct gp_flow *flow, struct draw_texture_params params)
{
struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_MATERIAL;
@ -38,25 +38,25 @@ void draw_texture(struct gp_handle flow, struct draw_texture_params params)
cmd.material.clip = params.clip;
cmd.material.tint = params.tint;
cmd.material.emittance = params.emittance;
gp_push_cmd(flow, cmd);
gp_push_cmd(flow, &cmd);
}
/* ========================== *
* Fill shapes
* ========================== */
void draw_poly_ex(struct gp_handle flow, struct v2_array vertices, struct gp_indices indices, u32 color)
void draw_poly_ex(struct gp_flow *flow, struct v2_array vertices, struct gp_indices indices, u32 color)
{
struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_SHAPE;
cmd.shape.vertices = vertices;
cmd.shape.indices = indices;
cmd.shape.color = color;
gp_push_cmd(flow, cmd);
gp_push_cmd(flow, &cmd);
}
/* Draws a filled polygon using triangles in a fan pattern */
void draw_poly(struct gp_handle flow, struct v2_array vertices, u32 color)
void draw_poly(struct gp_flow *flow, struct v2_array vertices, u32 color)
{
if (vertices.count >= 3) {
struct arena_temp scratch = scratch_begin_no_conflict();
@ -82,7 +82,7 @@ void draw_poly(struct gp_handle flow, struct v2_array vertices, u32 color)
}
}
void draw_circle(struct gp_handle flow, struct v2 pos, f32 radius, u32 color, u32 detail)
void draw_circle(struct gp_flow *flow, struct v2 pos, f32 radius, u32 color, u32 detail)
{
struct arena_temp scratch = scratch_begin_no_conflict();
@ -105,7 +105,7 @@ void draw_circle(struct gp_handle flow, struct v2 pos, f32 radius, u32 color, u3
scratch_end(scratch);
}
void draw_quad(struct gp_handle flow, struct quad quad, u32 color)
void draw_quad(struct gp_flow *flow, struct quad quad, u32 color)
{
LOCAL_PERSIST u32 indices_array[6] = {
0, 1, 2,
@ -120,7 +120,7 @@ void draw_quad(struct gp_handle flow, struct quad quad, u32 color)
* Line shapes
* ========================== */
void draw_gradient_line(struct gp_handle flow, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color)
void draw_gradient_line(struct gp_flow *flow, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color)
{
#if 0
struct quad quad = quad_from_line(start, end, thickness);
@ -133,19 +133,19 @@ void draw_gradient_line(struct gp_handle flow, struct v2 start, struct v2 end, f
#endif
}
void draw_line(struct gp_handle flow, struct v2 start, struct v2 end, f32 thickness, u32 color)
void draw_line(struct gp_flow *flow, struct v2 start, struct v2 end, f32 thickness, u32 color)
{
struct quad quad = quad_from_line(start, end, thickness);
draw_quad(flow, quad, color);
}
void draw_ray(struct gp_handle flow, struct v2 pos, struct v2 rel, f32 thickness, u32 color)
void draw_ray(struct gp_flow *flow, struct v2 pos, struct v2 rel, f32 thickness, u32 color)
{
struct quad quad = quad_from_ray(pos, rel, thickness);
draw_quad(flow, quad, color);
}
void draw_poly_line(struct gp_handle flow, struct v2_array points, b32 loop, f32 thickness, u32 color)
void draw_poly_line(struct gp_flow *flow, struct v2_array points, b32 loop, f32 thickness, u32 color)
{
if (points.count >= 2) {
for (u64 i = 1; i < points.count; ++i) {
@ -163,7 +163,7 @@ void draw_poly_line(struct gp_handle flow, struct v2_array points, b32 loop, f32
}
}
void draw_circle_line(struct gp_handle flow, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
void draw_circle_line(struct gp_flow *flow, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
{
struct arena_temp scratch = scratch_begin_no_conflict();
@ -186,14 +186,14 @@ void draw_circle_line(struct gp_handle flow, struct v2 pos, f32 radius, f32 thic
scratch_end(scratch);
}
void draw_quad_line(struct gp_handle flow, struct quad quad, f32 thickness, u32 color)
void draw_quad_line(struct gp_flow *flow, struct quad quad, f32 thickness, u32 color)
{
struct v2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
struct v2_array a = { .points = points, .count = ARRAY_COUNT(points) };
draw_poly_line(flow, a, true, thickness, color);
}
void draw_arrow_line(struct gp_handle flow, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color)
void draw_arrow_line(struct gp_flow *flow, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color)
{
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
@ -223,13 +223,13 @@ void draw_arrow_line(struct gp_handle flow, struct v2 start, struct v2 end, f32
draw_quad(flow, line_quad, color);
}
void draw_arrow_ray(struct gp_handle flow, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color)
void draw_arrow_ray(struct gp_flow *flow, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color)
{
struct v2 end = v2_add(pos, rel);
draw_arrow_line(flow, pos, end, thickness, arrowhead_height, color);
}
void draw_collider_line(struct gp_handle flow, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail)
void draw_collider_line(struct gp_flow *flow, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail)
{
struct arena_temp scratch = scratch_begin_no_conflict();
struct v2_array poly = ZI;
@ -258,24 +258,29 @@ void draw_collider_line(struct gp_handle flow, struct collider_shape shape, stru
* Grid
* ========================== */
void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset)
void draw_grid(struct gp_flow *flow, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset)
{
struct gp_grid_desc grid = ZI;
grid.bg0_color = bg0_color;
grid.bg1_color = bg1_color;
grid.line_color = line_color;
grid.x_color = x_color;
grid.y_color = y_color;
grid.line_thickness = thickness;
grid.line_spacing = spacing;
grid.offset = offset;
i32 grid_id = 0;
{
struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_PUSH_GRID;
cmd.grid.bg0_color = bg0_color;
cmd.grid.bg1_color = bg1_color;
cmd.grid.line_color = line_color;
cmd.grid.x_color = x_color;
cmd.grid.y_color = y_color;
cmd.grid.line_thickness = thickness;
cmd.grid.line_spacing = spacing;
cmd.grid.offset = offset;
grid_id = gp_push_cmd(flow, &cmd);
}
struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_MATERIAL;
cmd.material.xf = xf;
cmd.material.tint = COLOR_WHITE;
cmd.material.grid = &grid;
gp_push_cmd(flow, cmd);
cmd.material.grid_cmd_id = grid_id;
gp_push_cmd(flow, &cmd);
}
/* ========================== *
@ -283,7 +288,7 @@ void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_co
* ========================== */
/* Returns the rect of the text area */
struct rect draw_text(struct gp_handle flow, struct draw_text_params params)
struct rect draw_text(struct gp_flow *flow, struct draw_text_params params)
{
__prof;
struct arena_temp scratch = scratch_begin_no_conflict();

View File

@ -29,47 +29,47 @@ struct draw_texture_params {
f32 emittance;
};
void draw_texture(struct gp_handle flow, struct draw_texture_params params);
void draw_texture(struct gp_flow *flow, struct draw_texture_params params);
/* ========================== *
* Fill shapes
* ========================== */
void draw_poly_ex(struct gp_handle flow, struct v2_array vertices, struct gp_indices indices, u32 color);
void draw_poly_ex(struct gp_flow *flow, struct v2_array vertices, struct gp_indices indices, u32 color);
void draw_poly(struct gp_handle flow, struct v2_array points, u32 color);
void draw_poly(struct gp_flow *flow, struct v2_array points, u32 color);
void draw_circle(struct gp_handle flow, struct v2 pos, f32 radius, u32 color, u32 detail);
void draw_circle(struct gp_flow *flow, struct v2 pos, f32 radius, u32 color, u32 detail);
void draw_quad(struct gp_handle flow, struct quad quad, u32 color);
void draw_quad(struct gp_flow *flow, struct quad quad, u32 color);
/* ========================== *
* Line shapes
* ========================== */
void draw_gradient_line(struct gp_handle flow, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color);
void draw_gradient_line(struct gp_flow *flow, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color);
void draw_line(struct gp_handle flow, struct v2 start, struct v2 end, f32 thickness, u32 color);
void draw_line(struct gp_flow *flow, struct v2 start, struct v2 end, f32 thickness, u32 color);
void draw_ray(struct gp_handle flow, struct v2 pos, struct v2 rel, f32 thickness, u32 color);
void draw_ray(struct gp_flow *flow, struct v2 pos, struct v2 rel, f32 thickness, u32 color);
void draw_poly_line(struct gp_handle flow, struct v2_array points, b32 loop, f32 thickness, u32 color);
void draw_poly_line(struct gp_flow *flow, struct v2_array points, b32 loop, f32 thickness, u32 color);
void draw_circle_line(struct gp_handle flow, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail);
void draw_circle_line(struct gp_flow *flow, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail);
void draw_quad_line(struct gp_handle flow, struct quad quad, f32 thickness, u32 color);
void draw_quad_line(struct gp_flow *flow, struct quad quad, f32 thickness, u32 color);
void draw_arrow_line(struct gp_handle flow, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color);
void draw_arrow_line(struct gp_flow *flow, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color);
void draw_arrow_ray(struct gp_handle flow, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color);
void draw_arrow_ray(struct gp_flow *flow, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color);
void draw_collider_line(struct gp_handle flow, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail);
void draw_collider_line(struct gp_flow *flow, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail);
/* ========================== *
* Grid
* ========================== */
void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset);
void draw_grid(struct gp_flow *flow, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset);
/* ========================== *
* Text
@ -117,6 +117,6 @@ struct draw_text_params {
struct string str;
};
struct rect draw_text(struct gp_handle flow, struct draw_text_params params);
struct rect draw_text(struct gp_flow *flow, struct draw_text_params params);
#endif

View File

@ -63,28 +63,18 @@ struct v2i32 gp_texture_get_size(struct gp_handle texture);
* Flow
* ========================== */
struct gp_indices {
u32 count;
u32 *indices;
};
enum gp_cmd_kind {
GP_CMD_KIND_NONE,
GP_CMD_KIND_DRAW_SHAPE,
GP_CMD_KIND_DRAW_MATERIAL,
GP_CMD_KIND_PUSH_GRID,
NUM_GP_CMD_KINDS
};
struct gp_grid_desc {
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_color;
u32 bg1_color;
u32 line_color;
u32 x_color;
u32 y_color;
struct gp_indices {
u32 count;
u32 *indices;
};
struct gp_cmd_desc {
@ -97,27 +87,38 @@ struct gp_cmd_desc {
struct clip_rect clip;
u32 tint;
f32 emittance;
struct gp_grid_desc *grid;
i32 grid_cmd_id;
} material;
struct {
struct v2_array vertices;
struct gp_indices indices;
u32 color;
} shape;
struct {
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_color;
u32 bg1_color;
u32 line_color;
u32 x_color;
u32 y_color;
} grid;
};
};
struct gp_dispatch_params {
struct gp_handle flow;
struct gp_flow *flow;
struct gp_handle draw_target;
struct rect draw_target_viewport;
struct xform draw_target_view;
b32 clear_target;
};
struct gp_handle gp_flow_alloc(void);
struct gp_flow *gp_flow_alloc(void);
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params);
/* Returns a cmd id internal to the flow */
i32 gp_push_cmd(struct gp_flow *gp_flow, struct gp_cmd_desc *desc);
void gp_dispatch(struct gp_dispatch_params params);

View File

@ -121,13 +121,14 @@ struct command_queue {
D3D12_COMMAND_LIST_TYPE type;
ID3D12CommandQueue *cq;
struct arena *arena;
struct sys_mutex *mutex;
struct sys_mutex *submitted_command_lists_mutex;
struct command_list *first_submitted_command_list;
struct command_list *last_submitted_command_list;
struct atomic_u64 fence_target;
ID3D12Fence *fence;
struct sys_mutex *submit_fence_mutex;
u64 submit_fence_target;
ID3D12Fence *submit_fence;
#if PROFILING
struct __prof_dx12_ctx *prof;
@ -138,7 +139,7 @@ struct command_list {
struct command_queue *cq;
struct ID3D12CommandAllocator *ca;
struct ID3D12GraphicsCommandList *cl;
struct sys_lock global_lock;
struct sys_lock global_record_lock;
struct command_descriptor_heap *first_command_descriptor_heap;
struct command_buffer *first_command_buffer;
@ -195,17 +196,10 @@ struct descriptor {
struct dx12_resource {
ID3D12Resource *resource;
enum D3D12_RESOURCE_STATES state;
#if 0
D3D12_CPU_DESCRIPTOR_HANDLE cbv_handle;
D3D12_CPU_DESCRIPTOR_HANDLE srv_handle;
D3D12_CPU_DESCRIPTOR_HANDLE uav_handle;
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle;
#else
struct descriptor *cbv_descriptor;
struct descriptor *srv_descriptor;
struct descriptor *uav_descriptor;
struct descriptor *rtv_descriptor;
#endif
D3D12_GPU_VIRTUAL_ADDRESS gpu_address; /* NOTE: 0 for textures */
@ -213,6 +207,20 @@ struct dx12_resource {
struct dx12_resource *next_free;
};
struct swapchain_buffer {
struct swapchain *swapchain;
ID3D12Resource *resource;
struct descriptor *rtv_descriptor;
D3D12_RESOURCE_STATES state;
};
struct swapchain {
IDXGISwapChain3 *swapchain;
HWND hwnd;
struct v2i32 resolution;
struct swapchain_buffer buffers[DX12_SWAPCHAIN_BUFFER_COUNT];
};
struct cpu_descriptor_heap {
enum D3D12_DESCRIPTOR_HEAP_TYPE type;
struct arena *arena;
@ -231,7 +239,6 @@ struct cpu_descriptor_heap {
enum handle_kind {
DX12_HANDLE_KIND_NONE,
DX12_HANDLE_KIND_RESOURCE,
DX12_HANDLE_KIND_FLOW,
NUM_DX12_HANDLE_KINDS
};
@ -299,18 +306,15 @@ GLOBAL struct {
/* Command queues */
/* TODO: Add optional mode to route everything to direct queue */
struct sys_mutex *global_command_list_mutex;
struct sys_mutex *global_command_list_record_mutex;
struct sys_mutex *global_command_list_submit_mutex;
struct command_queue *cq_direct;
struct command_queue *cq_compute;
struct command_queue *cq_copy_critical;
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];
struct swapchain swapchain;
} G = ZI, DEBUG_ALIAS(G, G_gp_dx12);
/* ========================== *
@ -378,10 +382,7 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gp_shutdown)
__prof;
#if DX12_DEBUG
/* Release objects to make live object reporting less noisy */
for (u64 i = 0; i < ARRAY_COUNT(G.swapchain_resources); ++i) {
dx12_resource_release(G.swapchain_resources[i]);
}
IDXGISwapChain3_Release(G.swapchain);
//IDXGISwapChain3_Release(G.swapchain);
command_queue_release(G.cq_copy_background);
command_queue_release(G.cq_copy_critical);
command_queue_release(G.cq_compute);
@ -441,20 +442,27 @@ INTERNAL struct handle_entry *handle_get_entry(struct gp_handle handle, struct s
return res;
}
INTERNAL void *handle_get_data(struct gp_handle handle, enum handle_kind kind)
INTERNAL void *handle_get_data_locked(struct gp_handle handle, enum handle_kind kind, struct sys_lock *lock)
{
(UNUSED)kind;
sys_assert_locked_e_or_s(lock, G.handle_entries_mutex);
void *data = NULL;
if (handle.gen) {
struct sys_lock lock = sys_mutex_lock_s(G.handle_entries_mutex);
{
struct handle_entry *entry = handle_get_entry(handle, &lock);
data = entry->data;
struct handle_entry *entry = handle_get_entry(handle, lock);
data = entry->data;
#if RTC
/* Handle should match expected kind */
ASSERT(entry->kind == kind);
/* Handle should match expected kind */
ASSERT(entry->kind == kind);
#endif
}
}
return data;
}
INTERNAL void *handle_get_data(struct gp_handle handle, enum handle_kind kind)
{
void *data = NULL;
if (handle.gen) {
struct sys_lock lock = sys_mutex_lock_e(G.handle_entries_mutex);
data = handle_get_data_locked(handle, kind, &lock);
sys_mutex_unlock(&lock);
}
return data;
@ -670,7 +678,8 @@ INTERNAL void dx12_init_objects(void)
G.rtv_heap = cpu_descriptor_heap_alloc(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
/* Create command queues */
G.global_command_list_mutex = sys_mutex_alloc();
G.global_command_list_record_mutex = sys_mutex_alloc();
G.global_command_list_submit_mutex = sys_mutex_alloc();
G.cq_direct = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, LIT("Direct queue"));
G.cq_compute = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COMPUTE, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, LIT("Compute queue"));
G.cq_copy_critical = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COPY, D3D12_COMMAND_QUEUE_PRIORITY_HIGH, LIT("High priority copy queue"));
@ -1402,6 +1411,17 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
return d;
}
INTERNAL void descriptor_release(struct descriptor *descriptor)
{
struct cpu_descriptor_heap *dh = descriptor->heap;
struct sys_lock lock = sys_mutex_lock_e(dh->mutex);
{
descriptor->next_free = dh->first_free_descriptor;
dh->first_free_descriptor = descriptor;
}
sys_mutex_unlock(&lock);
}
/* ========================== *
* CPU descriptor heap
* ========================== */
@ -1456,16 +1476,42 @@ INTERNAL void cpu_descriptor_heap_release(struct cpu_descriptor_heap *dh)
struct flow {
struct arena *arena;
/* Below fields are reset each dispatch */
struct sprite_scope *sprite_scope;
struct arena *material_instances_arena;
struct arena *material_grids_arena;
/* Material instances */
u32 num_material_instance_descs;
struct arena *material_instance_descs_arena;
/* Grids */
u32 num_material_grid_descs;
struct arena *material_grid_descs_arena;
/* Shapes */
struct arena *shape_verts_arena;
struct arena *shape_indices_arena;
struct flow *next_free;
};
struct material_instance_desc {
struct xform xf;
struct sprite_tag sprite;
struct gp_handle texture;
struct clip_rect clip;
u32 tint;
f32 emittance;
i32 grid_id;
};
struct material_grid_desc {
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_color;
u32 bg1_color;
u32 line_color;
u32 x_color;
u32 y_color;
};
INTERNAL struct flow *flow_alloc(void)
{
__prof;
@ -1476,9 +1522,8 @@ INTERNAL struct flow *flow_alloc(void)
flow->arena = arena;
}
flow->sprite_scope = sprite_scope_begin();
flow->material_instances_arena = arena_alloc(GIGABYTE(1));
flow->material_grids_arena = arena_alloc(GIGABYTE(1));
flow->material_instance_descs_arena = arena_alloc(GIGABYTE(1));
flow->material_grid_descs_arena = arena_alloc(GIGABYTE(1));
flow->shape_verts_arena = arena_alloc(GIGABYTE(1));
flow->shape_indices_arena = arena_alloc(GIGABYTE(1));
@ -1488,90 +1533,81 @@ INTERNAL struct flow *flow_alloc(void)
INTERNAL void flow_reset(struct flow *flow)
{
__prof;
sprite_scope_end(flow->sprite_scope);
flow->sprite_scope = sprite_scope_begin();
arena_reset(flow->material_instances_arena);
arena_reset(flow->material_grids_arena);
/* Reset material instances */
flow->num_material_instance_descs = 0;
arena_reset(flow->material_instance_descs_arena);
/* Reset grids */
flow->num_material_grid_descs = 0;
arena_reset(flow->material_grid_descs_arena);
/* Reset shapes */
arena_reset(flow->shape_verts_arena);
arena_reset(flow->shape_indices_arena);
}
struct gp_handle gp_flow_alloc(void)
struct gp_flow *gp_flow_alloc(void)
{
__prof;
struct flow *flow = flow_alloc();
return handle_alloc(DX12_HANDLE_KIND_FLOW, flow);
return (struct gp_flow *)flow;
}
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc)
i32 gp_push_cmd(struct gp_flow *gp_flow, struct gp_cmd_desc *cmd_desc)
{
__prof;
struct flow *flow = handle_get_data(gp_flow, DX12_HANDLE_KIND_FLOW);
i32 ret = 0;
struct flow *flow = (struct flow *)gp_flow;
if (flow) {
switch (desc.kind) {
switch (cmd_desc->kind) {
default: break;
case GP_CMD_KIND_DRAW_MATERIAL:
{
i32 texture_id = -1;
{
struct dx12_resource *texture = NULL;
if (desc.material.texture.gen != 0) {
texture = handle_get_data(desc.material.texture, DX12_HANDLE_KIND_RESOURCE);
} else if (desc.material.sprite.hash != 0) {
struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, desc.material.sprite);
texture = handle_get_data(st->texture, DX12_HANDLE_KIND_RESOURCE);
}
if (texture) {
texture_id = texture->srv_descriptor->index;
}
}
i32 grid_id = -1;
if (desc.material.grid) {
struct gp_grid_desc *grid_desc = desc.material.grid;
struct sh_material_grid *grid = arena_push(flow->material_grids_arena, struct sh_material_grid);
grid->line_thickness = sh_float_from_f32(grid_desc->line_thickness);
grid->line_spacing = sh_float_from_f32(grid_desc->line_spacing);
grid->offset = sh_float2_from_v2(grid_desc->offset);
grid->bg0_srgb = sh_uint_from_u32(grid_desc->bg0_color);
grid->bg1_srgb = sh_uint_from_u32(grid_desc->bg1_color);
grid->line_srgb = sh_uint_from_u32(grid_desc->line_color);
grid->x_srgb = sh_uint_from_u32(grid_desc->x_color);
grid->y_srgb = sh_uint_from_u32(grid_desc->y_color);
grid_id = ((u8 *)grid - arena_base(flow->material_grids_arena)) / sizeof(grid);
}
if (texture_id >= 0 || grid_id >= 0) {
struct sh_material_instance *instance = arena_push(flow->material_instances_arena, struct sh_material_instance);
instance->flags = sh_uint_from_u32(SH_MATERIAL_FLAG_NONE);
instance->tex_nurid = sh_int_from_i32(texture_id);
instance->grid_id = sh_int_from_i32(grid_id);
instance->xf = sh_float2x3_from_xform(desc.material.xf);
instance->uv0 = sh_float2_from_v2(desc.material.clip.p0);
instance->uv1 = sh_float2_from_v2(desc.material.clip.p1);
instance->tint_srgb = sh_uint_from_u32(desc.material.tint);
instance->emittance = sh_float_from_f32(desc.material.emittance);
}
struct material_instance_desc *instance_desc = arena_push(flow->material_instance_descs_arena, struct material_instance_desc);
instance_desc->xf = cmd_desc->material.xf;
instance_desc->sprite = cmd_desc->material.sprite;
instance_desc->texture = cmd_desc->material.texture;
instance_desc->clip = cmd_desc->material.clip;
instance_desc->tint = cmd_desc->material.tint;
instance_desc->emittance = cmd_desc->material.emittance;
instance_desc->grid_id = cmd_desc->material.grid_cmd_id - 1;
ret = ++flow->num_material_instance_descs;
} break;
case GP_CMD_KIND_DRAW_SHAPE:
{
u32 color = desc.shape.color;
u32 vert_offset = flow->shape_verts_arena->pos / sizeof(struct sh_shape_vert);
struct sh_shape_vert *verts = arena_push_array_no_zero(flow->shape_verts_arena, struct sh_shape_vert, desc.shape.vertices.count);
u32 *indices = arena_push_array_no_zero(flow->shape_indices_arena, u32, desc.shape.indices.count);
for (u32 i = 0; i < desc.shape.vertices.count; ++i) {
u32 color = cmd_desc->shape.color;
struct sh_shape_vert *verts = arena_push_array_no_zero(flow->shape_verts_arena, struct sh_shape_vert, cmd_desc->shape.vertices.count);
u32 *indices = arena_push_array_no_zero(flow->shape_indices_arena, u32, cmd_desc->shape.indices.count);
for (u32 i = 0; i < cmd_desc->shape.vertices.count; ++i) {
struct sh_shape_vert *v = &verts[i];
v->pos = sh_float2_from_v2(desc.shape.vertices.points[i]);
v->pos = sh_float2_from_v2(cmd_desc->shape.vertices.points[i]);
v->color_srgb = sh_uint_from_u32(color);
}
for (u32 i = 0; i < desc.shape.indices.count; ++i) {
indices[i] = desc.shape.indices.indices[i] + vert_offset;
u32 vert_offset = verts - (struct sh_shape_vert *)arena_base(flow->shape_verts_arena);
for (u32 i = 0; i < cmd_desc->shape.indices.count; ++i) {
indices[i] = cmd_desc->shape.indices.indices[i] + vert_offset;
}
} break;
case GP_CMD_KIND_PUSH_GRID:
{
struct material_grid_desc *grid_desc = arena_push(flow->material_grid_descs_arena, struct material_grid_desc);
grid_desc->line_thickness = cmd_desc->grid.line_thickness;
grid_desc->line_spacing = cmd_desc->grid.line_spacing;
grid_desc->offset = cmd_desc->grid.offset;
grid_desc->bg0_color = cmd_desc->grid.bg0_color;
grid_desc->bg1_color = cmd_desc->grid.bg1_color;
grid_desc->line_color = cmd_desc->grid.line_color;
grid_desc->x_color = cmd_desc->grid.x_color;
grid_desc->y_color = cmd_desc->grid.y_color;
ret = ++flow->num_material_grid_descs;
} break;
}
}
return ret;
}
/* ========================== *
@ -1641,43 +1677,10 @@ 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, struct v2i32 texture_size)
{
__prof;
struct dx12_resource *r = NULL;
{
struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex);
if (G.first_free_resource) {
r = G.first_free_resource;
G.first_free_resource = r->next_free;
} else {
r = arena_push_no_zero(G.resources_arena, struct dx12_resource);
}
sys_mutex_unlock(&lock);
}
MEMZERO_STRUCT(r);
/* 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;
}
INTERNAL void dx12_resource_release(struct dx12_resource *t)
{
__prof;
(UNUSED)t;
}
INTERNAL void dx12_resource_release_now(struct dx12_resource *t)
{
__prof;
/* TODO */
(UNUSED)t;
}
@ -1717,8 +1720,9 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE
cq = arena_push(arena, struct command_queue);
cq->arena = arena;
}
cq->mutex = sys_mutex_alloc();
cq->type = type;
cq->submitted_command_lists_mutex = sys_mutex_alloc();
cq->submit_fence_mutex = sys_mutex_alloc();
D3D12_COMMAND_QUEUE_DESC desc = ZI;
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
@ -1729,7 +1733,7 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE
sys_panic(LIT("Failed to create command queue"));
}
hr = ID3D12Device_CreateFence(G.device, 0, 0, &IID_ID3D12Fence, (void **)&cq->fence);
hr = ID3D12Device_CreateFence(G.device, 0, 0, &IID_ID3D12Fence, (void **)&cq->submit_fence);
if (FAILED(hr)) {
sys_panic(LIT("Failed to create command queue fence"));
}
@ -1755,16 +1759,16 @@ INTERNAL void command_queue_release(struct command_queue *cq)
INTERNAL struct command_list *command_list_open(struct command_queue *cq)
{
__prof;
u64 queue_fence_value = ID3D12Fence_GetCompletedValue(cq->fence);
u64 completed_fence_value = ID3D12Fence_GetCompletedValue(cq->submit_fence);
struct command_list *cl = NULL;
struct ID3D12GraphicsCommandList *old_cl = NULL;
struct ID3D12CommandAllocator *old_ca = NULL;
{
struct sys_lock lock = sys_mutex_lock_e(cq->mutex);
struct sys_lock lock = sys_mutex_lock_e(cq->submitted_command_lists_mutex);
/* Find first command list ready for reuse */
for (struct command_list *tmp = cq->first_submitted_command_list; tmp; tmp = tmp->next_submitted) {
if (queue_fence_value >= tmp->submitted_fence_target) {
if (completed_fence_value >= tmp->submitted_fence_target) {
cl = tmp;
break;
}
@ -1792,7 +1796,7 @@ INTERNAL struct command_list *command_list_open(struct command_queue *cq)
}
MEMZERO_STRUCT(cl);
cl->cq = cq;
cl->global_lock = sys_mutex_lock_s(G.global_command_list_mutex);
cl->global_record_lock = sys_mutex_lock_s(G.global_command_list_record_mutex);
HRESULT hr = 0;
/* FIXME: Determine command list type from command queue */
@ -1816,7 +1820,7 @@ INTERNAL struct command_list *command_list_open(struct command_queue *cq)
}
}
/* Close */
/* Reset */
hr = ID3D12CommandAllocator_Reset(cl->ca);
if (FAILED(hr)) {
sys_panic(LIT("Failed to reset command allocator"));
@ -1836,24 +1840,37 @@ INTERNAL u64 command_list_close(struct command_list *cl)
__prof;
struct command_queue *cq = cl->cq;
/* Close & execute */
HRESULT hr = ID3D12GraphicsCommandList_Close(cl->cl);
if (FAILED(hr)) {
sys_panic(LIT("Failed to close command list before execution"));
/* Close */
{
__profscope(Close DX12 command list);
HRESULT hr = ID3D12GraphicsCommandList_Close(cl->cl);
if (FAILED(hr)) {
/* TODO: Don't panic */
sys_panic(LIT("Failed to close command list before execution"));
}
}
ID3D12CommandQueue_ExecuteCommandLists(cq->cq, 1, (ID3D12CommandList **)&cl->cl);
/* Queue fence signal */
/* FIXME: Wrap execute & signal in mutex */
u64 target_fence_value = atomic_u64_eval_add_u64(&cq->fence_target, 1) + 1;
ID3D12CommandQueue_Signal(cq->cq, cq->fence, target_fence_value);
/* Submit */
u64 submit_fence_target = 0;
{
__profscope(Execute);
struct sys_lock global_lock = sys_mutex_lock_s(G.global_command_list_submit_mutex);
struct sys_lock fence_lock = sys_mutex_lock_e(cq->submit_fence_mutex);
{
submit_fence_target = ++cq->submit_fence_target;
ID3D12CommandQueue_ExecuteCommandLists(cq->cq, 1, (ID3D12CommandList **)&cl->cl);
ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, submit_fence_target);
}
sys_mutex_unlock(&fence_lock);
sys_mutex_unlock(&global_lock);
}
/* Add descriptor heaps to submitted list */
{
struct sys_lock lock = sys_mutex_lock_e(G.command_descriptor_heaps_mutex);
for (struct command_descriptor_heap *cdh = cl->first_command_descriptor_heap; cdh; cdh = cdh->next_in_command_list) {
cdh->submitted_cq = cq;
cdh->submitted_fence_target = target_fence_value;
cdh->submitted_fence_target = submit_fence_target;
if (G.last_submitted_command_descriptor_heap) {
G.last_submitted_command_descriptor_heap->next_submitted = cdh;
} else {
@ -1870,7 +1887,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
for (struct command_buffer *cb = cl->first_command_buffer; cb; cb = cb->next_in_command_list) {
struct command_buffer_group *group = cb->group;
cb->submitted_cq = cq;
cb->submitted_fence_target = target_fence_value;
cb->submitted_fence_target = submit_fence_target;
if (group->last_submitted) {
group->last_submitted->next_submitted = cb;
} else {
@ -1882,10 +1899,10 @@ INTERNAL u64 command_list_close(struct command_list *cl)
}
/* Add command list to submitted list */
sys_mutex_unlock(&cl->global_lock);
cl->submitted_fence_target = target_fence_value;
sys_mutex_unlock(&cl->global_record_lock);
cl->submitted_fence_target = submit_fence_target;
{
struct sys_lock lock = sys_mutex_lock_e(cq->mutex);
struct sys_lock lock = sys_mutex_lock_e(cq->submitted_command_lists_mutex);
if (cq->last_submitted_command_list) {
cq->last_submitted_command_list->next_submitted = cl;
} else {
@ -1895,7 +1912,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
sys_mutex_unlock(&lock);
}
return target_fence_value;
return submit_fence_target;
}
/* ========================== *
@ -1917,8 +1934,8 @@ INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struc
/* Find first heap ready for reuse */
for (struct command_descriptor_heap *tmp = G.first_submitted_command_descriptor_heap; tmp; tmp = tmp->next_submitted) {
/* TODO: Cache completed fence values */
u64 queue_fence_value = ID3D12Fence_GetCompletedValue(tmp->submitted_cq->fence);
if (queue_fence_value >= tmp->submitted_fence_target) {
u64 completed_fence_value = ID3D12Fence_GetCompletedValue(tmp->submitted_cq->submit_fence);
if (completed_fence_value >= tmp->submitted_fence_target) {
cdh = tmp;
break;
}
@ -2032,8 +2049,8 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl
/* Find first command buffer ready for reuse */
for (struct command_buffer *tmp = cb_group->first_submitted; tmp; tmp = tmp->next_submitted) {
/* TODO: Cache completed fence values */
u64 queue_fence_value = ID3D12Fence_GetCompletedValue(tmp->submitted_cq->fence);
if (queue_fence_value >= tmp->submitted_fence_target) {
u64 completed_fence_value = ID3D12Fence_GetCompletedValue(tmp->submitted_cq->submit_fence);
if (completed_fence_value >= tmp->submitted_fence_target) {
cb = tmp;
break;
}
@ -2319,10 +2336,13 @@ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, stru
/* Wait */
/* TODO: Return async waitable to caller */
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
ID3D12Fence_SetEventOnCompletion(cq->fence, fence_target, event);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
{
__profscope(Wait for upload);
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
ID3D12Fence_SetEventOnCompletion(cq->submit_fence, fence_target, event);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
}
return handle_alloc(DX12_HANDLE_KIND_RESOURCE, r);
@ -2353,9 +2373,10 @@ INLINE struct mat4x4 calculate_vp(struct xform view, f32 viewport_width, f32 vie
void gp_dispatch(struct gp_dispatch_params params)
{
__prof;
struct arena_temp scratch = scratch_begin_no_conflict();
struct flow *flow = (struct flow *)params.flow;
struct flow *flow = handle_get_data(params.flow, DX12_HANDLE_KIND_FLOW);
struct sprite_scope *sprite_scope = sprite_scope_begin();
struct pipeline_scope *pipeline_scope = pipeline_scope_begin();
struct pipeline *material_pipeline = pipeline_from_name(pipeline_scope, LIT("material"));
struct pipeline *shape_pipeline = pipeline_from_name(pipeline_scope, LIT("shape"));
@ -2372,9 +2393,64 @@ void gp_dispatch(struct gp_dispatch_params params)
struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0));
struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices));
/* Process flow data into uploadable data */
struct sh_material_instance *material_instances = arena_push_array_no_zero(scratch.arena, struct sh_material_instance, flow->num_material_instance_descs);
struct sh_material_grid *grids = arena_push_array_no_zero(scratch.arena, struct sh_material_grid, flow->num_material_grid_descs);
{
__profscope(Process flow data);
/* Process material instances */
{
__profscope(Process material instances);
struct sys_lock handles_lock = sys_mutex_lock_s(G.handle_entries_mutex);
for (u32 i = 0; i < flow->num_material_instance_descs; ++i) {
struct material_instance_desc *desc = &((struct material_instance_desc *)arena_base(flow->material_instance_descs_arena))[i];
struct sh_material_instance *instance = &material_instances[i];
i32 texture_id = -1;
{
struct dx12_resource *texture = NULL;
if (desc->texture.gen != 0) {
texture = handle_get_data_locked(desc->texture, DX12_HANDLE_KIND_RESOURCE, &handles_lock);
} else if (desc->sprite.hash != 0) {
struct sprite_texture *st = sprite_texture_from_tag_async(sprite_scope, desc->sprite);
texture = handle_get_data_locked(st->texture, DX12_HANDLE_KIND_RESOURCE, &handles_lock);
}
if (texture) {
texture_id = texture->srv_descriptor->index;
}
}
instance->tex_nurid = sh_int_from_i32(texture_id);
instance->grid_id = sh_int_from_i32(desc->grid_id);
instance->xf = sh_float2x3_from_xform(desc->xf);
instance->uv0 = sh_float2_from_v2(desc->clip.p0);
instance->uv1 = sh_float2_from_v2(desc->clip.p1);
instance->tint_srgb = sh_uint_from_u32(desc->tint);
instance->emittance = sh_float_from_f32(desc->emittance);
}
sys_mutex_unlock(&handles_lock);
}
/* Process grids */
{
__profscope(Process grids);
for (u32 i = 0; i < flow->num_material_grid_descs; ++i) {
struct material_grid_desc *desc = &((struct material_grid_desc *)arena_base(flow->material_grid_descs_arena))[i];
struct sh_material_grid *grid = &grids[i];
grid->line_thickness = sh_float_from_f32(desc->line_thickness);
grid->line_spacing = sh_float_from_f32(desc->line_spacing);
grid->offset = sh_float2_from_v2(desc->offset);
grid->bg0_srgb = sh_uint_from_u32(desc->bg0_color);
grid->bg1_srgb = sh_uint_from_u32(desc->bg1_color);
grid->line_srgb = sh_uint_from_u32(desc->line_color);
grid->x_srgb = sh_uint_from_u32(desc->x_color);
grid->y_srgb = sh_uint_from_u32(desc->y_color);
}
}
}
/* Upload buffers */
struct command_buffer *material_instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena));
struct command_buffer *material_grid_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_grids_arena));
struct command_buffer *material_instance_buffer = command_list_push_buffer(cl, STRING(sizeof(*material_instances) * flow->num_material_instance_descs, (u8 *)material_instances));
struct command_buffer *grid_buffer = command_list_push_buffer(cl, STRING(sizeof(*grids) * flow->num_material_grid_descs, (u8 *)grids));
struct command_buffer *shape_verts_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->shape_verts_arena));
struct command_buffer *shape_indices_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->shape_indices_arena));
@ -2409,7 +2485,7 @@ void gp_dispatch(struct gp_dispatch_params params)
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, material_instance_buffer->resource->gpu_address);
/* Set grid buffer */
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 2, material_grid_buffer->resource->gpu_address);
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 2, grid_buffer->resource->gpu_address);
/* Set descriptor heap */
ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap };
@ -2469,7 +2545,10 @@ void gp_dispatch(struct gp_dispatch_params params)
}
command_list_close(cl);
pipeline_scope_end(pipeline_scope);
sprite_scope_end(sprite_scope);
flow_reset(flow);
scratch_end(scratch);
}
/* ========================== *
@ -2505,36 +2584,60 @@ struct gp_memory_info gp_query_memory_info(void)
}
/* ========================== *
* Present
* Swapchain
* ========================== */
INTERNAL struct dx12_resource *update_swapchain(struct sys_window *window, struct v2i32 resolution)
INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *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);
resolution.x = max_i32(resolution.x, 1);
resolution.y = max_i32(resolution.y, 1);
b32 should_rebuild = !v2i32_eq(swapchain->resolution, resolution);
if (should_rebuild) {
HRESULT hr = 0;
struct command_queue *cq = G.cq_direct;
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
if (swapchain->swapchain) {
ASSERT(hwnd == swapchain->hwnd);
if (G.swapchain) {
ASSERT(hwnd == G.swapchain_hwnd);
/* Resize existing swapchain */
/* FIXME: Fence */
/* Lock direct queue submissions (in case any write to backbuffer) */
/* TODO: Less overkill approach - Only flush present_blit since we know it's the only operation targeting backbuffer */
//struct sys_lock lock = sys_mutex_lock_e(cq->submit_fence_mutex);
DEBUGBREAKABLE;
struct sys_lock lock = sys_mutex_lock_e(G.global_command_list_record_mutex);
{
/* Flush direct queue */
//ID3D12CommandQueue_Signal(cq->cq, cq->submit_fence, ++cq->submit_fence_target);
{
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
ID3D12Fence_SetEventOnCompletion(cq->submit_fence, cq->submit_fence_target, event);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
/* 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);
/* Release buffers */
for (u32 i = 0; i < ARRAY_COUNT(swapchain->buffers); ++i) {
struct swapchain_buffer *sb = &swapchain->buffers[i];
descriptor_release(sb->rtv_descriptor);
ID3D12Resource_Release(sb->resource);
}
/* Resize buffers */
hr = IDXGISwapChain_ResizeBuffers(swapchain->swapchain, 0, resolution.x, resolution.y, DXGI_FORMAT_UNKNOWN, DX12_SWAPCHAIN_FLAGS);
if (FAILED(hr)) {
/* TODO: Don't panic */
sys_panic(LIT("Failed to resize swapchain"));
}
}
/* Resize buffers */
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, resolution.x, resolution.y, DXGI_FORMAT_UNKNOWN, DX12_SWAPCHAIN_FLAGS);
sys_mutex_unlock(&lock);
} else {
/* Create swapchain1 */
IDXGISwapChain1 *swapchain1 = NULL;
{
DXGI_SWAP_CHAIN_DESC1 desc = ZI;
desc.Format = DX12_SWAPCHAIN_FORMAT;
desc.Width = resolution.x;
desc.Height = resolution.y;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT;
@ -2543,44 +2646,54 @@ INTERNAL struct dx12_resource *update_swapchain(struct sys_window *window, struc
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);
hr = IDXGIFactory2_CreateSwapChainForHwnd(G.factory, (IUnknown *)cq->cq, hwnd, &desc, NULL, NULL, &swapchain1);
if (FAILED(hr)) {
dx12_init_error(LIT("Failed to create IDXGISwapChain1"));
sys_panic(LIT("Failed to create IDXGISwapChain1"));
}
}
/* Upgrade to swapchain3 */
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&G.swapchain);
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain->swapchain);
if (FAILED(hr)) {
dx12_init_error(LIT("Failed to create IDXGISwapChain3"));
sys_panic(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;
swapchain->hwnd = hwnd;
}
/* Allocate swapchain resources */
for (u32 i = 0; i < ARRAY_COUNT(G.swapchain_resources); ++i) {
for (u32 i = 0; i < ARRAY_COUNT(swapchain->buffers); ++i) {
ID3D12Resource *resource = NULL;
hr = IDXGISwapChain3_GetBuffer(G.swapchain, i, &IID_ID3D12Resource, (void **)&resource);
hr = IDXGISwapChain3_GetBuffer(swapchain->swapchain, i, &IID_ID3D12Resource, (void **)&resource);
if (FAILED(hr)) {
/* TODO: Don't panic */
dx12_init_error(LIT("Failed to get swapchain buffer"));
sys_panic(LIT("Failed to get swapchain buffer"));
}
G.swapchain_resources[i] = dx12_resource_alloc_from_swapchain_buffer(resource, resolution);
struct swapchain_buffer *sb = &swapchain->buffers[i];
MEMZERO_STRUCT(sb);
sb->swapchain = swapchain;
sb->resource = resource;
sb->rtv_descriptor = descriptor_alloc(G.rtv_heap);
sb->state = D3D12_RESOURCE_STATE_COMMON;
ID3D12Device_CreateRenderTargetView(G.device, sb->resource, NULL, sb->rtv_descriptor->handle);
}
G.swapchain_resolution = resolution;
swapchain->resolution = resolution;
}
G.swapchain_frame_index = IDXGISwapChain3_GetCurrentBackBufferIndex(G.swapchain);
return G.swapchain_resources[G.swapchain_frame_index];
u32 backbuffer_index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain->swapchain);
return &swapchain->buffers[backbuffer_index];
}
INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, struct xform src_xf)
/* ========================== *
* Present
* ========================== */
INTERNAL void present_blit(struct swapchain_buffer *dst, struct dx12_resource *src, struct xform src_xf)
{
__prof;
struct pipeline_scope *pipeline_scope = pipeline_scope_begin();
@ -2589,6 +2702,7 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
struct command_list *cl = command_list_open(G.cq_direct);
{
__profscope_dx12(cl->cq->prof, cl->cl, Blit, RGB32_F(0.5, 0.2, 0.2));
struct swapchain *swapchain = dst->swapchain;
/* Upload dummmy vert & index buffer */
/* TODO: Make these static */
@ -2600,13 +2714,25 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
/* Upload descriptor heap */
struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap);
struct rect viewport_rect = RECT_FROM_V2(V2(0, 0), V2(dst->texture_size.x, dst->texture_size.y));
struct rect viewport_rect = RECT_FROM_V2(V2(0, 0), V2(swapchain->resolution.x, swapchain->resolution.y));
D3D12_VIEWPORT viewport = viewport_from_rect(viewport_rect);
D3D12_RECT scissor = scissor_from_rect(viewport_rect);
struct mat4x4 vp_matrix = calculate_vp(src_xf, viewport.Width, viewport.Height);
/* Transition dst to render target */
dx12_resource_barrier(cl->cl, dst, D3D12_RESOURCE_STATE_RENDER_TARGET);
{
struct D3D12_RESOURCE_TRANSITION_BARRIER rtb = ZI;
rtb.pResource = dst->resource;
rtb.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
rtb.StateBefore = dst->state;
rtb.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
struct D3D12_RESOURCE_BARRIER rb = ZI;
rb.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
rb.Flags = 0;
rb.Transition = rtb;
ID3D12GraphicsCommandList_ResourceBarrier(cl->cl, 1, &rb);
dst->state = rtb.StateAfter;
}
ID3D12GraphicsCommandList_OMSetRenderTargets(cl->cl, 1, &dst->rtv_descriptor->handle, false, NULL);
/* Clear */
@ -2641,24 +2767,38 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv);
ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, 1, 0, 0, 0);
/* Set dst to presentable */
dx12_resource_barrier(cl->cl, dst, D3D12_RESOURCE_STATE_PRESENT);
/* Transition dst to presentable */
{
struct D3D12_RESOURCE_TRANSITION_BARRIER rtb = ZI;
rtb.pResource = dst->resource;
rtb.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
rtb.StateBefore = dst->state;
rtb.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
struct D3D12_RESOURCE_BARRIER rb = ZI;
rb.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
rb.Flags = 0;
rb.Transition = rtb;
ID3D12GraphicsCommandList_ResourceBarrier(cl->cl, 1, &rb);
dst->state = rtb.StateAfter;
}
ID3D12GraphicsCommandList_OMSetRenderTargets(cl->cl, 1, &dst->rtv_descriptor->handle, false, NULL);
}
command_list_close(cl);
}
pipeline_scope_end(pipeline_scope);
}
void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
void gp_present(struct sys_window *window, struct v2i32 backresolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
{
__prof;
//sys_sleep(0.1);
struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution);
struct swapchain *swapchain = &G.swapchain;
struct swapchain_buffer *swapchain_buffer = update_swapchain(swapchain, window, backresolution);
struct dx12_resource *texture_resource = handle_get_data(texture, DX12_HANDLE_KIND_RESOURCE);
/* Blit */
present_blit(backbuffer_resource, texture_resource, texture_xf);
present_blit(swapchain_buffer, texture_resource, texture_xf);
//sys_sleep(0.1);
@ -2666,7 +2806,7 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
/* FIXME: Resource barrier */
{
__profscope(Present);
HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0);
HRESULT hr = IDXGISwapChain3_Present(swapchain->swapchain, 0, 0);
if (!SUCCEEDED(hr)) {
ASSERT(false);
}
@ -2675,8 +2815,9 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
#if PROFILING
{
/* Lock because command shouldn't be recording during a frame mark */
struct sys_lock lock = sys_mutex_lock_e(G.global_command_list_mutex);
__profscope(Mark queue frames);
/* Lock because frame marks shouldn't occur while command lists are recording */
struct sys_lock lock = sys_mutex_lock_e(G.global_command_list_record_mutex);
__prof_dx12_new_frame(G.cq_direct->prof);
__prof_dx12_new_frame(G.cq_compute->prof);
__prof_dx12_new_frame(G.cq_copy_critical->prof);
@ -2684,6 +2825,7 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
sys_mutex_unlock(&lock);
}
{
__profscope(Collect queues);
__prof_dx12_collect(G.cq_direct->prof);
__prof_dx12_collect(G.cq_compute->prof);
__prof_dx12_collect(G.cq_copy_critical->prof);
@ -2692,7 +2834,7 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
#endif
(UNUSED)backbuffer_resolution;
(UNUSED)backresolution;
(UNUSED)texture;
(UNUSED)texture_xf;
(UNUSED)vsync;

View File

@ -898,8 +898,6 @@ INTERNAL struct sprite_scope_cache_ref *cache_lookup(struct sprite_scope *scope,
INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope *scope, struct sprite_tag tag, enum cache_entry_kind kind, b32 force_new)
{
__prof;
struct cache_entry_hash hash = cache_entry_hash_from_tag_hash(tag.hash, kind);
u64 bin_index = hash.v % CACHE_BINS_COUNT;
struct sprite_scope_cache_ref *scope_ref = NULL;

View File

@ -73,8 +73,8 @@ GLOBAL struct {
/* Gpu handles */
struct gp_handle user_texture;
struct gp_handle world_gp_flow;
struct gp_handle ui_gp_flow;
struct gp_flow *world_gp_flow;
struct gp_flow *ui_gp_flow;
struct xform world_to_user_xf;