diff --git a/res/shaders/common.hlsl b/res/shaders/common.hlsl index c15b17d8..3b145d8b 100644 --- a/res/shaders/common.hlsl +++ b/res/shaders/common.hlsl @@ -1,8 +1,31 @@ #define DECL(t, n) t n : n #define DESV(t, n, s) t n : s -/* Linear color form sRGB color */ +struct xform { + float2 bx; + float2 by; + float2 og; +}; + +/* Linear color from normalized sRGB */ float4 linear_from_srgb(float4 srgb) { return float4(pow(srgb.rgb, 2.2), srgb.a); } + +/* Linear color from R8G8B8A8 sRGB */ +float4 linear_from_srgb32(uint srgb32) +{ + float4 res; + res.r = ((srgb32 >> 0) & 0xFF) / 255.0; + res.g = ((srgb32 >> 8) & 0xFF) / 255.0; + res.b = ((srgb32 >> 16) & 0xFF) / 255.0; + res.a = ((srgb32 >> 24) & 0xFF) / 255.0; + return linear_from_srgb(res); +} + +float2 xform_mul(struct xform xf, float2 v) +{ + // return xf.bx * v.x + xf.by * v.y + xf.og; + return float2(xf.bx.x * v.x + xf.by.x * v.y, xf.bx.y * v.x + xf.by.y * v.y) + xf.og; +} \ No newline at end of file diff --git a/res/shaders/grid.hlsl b/res/shaders/grid.hlsl index 5d1f2319..68fbaad0 100644 --- a/res/shaders/grid.hlsl +++ b/res/shaders/grid.hlsl @@ -1,10 +1,5 @@ #include "shaders/common.hlsl" -cbuffer constants : register(b0) -{ - float4x4 G_projection; -}; - struct vs_input { DECL(float4, pos); DECL(float, line_thickness); @@ -29,6 +24,15 @@ struct ps_input { DECL(float4, y_lin); }; +/* ========================== * + * Globals + * ========================== */ + +cbuffer constants : register(b0) +{ + float4x4 G_projection; +}; + /* ========================== * * Vertex shader * ========================== */ diff --git a/res/shaders/texture.hlsl b/res/shaders/texture.hlsl new file mode 100644 index 00000000..50e2534c --- /dev/null +++ b/res/shaders/texture.hlsl @@ -0,0 +1,91 @@ +#include "shaders/common.hlsl" + +struct vs_instance { + struct xform xf; + float2 uv0; + float2 uv1; + uint tint_srgb; +}; + +struct ps_input { + DESV(float4, screen_pos, SV_POSITION); + DECL(float2, uv); + DECL(float4, tint_lin); +}; + +/* ========================== * + * Globals + * ========================== */ + +SamplerState G_sampler : register(s0); + +Texture2D G_Texture : register(t0); + +StructuredBuffer G_instance_buffer : register(t1); + +cbuffer constants : register(b0) +{ + float4x4 G_projection; + uint G_instance_offset; +}; + +/* ========================== * + * Vertex shader + * ========================== */ + +ps_input vs_main(uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID) +{ + // static float2 quad[4] = { + // float2(-0.5f, -0.5f), + // float2( 0.5f, -0.5f), + // float2( 0.5f, 0.5f), + // float2(-0.5f, 0.5f) + // }; + + static const uint indices[6] = { 0, 1, 2, 2, 3, 0 }; + static const float2 vertices[4] = { + float2(-0.5f, -0.5f), + float2( 0.5f, -0.5f), + float2( 0.5f, 0.5f), + float2(-0.5f, 0.5f) + }; + + vs_instance instance = G_instance_buffer[instance_id + G_instance_offset]; + int index = indices[vertex_id]; + + int top = index == 0 || index == 1; + int right = index == 1 || index == 2; + int bottom = index == 2 || index == 3; + int left = index == 3 || index == 0; + //int top = vertex_id == 0 || vertex_id == 2; + //int left = vertex_id == 0 || vertex_id == 1; + //int bottom = vertex_id == 1 || vertex_id == 3; + //int right = vertex_id == 2 || vertex_id == 3; + + float2 vert = vertices[index]; + float2 world_pos = xform_mul(instance.xf, vert); + float4 screen_pos = mul(G_projection, float4(world_pos, 0, 1)); + + float uv_x = instance.uv0.x * left; + uv_x += instance.uv1.x * right; + float uv_y = instance.uv0.y * top; + uv_y += instance.uv1.y * bottom; + + + ps_input output; + output.screen_pos = screen_pos; + output.uv = float2(uv_x, uv_y); + output.tint_lin = linear_from_srgb32(instance.tint_srgb); + + return output; +} + +/* ========================== * + * Pixel shader + * ========================== */ + +float4 ps_main(ps_input input) : SV_TARGET +{ + float4 color = G_Texture.Sample(G_sampler, input.uv) * input.tint_lin; + return color; +} diff --git a/res/shaders/triangle.hlsl b/res/shaders/triangle.hlsl index 3c233004..89ea1000 100644 --- a/res/shaders/triangle.hlsl +++ b/res/shaders/triangle.hlsl @@ -1,13 +1,5 @@ #include "shaders/common.hlsl" -SamplerState G_sampler0; -Texture2D G_texture0; - -cbuffer constants : register(b0) -{ - float4x4 G_projection; -}; - struct vs_input { DECL(float4, pos); DECL(float2, uv); @@ -20,6 +12,19 @@ struct ps_input { DECL(float4, tint_lin); }; +/* ========================== * + * Globals + * ========================== */ + +SamplerState G_sampler : register(s0); + +Texture2D G_texture : register(t0); + +cbuffer constants : register(b0) +{ + float4x4 G_projection; +}; + /* ========================== * * Vertex shader * ========================== */ @@ -41,6 +46,6 @@ ps_input vs_main(vs_input input) float4 ps_main(ps_input input) : SV_TARGET { - float4 color = G_texture0.Sample(G_sampler0, input.uv) * input.tint_lin; + float4 color = G_texture.Sample(G_sampler, input.uv) * input.tint_lin; return color; } diff --git a/src/ase.c b/src/ase.c index f84a5c59..89ff68c4 100644 --- a/src/ase.c +++ b/src/ase.c @@ -705,14 +705,6 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct stri } } break; - case CHUNK_TYPE_COLOR_PROFILE: { - u16 type = br_read_ubits(&br, 16); - if (type == 1) { - res.srgb = true; - } - br_seek_to_byte(&br, chunk_end_pos); - } break; - default: { br_seek_to_byte(&br, chunk_end_pos); } break; diff --git a/src/ase.h b/src/ase.h index cecbf898..5eea3b40 100644 --- a/src/ase.h +++ b/src/ase.h @@ -48,7 +48,6 @@ struct ase_frame { struct ase_decode_image_result { struct image_rgba image; struct ase_error_list errors; - b32 srgb; b32 success; }; diff --git a/src/draw.c b/src/draw.c index 843f8f95..339e5653 100644 --- a/src/draw.c +++ b/src/draw.c @@ -28,94 +28,60 @@ struct draw_startup_receipt draw_startup(struct gpu_startup_receipt *gpu_sr, * Texture * ========================== */ -void draw_quad_texture(struct gpu_cmd_buffer *cmdbuff, struct draw_texture_params params) +void draw_texture(struct gpu_cmd_store store, struct draw_texture_params params) { - struct gpu_cmd_parameters cmd_params = ZI; - cmd_params.kind = SHADER_TRIANGLE; - cmd_params.texture_params.texture = params.texture; - cmd_params.texture_params.sprite = params.sprite; - gpu_cmd_buffer_ensure_cmd(cmdbuff, &cmd_params); - - struct triangle_shader_vertex *vertices = NULL; - vidx *indices = NULL; - u32 offset = gpu_cmd_buffer_push_vertices(cmdbuff, (u8 **)&vertices, &indices, 4, 6); - - /* Top left */ - vertices[0] = (struct triangle_shader_vertex) { - .pos = params.quad.p0, - .uv = { params.clip.p0.x, params.clip.p0.y }, - .tint_srgb = params.tint0_srgb - }; - /* Top right */ - vertices[1] = (struct triangle_shader_vertex) { - .pos = params.quad.p1, - .uv = { params.clip.p1.x, params.clip.p0.y }, - .tint_srgb = params.tint0_srgb - }; - /* Bottom right */ - vertices[2] = (struct triangle_shader_vertex) { - .pos = params.quad.p2, - .uv = { params.clip.p1.x, params.clip.p1.y }, - .tint_srgb = params.tint1_srgb - }; - /* Bottom left */ - vertices[3] = (struct triangle_shader_vertex) { - .pos = params.quad.p3, - .uv = { params.clip.p0.x, params.clip.p1.y }, - .tint_srgb = params.tint1_srgb - }; - - /* Top / right triangle */ - indices[0] = offset + 0; - indices[1] = offset + 1; - indices[2] = offset + 2; - - /* Bottom / left triangle */ - indices[3] = offset + 0; - indices[4] = offset + 2; - indices[5] = offset + 3; + struct gpu_cmd_params cmd = ZI; + cmd.kind = GPU_CMD_KIND_DRAW_TEXTURE; + cmd.texture.xf = params.xf; + cmd.texture.sprite = params.sprite; + cmd.texture.texture = params.texture; + cmd.texture.clip = params.clip; + cmd.texture.tint = params.tint; + gpu_push_cmd(store, cmd); } /* ========================== * - * Solid fill shapes + * Fill shapes * ========================== */ -void draw_poly(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, u32 srgb) +void draw_poly_ex(struct gpu_cmd_store store, struct v2_array vertices, struct gpu_indices indices, u32 color) { - if (array.count < 3) { - return; - } + struct gpu_cmd_params cmd = ZI; + cmd.kind = GPU_CMD_KIND_DRAW_TRIANGLES; + cmd.triangles.vertices = vertices; + cmd.triangles.indices = indices; + cmd.triangles.color = color; + gpu_push_cmd(store, cmd); +} - struct gpu_cmd_parameters cmd_params = ZI; - cmd_params.kind = SHADER_TRIANGLE; - cmd_params.texture_params.texture = G.solid_white; - gpu_cmd_buffer_ensure_cmd(cmdbuff, &cmd_params); +/* Draws a filled polygon using triangles in a fan pattern */ +void draw_poly(struct gpu_cmd_store store, struct v2_array vertices, u32 color) +{ + if (vertices.count >= 3) { + struct temp_arena scratch = scratch_begin_no_conflict(); - u32 num_tris = array.count - 2; - u32 num_indices = num_tris * 3; + u32 num_tris = vertices.count - 2; + u32 num_indices = num_tris * 3; - struct triangle_shader_vertex *vertices = NULL; - vidx *indices = NULL; - u32 idx_offset = gpu_cmd_buffer_push_vertices(cmdbuff, (u8 **)&vertices, &indices, array.count, num_indices); - - /* Fill vertices */ - for (u32 i = 0; i < array.count; ++i) { - vertices[i] = (struct triangle_shader_vertex) { - .pos = array.points[i], - .tint_srgb = srgb + /* Generate indices in a fan pattern */ + struct gpu_indices indices = { + .count = num_indices, + .indices = arena_push_array_no_zero(scratch.arena, u16, num_indices) }; - } + for (u32 i = 0; i < num_tris; ++i) { + u32 tri_offset = i * 3; + indices.indices[tri_offset + 0] = 0; + indices.indices[tri_offset + 1] = (i + 1); + indices.indices[tri_offset + 2] = (i + 2); + } - /* Fill indices */ - for (u32 i = 0; i < num_tris; ++i) { - u32 tri_offset = i * 3; - indices[tri_offset + 0] = idx_offset + 0; - indices[tri_offset + 1] = idx_offset + (i + 1); - indices[tri_offset + 2] = idx_offset + (i + 2); + draw_poly_ex(store, vertices, indices, color); + + scratch_end(scratch); } } -void draw_circle(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 srgb, u32 detail) +void draw_circle(struct gpu_cmd_store store, struct v2 pos, f32 radius, u32 color, u32 detail) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -128,63 +94,74 @@ void draw_circle(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 points[i] = v2_add(pos, p); } - struct v2_array a = { + struct v2_array vertices = { .points = points, .count = detail }; - draw_poly(cmdbuff, a, srgb); + draw_poly(store, vertices, color); scratch_end(scratch); } -void draw_quad(struct gpu_cmd_buffer *cmdbuff, struct quad quad, u32 srgb) +void draw_quad(struct gpu_cmd_store store, struct quad quad, u32 color) { - draw_quad_texture(cmdbuff, DRAW_TEXTURE_PARAMS(.texture = G.solid_white, .tint0_srgb = srgb, .tint1_srgb = srgb, .quad = quad)); + LOCAL_PERSIST u16 indices_array[6] = { + 0, 1, 2, + 0, 2, 3 + }; + struct v2_array vertices = { .count = 4, .points = quad.e }; + struct gpu_indices indices = { .count = 6, .indices = indices_array }; + draw_poly_ex(store, vertices, indices, color); } /* ========================== * - * Solid line shapes + * Line shapes * ========================== */ -void draw_gradient_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 start_srgb, u32 end_srgb) +void draw_gradient_line(struct gpu_cmd_store store, 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); - draw_quad_texture(cmdbuff, DRAW_TEXTURE_PARAMS(.texture = G.solid_white, .tint0_srgb = start_srgb, .tint1_srgb = end_srgb, .quad = quad)); + draw_texture(store, DRAW_TEXTURE_PARAMS(.texture = G.solid_white, .tint0 = start_color, .tint1 = end_color, .quad = quad)); +#else + /* Placeholder */ + (UNUSED)end_color; + struct quad quad = quad_from_line(start, end, thickness); + draw_quad(store, quad, start_color); +#endif } -void draw_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 srgb) +void draw_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 color) { struct quad quad = quad_from_line(start, end, thickness); - draw_quad(cmdbuff, quad, srgb); + draw_quad(store, quad, color); } -void draw_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, u32 srgb) +void draw_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, u32 color) { struct quad quad = quad_from_ray(pos, rel, thickness); - draw_quad(cmdbuff, quad, srgb); + draw_quad(store, quad, color); } -void draw_poly_line(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 srgb) +void draw_poly_line(struct gpu_cmd_store store, struct v2_array points, b32 loop, f32 thickness, u32 color) { - if (array.count < 2) { - return; - } - - for (u64 i = 1; i < array.count; ++i) { - struct v2 p1 = array.points[i - 1]; - struct v2 p2 = array.points[i]; - struct quad q = quad_from_line(p1, p2, thickness); - draw_quad(cmdbuff, q, srgb); - } - if (loop && array.count > 2) { - struct v2 p1 = array.points[array.count - 1]; - struct v2 p2 = array.points[0]; - struct quad q = quad_from_line(p1, p2, thickness); - draw_quad(cmdbuff, q, srgb); + if (points.count >= 2) { + for (u64 i = 1; i < points.count; ++i) { + struct v2 p1 = points.points[i - 1]; + struct v2 p2 = points.points[i]; + struct quad q = quad_from_line(p1, p2, thickness); + draw_quad(store, q, color); + } + if (loop && points.count > 2) { + struct v2 p1 = points.points[points.count - 1]; + struct v2 p2 = points.points[0]; + struct quad q = quad_from_line(p1, p2, thickness); + draw_quad(store, q, color); + } } } -void draw_circle_line(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 srgb, u32 detail) +void draw_circle_line(struct gpu_cmd_store store, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -201,19 +178,19 @@ void draw_circle_line(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, .points = points, .count = detail }; - draw_poly_line(cmdbuff, a, true, thickness, srgb); + draw_poly_line(store, a, true, thickness, color); scratch_end(scratch); } -void draw_quad_line(struct gpu_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 srgb) +void draw_quad_line(struct gpu_cmd_store store, 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(cmdbuff, a, true, thickness, srgb); + draw_poly_line(store, a, true, thickness, color); } -void draw_arrow_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 srgb) +void draw_arrow_line(struct gpu_cmd_store store, 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 */ @@ -237,19 +214,19 @@ void draw_arrow_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 .points = head_points, .count = ARRAY_COUNT(head_points) }; - draw_poly(cmdbuff, head_points_v2_array, srgb); + draw_poly(store, head_points_v2_array, color); struct quad line_quad = quad_from_line(start, head_start, thickness); - draw_quad(cmdbuff, line_quad, srgb); + draw_quad(store, line_quad, color); } -void draw_arrow_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 srgb) +void draw_arrow_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color) { struct v2 end = v2_add(pos, rel); - draw_arrow_line(cmdbuff, pos, end, thickness, arrowhead_height, srgb); + draw_arrow_line(store, pos, end, thickness, arrowhead_height, color); } -void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 srgb, u32 detail) +void draw_collider_line(struct gpu_cmd_store store, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -262,16 +239,8 @@ void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, st points[i] = p; } -#if 1 struct v2_array poly = { .points = points, .count = detail }; - draw_poly_line(cmdbuff, poly, true, thickness, srgb); -#else - for (u64 i = 0; i < detail; ++i) { - struct v2 point = points[i]; - (UNUSED)thickness; - draw_circle(cmdbuff, point, 3, srgb, 10); - } -#endif + draw_poly_line(store, poly, true, thickness, color); scratch_end(scratch); } @@ -280,57 +249,28 @@ void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, st * Grid * ========================== */ -void draw_grid(struct gpu_cmd_buffer *cmdbuff, struct rect rect, u32 bg0_srgb, u32 bg1_srgb, u32 line_srgb, u32 x_srgb, u32 y_srgb, f32 thickness, f32 spacing, struct v2 offset) +void draw_grid(struct gpu_cmd_store store, 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 gpu_cmd_parameters cmd_params = ZI; - cmd_params.kind = SHADER_GRID; - gpu_cmd_buffer_ensure_cmd(cmdbuff, &cmd_params); - - struct grid_shader_vertex *vertices = NULL; - vidx *indices = NULL; - u32 index_offset = gpu_cmd_buffer_push_vertices(cmdbuff, (u8 **)&vertices, &indices, 4, 6); - - struct quad quad = quad_from_rect(rect); - - struct grid_shader_vertex attributes = ZI; - attributes.bg0_srgb = bg0_srgb; - attributes.bg1_srgb = bg1_srgb; - attributes.line_srgb = line_srgb; - attributes.x_srgb = x_srgb; - attributes.y_srgb = y_srgb; - attributes.line_thickness = thickness; - attributes.line_spacing = spacing; - attributes.offset = offset; - - /* Top left */ - vertices[0] = attributes; - vertices[0].pos = quad.p0; - /* Top right */ - vertices[1] = attributes; - vertices[1].pos = quad.p1; - /* Bottom right */ - vertices[2] = attributes; - vertices[2].pos = quad.p2; - /* Bottom left */ - vertices[3] = attributes; - vertices[3].pos = quad.p3; - - /* Top / right triangle */ - indices[0] = index_offset + 0; - indices[1] = index_offset + 1; - indices[2] = index_offset + 2; - /* Bottom / left triangle */ - indices[3] = index_offset + 0; - indices[4] = index_offset + 2; - indices[5] = index_offset + 3; + struct gpu_cmd_params cmd = ZI; + cmd.kind = GPU_CMD_KIND_DRAW_GRID; + cmd.grid.xf = xf; + 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; + gpu_push_cmd(store, cmd); } /* ========================== * * Text * ========================== */ - /* Returns the rect that the drawn text spans */ -struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params params) + /* Returns the rect of the text area */ +struct rect draw_text(struct gpu_cmd_store store, struct draw_text_params params) { struct temp_arena scratch = scratch_begin_no_conflict(); @@ -338,6 +278,10 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa f32 inv_font_image_height = 1.0 / (f32)params.font->image_height; f32 line_spacing = params.font->point_size * 1.5f * params.scale; + /* ========================== * + * Build line glyphs + * ========================== */ + struct drawable_glyph { f32 off_x; f32 off_y; @@ -428,6 +372,10 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa string_codepoint_iter_end(&iter); } + /* ========================== * + * Determine text bounds + * ========================== */ + struct rect bounds = ZI; bounds.x = params.pos.x; bounds.y = params.pos.y; @@ -462,6 +410,9 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa } break; } + /* ========================== * + * Draw lines + * ========================== */ u64 line_number = 0; for (struct drawable_line *line = first_line; line; line = line->next) { @@ -484,10 +435,11 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa /* Draw glyphs */ for (u64 i = 0; i < line->num_glyphs; ++i) { struct drawable_glyph *tg = &line->glyphs[i]; - f32 x = draw_pos.x + tg->off_x; - f32 y = draw_pos.y + tg->off_y; - struct quad quad = quad_from_rect(RECT(x, y, tg->width, tg->height)); - draw_quad_texture(cmdbuff, DRAW_TEXTURE_PARAMS(.texture = params.font->texture, .tint0_srgb = params.color, .tint1_srgb = params.color, .clip = tg->clip, .quad = quad)); + struct v2 pos = V2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y); + struct v2 size = V2(tg->width, tg->height); + struct v2 pos_center = v2_add(pos, v2_mul(size, 0.5)); + struct xform xf = XFORM_TRS(.t = pos_center, size); + draw_texture(store, DRAW_TEXTURE_PARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip)); draw_pos.x += tg->advance; } diff --git a/src/draw.h b/src/draw.h index 9965313e..07bcbebd 100644 --- a/src/draw.h +++ b/src/draw.h @@ -3,27 +3,86 @@ #include "gpu.h" -struct gpu_cmd_buffer; struct font; -struct gpu_startup_receipt; struct font_startup_receipt; +struct draw_startup_receipt { i32 _; }; +struct draw_startup_receipt draw_startup(struct gpu_startup_receipt *gpu_sr, + struct font_startup_receipt *font_sr); + +/* ========================== * + * Texture + * ========================== */ + #define DRAW_TEXTURE_PARAMS(...) ((struct draw_texture_params) { \ - .tint0_srgb = COLOR_WHITE, \ - .tint1_srgb = COLOR_WHITE, \ + .tint = COLOR_WHITE, \ .clip = CLIP_ALL, \ __VA_ARGS__ \ }) struct draw_texture_params { + struct xform xf; struct gpu_texture texture; /* Overrides sprite if set */ struct sprite_tag sprite; struct clip_rect clip; - struct quad quad; - u32 tint0_srgb; - u32 tint1_srgb; + u32 tint; }; +void draw_texture(struct gpu_cmd_store store, struct draw_texture_params params); + +/* ========================== * + * Fill shapes + * ========================== */ + +void draw_poly_ex(struct gpu_cmd_store store, struct v2_array vertices, struct gpu_indices indices, u32 color); + +void draw_poly(struct gpu_cmd_store store, struct v2_array points, u32 color); + +void draw_circle(struct gpu_cmd_store store, struct v2 pos, f32 radius, u32 color, u32 detail); + +void draw_quad(struct gpu_cmd_store store, struct quad quad, u32 color); + +/* ========================== * + * Line shapes + * ========================== */ + +void draw_gradient_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color); + +void draw_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 color); + +void draw_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, u32 color); + +void draw_poly_line(struct gpu_cmd_store store, struct v2_array points, b32 loop, f32 thickness, u32 color); + +void draw_circle_line(struct gpu_cmd_store store, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail); + +void draw_quad_line(struct gpu_cmd_store store, struct quad quad, f32 thickness, u32 color); + +void draw_arrow_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color); + +void draw_arrow_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color); + +void draw_collider_line(struct gpu_cmd_store store, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail); + +/* ========================== * + * Grid + * ========================== */ + +void draw_grid(struct gpu_cmd_store store, 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 + * ========================== */ + +#define DRAW_TEXT_PARAMS(...) ((struct draw_text_params) { \ + .scale = 1.0, \ + .alignment = DRAW_TEXT_ALIGNMENT_LEFT, \ + .offset_x = DRAW_TEXT_OFFSET_X_LEFT, \ + .offset_y = DRAW_TEXT_OFFSET_Y_TOP, \ + .color = COLOR_WHITE, \ + __VA_ARGS__ \ +}) + /* How is text aligned within its area */ enum draw_text_alignment { DRAW_TEXT_ALIGNMENT_LEFT, /* Default */ @@ -39,55 +98,13 @@ enum draw_text_offset_x { DRAW_TEXT_OFFSET_X_CENTER, DRAW_TEXT_OFFSET_X_RIGHT }; + enum draw_text_offset_y { DRAW_TEXT_OFFSET_Y_TOP, /* Default */ DRAW_TEXT_OFFSET_Y_CENTER, DRAW_TEXT_OFFSET_Y_BOTTOM }; -struct draw_startup_receipt { i32 _; }; -struct draw_startup_receipt draw_startup(struct gpu_startup_receipt *gpu_sr, - struct font_startup_receipt *font_sr); - -/* ========================== * - * Textures - * ========================== */ - -void draw_quad_texture(struct gpu_cmd_buffer *cmdbuff, struct draw_texture_params params); - -/* ========================== * - * Shapes - * ========================== */ - -void draw_poly(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, u32 srgb); -void draw_circle(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 srgb, u32 detail); -void draw_quad(struct gpu_cmd_buffer *cmdbuff, struct quad quad, u32 srgb); - -void draw_gradient_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 start_srgb, u32 end_srgb); -void draw_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 srgb); -void draw_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 ray, f32 thickness, u32 srgb); -void draw_poly_line(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 srgb); -void draw_circle_line(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 srgb, u32 detail); -void draw_quad_line(struct gpu_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 srgb); -void draw_arrow_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 srgb); -void draw_arrow_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 srgb); -void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 srgb, u32 detail); - -void draw_grid(struct gpu_cmd_buffer *cmdbuff, struct rect rect, u32 bg0_srgb, u32 bg1_srgb, u32 line_srgb, u32 x_srgb, u32 y_srgb, f32 thickness, f32 spacing, struct v2 offset); - -/* ========================== * - * Text - * ========================== */ - -#define DRAW_TEXT_PARAMS(...) ((struct draw_text_params) { \ - .scale = 1.0, \ - .alignment = DRAW_TEXT_ALIGNMENT_LEFT, \ - .offset_x = DRAW_TEXT_OFFSET_X_LEFT, \ - .offset_y = DRAW_TEXT_OFFSET_Y_TOP, \ - .color = COLOR_WHITE, \ - __VA_ARGS__ \ -}) - struct draw_text_params { struct font *font; struct v2 pos; @@ -99,6 +116,6 @@ struct draw_text_params { struct string str; }; -struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params params); +struct rect draw_text(struct gpu_cmd_store store, struct draw_text_params params); #endif diff --git a/src/gpu.h b/src/gpu.h index 8be7e4be..0507ac7a 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -6,54 +6,6 @@ struct sys_window; #define GPU_TEXTURE_MAX_WIDTH 16384 #define GPU_TEXTURE_MAX_HEIGHT 16384 -typedef u32 vidx; - -struct gpu_cmd_buffer; - -struct gpu_texture { - u64 handle; -}; - -/* ========================== * - * Shaders - * ========================== */ - -enum shader_kind { - SHADER_NONE, - SHADER_TRIANGLE, - SHADER_GRID, - - NUM_SHADERS -}; - -struct gpu_cmd_parameters { - enum shader_kind kind; - union { - struct { - struct gpu_texture texture; /* Overrides sprite if set */ - struct sprite_tag sprite; - } texture_params; - }; -}; - -PACK(struct triangle_shader_vertex { - struct v2 pos; - struct v2 uv; - u32 tint_srgb; -}); - -PACK(struct grid_shader_vertex { - struct v2 pos; - f32 line_thickness; - f32 line_spacing; - struct v2 offset; - u32 bg0_srgb; - u32 bg1_srgb; - u32 line_srgb; - u32 x_srgb; - u32 y_srgb; -}); - /* ========================== * * Startup * ========================== */ @@ -67,55 +19,98 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window); enum gpu_texture_format { GPU_TEXTURE_FORMAT_NONE, - GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, NUM_GPU_TEXTURE_FORMATS }; -#define GPU_TEXTURE_FLAG_NONE (0) -#define GPU_TEXTURE_FLAG_TARGET (1<<0) +enum gpu_texture_flag { + GPU_TEXTURE_FLAG_NONE = (0), + GPU_TEXTURE_FLAG_TARGETABLE = (1 << 0) +}; + +struct gpu_texture { + u64 handle; +}; struct gpu_texture gpu_texture_alloc(enum gpu_texture_format format, u32 flags, struct v2i32 size, void *initial_data); + void gpu_texture_release(struct gpu_texture t); void gpu_texture_clear(struct gpu_texture target_texture, u32 clear_color); -void gpu_texture_render(struct gpu_texture texture, struct gpu_cmd_buffer *cmdbuff, struct xform view, struct rect viewport); + struct v2i32 gpu_texture_get_size(struct gpu_texture texture); /* ========================== * * Backbuffer * ========================== */ - /* Returns a texture linking to the internal backbuffer. Lifetime is managed by gpu layer. */ + /* Returns a texture representing the internal backbuffer. Lifetime is managed by gpu layer. */ struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size); -void gpu_present_backbuffer(i32 vsync); +/* Presents the backbuffer to the screen */ +void gpu_swap_backbuffer(i32 vsync); /* ========================== * * Cmd buffer * ========================== */ -struct gpu_cmd_buffer *gpu_cmd_buffer_alloc(void); +struct gpu_indices { + u16 count; + u16 *indices; +}; -void gpu_cmd_buffer_release(struct gpu_cmd_buffer *cmdbuff); +enum gpu_cmd_kind { + GPU_CMD_KIND_NONE, + GPU_CMD_KIND_DRAW_TRIANGLES, + GPU_CMD_KIND_DRAW_TEXTURE, + GPU_CMD_KIND_DRAW_GRID, -/* Pushes array of vertices based on `vertices_count` & `indices_count`. - * Sets `vertices_out` and `indices_out` to start of the pushed arrays, to be filled out by the caller. - * Returns the index of the first vertex. Each inserted index should be incremented by this. - * - * NOTE: This should be preceded by an `ensure_cmd` call to ensure that the correct vertex types - * are being pushed. - */ -u32 gpu_cmd_buffer_push_vertices(struct gpu_cmd_buffer *cmdbuff, u8 **vertices_out, vidx **indices_out, u32 vertices_count, u32 indices_count); + NU +}; -/* Checks the currently active draw command. Ensures a new command is created - * if it doesn't match the expected parameters (otherwise the existing command - * can be re-used for batching). */ -void gpu_cmd_buffer_ensure_cmd(struct gpu_cmd_buffer *cmdbuff, struct gpu_cmd_parameters *params); +struct gpu_cmd_params { + enum gpu_cmd_kind kind; + union { + struct { + struct v2_array vertices; + struct gpu_indices indices; + u32 color; + } triangles; + struct { + struct xform xf; + struct sprite_tag sprite; + struct gpu_texture texture; + struct clip_rect clip; + u32 tint; + } texture; + struct { + struct xform xf; + 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; + }; +}; -void gpu_cmd_buffer_flush_to_gpu(struct gpu_cmd_buffer *cmdbuff); +struct gpu_cmd_store { + u64 handle; +}; +struct gpu_cmd_store gpu_cmd_store_alloc(void); + +void gpu_cmd_store_release(struct gpu_cmd_store gpu_cmd_store); + +void gpu_push_cmd(struct gpu_cmd_store gpu_cmd_store, struct gpu_cmd_params params); + +void gpu_submit_cmds(struct gpu_cmd_store gpu_cmd_store); + +void gpu_run_cmds(struct gpu_cmd_store gpu_cmd_store, struct gpu_texture target, struct xform view, struct rect viewport); #endif diff --git a/src/gpu_dx11.c b/src/gpu_dx11.c index f54bdb40..19a23307 100644 --- a/src/gpu_dx11.c +++ b/src/gpu_dx11.c @@ -26,12 +26,11 @@ #pragma comment(lib, "dxguid") #pragma comment(lib, "d3dcompiler") -#define MAX_CMD_BUFFERS 1024 -#define SHADER_INFO_LOOKUP_BINS 64 +#define MAX_CMD_STORES 1024 /* FIXME: Enable this and resolve unreleased references */ #if RTC -# define DX11_DEBUG 0 +# define DX11_DEBUG 1 # define DX11_SHADER_DEBUG 1 #else # define DX11_DEBUG 0 @@ -43,8 +42,17 @@ #define DX11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM) #define DX11_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) +enum dx11_shader_kind { + DX11_SHADER_KIND_NONE, + DX11_SHADER_KIND_TRIANGLE, + DX11_SHADER_KIND_TEXTURE, + DX11_SHADER_KIND_GRID, + + NUM_DX11_SHADER_KINDS +}; + struct dx11_shader { - enum shader_kind kind; + enum dx11_shader_kind kind; b32 valid; /* Is this shader allocated */ u32 vertex_size; ID3D11InputLayout *input_layout; @@ -52,54 +60,85 @@ struct dx11_shader { ID3D11PixelShader *ps; }; -struct dx11_constant_buffer_data { - struct mat4x4 vp; -}; - struct dx11_buffer { - u32 vertex_count; - u32 index_count; + D3D11_BUFFER_DESC desc; - u8 *cpu_vertex_buffer; /* Array of homogeneous vertices (size depends on shader) */ - vidx *cpu_index_buffer; /* Array of vertex indices into cpu_vertex_buffer */ - struct arena vertex_arena; - struct arena index_arena; + /* Cpu buffer */ + struct arena cpu_buffer_arena; + u8 *cpu_buffer; - u32 gpu_vertex_buffer_capacity; - u32 gpu_index_buffer_capacity; - ID3D11Buffer *gpu_vertex_buffer; - ID3D11Buffer *gpu_index_buffer; + /* Gpu buffer */ + ID3D11ShaderResourceView *srv; + ID3D11Buffer *gpu_buffer; + u64 gpu_buffer_pos; + u64 gpu_buffer_capacity; + + struct dx11_buffer *next_free; }; -struct gpu_cmd { - struct dx11_shader *shader; - - struct gpu_texture texture; /* Overrides sprite if set */ - struct sprite_tag sprite; - - /* Associated buffer data */ - u32 vertex_count; - u32 index_count; - u32 vertex_offset; - u32 index_offset; - b32 offsets_set; - - struct gpu_cmd *next; +struct dx11_cmd_buffers { + union { + struct { + struct dx11_buffer *vertex_buffer; + struct dx11_buffer *index_buffer; + } triangles; + struct { + struct dx11_buffer *instance_buffer; + } texture; + struct { + struct dx11_buffer *instance_buffer; + } grid; + }; }; -struct cmd_store { - struct gpu_cmd *cmd_first; - struct gpu_cmd *cmd_last; - struct arena arena; +struct dx11_cmd { + enum gpu_cmd_kind kind; + union { + struct { + u32 vertex_offset; + u32 vertex_count; + u32 index_offset; + u32 index_count; + } triangles; + struct { + struct gpu_texture 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 dx11_cmd *next; }; -struct gpu_cmd_buffer { - struct dx11_buffer buffers[NUM_SHADERS]; +struct dx11_cmd_store { + struct arena cpu_cmds_arena; + struct dx11_cmd *cpu_first_cmd; + struct dx11_cmd *cpu_last_cmd; - struct cmd_store cpu_cmd_store; - struct cmd_store gpu_cmd_store; + struct arena gpu_cmds_arena; + struct dx11_cmd *gpu_first_cmd; + struct dx11_cmd *gpu_last_cmd; - b32 valid; /* False if uninitialized (in sparse array) */ + struct { + struct dx11_buffer *constant_buffer; + struct { + struct dx11_buffer *vertex_buffer; + struct dx11_buffer *index_buffer; + } triangles; + struct { + struct dx11_buffer *instance_buffer; + } texture; + struct { + struct dx11_buffer *instance_buffer; + } grid; + } buffers; + + struct dx11_cmd_store *next_free; }; struct dx11_format { @@ -109,15 +148,12 @@ struct dx11_format { struct dx11_texture { ID3D11Texture2D *texture; + ID3D11ShaderResourceView *srv; + ID3D11RenderTargetView *rtv; b32 is_backbuffer; - - struct dx11_texture *prev; - struct dx11_texture *next; struct dx11_texture *next_free; }; -INTERNAL void gpu_capture_image_for_profiler(void); - /* ========================== * * Global state * ========================== */ @@ -138,7 +174,7 @@ struct handle_store { }; struct dx11_shader_desc { - enum shader_kind kind; + enum dx11_shader_kind kind; char *name_cstr; u32 vertex_size; D3D11_INPUT_ELEMENT_DESC input_layout_desc[64]; /* NULL terminated array */ @@ -170,20 +206,26 @@ GLOBAL struct { ID3D11DepthStencilState *depth_stencil_state; ID3D11SamplerState *sampler_state; - ID3D11Buffer *vs_constant_buffer; + /* Buffer pool */ + struct sys_mutex buffers_mutex; + struct arena buffers_arena; + struct dx11_buffer *first_free_buffer; - /* Texture store */ + /* Cmd store pool */ + struct sys_mutex cmd_stores_mutex; + struct arena cmd_stores_arena; + struct dx11_cmd_store *first_free_cmd_store; + + /* Texture pool */ struct sys_mutex textures_mutex; struct arena textures_arena; - struct dx11_texture *textures_first; - struct dx11_texture *textures_last; - struct dx11_texture *textures_first_free; + struct dx11_texture *first_free_texture; - /* Sparse array (cmdbuff.valid) */ - struct gpu_cmd_buffer cmdbuffs[MAX_CMD_BUFFERS]; + /* Sparse array (store.valid) */ + struct gpu_cmd_store stores[MAX_CMD_STORES]; - struct dx11_shader shaders[NUM_SHADERS]; - struct dx11_shader_desc shader_info[NUM_SHADERS]; + struct dx11_shader shaders[NUM_DX11_SHADER_KINDS]; + struct dx11_shader_desc shader_info[NUM_DX11_SHADER_KINDS]; } G = ZI, DEBUG_ALIAS(G, G_gpu_dx11); @@ -199,18 +241,6 @@ INLINE struct mat4x4 calculate_vp(struct xform view, f32 viewport_width, f32 vie return mat4x4_mul(projection, view4x4); } -INTERNAL void send_constant_buffer_data(ID3D11Buffer *buffer, struct mat4x4 vp) -{ - D3D11_MAPPED_SUBRESOURCE ms; - if (ID3D11DeviceContext_Map(G.devcon, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms) != S_OK) { - ASSERT(false); - return; - } - struct dx11_constant_buffer_data *data = (struct dx11_constant_buffer_data *)ms.pData; - MEMCPY(&data->vp, &vp, sizeof(vp)); - ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)buffer, 0); -} - /* ========================== * * Startup * ========================== */ @@ -228,7 +258,15 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window) G.arena = arena_alloc(GIGABYTE(64)); - /* Initialize texture store */ + /* Initialize buffers pool */ + G.buffers_mutex = sys_mutex_alloc(); + G.buffers_arena = arena_alloc(GIGABYTE(64)); + + /* Initialize cmd store pool */ + G.cmd_stores_mutex = sys_mutex_alloc(); + G.cmd_stores_arena = arena_alloc(GIGABYTE(64)); + + /* Initialize texture pool */ G.textures_mutex = sys_mutex_alloc(); G.textures_arena = arena_alloc(GIGABYTE(64)); @@ -339,7 +377,7 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window) (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 blending setup */ + /* Create the blend state */ { __profscope(create_blend_state); const f32 blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; @@ -412,25 +450,9 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window) ID3D11DeviceContext_PSSetSamplers(G.devcon, 0, 1, &G.sampler_state); } - /* Create the constant buffer */ - { - __profscope(create_const_buffer); - D3D11_BUFFER_DESC desc = { - .ByteWidth = sizeof(struct dx11_constant_buffer_data), - .Usage = D3D11_USAGE_DYNAMIC, - .BindFlags = D3D11_BIND_CONSTANT_BUFFER, - .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE, - .MiscFlags = 0 - }; - ID3D11Device_CreateBuffer(G.dev, &desc, NULL, &G.vs_constant_buffer); - - /* Apparently ByteWidth needs to be in multiples of 16? */ - ASSERT(desc.ByteWidth % 16 == 0); - } - /* Init shaders */ logf_info("Compiling shaders"); - for (u32 i = SHADER_NONE + 1; i < NUM_SHADERS; ++i) { + 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); @@ -449,15 +471,63 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window) * Shader table * ========================== */ +/* Triangle structs */ + +PACK(struct dx11_triangle_uniform { + struct mat4x4 vp; +}); + +PACK(struct dx11_triangle_vertex { + struct v2 pos; + struct v2 uv; + u32 tint_srgb; +}); + +PACK(struct dx11_texture_vertex { + struct v2 pos; +}); + +/* Texture 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; +}); + +/* Grid structs */ + +PACK(struct dx11_grid_uniform { + struct mat4x4 vp; +}); + +PACK(struct dx11_grid_vertex { + struct v2 pos; + f32 line_thickness; + f32 line_spacing; + struct v2 offset; + u32 bg0_srgb; + u32 bg1_srgb; + u32 line_srgb; + u32 x_srgb; + u32 y_srgb; +}); + INTERNAL void init_shader_table(void) { MEMZERO_ARRAY(G.shader_info); /* Triangle shader layout */ - G.shader_info[SHADER_TRIANGLE] = (struct dx11_shader_desc) { - .kind = SHADER_TRIANGLE, + G.shader_info[DX11_SHADER_KIND_TRIANGLE] = (struct dx11_shader_desc) { + .kind = DX11_SHADER_KIND_TRIANGLE, .name_cstr = "shaders/triangle.hlsl", - .vertex_size = sizeof(struct triangle_shader_vertex), + .vertex_size = sizeof(struct dx11_triangle_vertex), .input_layout_desc = { { "pos", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "uv", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, @@ -465,11 +535,21 @@ INTERNAL void init_shader_table(void) } }; + /* Texture shader layout */ + G.shader_info[DX11_SHADER_KIND_TEXTURE] = (struct dx11_shader_desc) { + .kind = DX11_SHADER_KIND_TEXTURE, + .name_cstr = "shaders/texture.hlsl", + .vertex_size = sizeof(struct dx11_texture_vertex), + .input_layout_desc = { + { "pos", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + } + }; + /* Grid shader layout */ - G.shader_info[SHADER_GRID] = (struct dx11_shader_desc) { - .kind = SHADER_GRID, + G.shader_info[DX11_SHADER_KIND_GRID] = (struct dx11_shader_desc) { + .kind = DX11_SHADER_KIND_GRID, .name_cstr = "shaders/grid.hlsl", - .vertex_size = sizeof(struct grid_shader_vertex), + .vertex_size = sizeof(struct dx11_grid_vertex), .input_layout_desc = { { "pos", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "line_thickness", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, @@ -525,7 +605,7 @@ INTERNAL b32 shader_set_dirty(struct string name) { __prof; b32 caused_dirty = false; - for (u64 i = 0; i < NUM_SHADERS; ++i) { + 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)) { @@ -787,11 +867,10 @@ INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_d } resource_close(&src_res); if (error_msg.len != 0) { - if (old_shader->valid) { - /* If shader failed to load but a working shader already exists, just error rather than panicking */ - log_error(error_msg); - } else { - sys_panic(error_msg); + 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); } } } @@ -808,20 +887,307 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name) #endif /* ========================== * - * Render + * Dx11 buffer * ========================== */ - /* TODO: Lock cmdbuff or at least global state? (in-case multi-threaded present). - * Another option is to store a separate device on each cmdbuff? - * - * I'm thinking we may also just need to lock texture modification access while presenting */ -INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer *cmdbuff, struct xform view, struct rect viewport) +/* TODO: Buffer caching based on size */ + +/* NOTE: desc ByteWidth will be ignored (set dynamically when buffer grows) */ +INTERNAL struct dx11_buffer *dx11_buffer_alloc(struct D3D11_BUFFER_DESC desc) { __prof; - __profscope_dx11(G.profiling_ctx, Render, RGB_F(0.5, 0.2, 0.2)); + struct dx11_buffer *buffer = NULL; + { + struct arena cpu_buffer_arena = ZI; + { + 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.base) { + cpu_buffer_arena = arena_alloc(GIGABYTE(64)); + } + buffer->cpu_buffer_arena = cpu_buffer_arena; + } + buffer->desc = desc; + buffer->cpu_buffer = arena_dry_push(&buffer->cpu_buffer_arena, u8); + return buffer; +} + +/* TODO */ +#if 0 +INTERNAL void dx11_buffer_release(struct dx11_buffer *buffer) +{ + (UNUSED)buffer; +} +#endif + +INTERNAL void *dx11_buffer_push(struct dx11_buffer *buffer, u64 size) +{ + __prof; + 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); +} + +/* ========================== * + * Cmd store + * ========================== */ + +struct gpu_cmd_store gpu_cmd_store_alloc(void) +{ + struct dx11_cmd_store *store = NULL; + { + struct arena cpu_cmds_arena = ZI; + struct arena gpu_cmds_arena = ZI; + { + struct sys_lock lock = sys_mutex_lock_e(&G.cmd_stores_mutex); + if (G.first_free_cmd_store) { + store = G.first_free_cmd_store; + G.first_free_cmd_store = store->next_free; + cpu_cmds_arena = store->cpu_cmds_arena; + gpu_cmds_arena = store->gpu_cmds_arena; + } else { + store = arena_push_no_zero(&G.cmd_stores_arena, struct dx11_cmd_store); + } + sys_mutex_unlock(&lock); + } + MEMZERO_STRUCT(store); + if (!cpu_cmds_arena.base) { + cpu_cmds_arena = arena_alloc(GIGABYTE(64)); + } + if (!gpu_cmds_arena.base) { + gpu_cmds_arena = arena_alloc(GIGABYTE(64)); + } + store->cpu_cmds_arena = cpu_cmds_arena; + store->gpu_cmds_arena = gpu_cmds_arena; + arena_reset(&store->cpu_cmds_arena); + arena_reset(&store->gpu_cmds_arena); + } + + + /* Desc templates */ + const D3D11_BUFFER_DESC constant_buffer_desc = { + .Usage = D3D11_USAGE_DYNAMIC, + .BindFlags = D3D11_BIND_CONSTANT_BUFFER, + .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE + }; + 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 */ + { + /* Constant buffer */ + { + store->buffers.constant_buffer = dx11_buffer_alloc(constant_buffer_desc); + } + + /* Triangle buffers */ + { +#if 0 + store->buffers.triangles.vertex_buffer = dx11_buffer_alloc(D3D11_BIND_VERTEX_BUFFER); + store->buffers.triangles.index_buffer = dx11_buffer_alloc(D3D11_BIND_INDEX_BUFFER); +#endif + } + + /* Texture buffers */ + { + struct D3D11_BUFFER_DESC desc = structured_buffer_desc; + desc.StructureByteStride = sizeof(struct dx11_texture_instance); + store->buffers.texture.instance_buffer = dx11_buffer_alloc(desc); + } + + /* Grid buffers */ + { +#if 0 + struct D3D11_BUFFER_DESC desc = structured_buffer_desc; + desc.StructureByteStride = sizeof(struct dx11_grid_instance), + store->buffers.texture.instance_buffer = dx11_buffer_alloc(D3D11_BIND_SHADER_RESOURCE); +#endif + } + } + + struct gpu_cmd_store res = ZI; + res.handle = (u64)store; + return res; +} + +void gpu_cmd_store_release(struct gpu_cmd_store gpu_cmd_store) +{ + /* TODO */ + (UNUSED)gpu_cmd_store; +} + +void gpu_push_cmd(struct gpu_cmd_store gpu_cmd_store, struct gpu_cmd_params params) +{ + struct dx11_cmd_store *store = (struct dx11_cmd_store *)gpu_cmd_store.handle; + + switch (params.kind) { + default: + { + /* Unknown cmd kind */ + ASSERT(false); + } break; + + case GPU_CMD_KIND_DRAW_TRIANGLES: + { + /* TODO */ + } break; + + case GPU_CMD_KIND_DRAW_TEXTURE: + { + struct dx11_cmd *cmd = store->cpu_last_cmd; + if (cmd && + ((cmd->kind != params.kind) || + (cmd->texture.sprite.hash != params.texture.sprite.hash) || + (cmd->texture.texture.handle != params.texture.texture.handle))) { + /* Cannot batch */ + cmd = NULL; + } + + /* Start new cmd */ + if (!cmd) { + /* TODO: Better count method */ + u32 instance_offset = (store->buffers.texture.instance_buffer->cpu_buffer_arena.pos / sizeof(struct dx11_texture_instance)); + + cmd = arena_push(&store->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 = instance_offset; + if (store->cpu_last_cmd) { + store->cpu_last_cmd->next = cmd; + } else { + store->cpu_first_cmd = cmd; + } + store->cpu_last_cmd = cmd; + } + + /* Push instance data */ + ++cmd->texture.instance_count; + struct dx11_texture_instance *instance = dx11_buffer_push(store->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; + } break; + + case GPU_CMD_KIND_DRAW_GRID: + { + /* TODO */ + } break; + } +} + +void gpu_submit_cmds(struct gpu_cmd_store gpu_cmd_store) +{ + __prof; + struct dx11_cmd_store *store = (struct dx11_cmd_store *)gpu_cmd_store.handle; + + /* Swap cmd lists */ + struct arena swp_arena = store->gpu_cmds_arena; + store->gpu_cmds_arena = store->cpu_cmds_arena; + store->gpu_first_cmd = store->cpu_first_cmd; + store->gpu_last_cmd = store->cpu_last_cmd; + + /* Reset cpu cmds */ + store->cpu_cmds_arena = swp_arena; + store->cpu_first_cmd = NULL; + store->cpu_last_cmd = NULL; + arena_reset(&store->cpu_cmds_arena); + + /* Submit triangle buffers */ + //dx11_buffer_submit(store->buffers.triangles.vertex_buffer); + //dx11_buffer_submit(store->buffers.triangles.index_buffer); + + /* Submit texture buffers */ + dx11_buffer_submit(store->buffers.texture.instance_buffer); + + /* Submit grid buffers */ + //dx11_buffer_submit(store->buffers.grid.instance_buffer); +} + +/* TODO: Lock resources during run */ +void gpu_run_cmds(struct gpu_cmd_store gpu_cmd_store, struct gpu_texture target, struct xform view, struct rect viewport) +{ + __prof; + __profscope_dx11(G.profiling_ctx, Run, RGB_F(0.5, 0.2, 0.2)); struct sprite_scope *sprite_scope = sprite_scope_begin(); - ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target, NULL); + ID3D11RenderTargetView *null_rtvs[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + ID3D11ShaderResourceView *null_srvs[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + + struct dx11_cmd_store *store = (struct dx11_cmd_store *)gpu_cmd_store.handle; + struct dx11_texture *target_texture = (struct dx11_texture *)target.handle; + + + /* Set render targets */ + ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target_texture->rtv, NULL); D3D11_VIEWPORT d3d11_viewport = ZI; d3d11_viewport.Width = viewport.width; @@ -832,41 +1198,25 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer d3d11_viewport.TopLeftY = viewport.y; ID3D11DeviceContext_RSSetViewports(G.devcon, 1, &d3d11_viewport); - /* Fill and set constant buffer - * NOTE: We're only doing this once per render, rather than once per - * draw call since the only constant right now is VP. */ + /* TODO: Set viewport & vp matrix in a cmd */ struct mat4x4 vp_matrix = calculate_vp(view, viewport.width, viewport.height); - send_constant_buffer_data(G.vs_constant_buffer, vp_matrix); - ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &G.vs_constant_buffer); - ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &G.vs_constant_buffer); - struct dx11_shader *prev_shader = NULL; + for (struct dx11_cmd *cmd = store->gpu_first_cmd; cmd; cmd = cmd->next) { + enum gpu_cmd_kind cmd_kind = cmd->kind; - struct gpu_cmd *cmd = cmdbuff ? cmdbuff->gpu_cmd_store.cmd_first : NULL; - for (; cmd; cmd = cmd->next) { - struct dx11_shader *shader = cmd->shader; - struct dx11_buffer *buffer = &cmdbuff->buffers[shader->kind]; - - /* Activate shader */ - if (shader != prev_shader) { - ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0); - ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0); - ID3D11DeviceContext_IASetInputLayout(G.devcon, shader->input_layout); - prev_shader = shader; - } - - ID3D11ShaderResourceView *null_srv[1] = { NULL }; - - switch (shader->kind) { + switch (cmd_kind) { default: { /* Unknown shader */ ASSERT(false); } break; - case SHADER_TRIANGLE: + case GPU_CMD_KIND_DRAW_TRIANGLES: { - __profscope_dx11(G.profiling_ctx, Triangle Shader, RGB_F(0.2, 0.2, 0.5)); + /* TODO */ +#if 0 + __profscope_dx11(G.profiling_ctx, Triangles, RGB_F(0.2, 0.2, 0.5)); + /* FIXME: Texture refcount needs to be increased here to prevent release mid-render */ ID3D11Texture2D *texture = NULL; if (cmd->texture.handle) { @@ -881,8 +1231,6 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer } if (texture) { - /* Bind texture */ - /* Create SRV */ D3D11_TEXTURE2D_DESC texture_desc = ZI; ID3D11Texture2D_GetDesc(texture, &texture_desc); @@ -890,10 +1238,9 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer ID3D11ShaderResourceView *texture_srv = NULL; ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)texture, &srv_desc, &texture_srv); + /* Bind texture */ ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &texture_srv); - ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - /* Activate buffer */ u32 zero = 0; UINT vertex_stride = shader->vertex_size; @@ -904,6 +1251,7 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer u32 vertex_offset = cmd->vertex_offset; u32 index_offset = cmd->index_offset; u32 index_count = cmd->index_count; + ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset); /* Release SRV */ @@ -911,12 +1259,88 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer /* Unbind */ ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, null_srv); - } +#endif } break; - case SHADER_GRID: + case GPU_CMD_KIND_DRAW_TEXTURE: { - __profscope_dx11(G.profiling_ctx, Grid Shader, RGB_F(0.2, 0.5, 0.2)); + __profscope_dx11(G.profiling_ctx, Texture, RGB_F(0.2, 0.2, 0.5)); + struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE]; + if (shader->valid) { + struct dx11_texture *texture = NULL; + if (cmd->texture.texture.handle) { + /* Load texture if handle is set */ + texture = (struct dx11_texture *)cmd->texture.texture.handle; + } 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.handle; + } + if (cmd->texture.sprite.hash == 13036381201575792585ULL) { + DEBUGBREAKABLE; + } + } + + if (texture && texture->srv && shader->valid) { + struct dx11_buffer *constant_buffer = store->buffers.constant_buffer; + struct dx11_buffer *instance_buffer = store->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); + +#if 0 + /* Build & bind constant buffer */ + struct texture_shader_uniforms uniforms = ZI; + uniforms.vp = vp_matrix; + { + D3D11_MAPPED_SUBRESOURCE subres = ZI; + ID3D11DeviceContext_Map(G.devcon, (ID3D11Resource *)constant_buffer->gpu_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subres); + struct texture_shader_uniforms *subres_ptr = (struct texture_shader_uniforms *)subres.pData; + MEMCPY(subres_ptr, &uniforms, sizeof(uniforms)); + ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)constant_buffer->gpu_buffer, 0); + } + ID3D11DeviceContext_SetConstantBuffers(G.devcon, 0, 1, &constant_buffer->srv); +#else + /* 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); +#endif + + /* Bind texture */ + ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &texture->srv); + ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &texture->srv); + + /* Bind instance buffer */ + ID3D11DeviceContext_VSSetShaderResources(G.devcon, 1, 1, &instance_buffer->srv); + ID3D11DeviceContext_PSSetShaderResources(G.devcon, 1, 1, &instance_buffer->srv); + + /* Draw */ + ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D11DeviceContext_DrawInstanced(G.devcon, 6, instance_count, 0, 0); + + /* Unbind SRVs */ + ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 8, null_srvs); + ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 8, null_srvs); + } + } + + } break; + + case GPU_CMD_KIND_DRAW_GRID: + { + /* TODO */ +#if 0 + __profscope_dx11(G.profiling_ctx, Grid, RGB_F(0.2, 0.5, 0.2)); ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); /* Activate buffer */ @@ -930,10 +1354,14 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct gpu_cmd_buffer u32 index_offset = cmd->index_offset; u32 index_count = cmd->index_count; ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset); +#endif } break; } } + /* Unbind render target */ + ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 8, null_rtvs, NULL); + sprite_scope_end(sprite_scope); } @@ -964,24 +1392,17 @@ INTERNAL struct dx11_texture *dx11_texture_alloc(enum gpu_texture_format format, { struct dx11_texture *t = NULL; { - /* Allocate to list */ struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex); - if (G.textures_first_free) { - t = G.textures_first_free; - G.textures_first_free = t->next_free; + 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); } - MEMZERO_STRUCT(t); - if (!G.textures_first) { - G.textures_first = t; - } else { - G.textures_last->next = t; - } - t->prev = G.textures_last; - G.textures_last = t; sys_mutex_unlock(&lock); } + MEMZERO_STRUCT(t); + struct dx11_format dx11_format = dx11_format_from_gpu_format(format); if (dx11_format.format == DXGI_FORMAT_UNKNOWN) { /* Unknown format */ @@ -990,7 +1411,7 @@ INTERNAL struct dx11_texture *dx11_texture_alloc(enum gpu_texture_format format, } u32 bind_flags = D3D11_BIND_SHADER_RESOURCE; - if (flags & GPU_TEXTURE_FLAG_TARGET) { + if (flags & GPU_TEXTURE_FLAG_TARGETABLE) { bind_flags |= D3D11_BIND_RENDER_TARGET; } @@ -1005,6 +1426,7 @@ INTERNAL struct dx11_texture *dx11_texture_alloc(enum gpu_texture_format format, desc.BindFlags = bind_flags; desc.Format = dx11_format.format; + /* Create texture */ ID3D11Texture2D *texture = NULL; if (initial_data) { D3D11_SUBRESOURCE_DATA subresource_data = { .pSysMem = initial_data, .SysMemPitch = size.x * dx11_format.pixel_size, .SysMemSlicePitch = 0 }; @@ -1015,6 +1437,20 @@ INTERNAL struct dx11_texture *dx11_texture_alloc(enum gpu_texture_format format, ASSERT(texture != NULL); t->texture = texture; + /* Create SRV */ + if (t->texture && (bind_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 && (bind_flags & D3D11_BIND_RENDER_TARGET)) { + ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &t->rtv); + } + return t; } @@ -1022,26 +1458,17 @@ INTERNAL void dx11_texture_release(struct dx11_texture *t) { if (!t->is_backbuffer) { { - /* Free from list */ struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex); - struct dx11_texture *prev = t->prev; - struct dx11_texture *next = t->next; - if (prev) { - prev->next = next; - } - if (next) { - next->prev = prev; - } - if (G.textures_first == t) { - G.textures_first = next; - } - if (G.textures_last == t) { - G.textures_last = prev; - } - t->next_free = G.textures_first_free; - G.textures_first_free = t; + 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); } @@ -1066,47 +1493,14 @@ void gpu_texture_release(struct gpu_texture t) void gpu_texture_clear(struct gpu_texture target_texture, u32 clear_color) { __prof; - - ID3D11Texture2D *texture = ((struct dx11_texture *)target_texture.handle)->texture; - - ID3D11RenderTargetView *target_view = NULL; - ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)texture, NULL, &target_view); - if (target_view) { + struct dx11_texture *t = (struct dx11_texture *)target_texture.handle; + if (t->rtv) { 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, target_view, fill); - } - - if (target_view) { - ID3D11RenderTargetView_Release(target_view); - } -} - -void gpu_texture_render(struct gpu_texture texture, struct gpu_cmd_buffer *cmdbuff, struct xform view, struct rect viewport) -{ - __prof; - - struct dx11_texture *t = (struct dx11_texture *)texture.handle; - - D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = ZI; - D3D11_RENDER_TARGET_VIEW_DESC *rtv_desc_param = NULL; - if (t->is_backbuffer) { - rtv_desc.Format = DX11_SWAPCHAIN_RTV_FORMAT; - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtv_desc_param = &rtv_desc; - } - - ID3D11RenderTargetView *target_view = NULL; - ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, rtv_desc_param, &target_view); - if (target_view) { - dx11_render(target_view, cmdbuff, view, viewport); - } - - if (target_view) { - ID3D11RenderTargetView_Release(target_view); + ID3D11DeviceContext_ClearRenderTargetView(G.devcon, t->rtv, fill); } } @@ -1124,6 +1518,8 @@ struct v2i32 gpu_texture_get_size(struct gpu_texture texture) * Backbuffer * ========================== */ +INTERNAL void gpu_capture_image_for_profiler(void); + #if GSTAT_ENABLED || PROFILING INTERNAL struct DXGI_QUERY_VIDEO_MEMORY_INFO get_memory_info(void) { @@ -1164,22 +1560,31 @@ struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size) { struct gpu_texture res = ZI; - /* Resize */ + /* 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); + /* 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); + res.handle = (u64)&G.backbuffer_texture; return res; } -void gpu_present_backbuffer(i32 vsync) +void gpu_swap_backbuffer(i32 vsync) { __prof; #if RESOURCE_RELOADING - for (u64 i = SHADER_NONE + 1; i < NUM_SHADERS; ++i) { + 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); @@ -1191,20 +1596,26 @@ void gpu_present_backbuffer(i32 vsync) { struct DXGI_QUERY_VIDEO_MEMORY_INFO info = get_memory_info(); u64 vram = info.CurrentUsage; - u64 budget = info.Budget; - gstat_set(GSTAT_VRAM_USAGE, vram); - gstat_set(GSTAT_VRAM_BUDGET, budget); +# if GSTAT_ENABLED + { + u64 budget = info.Budget; + gstat_set(GSTAT_VRAM_USAGE, vram); + gstat_set(GSTAT_VRAM_BUDGET, budget); + } +# endif # if PROFILING - static char *plot_name = NULL; - static u64 prev_vram = 0; - if (!plot_name) { - plot_name = "Video memory usage"; - __prof_plot_init(plot_name, __prof_plot_type_memory, 1, 1, 0); + { + LOCAL_PERSIST char *plot_name = NULL; + LOCAL_PERSIST u64 prev_vram = 0; + if (!plot_name) { + plot_name = "Video memory usage"; + __prof_plot_init(plot_name, __prof_plot_type_memory, 1, 1, 0); + } + if (vram != prev_vram) { + __prof_plot_i(plot_name, vram); + } + prev_vram = vram; } - if (vram != prev_vram) { - __prof_plot_i(plot_name, vram); - } - prev_vram = vram; # endif } #endif @@ -1223,214 +1634,6 @@ void gpu_present_backbuffer(i32 vsync) } } -/* ========================== * - * Cmd buffer - * ========================== */ - -struct gpu_cmd_buffer *gpu_cmd_buffer_alloc(void) -{ - struct gpu_cmd_buffer *cmdbuff = NULL; - for (u32 i = 0; i < MAX_CMD_BUFFERS; ++i) { - if (!G.cmdbuffs[i].valid) { - cmdbuff = &G.cmdbuffs[i]; - break; - } - } - - if (!cmdbuff) { - sys_panic(LIT("Max gpu cmdbuffs reached")); - return NULL; - } - - MEMZERO_STRUCT(cmdbuff); - cmdbuff->cpu_cmd_store.arena = arena_alloc(GIGABYTE(8)); - cmdbuff->gpu_cmd_store.arena = arena_alloc(GIGABYTE(8)); - cmdbuff->valid = true; - - /* Initialize buffers */ - for (u32 i = SHADER_NONE + 1; i < ARRAY_COUNT(cmdbuff->buffers); ++i) { - struct dx11_buffer *buffer = &cmdbuff->buffers[i]; - buffer->vertex_arena = arena_alloc(GIGABYTE(8)); - buffer->index_arena = arena_alloc(GIGABYTE(8)); - buffer->cpu_vertex_buffer = arena_dry_push(&buffer->vertex_arena, u8); - buffer->cpu_index_buffer = arena_dry_push(&buffer->index_arena, vidx); - } - - return cmdbuff; -} - -void gpu_cmd_buffer_release(struct gpu_cmd_buffer *cmdbuff) -{ - cmdbuff->valid = false; - arena_release(&cmdbuff->cpu_cmd_store.arena); - arena_release(&cmdbuff->gpu_cmd_store.arena); - - /* Destroy buffers */ - for (u32 i = SHADER_NONE + 1; i < ARRAY_COUNT(cmdbuff->buffers); ++i) { - struct dx11_buffer *buffer = &cmdbuff->buffers[i]; - arena_release(&buffer->vertex_arena); - arena_release(&buffer->index_arena); - - /* FIXME: Clear GPU buffers */ - } -} - -u32 gpu_cmd_buffer_push_vertices(struct gpu_cmd_buffer *cmdbuff, u8 **vertices_out, vidx **indices_out, u32 vertices_count, u32 indices_count) -{ - struct gpu_cmd *cmd = cmdbuff->cpu_cmd_store.cmd_last; - - if (!cmd) { - /* Tried to draw to cmdbuff with no active draw cmd */ - ASSERT(false); - return 0; - } - - struct dx11_shader *shader = cmd->shader; - struct dx11_buffer *buffer = &cmdbuff->buffers[shader->kind]; - - if (!cmd->offsets_set) { - cmd->vertex_offset = buffer->vertex_count; - cmd->index_offset = buffer->index_count; - cmd->offsets_set = true; - } - - u32 first_vertex_index = cmd->vertex_count; - cmd->vertex_count += vertices_count; - cmd->index_count += indices_count; - buffer->vertex_count += vertices_count; - buffer->index_count += indices_count; - - *vertices_out = arena_push_array_no_zero(&buffer->vertex_arena, u8, shader->vertex_size * vertices_count); - *indices_out = arena_push_array_no_zero(&buffer->index_arena, vidx, indices_count); - - return first_vertex_index; -} - -void gpu_cmd_buffer_ensure_cmd(struct gpu_cmd_buffer *cmdbuff, struct gpu_cmd_parameters *params) -{ - struct gpu_cmd *last_cmd = cmdbuff->cpu_cmd_store.cmd_last; - - struct gpu_cmd *new_cmd = NULL; - switch (params->kind) { - default: - { - /* Unknown shader kind */ - ASSERT(false); - } break; - - case SHADER_TRIANGLE: - { - if (!last_cmd - || last_cmd->shader->kind != SHADER_TRIANGLE - || (last_cmd->texture.handle != params->texture_params.texture.handle) - || !sprite_tag_eq(last_cmd->sprite, params->texture_params.sprite)) { - new_cmd = arena_push(&cmdbuff->cpu_cmd_store.arena, struct gpu_cmd); - new_cmd->shader = &G.shaders[SHADER_TRIANGLE]; - new_cmd->texture = params->texture_params.texture; - new_cmd->sprite = params->texture_params.sprite; - } - } break; - - case SHADER_GRID: - { - if (!last_cmd || last_cmd->shader->kind != SHADER_GRID) { - new_cmd = arena_push(&cmdbuff->cpu_cmd_store.arena, struct gpu_cmd); - new_cmd->shader = &G.shaders[SHADER_GRID]; - } - } break; - } - - if (new_cmd) { - if (!cmdbuff->cpu_cmd_store.cmd_first) { - cmdbuff->cpu_cmd_store.cmd_first = new_cmd; - } else { - last_cmd->next = new_cmd; - } - cmdbuff->cpu_cmd_store.cmd_last = new_cmd; - } -} - -void gpu_cmd_buffer_flush_to_gpu(struct gpu_cmd_buffer *cmdbuff) -{ - __prof; - - /* Create / grow vertex buffers */ - for (u32 i = 1; i < ARRAY_COUNT(cmdbuff->buffers); ++i) { - struct dx11_buffer *buffer = &cmdbuff->buffers[i]; - struct dx11_shader *shader = &G.shaders[i]; - u32 vertex_size = shader->vertex_size; - u32 index_size = sizeof(vidx); - - if (buffer->vertex_count == 0 || buffer->index_count == 0) { - continue; - } - - /* Grow vertex buffer */ - if (buffer->gpu_vertex_buffer_capacity < buffer->vertex_count) { - buffer->gpu_vertex_buffer_capacity = buffer->vertex_count + 5000; - D3D11_BUFFER_DESC desc = { - .Usage = D3D11_USAGE_DYNAMIC, - .ByteWidth = buffer->gpu_vertex_buffer_capacity * vertex_size, - .BindFlags = D3D11_BIND_VERTEX_BUFFER, - .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE - }; - /* TODO: Error checking */ - if (buffer->gpu_vertex_buffer) { - ID3D11Buffer_Release(buffer->gpu_vertex_buffer); - } - ID3D11Device_CreateBuffer(G.dev, &desc, NULL, &buffer->gpu_vertex_buffer); - } - - /* Grow index buffer */ - if (buffer->gpu_index_buffer_capacity < buffer->index_count) { - buffer->gpu_index_buffer_capacity = buffer->index_count + 5000; - D3D11_BUFFER_DESC desc = { - .Usage = D3D11_USAGE_DYNAMIC, - .ByteWidth = buffer->gpu_index_buffer_capacity * index_size, - .BindFlags = D3D11_BIND_INDEX_BUFFER, - .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE - }; - /* TODO: Error checking */ - if (buffer->gpu_index_buffer) { - ID3D11Buffer_Release(buffer->gpu_index_buffer); - } - ID3D11Device_CreateBuffer(G.dev, &desc, NULL, &buffer->gpu_index_buffer); - } - - /* Fill GPU vertex buffer */ - if (buffer->gpu_vertex_buffer) { - D3D11_MAPPED_SUBRESOURCE res; - ID3D11DeviceContext_Map(G.devcon, (ID3D11Resource *)buffer->gpu_vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &res); - MEMCPY(res.pData, buffer->cpu_vertex_buffer, buffer->vertex_count * vertex_size); - ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)buffer->gpu_vertex_buffer, 0); - } - - /* Fill GPU index buffer */ - if (buffer->gpu_index_buffer) { - D3D11_MAPPED_SUBRESOURCE res; - ID3D11DeviceContext_Map(G.devcon, (ID3D11Resource *)buffer->gpu_index_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &res); - MEMCPY(res.pData, buffer->cpu_index_buffer, buffer->index_count * index_size); - ID3D11DeviceContext_Unmap(G.devcon, (ID3D11Resource *)buffer->gpu_index_buffer, 0); - } - - /* Reset CPU buffers */ - buffer->vertex_count = 0; - buffer->index_count = 0; - arena_reset(&buffer->vertex_arena); - arena_reset(&buffer->index_arena); - } - - /* Swap CPU cmds to GPU store */ - struct cmd_store temp = cmdbuff->gpu_cmd_store; - cmdbuff->gpu_cmd_store = cmdbuff->cpu_cmd_store; - cmdbuff->cpu_cmd_store = temp; - - /* Reset CPU cmds */ - cmdbuff->cpu_cmd_store.cmd_first = NULL; - cmdbuff->cpu_cmd_store.cmd_last = NULL; - arena_reset(&cmdbuff->cpu_cmd_store.arena); -} - /* ========================== * * Profiling frame capture * ========================== */ diff --git a/src/sprite.c b/src/sprite.c index c2c02f60..1d25e73d 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -375,16 +375,11 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t } if (decoded.success) { - enum gpu_texture_format format = GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM; - if (decoded.srgb) { - format = GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB; - } - /* Initialize */ e->texture = arena_push(&e->arena, struct sprite_texture); e->texture->width = decoded.image.width; e->texture->height = decoded.image.height; - e->texture->texture = gpu_texture_alloc(format, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels); + e->texture->texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels); e->texture->valid = true; e->texture->loaded = true; /* TODO: Query gpu for more accurate texture size in VRAM */ diff --git a/src/user.c b/src/user.c index c642b7a3..cc9f3987 100644 --- a/src/user.c +++ b/src/user.c @@ -71,17 +71,14 @@ GLOBAL struct { struct second_stat net_bytes_sent; /* Render targets */ - struct gpu_texture final_texture; - struct gpu_texture world_texture; - struct gpu_texture ui_texture; + struct gpu_texture user_texture; struct gpu_texture backbuffer_texture; - struct gpu_cmd_buffer *world_cmd_buffer; - struct gpu_cmd_buffer *ui_cmd_buffer; - struct gpu_cmd_buffer *final_cmd_buffer; - struct gpu_cmd_buffer *backbuffer_cmd_buffer; + struct gpu_cmd_store world_gpu_cmd_store; + struct gpu_cmd_store user_gpu_cmd_store; + struct gpu_cmd_store backbuffer_gpu_cmd_store; - struct xform world_to_ui_xf; + struct xform world_to_user_xf; struct bind_state bind_states[USER_BIND_KIND_COUNT]; @@ -139,10 +136,10 @@ GLOBAL struct { /* Per-frame */ struct v2 screen_size; struct v2 screen_cursor; - struct v2 ui_screen_offset; - struct v2 ui_size; - struct v2 ui_center; - struct v2 ui_cursor; + struct v2 user_screen_offset; + struct v2 user_size; + struct v2 user_center; + struct v2 user_cursor; struct v2 world_cursor; struct v2 focus_send; } G = ZI, DEBUG_ALIAS(G, G_user); @@ -255,11 +252,10 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr, /* User sim control */ G.user_sim_cmd_mutex = sys_mutex_alloc(); - G.world_to_ui_xf = XFORM_IDENT; - G.world_cmd_buffer = gpu_cmd_buffer_alloc(); - G.ui_cmd_buffer = gpu_cmd_buffer_alloc(); - G.final_cmd_buffer = gpu_cmd_buffer_alloc(); - G.backbuffer_cmd_buffer = gpu_cmd_buffer_alloc(); + G.world_to_user_xf = XFORM_IDENT; + G.world_gpu_cmd_store = gpu_cmd_store_alloc(); + G.user_gpu_cmd_store = gpu_cmd_store_alloc(); + G.backbuffer_gpu_cmd_store = gpu_cmd_store_alloc(); //log_register_callback(debug_console_log_callback, LOG_LEVEL_SUCCESS); log_register_callback(debug_console_log_callback, LOG_LEVEL_DEBUG); @@ -338,21 +334,21 @@ INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y) f32 thickness = 2.f; f32 arrowhead_len = 15.f; - struct v2 pos = xform_mul_v2(G.world_to_ui_xf, xf.og); - struct v2 x_ray = xform_basis_mul_v2(G.world_to_ui_xf, xform_get_right(xf)); - struct v2 y_ray = xform_basis_mul_v2(G.world_to_ui_xf, xform_get_up(xf)); + struct v2 pos = xform_mul_v2(G.world_to_user_xf, xf.og); + struct v2 x_ray = xform_basis_mul_v2(G.world_to_user_xf, xform_get_right(xf)); + struct v2 y_ray = xform_basis_mul_v2(G.world_to_user_xf, xform_get_up(xf)); f32 ray_scale = 1; x_ray = v2_mul(x_ray, ray_scale); y_ray = v2_mul(y_ray, ray_scale); - draw_arrow_ray(G.ui_cmd_buffer, pos, x_ray, thickness, arrowhead_len, color_x); - draw_arrow_ray(G.ui_cmd_buffer, pos, y_ray, thickness, arrowhead_len, color_y); + draw_arrow_ray(G.user_gpu_cmd_store, pos, x_ray, thickness, arrowhead_len, color_x); + draw_arrow_ray(G.user_gpu_cmd_store, pos, y_ray, thickness, arrowhead_len, color_y); //u32 color_quad = RGBA_F(0, 1, 1, 0.3); //struct quad quad = quad_from_rect(RECT(0, 0, 1, -1)); //quad = xform_mul_quad(xf, quad_scale(quad, 0.075f)); - //draw_quad(G.ui_cmd_buffer, quad, color); + //draw_quad(G.user_gpu_cmd_store, quad, color); } INTERNAL void debug_draw_movement(struct sim_ent *ent) @@ -365,11 +361,11 @@ INTERNAL void debug_draw_movement(struct sim_ent *ent) struct xform xf = sim_ent_get_xform(ent); struct v2 velocity = ent->linear_velocity; - struct v2 pos = xform_mul_v2(G.world_to_ui_xf, xf.og); - struct v2 vel_ray = xform_basis_mul_v2(G.world_to_ui_xf, velocity); + struct v2 pos = xform_mul_v2(G.world_to_user_xf, xf.og); + struct v2 vel_ray = xform_basis_mul_v2(G.world_to_user_xf, velocity); if (v2_len(vel_ray) > 0.00001) { - draw_arrow_ray(G.ui_cmd_buffer, pos, vel_ray, thickness, arrow_len, color_vel); + draw_arrow_ray(G.user_gpu_cmd_store, pos, vel_ray, thickness, arrow_len, color_vel); } } @@ -539,7 +535,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized) if (log->level <= level) { /* Draw background */ u32 color = colors[log->level][log->color_index]; - draw_quad(G.ui_cmd_buffer, quad_from_rect(log->bounds), ALPHA_F(color, opacity)); + draw_quad(G.user_gpu_cmd_store, quad_from_rect(log->bounds), ALPHA_F(color, opacity)); /* Draw text */ struct string text = log->msg; @@ -556,7 +552,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized) } struct draw_text_params params = DRAW_TEXT_PARAMS(.font = font, .pos = draw_pos, .offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM, .color = ALPHA_F(COLOR_WHITE, opacity), .str = text); - struct rect bounds = draw_text(G.ui_cmd_buffer, params); + struct rect bounds = draw_text(G.user_gpu_cmd_store, params); struct rect draw_bounds = bounds; draw_bounds.x -= bg_margin; @@ -780,10 +776,10 @@ INTERNAL void user_update(void) b32 pressed = event->kind == SYS_EVENT_KIND_BUTTON_DOWN; #if 0 b32 out_of_bounds = button >= SYS_BTN_M1 && button <= SYS_BTN_M5 && - (G.ui_cursor.x < 0 || - G.ui_cursor.y < 0 || - G.ui_cursor.x > G.ui_size.x || - G.ui_cursor.y > G.ui_size.y); + (G.user_cursor.x < 0 || + G.user_cursor.y < 0 || + G.user_cursor.x > G.user_size.x || + G.user_cursor.y > G.user_size.y); #else b32 out_of_bounds = false; #endif @@ -931,8 +927,8 @@ INTERNAL void user_update(void) /* Calculate ui dimensions */ if (G.debug_camera) { - G.ui_size = G.screen_size; - G.ui_screen_offset = V2(0, 0); + G.user_size = G.screen_size; + G.user_screen_offset = V2(0, 0); } else { /* Determine ui size by camera & window dimensions */ f32 aspect_ratio = DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT; @@ -950,27 +946,27 @@ INTERNAL void user_update(void) } else { height = math_ceil(width / aspect_ratio); } - G.ui_size = V2(width, height); + G.user_size = V2(width, height); /* Center ui in window */ f32 x = 0; f32 y = 0; x = math_round(G.screen_size.x / 2 - width / 2); y = math_round(G.screen_size.y / 2 - height / 2); - G.ui_screen_offset = V2(x, y); + G.user_screen_offset = V2(x, y); } - G.ui_center = v2_mul(G.ui_size, 0.5); - G.ui_cursor = v2_sub(G.screen_cursor, G.ui_screen_offset); + G.user_center = v2_mul(G.user_size, 0.5); + G.user_cursor = v2_sub(G.screen_cursor, G.user_screen_offset); /* ========================== * * Update view from camera * ========================== */ if (G.debug_camera) { - G.world_to_ui_xf = xform_basis_with_rotation_world(G.world_to_ui_xf, 0); + G.world_to_user_xf = xform_basis_with_rotation_world(G.world_to_user_xf, 0); - struct v2 world_cursor = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_cursor); + struct v2 world_cursor = xform_invert_mul_v2(G.world_to_user_xf, G.user_cursor); /* Pan view */ if (G.bind_states[USER_BIND_KIND_PAN].is_held) { @@ -979,8 +975,8 @@ INTERNAL void user_update(void) G.debug_camera_panning = true; } struct v2 offset = v2_neg(v2_sub(G.debug_camera_pan_start, world_cursor)); - G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, offset); - world_cursor = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_cursor); + G.world_to_user_xf = xform_translated(G.world_to_user_xf, offset); + world_cursor = xform_invert_mul_v2(G.world_to_user_xf, G.user_cursor); G.debug_camera_pan_start = world_cursor; } else { G.debug_camera_panning = false; @@ -992,9 +988,9 @@ INTERNAL void user_update(void) /* Zoom to cursor */ f32 zoom_rate = 2; f32 zoom = math_pow(zoom_rate, input_zooms); - G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, world_cursor); - G.world_to_ui_xf = xform_scaled(G.world_to_ui_xf, V2(zoom, zoom)); - G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, v2_neg(world_cursor)); + G.world_to_user_xf = xform_translated(G.world_to_user_xf, world_cursor); + G.world_to_user_xf = xform_scaled(G.world_to_user_xf, V2(zoom, zoom)); + G.world_to_user_xf = xform_translated(G.world_to_user_xf, v2_neg(world_cursor)); } } else { struct xform xf = sim_ent_get_xform(local_camera); @@ -1003,7 +999,7 @@ INTERNAL void user_update(void) f32 rot = xform_get_rotation(xf); /* Scale view into viewport based on camera size */ - struct v2 size = G.ui_size; + struct v2 size = G.user_size; { struct xform quad_xf = xform_mul(xf, local_camera->camera_quad_xform); struct v2 camera_size = xform_get_scale(quad_xf); @@ -1013,16 +1009,16 @@ INTERNAL void user_update(void) } f32 scale_ui = min_f32(size.x, size.y); - struct trs trs = TRS(.t = v2_sub(G.ui_center, center), .r = rot, .s = V2(scale_ui, scale_ui)); + struct trs trs = TRS(.t = v2_sub(G.user_center, center), .r = rot, .s = V2(scale_ui, scale_ui)); struct v2 pivot = center; - G.world_to_ui_xf = XFORM_IDENT; - G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, pivot); - G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, trs.t); - G.world_to_ui_xf = xform_rotated(G.world_to_ui_xf, trs.r); - G.world_to_ui_xf = xform_scaled(G.world_to_ui_xf, trs.s); - G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, v2_neg(pivot)); + G.world_to_user_xf = XFORM_IDENT; + G.world_to_user_xf = xform_translated(G.world_to_user_xf, pivot); + G.world_to_user_xf = xform_translated(G.world_to_user_xf, trs.t); + G.world_to_user_xf = xform_rotated(G.world_to_user_xf, trs.r); + G.world_to_user_xf = xform_scaled(G.world_to_user_xf, trs.s); + G.world_to_user_xf = xform_translated(G.world_to_user_xf, v2_neg(pivot)); } - G.world_cursor = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_cursor); + G.world_cursor = xform_invert_mul_v2(G.world_to_user_xf, G.user_cursor); /* ========================== * * Update listener from view @@ -1030,8 +1026,8 @@ INTERNAL void user_update(void) { struct v2 up = V2(0, -1); - struct v2 listener_pos = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_center); - struct v2 listener_dir = v2_norm(xform_basis_invert_mul_v2(G.world_to_ui_xf, up)); + struct v2 listener_pos = xform_invert_mul_v2(G.world_to_user_xf, G.user_center); + struct v2 listener_dir = v2_norm(xform_basis_invert_mul_v2(G.world_to_user_xf, up)); mixer_set_listener(listener_pos, listener_dir); } @@ -1042,14 +1038,14 @@ INTERNAL void user_update(void) { f32 thickness = 2; - struct v2 offset = v2_neg(xform_mul_v2(G.world_to_ui_xf, V2(0, 0))); - f32 spacing = xform_get_scale(G.world_to_ui_xf).x; + struct v2 offset = v2_neg(xform_mul_v2(G.world_to_user_xf, V2(0, 0))); + f32 spacing = xform_get_scale(G.world_to_user_xf).x; - struct v2 pos = xform_invert_mul_v2(G.world_to_ui_xf, V2(0, 0)); - struct v2 size = xform_basis_invert_mul_v2(G.world_to_ui_xf, G.ui_size); + struct v2 pos = xform_invert_mul_v2(G.world_to_user_xf, V2(0, 0)); + struct v2 size = xform_basis_invert_mul_v2(G.world_to_user_xf, G.user_size); u32 color0 = RGBA_F(0.17f, 0.17f, 0.17f, 1.f); u32 color1 = RGBA_F(0.15f, 0.15f, 0.15f, 1.f); - draw_grid(G.world_cmd_buffer, RECT_FROM_V2(pos, size), color0, color1, RGBA(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset); + draw_grid(G.world_gpu_cmd_store, XFORM_TRS(.t = pos, .s = size), color0, color1, RGBA(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset); } #if 0 @@ -1231,9 +1227,9 @@ INTERNAL void user_update(void) u32 color_end = RGBA_F(1, 0.8, 0.4, opacity_b); if (opacity_b > 0.99f) { - draw_circle(G.world_cmd_buffer, b, thickness / 2, color_end, 20); + draw_circle(G.world_gpu_cmd_store, b, thickness / 2, color_end, 20); } - draw_gradient_line(G.world_cmd_buffer, a, b, thickness, color_start, color_end); + draw_gradient_line(G.world_gpu_cmd_store, a, b, thickness, color_start, color_end); } @@ -1252,9 +1248,8 @@ INTERNAL void user_update(void) if (sheet->loaded) { u32 tint = ent->sprite_tint; struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, ent->animation_frame); - struct quad quad = xform_mul_quad(sprite_xform, QUAD_UNIT_SQUARE_CENTERED); - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.sprite = sprite, .tint0_srgb = tint, .tint1_srgb = tint, .clip = frame.clip, .quad = quad); - draw_quad_texture(G.world_cmd_buffer, params); + struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = sprite_xform, .sprite = sprite, .tint = tint, .clip = frame.clip); + draw_texture(G.world_gpu_cmd_store, params); } } @@ -1271,12 +1266,10 @@ INTERNAL void user_update(void) //if (tile > -1) { if (tile == SIM_TILE_KIND_WALL) { struct v2i32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index); - struct v2 pos = sim_pos_from_world_tile_index(world_tile_index); - - struct quad quad = quad_from_rect(RECT(pos.x, pos.y, tile_size, tile_size)); - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.sprite = tile_sprite, .quad = quad); - draw_quad_texture(G.world_cmd_buffer, params); + struct xform tile_xf = XFORM_TRS(.t = pos, .s = V2(tile_size, tile_size)); + struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = tile_xf, .sprite = tile_sprite); + draw_texture(G.world_gpu_cmd_store, params); } } } @@ -1303,8 +1296,8 @@ INTERNAL void user_update(void) f32 thickness = 1; u32 color = RGBA_F(1, 0, 1, 0.5); struct quad quad = quad_from_aabb(aabb); - quad = xform_mul_quad(G.world_to_ui_xf, quad); - draw_quad_line(G.ui_cmd_buffer, quad, thickness, color); + quad = xform_mul_quad(G.world_to_user_xf, quad); + draw_quad_line(G.user_gpu_cmd_store, quad, thickness, color); } /* Draw focus arrow */ @@ -1312,10 +1305,10 @@ INTERNAL void user_update(void) struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite); struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame); struct v2 start = xform_mul_v2(sprite_xform, slice.center); - start = xform_mul_v2(G.world_to_ui_xf, start); + start = xform_mul_v2(G.world_to_user_xf, start); struct v2 end = v2_add(xf.og, ent->control.focus); - end = xform_mul_v2(G.world_to_ui_xf, end); - draw_arrow_line(G.ui_cmd_buffer, start, end, 3, 10, RGBA_F(1, 1, 1, 0.5)); + end = xform_mul_v2(G.world_to_user_xf, end); + draw_arrow_line(G.user_gpu_cmd_store, start, end, 3, 10, RGBA_F(1, 1, 1, 0.5)); } #if 0 @@ -1335,22 +1328,22 @@ INTERNAL void user_update(void) struct sprite_sheet_slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j]; struct v2 center = xform_mul_v2(sprite_xform, slice.center); - center = xform_mul_v2(G.world_to_ui_xf, center); + center = xform_mul_v2(G.world_to_user_xf, center); if (!slice.has_ray) { struct quad quad = quad_from_rect(slice.rect); quad = xform_mul_quad(sprite_xform, quad); - quad = xform_mul_quad(G.world_to_ui_xf, quad); - draw_quad_line(G.ui_cmd_buffer, quad, 2, quad_color); + quad = xform_mul_quad(G.world_to_user_xf, quad); + draw_quad_line(G.user_gpu_cmd_store, quad, 2, quad_color); } - draw_circle(G.ui_cmd_buffer, center, 3, point_color, 20); + draw_circle(G.user_gpu_cmd_store, center, 3, point_color, 20); if (slice.has_ray) { struct v2 ray = xform_basis_mul_v2(sprite_xform, slice.dir); - ray = xform_basis_mul_v2(G.world_to_ui_xf, ray); + ray = xform_basis_mul_v2(G.world_to_user_xf, ray); ray = v2_with_len(ray, 25); - draw_arrow_ray(G.ui_cmd_buffer, center, ray, 2, 10, ray_color); + draw_arrow_ray(G.user_gpu_cmd_store, center, ray, 2, 10, ray_color); } } } @@ -1366,8 +1359,8 @@ INTERNAL void user_update(void) u32 color = COLOR_YELLOW; f32 radius = 3; struct v2 point = xform_mul_v2(e1_xf, ent->weld_joint_data.point_local_e1); - point = xform_mul_v2(G.world_to_ui_xf, point); - draw_circle(G.ui_cmd_buffer, point, radius, color, 10); + point = xform_mul_v2(G.world_to_user_xf, point); + draw_circle(G.user_gpu_cmd_store, point, radius, color, 10); DEBUGBREAKABLE; } @@ -1380,10 +1373,10 @@ INTERNAL void user_update(void) u32 color = COLOR_WHITE; struct v2 point_start = xform_mul_v2(target_xf, ent->mouse_joint_data.point_local_start); struct v2 point_end = G.world_cursor; - point_start = xform_mul_v2(G.world_to_ui_xf, point_start); - point_end = xform_mul_v2(G.world_to_ui_xf, point_end); - draw_arrow_line(G.ui_cmd_buffer, point_start, point_end, 3, 10, color); - draw_circle(G.ui_cmd_buffer, point_start, 4, color, 10); + point_start = xform_mul_v2(G.world_to_user_xf, point_start); + point_end = xform_mul_v2(G.world_to_user_xf, point_end); + draw_arrow_line(G.user_gpu_cmd_store, point_start, point_end, 3, 10, color); + draw_circle(G.user_gpu_cmd_store, point_start, 4, color, 10); } /* Draw collider */ @@ -1394,29 +1387,29 @@ INTERNAL void user_update(void) { /* Draw collider using support points */ u32 detail = 32; - draw_collider_line(G.ui_cmd_buffer, G.world_to_ui_xf, collider, xf, thickness, color, detail); + draw_collider_line(G.user_gpu_cmd_store, G.world_to_user_xf, collider, xf, thickness, color, detail); } { /* Draw collider shape points */ for (u32 i = 0; i < collider.count; ++i) { - struct v2 p = xform_mul_v2(xform_mul(G.world_to_ui_xf, xf), collider.points[i]); - draw_circle(G.ui_cmd_buffer, p, 3, COLOR_BLUE, 10); + struct v2 p = xform_mul_v2(xform_mul(G.world_to_user_xf, xf), collider.points[i]); + draw_circle(G.user_gpu_cmd_store, p, 3, COLOR_BLUE, 10); } } if (collider.count == 1 && collider.radius > 0) { /* Draw upwards line for circle */ struct v2 start = xf.og; struct v2 end = collider_get_support_point(&collider, xf, v2_neg(xf.by)).p; - start = xform_mul_v2(G.world_to_ui_xf, start); - end = xform_mul_v2(G.world_to_ui_xf, end); - draw_line(G.ui_cmd_buffer, start, end, thickness, color); + start = xform_mul_v2(G.world_to_user_xf, start); + end = xform_mul_v2(G.world_to_user_xf, end); + draw_line(G.user_gpu_cmd_store, start, end, thickness, color); } #if 0 /* Draw support point at focus dir */ { struct v2 p = collider_support_point(&collider, xf, ent->control.focus); - p = xform_mul_v2(G.world_to_ui_xf, p); - draw_circle(G.ui_cmd_buffer, p, 3, COLOR_RED, 10); + p = xform_mul_v2(G.world_to_user_xf, p); + draw_circle(G.user_gpu_cmd_store, p, 3, COLOR_RED, 10); } #endif } @@ -1441,7 +1434,7 @@ INTERNAL void user_update(void) /* Draw point */ { u32 color = ALPHA_F(COLOR_YELLOW, 0.50); - draw_circle(G.ui_cmd_buffer, xform_mul_v2(G.world_to_ui_xf, dbg_pt), radius, color, 10); + draw_circle(G.user_gpu_cmd_store, xform_mul_v2(G.world_to_user_xf, dbg_pt), radius, color, 10); } /* Draw normal */ @@ -1450,9 +1443,9 @@ INTERNAL void user_update(void) f32 len = 0.1f; f32 arrow_thickness = 2; f32 arrow_height = 5; - struct v2 start = xform_mul_v2(G.world_to_ui_xf, dbg_pt); - struct v2 end = xform_mul_v2(G.world_to_ui_xf, v2_add(dbg_pt, v2_mul(v2_norm(data->normal), len))); - draw_arrow_line(G.ui_cmd_buffer, start, end, arrow_thickness, arrow_height, color); + struct v2 start = xform_mul_v2(G.world_to_user_xf, dbg_pt); + struct v2 end = xform_mul_v2(G.world_to_user_xf, v2_add(dbg_pt, v2_mul(v2_norm(data->normal), len))); + draw_arrow_line(G.user_gpu_cmd_store, start, end, arrow_thickness, arrow_height, color); } #if 0 /* Draw contact info */ @@ -1482,7 +1475,7 @@ INTERNAL void user_update(void) FMT_UINT(data->num_points)); - draw_text(G.ui_cmd_buffer, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_ui_xf, dbg_pt)), V2(0, offset_px)), text); + draw_text(G.user_gpu_cmd_store, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_user_xf, dbg_pt)), V2(0, offset_px)), text); } } #endif @@ -1508,10 +1501,10 @@ INTERNAL void user_update(void) { f32 radius = 4; u32 color = RGBA_F(1, 1, 0, 0.5); - struct v2 a = xform_mul_v2(G.world_to_ui_xf, data->closest0); - struct v2 b = xform_mul_v2(G.world_to_ui_xf, data->closest1); - draw_circle(G.ui_cmd_buffer, a, radius, color, 10); - draw_circle(G.ui_cmd_buffer, b, radius, color, 10); + struct v2 a = xform_mul_v2(G.world_to_user_xf, data->closest0); + struct v2 b = xform_mul_v2(G.world_to_user_xf, data->closest1); + draw_circle(G.user_gpu_cmd_store, a, radius, color, 10); + draw_circle(G.user_gpu_cmd_store, b, radius, color, 10); } #endif @@ -1526,30 +1519,30 @@ INTERNAL void user_update(void) u32 color_a_clipped = RGBA_F(1, 0, 0, 1); u32 color_b_clipped = RGBA_F(0, 1, 0, 1); { - struct v2 a = xform_mul_v2(G.world_to_ui_xf, collider_res.a0); - struct v2 b = xform_mul_v2(G.world_to_ui_xf, collider_res.b0); - draw_line(G.ui_cmd_buffer, a, b, thickness, color_line); - draw_circle(G.ui_cmd_buffer, a, radius, color_a, 10); - draw_circle(G.ui_cmd_buffer, b, radius, color_b, 10); + struct v2 a = xform_mul_v2(G.world_to_user_xf, collider_res.a0); + struct v2 b = xform_mul_v2(G.world_to_user_xf, collider_res.b0); + draw_line(G.user_gpu_cmd_store, a, b, thickness, color_line); + draw_circle(G.user_gpu_cmd_store, a, radius, color_a, 10); + draw_circle(G.user_gpu_cmd_store, b, radius, color_b, 10); - struct v2 a_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.a0_clipped); - struct v2 b_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.b0_clipped); - draw_line(G.ui_cmd_buffer, a_clipped, b_clipped, thickness, color_line_clipped); - draw_circle(G.ui_cmd_buffer, a_clipped, radius, color_a_clipped, 10); - draw_circle(G.ui_cmd_buffer, b_clipped, radius, color_b_clipped, 10); + struct v2 a_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.a0_clipped); + struct v2 b_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.b0_clipped); + draw_line(G.user_gpu_cmd_store, a_clipped, b_clipped, thickness, color_line_clipped); + draw_circle(G.user_gpu_cmd_store, a_clipped, radius, color_a_clipped, 10); + draw_circle(G.user_gpu_cmd_store, b_clipped, radius, color_b_clipped, 10); } { - struct v2 a = xform_mul_v2(G.world_to_ui_xf, collider_res.a1); - struct v2 b = xform_mul_v2(G.world_to_ui_xf, collider_res.b1); - draw_line(G.ui_cmd_buffer, a, b, thickness, color_line); - draw_circle(G.ui_cmd_buffer, a, radius, color_a, 10); - draw_circle(G.ui_cmd_buffer, b, radius, color_b, 10); + struct v2 a = xform_mul_v2(G.world_to_user_xf, collider_res.a1); + struct v2 b = xform_mul_v2(G.world_to_user_xf, collider_res.b1); + draw_line(G.user_gpu_cmd_store, a, b, thickness, color_line); + draw_circle(G.user_gpu_cmd_store, a, radius, color_a, 10); + draw_circle(G.user_gpu_cmd_store, b, radius, color_b, 10); - struct v2 a_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.a1_clipped); - struct v2 b_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.b1_clipped); - draw_line(G.ui_cmd_buffer, a_clipped, b_clipped, thickness, color_line_clipped); - draw_circle(G.ui_cmd_buffer, a_clipped, radius, color_a_clipped, 10); - draw_circle(G.ui_cmd_buffer, b_clipped, radius, color_b_clipped, 10); + struct v2 a_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.a1_clipped); + struct v2 b_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.b1_clipped); + draw_line(G.user_gpu_cmd_store, a_clipped, b_clipped, thickness, color_line_clipped); + draw_circle(G.user_gpu_cmd_store, a_clipped, radius, color_a_clipped, 10); + draw_circle(G.user_gpu_cmd_store, b_clipped, radius, color_b_clipped, 10); } } @@ -1590,7 +1583,7 @@ INTERNAL void user_update(void) FMT_FLOAT_P(xform_get_rotation(e1_xf), 24)); - draw_text(G.ui_cmd_buffer, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_ui_xf, V2(0, 0))), V2(0, offset_px)), text); + draw_text(G.user_gpu_cmd_store, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_user_xf, V2(0, 0))), V2(0, offset_px)), text); } } #endif @@ -1605,9 +1598,9 @@ INTERNAL void user_update(void) struct v2_array m = menkowski(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf, detail); - for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_ui_xf, m.points[i]); - draw_poly_line(G.ui_cmd_buffer, m, true, thickness, color); - //draw_poly(G.ui_cmd_buffer, m, color); + for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_user_xf, m.points[i]); + draw_poly_line(G.user_gpu_cmd_store, m, true, thickness, color); + //draw_poly(G.user_gpu_cmd_store, m, color); } /* Draw cloud */ @@ -1618,8 +1611,8 @@ INTERNAL void user_update(void) struct v2_array m = cloud(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf); for (u64 i = 0; i < m.count; ++i) { - struct v2 p = xform_mul_v2(G.world_to_ui_xf, m.points[i]); - draw_circle(G.ui_cmd_buffer, p, radius, color, 10); + struct v2 p = xform_mul_v2(G.world_to_user_xf, m.points[i]); + draw_circle(G.user_gpu_cmd_store, p, radius, color, 10); } } @@ -1632,9 +1625,9 @@ INTERNAL void user_update(void) .points = collider_res.prototype.points, .count = collider_res.prototype.len }; - for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_ui_xf, m.points[i]); - draw_poly_line(G.ui_cmd_buffer, m, true, thickness, color); - for (u64 i = 0; i < m.count; ++i) draw_circle(G.ui_cmd_buffer, m.points[i], 10, color, 10); + for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_user_xf, m.points[i]); + draw_poly_line(G.user_gpu_cmd_store, m, true, thickness, color); + for (u64 i = 0; i < m.count; ++i) draw_circle(G.user_gpu_cmd_store, m.points[i], 10, color, 10); } /* Draw simplex */ @@ -1647,23 +1640,23 @@ INTERNAL void user_update(void) struct collider_menkowski_simplex simplex = collider_res.simplex; struct v2 simplex_points[] = { simplex.a.p, simplex.b.p, simplex.c.p }; - for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_to_ui_xf, simplex_points[i]); + for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_to_user_xf, simplex_points[i]); struct v2_array simplex_array = { .count = simplex.len, .points = simplex_points }; if (simplex.len >= 1) { u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third); - draw_circle(G.ui_cmd_buffer, simplex_array.points[0], thickness * 3, color, 10); + draw_circle(G.user_gpu_cmd_store, simplex_array.points[0], thickness * 3, color, 10); } if (simplex.len >= 2) { u32 color = simplex.len == 2 ? color_first : color_second; - draw_circle(G.ui_cmd_buffer, simplex_array.points[1], thickness * 3, color, 10); + draw_circle(G.user_gpu_cmd_store, simplex_array.points[1], thickness * 3, color, 10); } if (simplex.len >= 3) { u32 color = color_first; - draw_circle(G.ui_cmd_buffer, simplex_array.points[2], thickness * 3, color, 10); + draw_circle(G.user_gpu_cmd_store, simplex_array.points[2], thickness * 3, color, 10); } if (simplex.len >= 2) { - draw_poly_line(G.ui_cmd_buffer, simplex_array, simplex.len > 2, thickness, line_color); + draw_poly_line(G.user_gpu_cmd_store, simplex_array, simplex.len > 2, thickness, line_color); } } @@ -1673,9 +1666,9 @@ INTERNAL void user_update(void) f32 len = 0.1f; f32 arrow_thickness = 4; f32 arrowhead_height = 10; - struct v2 start = xform_mul_v2(G.world_to_ui_xf, V2(0, 0)); - struct v2 end = xform_mul_v2(G.world_to_ui_xf, v2_mul(v2_norm(collider_res.normal), len)); - draw_arrow_line(G.ui_cmd_buffer, start, end, arrow_thickness, arrowhead_height, color); + struct v2 start = xform_mul_v2(G.world_to_user_xf, V2(0, 0)); + struct v2 end = xform_mul_v2(G.world_to_user_xf, v2_mul(v2_norm(collider_res.normal), len)); + draw_arrow_line(G.user_gpu_cmd_store, start, end, arrow_thickness, arrowhead_height, color); } } #endif @@ -1689,9 +1682,9 @@ INTERNAL void user_update(void) f32 thickness = 2; f32 arrow_height = 15; - struct v2 start = xform_mul_v2(G.world_to_ui_xf, xf.og); - struct v2 end = xform_mul_v2(G.world_to_ui_xf, parent_xf.og); - draw_arrow_line(G.ui_cmd_buffer, start, end, thickness, arrow_height, color); + struct v2 start = xform_mul_v2(G.world_to_user_xf, xf.og); + struct v2 end = xform_mul_v2(G.world_to_user_xf, parent_xf.og); + draw_arrow_line(G.user_gpu_cmd_store, start, end, thickness, arrow_height, color); } /* Draw camera rect */ @@ -1701,9 +1694,9 @@ INTERNAL void user_update(void) struct xform quad_xf = xform_mul(xf, ent->camera_quad_xform); struct quad quad = xform_mul_quad(quad_xf, QUAD_UNIT_SQUARE_CENTERED); - quad = xform_mul_quad(G.world_to_ui_xf, quad); + quad = xform_mul_quad(G.world_to_user_xf, quad); - draw_quad_line(G.ui_cmd_buffer, quad, thickness, color); + draw_quad_line(G.user_gpu_cmd_store, quad, thickness, color); } arena_temp_end(temp); @@ -1714,17 +1707,16 @@ INTERNAL void user_update(void) /* Draw crosshair or show cursor */ if (!G.debug_camera) { __profscope(draw_crosshair); - struct v2 crosshair_pos = G.ui_cursor; + struct v2 crosshair_pos = G.user_cursor; struct sprite_tag crosshair_tag = sprite_tag_from_path(LIT("sprites/crosshair.ase")); struct sprite_texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair_tag); struct v2 size = V2(t->width, t->height); struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = size); - struct quad quad = xform_mul_quad(xf, QUAD_UNIT_SQUARE_CENTERED); - draw_quad_texture(G.ui_cmd_buffer, DRAW_TEXTURE_PARAMS(.sprite = crosshair_tag, .quad = quad)); + draw_texture(G.user_gpu_cmd_store, DRAW_TEXTURE_PARAMS(.xf = xf, .sprite = crosshair_tag)); - struct rect cursor_clip = RECT_FROM_V2(G.ui_screen_offset, G.ui_size); + struct rect cursor_clip = RECT_FROM_V2(G.user_screen_offset, G.user_size); cursor_clip.pos = v2_add(cursor_clip.pos, v2_mul(size, 0.5f)); cursor_clip.pos = v2_add(cursor_clip.pos, V2(1, 1)); cursor_clip.size = v2_sub(cursor_clip.size, size); @@ -1784,7 +1776,7 @@ INTERNAL void user_update(void) } } - input_move_dir = xform_basis_invert_mul_v2(G.world_to_ui_xf, input_move_dir); /* Make move dir relative to world view */ + input_move_dir = xform_basis_invert_mul_v2(G.world_to_user_xf, input_move_dir); /* Make move dir relative to world view */ input_move_dir = v2_mul(v2_norm(input_move_dir), move_speed); } @@ -1908,7 +1900,7 @@ INTERNAL void user_update(void) if (G.debug_draw && hovered_ent->valid) { struct sim_ent *ent = hovered_ent; - struct v2 pos = v2_add(G.ui_cursor, V2(15, 15)); + struct v2 pos = v2_add(G.user_cursor, V2(15, 15)); struct font *font = font_load_async(LIT("fonts/fixedsys.ttf"), 12.0f); if (font) { struct temp_arena temp = arena_temp_begin(scratch.arena); @@ -1916,7 +1908,7 @@ INTERNAL void user_update(void) struct string dbg_text = ZI; dbg_text.text = arena_dry_push(temp.arena, u8); dbg_text.len += get_ent_debug_text(temp.arena, ent).len; - draw_text(G.ui_cmd_buffer, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = dbg_text)); + draw_text(G.user_gpu_cmd_store, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = dbg_text)); arena_temp_end(temp); } @@ -2016,16 +2008,16 @@ INTERNAL void user_update(void) //text.len += string_copy(temp.arena, LIT("\n")).len; #if COLLIDER_DEBUG - draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("collider gjk steps: %F"), FMT_UINT(collider_debug_steps))); + draw_text(G.user_gpu_cmd_store, font, pos, string_format(temp.arena, LIT("collider gjk steps: %F"), FMT_UINT(collider_debug_steps))); pos.y += spacing; #endif - //draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("blended world entities: %F/%F"), FMT_UINT(G.ss_blended->num_ents_allocated), FMT_UINT(G.ss_blended->num_ents_reserved))); - //draw_text(G.ui_cmd_buffer, font, pos, text); + //draw_text(G.user_gpu_cmd_store, font, pos, string_format(temp.arena, LIT("blended world entities: %F/%F"), FMT_UINT(G.ss_blended->num_ents_allocated), FMT_UINT(G.ss_blended->num_ents_reserved))); + //draw_text(G.user_gpu_cmd_store, font, pos, text); - struct v2 pos = V2(10, G.ui_size.y); + struct v2 pos = V2(10, G.user_size.y); enum draw_text_offset_y offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM; - draw_text(G.ui_cmd_buffer, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = text, .offset_y = offset_y, .color = COLOR_WHITE)); + draw_text(G.user_gpu_cmd_store, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = text, .offset_y = offset_y, .color = COLOR_WHITE)); arena_temp_end(temp); } } @@ -2048,95 +2040,59 @@ INTERNAL void user_update(void) { __profscope(render); - struct rect ui_viewport = RECT_FROM_V2(V2(0, 0), G.ui_size); + struct rect user_viewport = RECT_FROM_V2(V2(0, 0), G.user_size); struct rect backbuffer_viewport = RECT_FROM_V2(V2(0, 0), G.screen_size); - - /* Allocate render textures */ - struct v2i32 ui_resolution = v2_round_to_int(ui_viewport.size); + struct v2i32 user_resolution = v2_round_to_int(user_viewport.size); struct v2i32 backbuffer_resolution = v2_round_to_int(backbuffer_viewport.size); - struct v2i32 world_resolution = ui_resolution; + /* Allocate target textures */ { - /* World texture */ - if (!G.world_texture.handle || !v2i32_eq(gpu_texture_get_size(G.world_texture), world_resolution)) { - if (G.world_texture.handle) { - gpu_texture_release(G.world_texture); + + /* User texture */ + if (!G.user_texture.handle || !v2i32_eq(gpu_texture_get_size(G.user_texture), user_resolution)) { + if (G.user_texture.handle) { + gpu_texture_release(G.user_texture); } - G.world_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGET, world_resolution, NULL); - } - /* Ui texture */ - if (!G.ui_texture.handle || !v2i32_eq(gpu_texture_get_size(G.ui_texture), ui_resolution)) { - if (G.ui_texture.handle) { - gpu_texture_release(G.ui_texture); - } - G.ui_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGET, ui_resolution, NULL); - } - /* Final texture */ - if (!G.final_texture.handle || !v2i32_eq(gpu_texture_get_size(G.final_texture), ui_resolution)) { - if (G.final_texture.handle) { - gpu_texture_release(G.final_texture); - } - G.final_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGET, ui_resolution, NULL); + G.user_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGETABLE, user_resolution, NULL); } + /* Backbuffer texture */ if (!G.backbuffer_texture.handle || !v2i32_eq(gpu_texture_get_size(G.backbuffer_texture), backbuffer_resolution)) { G.backbuffer_texture = gpu_recreate_backbuffer(backbuffer_resolution); } } - /* Combine render textures w/ quad draw cmds */ + /* Draw user texture to backbuffer texture */ { - /* Draw world texture to final */ - { - struct quad quad = quad_from_rect(RECT_FROM_V2(V2(0, 0), V2_FROM_V2I32(ui_resolution))); - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.world_texture, .quad = quad); - draw_quad_texture(G.final_cmd_buffer, params); - } - - /* Draw ui texture to final */ - { - struct quad quad = quad_from_rect(RECT_FROM_V2(V2(0, 0), V2_FROM_V2I32(ui_resolution))); - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.ui_texture, .quad = quad); - draw_quad_texture(G.final_cmd_buffer, params); - } - - /* Draw final texture to backbuffer */ - { - struct quad quad = quad_from_rect(RECT_FROM_V2(G.ui_screen_offset, V2_FROM_V2I32(G.ui_size))); - struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.final_texture, .quad = quad); - draw_quad_texture(G.backbuffer_cmd_buffer, params); - } + //struct xform xf = XFORM_TRS(.t = G.user_screen_offset, .s = G.user_size); + //xf = xform_translated(xf, V2(0.5, 0.5)); + //struct xform xf = XFORM_IDENT; + struct xform xf = XFORM_TRS(.t = v2_mul(V2(backbuffer_resolution.x, backbuffer_resolution.y), 0.5), .s = G.user_size); + struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = xf, .texture = G.user_texture); + draw_texture(G.backbuffer_gpu_cmd_store, params); } - /* Send cmd buffers to GPU */ - gpu_cmd_buffer_flush_to_gpu(G.world_cmd_buffer); - gpu_cmd_buffer_flush_to_gpu(G.ui_cmd_buffer); - gpu_cmd_buffer_flush_to_gpu(G.final_cmd_buffer); - gpu_cmd_buffer_flush_to_gpu(G.backbuffer_cmd_buffer); + /* Send cmds to GPU */ + gpu_submit_cmds(G.world_gpu_cmd_store); + gpu_submit_cmds(G.user_gpu_cmd_store); + gpu_submit_cmds(G.backbuffer_gpu_cmd_store); - /* Execute render cmds */ + /* Clear textures */ + gpu_texture_clear(G.user_texture, 0); + gpu_texture_clear(G.backbuffer_texture, RGBA_F(0, 0, 0, 1)); + + /* Execute cmds */ { - /* Clear textures */ - gpu_texture_clear(G.world_texture, 0); - gpu_texture_clear(G.ui_texture, 0); - gpu_texture_clear(G.final_texture, 0); - gpu_texture_clear(G.backbuffer_texture, RGBA_F(0, 0, 0, 1)); - - /* Render to world texture */ - gpu_texture_render(G.world_texture, G.world_cmd_buffer, G.world_to_ui_xf, ui_viewport); - - /* Render to UI texture */ - gpu_texture_render(G.ui_texture, G.ui_cmd_buffer, XFORM_IDENT, ui_viewport); - - /* Render to final texture */ - gpu_texture_render(G.final_texture, G.final_cmd_buffer, XFORM_IDENT, ui_viewport); + /* Render to user texture */ + gpu_run_cmds(G.world_gpu_cmd_store, G.user_texture, G.world_to_user_xf, user_viewport); + gpu_run_cmds(G.user_gpu_cmd_store, G.user_texture, XFORM_IDENT, user_viewport); /* Render to backbuffer */ - gpu_texture_render(G.backbuffer_texture, G.backbuffer_cmd_buffer, XFORM_IDENT, backbuffer_viewport); + gpu_run_cmds(G.backbuffer_gpu_cmd_store, G.backbuffer_texture, XFORM_IDENT, backbuffer_viewport); } - /* Present */ - gpu_present_backbuffer(VSYNC_ENABLED); + /* Swap backbuffer */ + gpu_swap_backbuffer(VSYNC_ENABLED); } /* ========================== *