shape shader start

This commit is contained in:
jacob 2025-06-25 00:11:05 -05:00
parent 5bdaba67e7
commit 5a9d9debba
15 changed files with 649 additions and 525 deletions

5
imgui.ini Normal file
View File

@ -0,0 +1,5 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0

View File

@ -24,12 +24,12 @@ SamplerState g_sampler : register(s0);
* ========================== */ * ========================== */
struct vs_input { struct vs_input {
DECL(uint, SV_VertexID); DECLS(uint, SV_VertexID);
}; };
struct vs_output { struct vs_output {
DECL(float4, SV_Position); DECLS(float4, SV_Position);
DECL(float2, uv); DECLS(float2, uv);
}; };
SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
@ -58,13 +58,13 @@ struct ps_input {
}; };
struct ps_output { struct ps_output {
DECL(float4, SV_Target); DECLS(float4, SV_Target);
}; };
SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
{ {
struct ps_output output; struct ps_output output;
const float gamma = g_constants.gamma; const float gamma = g_constants.gamma;
output.SV_Target = pow(g_textures[g_constants.tex_urid].Sample(g_sampler, input.vs.uv), 1/gamma); output.SV_Target = pow(abs(g_textures[g_constants.tex_urid].Sample(g_sampler, input.vs.uv)), 1/gamma);
return output; return output;
} }

View File

@ -3,7 +3,7 @@
#define PI 3.14159265359 #define PI 3.14159265359
#define GOLDEN 1.61803398875 #define GOLDEN 1.61803398875
#define DECL(t, n) t n : n #define DECLS(t, n) t n : n
#define NURID(i) NonUniformResourceIndex(i) #define NURID(i) NonUniformResourceIndex(i)
#if !SH_CPU #if !SH_CPU

View File

@ -28,17 +28,17 @@ SamplerState g_sampler : register(s0);
* ========================== */ * ========================== */
struct vs_input { struct vs_input {
DECL(uint, SV_InstanceID); DECLS(uint, SV_InstanceID);
DECL(uint, SV_VertexID); DECLS(uint, SV_VertexID);
}; };
struct vs_output { struct vs_output {
nointerpolation DECL(uint, flags); nointerpolation DECLS(uint, flags);
nointerpolation DECL(int, tex_nurid); nointerpolation DECLS(int, tex_nurid);
nointerpolation DECL(int, grid_id); nointerpolation DECLS(int, grid_id);
DECL(float2, uv); DECLS(float2, uv);
DECL(float4, tint_lin); DECLS(float4, tint_lin);
DECL(float4, SV_Position); DECLS(float4, SV_Position);
}; };
SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input) SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
@ -73,13 +73,13 @@ struct ps_input {
}; };
struct ps_output { struct ps_output {
DECL(float4, SV_Target); DECLS(float4, SV_Target);
}; };
SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input) SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
{ {
struct ps_output output; struct ps_output output;
output.SV_Target = float4(1, 1, 1, 1); output.SV_Target = input.vs.tint_lin;
/* Texture */ /* Texture */
if (input.vs.tex_nurid >= 0) { if (input.vs.tex_nurid >= 0) {
@ -92,15 +92,15 @@ SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
float2 grid_pos = input.vs.SV_Position.xy + grid.offset; float2 grid_pos = input.vs.SV_Position.xy + grid.offset;
float half_thickness = grid.line_thickness / 2; float half_thickness = grid.line_thickness / 2;
float spacing = grid.line_spacing; float spacing = grid.line_spacing;
float4 color = linear_from_srgb32(grid.bg0_srgb); uint color_srgb = grid.bg0_srgb;
float2 v = abs(round(grid_pos / spacing) * spacing - grid_pos); float2 v = abs(round(grid_pos / spacing) * spacing - grid_pos);
float dist = min(v.x, v.y); float dist = min(v.x, v.y);
if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) { if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) {
color = linear_from_srgb32(grid.x_srgb); color_srgb = grid.x_srgb;
} else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) { } else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) {
color = linear_from_srgb32(grid.y_srgb); color_srgb = grid.y_srgb;
} else if (dist < half_thickness) { } else if (dist < half_thickness) {
color = linear_from_srgb32(grid.line_srgb); color_srgb = grid.line_srgb;
} else { } else {
bool checker = false; bool checker = false;
uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0); uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0);
@ -111,12 +111,11 @@ SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
checker = cell_y % 2 == 1; checker = cell_y % 2 == 1;
} }
if (checker) { if (checker) {
color = linear_from_srgb32(grid.bg1_srgb); color_srgb = grid.bg1_srgb;
} }
} }
output.SV_Target *= color; output.SV_Target *= linear_from_srgb32(color_srgb);
} }
output.SV_Target *= input.vs.tint_lin;
return output; return output;
} }

View File

@ -2,6 +2,7 @@
#define SH_STRUCT(s) PACK(struct s) #define SH_STRUCT(s) PACK(struct s)
#define SH_DECL(t, n) struct CAT(sh_, t) n #define SH_DECL(t, n) struct CAT(sh_, t) n
#define SH_DECLS(t, n) SH_DECL(t, n)
#define SH_ENTRY(rootsig) static #define SH_ENTRY(rootsig) static
#define SH_ASSERT_32BIT(s, n) CT_ASSERT((sizeof(s) / 4) == n) #define SH_ASSERT_32BIT(s, n) CT_ASSERT((sizeof(s) / 4) == n)
@ -51,6 +52,7 @@ INLINE struct sh_float2x3 sh_float2x3_from_xform(struct xform v)
#define SH_STRUCT(s) struct s #define SH_STRUCT(s) struct s
#define SH_DECL(t, n) t n #define SH_DECL(t, n) t n
#define SH_DECLS(t, n) t n : n
#define SH_ENTRY(rootsig) [RootSignature(rootsig)] #define SH_ENTRY(rootsig) [RootSignature(rootsig)]
#define SH_ASSERT_32BIT(s, n) #define SH_ASSERT_32BIT(s, n)
@ -99,3 +101,17 @@ SH_STRUCT(sh_material_grid {
SH_DECL(uint, x_srgb); SH_DECL(uint, x_srgb);
SH_DECL(uint, y_srgb); SH_DECL(uint, y_srgb);
}); });
/* ========================== *
* Shape shader structures
* ========================== */
SH_STRUCT(sh_shape_constants {
SH_DECL(float4x4, projection);
});
SH_ASSERT_32BIT(struct sh_shape_constants, 16); /* Expected 32bit root constant size in shader */
SH_STRUCT(sh_shape_vert {
SH_DECLS(float2, pos);
SH_DECLS(uint, color_srgb);
});

60
res/sh/shape.hlsl Normal file
View File

@ -0,0 +1,60 @@
#include "sh/common.hlsl"
/* ========================== *
* Root signature
* ========================== */
#define ROOTSIG \
"RootConstants(num32BitConstants=16, b0), " \
"SRV(t0), " \
"SRV(t1), " \
"DescriptorTable(SRV(t2, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)), " \
"StaticSampler(s0, " \
"filter = FILTER_MIN_MAG_MIP_POINT, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"addressV = TEXTURE_ADDRESS_CLAMP, " \
"addressW = TEXTURE_ADDRESS_CLAMP, " \
"maxAnisotropy = 1)"
ConstantBuffer<struct sh_material_constants> g_constants : register(b0);
StructuredBuffer<struct sh_material_instance> g_instances : register(t0);
StructuredBuffer<struct sh_material_grid> g_grids : register(t1);
Texture2D g_textures[] : register(t2);
SamplerState g_sampler : register(s0);
/* ========================== *
* Vertex shader
* ========================== */
struct vs_output {
DECLS(float4, SV_Position);
DECLS(float4, color_lin);
};
SH_ENTRY(ROOTSIG) struct vs_output vs(struct sh_shape_vert input)
{
struct vs_output output;
output.SV_Position = mul(g_constants.projection, float4(input.pos, 0, 1));
output.color_lin = linear_from_srgb32(input.color_srgb);
return output;
}
/* ========================== *
* Pixel shader
* ========================== */
struct ps_input {
struct vs_output vs;
};
struct ps_output {
DECLS(float4, SV_Target);
};
SH_ENTRY(ROOTSIG) struct ps_output ps(struct ps_input input)
{
struct ps_output output;
output.SV_Target = input.vs.color_lin;
return output;
}

View File

@ -634,7 +634,7 @@ INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ?
#include STRINGIZE(TRACY_INCLUDE_PATH) #include STRINGIZE(TRACY_INCLUDE_PATH)
#define PROFILING_CAPTURE_FRAME_IMAGE 1 #define PROFILING_CAPTURE_FRAME_IMAGE 0
/* Clang/GCC cleanup macros */ /* Clang/GCC cleanup macros */
#if COMPILER_MSVC #if COMPILER_MSVC

View File

@ -31,13 +31,13 @@ struct draw_startup_receipt draw_startup(struct gp_startup_receipt *gp_sr,
void draw_texture(struct gp_handle flow, struct draw_texture_params params) void draw_texture(struct gp_handle flow, struct draw_texture_params params)
{ {
struct gp_cmd_desc cmd = ZI; struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_TEXTURE; cmd.kind = GP_CMD_KIND_DRAW_MATERIAL;
cmd.texture.xf = params.xf; cmd.material.xf = params.xf;
cmd.texture.sprite = params.sprite; cmd.material.sprite = params.sprite;
cmd.texture.texture = params.texture; cmd.material.texture = params.texture;
cmd.texture.clip = params.clip; cmd.material.clip = params.clip;
cmd.texture.tint = params.tint; cmd.material.tint = params.tint;
cmd.texture.emittance = params.emittance; cmd.material.emittance = params.emittance;
gp_push_cmd(flow, cmd); gp_push_cmd(flow, cmd);
} }
@ -48,10 +48,10 @@ void draw_texture(struct gp_handle flow, struct draw_texture_params params)
void draw_poly_ex(struct gp_handle flow, struct v2_array vertices, struct gp_indices indices, u32 color) void draw_poly_ex(struct gp_handle flow, struct v2_array vertices, struct gp_indices indices, u32 color)
{ {
struct gp_cmd_desc cmd = ZI; struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_MESH; cmd.kind = GP_CMD_KIND_DRAW_SHAPE;
cmd.mesh.vertices = vertices; cmd.shape.vertices = vertices;
cmd.mesh.indices = indices; cmd.shape.indices = indices;
cmd.mesh.color = color; cmd.shape.color = color;
gp_push_cmd(flow, cmd); gp_push_cmd(flow, cmd);
} }
@ -271,10 +271,10 @@ void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_co
grid.offset = offset; grid.offset = offset;
struct gp_cmd_desc cmd = ZI; struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_DRAW_TEXTURE; cmd.kind = GP_CMD_KIND_DRAW_MATERIAL;
cmd.texture.xf = xf; cmd.material.xf = xf;
cmd.texture.tint = COLOR_WHITE; cmd.material.tint = COLOR_WHITE;
cmd.texture.grid = &grid; cmd.material.grid = &grid;
gp_push_cmd(flow, cmd); gp_push_cmd(flow, cmd);
} }
@ -285,6 +285,7 @@ void draw_grid(struct gp_handle flow, struct xform xf, u32 bg0_color, u32 bg1_co
/* Returns the rect of the text area */ /* Returns the rect of the text area */
struct rect draw_text(struct gp_handle flow, struct draw_text_params params) struct rect draw_text(struct gp_handle flow, struct draw_text_params params)
{ {
__prof;
struct arena_temp scratch = scratch_begin_no_conflict(); struct arena_temp scratch = scratch_begin_no_conflict();
f32 inv_font_image_width = 1.0 / (f32)params.font->image_width; f32 inv_font_image_width = 1.0 / (f32)params.font->image_width;

View File

@ -70,9 +70,8 @@ struct gp_indices {
enum gp_cmd_kind { enum gp_cmd_kind {
GP_CMD_KIND_NONE, GP_CMD_KIND_NONE,
GP_CMD_KIND_DRAW_MESH, GP_CMD_KIND_DRAW_SHAPE,
GP_CMD_KIND_DRAW_TEXTURE, GP_CMD_KIND_DRAW_MATERIAL,
GP_CMD_KIND_TEST,
NUM_GP_CMD_KINDS NUM_GP_CMD_KINDS
}; };
@ -91,11 +90,6 @@ struct gp_grid_desc {
struct gp_cmd_desc { struct gp_cmd_desc {
enum gp_cmd_kind kind; enum gp_cmd_kind kind;
union { union {
struct {
struct v2_array vertices;
struct gp_indices indices;
u32 color;
} mesh;
struct { struct {
struct xform xf; struct xform xf;
struct sprite_tag sprite; struct sprite_tag sprite;
@ -104,10 +98,12 @@ struct gp_cmd_desc {
u32 tint; u32 tint;
f32 emittance; f32 emittance;
struct gp_grid_desc *grid; struct gp_grid_desc *grid;
} texture; } material;
struct { struct {
struct xform xf; struct v2_array vertices;
} test; struct gp_indices indices;
u32 color;
} shape;
}; };
}; };

View File

@ -128,6 +128,7 @@ struct dx11_cmd_buffers {
struct dx11_cmd { struct dx11_cmd {
enum gp_cmd_kind kind; enum gp_cmd_kind kind;
b32 is_grid;
union { union {
struct { struct {
struct xform xf; struct xform xf;
@ -285,7 +286,7 @@ INTERNAL struct dx11_buffer *dx11_buffer_alloc(struct D3D11_BUFFER_DESC desc, D3
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name); INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name);
#endif #endif
struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struct sys_window *window) struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr)
{ {
__prof; __prof;
(UNUSED)work_sr; (UNUSED)work_sr;
@ -314,7 +315,6 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc
HRESULT hr; HRESULT hr;
ID3D11Device *device = NULL; ID3D11Device *device = NULL;
ID3D11DeviceContext *context = NULL; ID3D11DeviceContext *context = NULL;
IDXGISwapChain2 *swapchain = NULL;
/* Create D3D11 device & context */ /* Create D3D11 device & context */
{ {
@ -361,71 +361,13 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc
} }
#endif #endif
/* Create swap chain */ if (!SUCCEEDED(hr) || !device || !context) {
{
__profscope(Create swapchain);
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
/* Get DXGI device from D3D11 device */
IDXGIDevice *dxgiDevice;
hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgiDevice);
ASSERT(SUCCEEDED(hr));
/* Get DXGI adapter from DXGI device */
IDXGIAdapter *dxgiAdapter;
hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter);
ASSERT(SUCCEEDED(hr));
/* Get DXGI factory from DXGI adapter */
IDXGIFactory2 *factory;
hr = IDXGIAdapter_GetParent(dxgiAdapter, &IID_IDXGIFactory2, (void **)&factory);
ASSERT(SUCCEEDED(hr));
DXGI_SWAP_CHAIN_DESC1 desc = {
.Format = DX11_SWAPCHAIN_FORMAT,
.SampleDesc = { 1, 0 },
.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT,
.BufferCount = 3,
.Scaling = DXGI_SCALING_NONE,
.Flags = DX11_SWAPCHAIN_FLAGS,
.AlphaMode = DXGI_ALPHA_MODE_IGNORE,
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD
};
IDXGISwapChain1 *swapchain1 = NULL;
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)device, hwnd, &desc, NULL, NULL, &swapchain1);
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr)) {
IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void **)&swapchain);
}
/* Disable Alt+Enter changing monitor resolution to match window size */
IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
IDXGISwapChain1_Release(swapchain1);
IDXGIFactory2_Release(factory);
IDXGIAdapter_Release(dxgiAdapter);
IDXGIDevice_Release(dxgiDevice);
}
if (!SUCCEEDED(hr) || !device || !context || !swapchain) {
/* Gpu initialization failure */ /* Gpu initialization failure */
/* TODO: Better message */ /* TODO: Better message */
sys_panic(LIT("Failed to initialize DirectX 11")); sys_panic(LIT("Failed to initialize DirectX 11"));
} }
G.dev = device; G.dev = device;
G.devcon = context; G.devcon = context;
G.swapchain = swapchain;
/* Create the swapchain waitable object */
#if DX11_WAIT_FRAME_LATENCY
if (G.swapchain != NULL) {
IDXGISwapChain2_SetMaximumFrameLatency(G.swapchain, 1);
G.swapchain_waitable = IDXGISwapChain2_GetFrameLatencyWaitableObject(G.swapchain);
ASSERT(G.swapchain_waitable != NULL);
}
#endif
struct string prof_ctx_name = LIT("D3d11 Context"); struct string prof_ctx_name = LIT("D3d11 Context");
(UNUSED)prof_ctx_name; (UNUSED)prof_ctx_name;
@ -1137,21 +1079,6 @@ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, stru
return res; return res;
} }
void gp_texture_clear(struct gp_handle target_texture, u32 clear_color)
{
__prof;
struct dx11_texture *t = (struct dx11_texture *)target_texture.v;
if (t->rtv) {
__profscope_dx11(G.profiling_ctx, Clear, RGB32_F(0.5, 0.1, 0.1));
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f;
f32 fill[4] = { r, g, b, a };
ID3D11DeviceContext_ClearRenderTargetView(G.devcon, t->rtv, fill);
}
}
struct v2i32 gp_texture_get_size(struct gp_handle texture) struct v2i32 gp_texture_get_size(struct gp_handle texture)
{ {
return ((struct dx11_texture *)texture.v)->size; return ((struct dx11_texture *)texture.v)->size;
@ -1384,7 +1311,7 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params)
ASSERT(false); ASSERT(false);
} break; } break;
case GP_CMD_KIND_DRAW_MESH: case GP_CMD_KIND_DRAW_SHAPE:
{ {
struct dx11_cmd *cmd = flow->cpu_last_cmd; struct dx11_cmd *cmd = flow->cpu_last_cmd;
if (cmd && cmd->kind != params.kind) { if (cmd && cmd->kind != params.kind) {
@ -1429,11 +1356,47 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params)
case GP_CMD_KIND_DRAW_TEXTURE: case GP_CMD_KIND_DRAW_TEXTURE:
{ {
if (params.texture.grid) {
struct dx11_cmd *cmd = flow->cpu_last_cmd;
if (cmd && (cmd->kind != params.kind || !cmd->is_grid)) {
/* Cannot batch */
cmd = NULL;
}
/* Start new cmd */
if (!cmd) {
/* TODO: Better count method */
cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd);
cmd->kind = params.kind;
cmd->is_grid = true;
cmd->grid.instance_offset = (flow->cmd_buffers.grid.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_grid_instance));
if (flow->cpu_last_cmd) {
flow->cpu_last_cmd->next = cmd;
} else {
flow->cpu_first_cmd = cmd;
}
flow->cpu_last_cmd = cmd;
}
/* Push instance data */
++cmd->grid.instance_count;
struct dx11_grid_instance *instance = dx11_buffer_push(flow->cmd_buffers.grid.instance_buffer, sizeof(struct dx11_grid_instance));
instance->xf = params.texture.xf;
instance->line_thickness = params.texture.grid->line_thickness;
instance->line_spacing = params.texture.grid->line_spacing;
instance->offset = params.texture.grid->offset;
instance->bg0_srgb = params.texture.grid->bg0_color;
instance->bg1_srgb = params.texture.grid->bg1_color;
instance->line_srgb = params.texture.grid->line_color;
instance->x_srgb = params.texture.grid->x_color;
instance->y_srgb = params.texture.grid->y_color;
} else {
struct dx11_cmd *cmd = flow->cpu_last_cmd; struct dx11_cmd *cmd = flow->cpu_last_cmd;
if (cmd && if (cmd &&
((cmd->kind != params.kind) || ((cmd->kind != params.kind) ||
(cmd->texture.sprite.hash != params.texture.sprite.hash) || (cmd->texture.sprite.hash != params.texture.sprite.hash) ||
(cmd->texture.texture.v != params.texture.texture.v))) { (cmd->texture.texture.v != params.texture.texture.v) ||
(cmd->is_grid))) {
/* Cannot batch */ /* Cannot batch */
cmd = NULL; cmd = NULL;
} }
@ -1462,42 +1425,7 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc params)
instance->uv1 = params.texture.clip.p1; instance->uv1 = params.texture.clip.p1;
instance->tint_srgb = params.texture.tint; instance->tint_srgb = params.texture.tint;
instance->emittance = params.texture.emittance; instance->emittance = params.texture.emittance;
} break;
case GP_CMD_KIND_DRAW_GRID:
{
struct dx11_cmd *cmd = flow->cpu_last_cmd;
if (cmd && cmd->kind != params.kind) {
/* Cannot batch */
cmd = NULL;
} }
/* Start new cmd */
if (!cmd) {
/* TODO: Better count method */
cmd = arena_push(flow->cpu_cmds_arena, struct dx11_cmd);
cmd->kind = params.kind;
cmd->grid.instance_offset = (flow->cmd_buffers.grid.instance_buffer->cpu_buffer_arena->pos / sizeof(struct dx11_grid_instance));
if (flow->cpu_last_cmd) {
flow->cpu_last_cmd->next = cmd;
} else {
flow->cpu_first_cmd = cmd;
}
flow->cpu_last_cmd = cmd;
}
/* Push instance data */
++cmd->grid.instance_count;
struct dx11_grid_instance *instance = dx11_buffer_push(flow->cmd_buffers.grid.instance_buffer, sizeof(struct dx11_grid_instance));
instance->xf = params.grid.xf;
instance->line_thickness = params.grid.line_thickness;
instance->line_spacing = params.grid.line_spacing;
instance->offset = params.grid.offset;
instance->bg0_srgb = params.grid.bg0_color;
instance->bg1_srgb = params.grid.bg1_color;
instance->line_srgb = params.grid.line_color;
instance->x_srgb = params.grid.x_color;
instance->y_srgb = params.grid.y_color;
} break; } break;
case GP_CMD_KIND_TEST: case GP_CMD_KIND_TEST:
@ -1655,6 +1583,20 @@ void gp_dispatch(struct gp_dispatch_params params)
flow->constant_buffer = constant_buffer; flow->constant_buffer = constant_buffer;
} }
/* Clear target */
if (params.clear_target) {
u32 clear_color = 0;
if (final_tex->rtv) {
__profscope_dx11(G.profiling_ctx, Clear, RGB32_F(0.5, 0.1, 0.1));
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f;
f32 fill[4] = { r, g, b, a };
ID3D11DeviceContext_ClearRenderTargetView(G.devcon, final_tex->rtv, fill);
}
}
/* Regular pass */ /* Regular pass */
struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, viewport.width, viewport.height); struct mat4x4 vp_matrix = calculate_vp(params.draw_target_view, viewport.width, viewport.height);
{ {
@ -1670,7 +1612,7 @@ void gp_dispatch(struct gp_dispatch_params params)
ASSERT(false); ASSERT(false);
} break; } break;
case GP_CMD_KIND_DRAW_MESH: case GP_CMD_KIND_DRAW_SHAPE:
{ {
__profscope(Draw mesh); __profscope(Draw mesh);
__profscope_dx11(G.profiling_ctx, Draw mesh, RGB32_F(0.5, 0.2, 0.2)); __profscope_dx11(G.profiling_ctx, Draw mesh, RGB32_F(0.5, 0.2, 0.2));
@ -1718,6 +1660,51 @@ void gp_dispatch(struct gp_dispatch_params params)
case GP_CMD_KIND_DRAW_TEXTURE: case GP_CMD_KIND_DRAW_TEXTURE:
{ {
if (cmd->is_grid) {
__profscope(Draw grid);
__profscope_dx11(G.profiling_ctx, Draw grid, RGB32_F(0.2, 0.2, 0.5));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID];
if (shader->valid) {
struct dx11_buffer *instance_buffer = flow->cmd_buffers.grid.instance_buffer;
u32 instance_offset = cmd->grid.instance_offset;
u32 instance_count = cmd->grid.instance_count;
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
/* Fill & bind constant buffer */
{
struct dx11_grid_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_grid_uniform));
uniform->vp = vp_matrix;
uniform->instance_offset = instance_offset;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind dummy vertex buffer */
u32 zero = 0;
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* Bind SRVs */
ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv };
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs);
/* Bind RTVs */
ID3D11RenderTargetView *rtvs[] = { final_tex->rtv };
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, ARRAY_COUNT(rtvs), rtvs, NULL);
/* Draw */
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0);
/* Unbind */
dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV);
}
} else {
__profscope(Draw texture); __profscope(Draw texture);
__profscope_dx11(G.profiling_ctx, Draw texture, RGB32_F(0.2, 0.5, 0.2)); __profscope_dx11(G.profiling_ctx, Draw texture, RGB32_F(0.2, 0.5, 0.2));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE]; struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE];
@ -1775,52 +1762,6 @@ void gp_dispatch(struct gp_dispatch_params params)
dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV); dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV);
} }
} }
} break;
case GP_CMD_KIND_DRAW_GRID:
{
__profscope(Draw grid);
__profscope_dx11(G.profiling_ctx, Draw grid, RGB32_F(0.2, 0.2, 0.5));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID];
if (shader->valid) {
struct dx11_buffer *instance_buffer = flow->cmd_buffers.grid.instance_buffer;
u32 instance_offset = cmd->grid.instance_offset;
u32 instance_count = cmd->grid.instance_count;
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
/* Fill & bind constant buffer */
{
struct dx11_grid_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_grid_uniform));
uniform->vp = vp_matrix;
uniform->instance_offset = instance_offset;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind dummy vertex buffer */
u32 zero = 0;
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* Bind SRVs */
ID3D11ShaderResourceView *srvs[] = { instance_buffer->srv };
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, ARRAY_COUNT(srvs), srvs);
/* Bind RTVs */
ID3D11RenderTargetView *rtvs[] = { final_tex->rtv };
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, ARRAY_COUNT(rtvs), rtvs, NULL);
/* Draw */
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0);
/* Unbind */
dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV);
} }
} break; } break;
@ -1878,47 +1819,20 @@ void gp_dispatch(struct gp_dispatch_params params)
} }
/* ========================== * /* ========================== *
* Backbuffer * Memory info
* ========================== */
struct gp_memory_info gp_query_memory_info(void)
{
return (struct gp_memory_info) { 0 };
}
/* ========================== *
* Present
* ========================== */ * ========================== */
INTERNAL void capture_image_for_profiler(void); INTERNAL void capture_image_for_profiler(void);
#if GSTAT_ENABLED || PROFILING
INTERNAL struct DXGI_QUERY_VIDEO_MEMORY_INFO get_memory_info(void)
{
__prof;
/* Get DXGI device from D3D11 device */
IDXGIDevice *dxgiDevice;
HRESULT hr = ID3D11Device_QueryInterface(G.dev, &IID_IDXGIDevice, (void **)&dxgiDevice);
(UNUSED)hr;
ASSERT(SUCCEEDED(hr));
/* Get DXGI adapter from DXGI device */
IDXGIAdapter *dxgiAdapter;
hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter);
ASSERT(SUCCEEDED(hr));
IDXGIAdapter3 *dxgiAdapter3 = NULL;
hr = IDXGIAdapter_QueryInterface(dxgiAdapter, &IID_IDXGIAdapter3, (void **)&dxgiAdapter3);
ASSERT(SUCCEEDED(hr));
struct DXGI_QUERY_VIDEO_MEMORY_INFO info = ZI;
IDXGIAdapter3_QueryVideoMemoryInfo(
dxgiAdapter3,
0,
DXGI_MEMORY_SEGMENT_GROUP_LOCAL,
&info
);
IDXGIAdapter_Release(dxgiAdapter3);
IDXGIAdapter_Release(dxgiAdapter);
IDXGIDevice_Release(dxgiDevice);
return info;
}
#endif
INTERNAL void present_resize(struct v2i32 size) INTERNAL void present_resize(struct v2i32 size)
{ {
__prof; __prof;
@ -1968,19 +1882,78 @@ INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, s
draw_texture(G.present_blit_flow, params); draw_texture(G.present_blit_flow, params);
} }
/* Clear texture */
gp_texture_clear(dst_texture_handle, RGBA32_F(0, 0, 0, 1));
/* Render to backbuffer texture */ /* Render to backbuffer texture */
struct gp_dispatch_params params = ZI; struct gp_dispatch_params params = ZI;
params.flow = G.present_blit_flow; params.flow = G.present_blit_flow;
params.draw_target = dst_texture_handle; params.draw_target = dst_texture_handle;
params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->size.x, dst->size.y)); params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->size.x, dst->size.y));
params.draw_target_view = XFORM_IDENT; params.draw_target_view = XFORM_IDENT;
params.clear_target = true;
gp_dispatch(params); gp_dispatch(params);
} }
void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) INTERNAL void present_init_swapchain(struct sys_window *window)
{
/* Create swap chain */
{
__profscope(Create swapchain);
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
/* Get DXGI device from D3D11 device */
IDXGIDevice *dxgiDevice;
HRESULT hr = ID3D11Device_QueryInterface(G.dev, &IID_IDXGIDevice, (void **)&dxgiDevice);
ASSERT(SUCCEEDED(hr));
/* Get DXGI adapter from DXGI device */
IDXGIAdapter *dxgiAdapter;
hr = IDXGIDevice_GetAdapter(dxgiDevice, &dxgiAdapter);
ASSERT(SUCCEEDED(hr));
/* Get DXGI factory from DXGI adapter */
IDXGIFactory2 *factory;
hr = IDXGIAdapter_GetParent(dxgiAdapter, &IID_IDXGIFactory2, (void **)&factory);
ASSERT(SUCCEEDED(hr));
DXGI_SWAP_CHAIN_DESC1 desc = {
.Format = DX11_SWAPCHAIN_FORMAT,
.SampleDesc = { 1, 0 },
.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT,
.BufferCount = 3,
.Scaling = DXGI_SCALING_NONE,
.Flags = DX11_SWAPCHAIN_FLAGS,
.AlphaMode = DXGI_ALPHA_MODE_IGNORE,
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD
};
IDXGISwapChain1 *swapchain1 = NULL;
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)G.dev, hwnd, &desc, NULL, NULL, &swapchain1);
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr)) {
IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void **)&G.swapchain);
}
/* Disable Alt+Enter changing monitor resolution to match window size */
IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
IDXGISwapChain1_Release(swapchain1);
IDXGIFactory2_Release(factory);
IDXGIAdapter_Release(dxgiAdapter);
IDXGIDevice_Release(dxgiDevice);
}
/* Create the swapchain waitable object */
#if DX11_WAIT_FRAME_LATENCY
if (G.swapchain != NULL) {
IDXGISwapChain2_SetMaximumFrameLatency(G.swapchain, 1);
G.swapchain_waitable = IDXGISwapChain2_GetFrameLatencyWaitableObject(G.swapchain);
ASSERT(G.swapchain_waitable != NULL);
}
#endif
}
void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
{ {
__prof; __prof;
@ -1994,36 +1967,9 @@ void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, st
} }
#endif #endif
/* Track vram usage */ if (!G.swapchain) {
#if GSTAT_ENABLED || PROFILING present_init_swapchain(window);
{
struct DXGI_QUERY_VIDEO_MEMORY_INFO info = get_memory_info();
u64 vram = info.CurrentUsage;
u64 budget = info.Budget;
(UNUSED)vram;
(UNUSED)budget;
# if GSTAT_ENABLED
{
gstat_set(GSTAT_VRAM_USAGE, vram);
gstat_set(GSTAT_VRAM_BUDGET, budget);
} }
# endif
# if PROFILING
{
LOCAL_PERSIST char *vram_plot_name = NULL;
LOCAL_PERSIST u64 prev_vram = 0;
if (!vram_plot_name) {
vram_plot_name = "Video memory usage";
__prof_plot_init(vram_plot_name, __prof_plot_type_memory, 1, 1, 0);
}
if (vram != prev_vram) {
__prof_plot_i(vram_plot_name, vram);
}
prev_vram = vram;
}
# endif
}
#endif
/* Wait */ /* Wait */
i32 flags = 0; i32 flags = 0;

View File

@ -36,6 +36,12 @@
#pragma comment(lib, "dxguid") #pragma comment(lib, "dxguid")
#pragma comment(lib, "d3dcompiler") #pragma comment(lib, "d3dcompiler")
#if PROFILING
/* For RegOpenKeyEx */
# include <winreg.h>
# pragma comment(lib, "advapi32")
#endif
//#define DX12_WAIT_FRAME_LATENCY 1 //#define DX12_WAIT_FRAME_LATENCY 1
//#define DX12_SWAPCHAIN_FLAGS ((DX12_ALLOW_TEARING * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | (DX12_WAIT_FRAME_LATENCY * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) //#define DX12_SWAPCHAIN_FLAGS ((DX12_ALLOW_TEARING * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | (DX12_WAIT_FRAME_LATENCY * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
@ -153,8 +159,10 @@ struct command_descriptor_heap {
struct command_buffer { struct command_buffer {
struct command_buffer_group *group; struct command_buffer_group *group;
struct dx12_resource *resource;
u64 size; u64 size;
struct dx12_resource *resource;
D3D12_VERTEX_BUFFER_VIEW vbv;
D3D12_INDEX_BUFFER_VIEW Ibv;
struct command_buffer *next_in_command_list; struct command_buffer *next_in_command_list;
@ -372,6 +380,8 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gp_shutdown)
command_queue_release(G.cq_compute); command_queue_release(G.cq_compute);
command_queue_release(G.cq_direct); command_queue_release(G.cq_direct);
ID3D12Device_Release(G.device); ID3D12Device_Release(G.device);
#else
(UNUSED)command_queue_release;
#endif #endif
} }
@ -426,6 +436,7 @@ INTERNAL struct handle_entry *handle_get_entry(struct gp_handle handle, struct s
INTERNAL void *handle_get_data(struct gp_handle handle, enum handle_kind kind) INTERNAL void *handle_get_data(struct gp_handle handle, enum handle_kind kind)
{ {
(UNUSED)kind;
void *data = NULL; void *data = NULL;
if (handle.gen) { if (handle.gen) {
struct sys_lock lock = sys_mutex_lock_s(G.handle_entries_mutex); struct sys_lock lock = sys_mutex_lock_s(G.handle_entries_mutex);
@ -593,6 +604,41 @@ INTERNAL void dx12_init_device(void)
} }
#endif #endif
#if PROFILING
/* Enable stable power state */
{
b32 success = true;
__profscope(Set stable power state);
HKEY key = 0;
success = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock", 0, KEY_READ, &key) == ERROR_SUCCESS;
if (success) {
DWORD value = ZI;
DWORD dword_size = sizeof(DWORD);
success = RegQueryValueExW(key, L"AllowDevelopmentWithoutDevLicense", 0, NULL, (LPBYTE)&value, &dword_size) == ERROR_SUCCESS;
RegCloseKey(key);
if (success) {
success = value != 0;
}
}
logf_info("D3D12 profiling is enabled, attempting to set stable power state (this will increase GPU timing stability at the cost of performance)");
if (success) {
logf_info("Machine is in developer mode, calling ID3D12Device::SetStablePowerState");
hr = ID3D12Device_SetStablePowerState(G.device, 1);
if (SUCCEEDED(hr)) {
logf_info("ID3D12Device::SetStablePowerState succeeded");
} else {
success = false;
logf_error("ID3D12Device::SetStablePowerState failed");
}
} else {
logf_warning("Machine is not in developer mode, cannot call ID3D12Device::SetStablePowerState");
}
if (!success) {
logf_warning("Profiling is enabled, but ID3D12Device::SetStablePowerState could not be called. This means that GPU timing may be unreliable.");
}
}
#endif
scratch_end(scratch); scratch_end(scratch);
} }
@ -648,6 +694,16 @@ INTERNAL void dx12_init_pipelines(void)
desc->ps.func = LIT("ps"); desc->ps.func = LIT("ps");
dict_set(G.pipelines_arena, G.pipeline_descs, hash_fnv64(HASH_FNV64_BASIS, desc->name), (u64)desc); dict_set(G.pipelines_arena, G.pipeline_descs, hash_fnv64(HASH_FNV64_BASIS, desc->name), (u64)desc);
} }
/* Shape pipeline */
{
struct pipeline_desc *desc = arena_push(G.pipelines_arena, struct pipeline_desc);
desc->name = LIT("shape");
desc->vs.file = LIT("sh/shape.hlsl");
desc->ps.file = LIT("sh/shape.hlsl");
desc->vs.func = LIT("vs");
desc->ps.func = LIT("ps");
dict_set(G.pipelines_arena, G.pipeline_descs, hash_fnv64(HASH_FNV64_BASIS, desc->name), (u64)desc);
}
/* Blit pipeilne */ /* Blit pipeilne */
{ {
struct pipeline_desc *desc = arena_push(G.pipelines_arena, struct pipeline_desc); struct pipeline_desc *desc = arena_push(G.pipelines_arena, struct pipeline_desc);
@ -674,7 +730,8 @@ INTERNAL void dx12_init_pipelines(void)
struct pipeline *pipeline = pipelines[i]; struct pipeline *pipeline = pipelines[i];
if (!pipeline->success) { if (!pipeline->success) {
struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error");
struct string msg = string_format(scratch.arena, LIT("Error creating pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); struct string msg = string_format(scratch.arena, LIT("Error initializing pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
log_error(msg);
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg); sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
} }
} }
@ -1142,6 +1199,7 @@ INTERNAL void pipeline_release(struct pipeline *pipeline)
INTERNAL struct pipeline_scope *pipeline_scope_begin(void) INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
{ {
__prof;
struct pipeline_scope *scope = NULL; struct pipeline_scope *scope = NULL;
{ {
struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex);
@ -1166,6 +1224,7 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
INTERNAL void pipeline_scope_end(struct pipeline_scope *scope) INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
{ {
__prof;
struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex);
{ {
for (struct dict_entry *entry = scope->refs->first; entry; entry = entry->next) { for (struct dict_entry *entry = scope->refs->first; entry; entry = entry->next) {
@ -1183,6 +1242,7 @@ INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI; INTERNAL READONLY struct pipeline g_nil_pipeline = ZI;
INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name) INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name)
{ {
__prof;
struct pipeline *res = &g_nil_pipeline; struct pipeline *res = &g_nil_pipeline;
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name); u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
@ -1209,6 +1269,7 @@ INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struc
INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines) INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines)
{ {
__prof;
struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex); struct sys_lock lock = sys_mutex_lock_e(G.pipelines_mutex);
{ {
for (u64 i = 0; i < num_pipelines; ++i) { for (u64 i = 0; i < num_pipelines; ++i) {
@ -1240,6 +1301,7 @@ INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines)
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name) INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name)
{ {
__prof;
struct arena_temp scratch = scratch_begin_no_conflict(); struct arena_temp scratch = scratch_begin_no_conflict();
/* Find dirty pipelines */ /* Find dirty pipelines */
@ -1260,6 +1322,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
} }
/* Recompile dirty pipelines */ /* Recompile dirty pipelines */
if (num_pipelines > 0) {
struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines); struct pipeline **pipelines = arena_push_array(scratch.arena, struct pipeline *, num_pipelines);
pipeline_alloc_from_desc(num_pipelines, pipeline_descs, pipelines); pipeline_alloc_from_desc(num_pipelines, pipeline_descs, pipelines);
{ {
@ -1269,12 +1332,13 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
if (pipeline->success) { if (pipeline->success) {
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns))); logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
} else { } else {
struct pipeline *old_pipeline = dict_get(G.top_successful_pipelines, pipeline->hash); {
if (old_pipeline) {
struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error");
struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
log_error(msg); log_error(msg);
} else { }
struct pipeline *old_pipeline = dict_get(G.top_successful_pipelines, pipeline->hash);
if (!old_pipeline) {
/* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */ /* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */
struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error"); struct string error = pipeline->first_error ? pipeline->first_error->msg : LIT("Unknown error");
struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error)); struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
@ -1286,6 +1350,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
pipeline_register(num_pipelines, pipelines); pipeline_register(num_pipelines, pipelines);
}
scratch_end(scratch); scratch_end(scratch);
} }
@ -1297,6 +1362,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(pipeline_resource_watch_callback, name
INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh) INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
{ {
__prof;
struct descriptor *d = NULL; struct descriptor *d = NULL;
u32 index = 0; u32 index = 0;
D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI; D3D12_CPU_DESCRIPTOR_HANDLE handle = ZI;
@ -1331,6 +1397,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type) INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type)
{ {
__prof;
struct cpu_descriptor_heap *dh = NULL; struct cpu_descriptor_heap *dh = NULL;
{ {
struct arena *arena = arena_alloc(MEGABYTE(64)); struct arena *arena = arena_alloc(MEGABYTE(64));
@ -1382,12 +1449,15 @@ struct flow {
struct sprite_scope *sprite_scope; struct sprite_scope *sprite_scope;
struct arena *material_instances_arena; struct arena *material_instances_arena;
struct arena *material_grids_arena; struct arena *material_grids_arena;
struct arena *shape_verts_arena;
struct arena *shape_indices_arena;
struct flow *next_free; struct flow *next_free;
}; };
INTERNAL struct flow *flow_alloc(void) INTERNAL struct flow *flow_alloc(void)
{ {
__prof;
struct flow *flow = NULL; struct flow *flow = NULL;
{ {
struct arena *arena = arena_alloc(MEGABYTE(64)); struct arena *arena = arena_alloc(MEGABYTE(64));
@ -1398,40 +1468,47 @@ INTERNAL struct flow *flow_alloc(void)
flow->sprite_scope = sprite_scope_begin(); flow->sprite_scope = sprite_scope_begin();
flow->material_instances_arena = arena_alloc(GIGABYTE(1)); flow->material_instances_arena = arena_alloc(GIGABYTE(1));
flow->material_grids_arena = arena_alloc(GIGABYTE(1)); flow->material_grids_arena = arena_alloc(GIGABYTE(1));
flow->shape_verts_arena = arena_alloc(GIGABYTE(1));
flow->shape_indices_arena = arena_alloc(GIGABYTE(1));
return flow; return flow;
} }
INTERNAL void flow_reset(struct flow *flow) INTERNAL void flow_reset(struct flow *flow)
{ {
__prof;
sprite_scope_end(flow->sprite_scope); sprite_scope_end(flow->sprite_scope);
flow->sprite_scope = sprite_scope_begin(); flow->sprite_scope = sprite_scope_begin();
arena_reset(flow->material_instances_arena); arena_reset(flow->material_instances_arena);
arena_reset(flow->material_grids_arena); arena_reset(flow->material_grids_arena);
arena_reset(flow->shape_verts_arena);
arena_reset(flow->shape_indices_arena);
} }
struct gp_handle gp_flow_alloc(void) struct gp_handle gp_flow_alloc(void)
{ {
__prof;
struct flow *flow = flow_alloc(); struct flow *flow = flow_alloc();
return handle_alloc(DX12_HANDLE_KIND_FLOW, flow); return handle_alloc(DX12_HANDLE_KIND_FLOW, flow);
} }
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc) void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc)
{ {
__prof;
struct flow *flow = handle_get_data(gp_flow, DX12_HANDLE_KIND_FLOW); struct flow *flow = handle_get_data(gp_flow, DX12_HANDLE_KIND_FLOW);
if (flow) { if (flow) {
switch (desc.kind) { switch (desc.kind) {
default: break; default: break;
case GP_CMD_KIND_DRAW_TEXTURE: case GP_CMD_KIND_DRAW_MATERIAL:
{ {
i32 texture_id = -1; i32 texture_id = -1;
{ {
struct dx12_resource *texture = NULL; struct dx12_resource *texture = NULL;
if (desc.texture.texture.gen != 0) { if (desc.material.texture.gen != 0) {
texture = handle_get_data(desc.texture.texture, DX12_HANDLE_KIND_RESOURCE); texture = handle_get_data(desc.material.texture, DX12_HANDLE_KIND_RESOURCE);
} else if (desc.texture.sprite.hash != 0) { } else if (desc.material.sprite.hash != 0) {
struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, desc.texture.sprite); struct sprite_texture *st = sprite_texture_from_tag_async(flow->sprite_scope, desc.material.sprite);
texture = handle_get_data(st->texture, DX12_HANDLE_KIND_RESOURCE); texture = handle_get_data(st->texture, DX12_HANDLE_KIND_RESOURCE);
} }
if (texture) { if (texture) {
@ -1440,8 +1517,8 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc)
} }
i32 grid_id = -1; i32 grid_id = -1;
if (desc.texture.grid) { if (desc.material.grid) {
struct gp_grid_desc *grid_desc = desc.texture.grid; struct gp_grid_desc *grid_desc = desc.material.grid;
struct sh_material_grid *grid = arena_push(flow->material_grids_arena, struct sh_material_grid); struct sh_material_grid *grid = arena_push(flow->material_grids_arena, struct sh_material_grid);
grid->line_thickness = sh_float_from_f32(grid_desc->line_thickness); grid->line_thickness = sh_float_from_f32(grid_desc->line_thickness);
grid->line_spacing = sh_float_from_f32(grid_desc->line_spacing); grid->line_spacing = sh_float_from_f32(grid_desc->line_spacing);
@ -1459,11 +1536,27 @@ void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_desc desc)
instance->flags = sh_uint_from_u32(SH_MATERIAL_FLAG_NONE); instance->flags = sh_uint_from_u32(SH_MATERIAL_FLAG_NONE);
instance->tex_nurid = sh_int_from_i32(texture_id); instance->tex_nurid = sh_int_from_i32(texture_id);
instance->grid_id = sh_int_from_i32(grid_id); instance->grid_id = sh_int_from_i32(grid_id);
instance->xf = sh_float2x3_from_xform(desc.texture.xf); instance->xf = sh_float2x3_from_xform(desc.material.xf);
instance->uv0 = sh_float2_from_v2(desc.texture.clip.p0); instance->uv0 = sh_float2_from_v2(desc.material.clip.p0);
instance->uv1 = sh_float2_from_v2(desc.texture.clip.p1); instance->uv1 = sh_float2_from_v2(desc.material.clip.p1);
instance->tint_srgb = sh_uint_from_u32(desc.texture.tint); instance->tint_srgb = sh_uint_from_u32(desc.material.tint);
instance->emittance = sh_float_from_f32(desc.texture.emittance); instance->emittance = sh_float_from_f32(desc.material.emittance);
}
} break;
case GP_CMD_KIND_DRAW_SHAPE:
{
u32 color = desc.shape.color;
u32 vert_offset = flow->shape_verts_arena->pos / sizeof(struct sh_shape_vert);
struct sh_shape_vert *verts = arena_push_array_no_zero(flow->shape_verts_arena, struct sh_shape_vert, desc.shape.vertices.count);
u32 *indices = arena_push_array_no_zero(flow->shape_indices_arena, u32, desc.shape.indices.count);
for (u32 i = 0; i < desc.shape.vertices.count; ++i) {
struct sh_shape_vert *v = &verts[i];
v->pos = sh_float2_from_v2(desc.shape.vertices.points[i]);
v->color_srgb = sh_uint_from_u32(color);
}
for (u32 i = 0; i < desc.shape.indices.count; ++i) {
indices[i] = desc.shape.indices.indices[i] + vert_offset;
} }
} break; } break;
} }
@ -1484,6 +1577,7 @@ enum dx12_resource_view_flags {
INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_props, D3D12_HEAP_FLAGS heap_flags, D3D12_RESOURCE_DESC desc, D3D12_RESOURCE_STATES initial_state, enum dx12_resource_view_flags view_flags) INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_props, D3D12_HEAP_FLAGS heap_flags, D3D12_RESOURCE_DESC desc, D3D12_RESOURCE_STATES initial_state, enum dx12_resource_view_flags view_flags)
{ {
__prof;
struct dx12_resource *r = NULL; struct dx12_resource *r = NULL;
{ {
struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex); struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex);
@ -1538,6 +1632,7 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr
INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff, struct v2i32 texture_size) INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff, struct v2i32 texture_size)
{ {
__prof;
struct dx12_resource *r = NULL; struct dx12_resource *r = NULL;
{ {
struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex); struct sys_lock lock = sys_mutex_lock_e(G.resources_mutex);
@ -1565,16 +1660,19 @@ INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12R
INTERNAL void dx12_resource_release(struct dx12_resource *t) INTERNAL void dx12_resource_release(struct dx12_resource *t)
{ {
__prof;
(UNUSED)t; (UNUSED)t;
} }
INTERNAL void dx12_resource_release_now(struct dx12_resource *t) INTERNAL void dx12_resource_release_now(struct dx12_resource *t)
{ {
__prof;
(UNUSED)t; (UNUSED)t;
} }
INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandList *cl, struct dx12_resource *resource, enum D3D12_RESOURCE_STATES state) INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandList *cl, struct dx12_resource *resource, enum D3D12_RESOURCE_STATES state)
{ {
__prof;
enum D3D12_RESOURCE_STATES old_state = resource->state; enum D3D12_RESOURCE_STATES old_state = resource->state;
if (state != resource->state) { if (state != resource->state) {
struct D3D12_RESOURCE_TRANSITION_BARRIER rtb = ZI; struct D3D12_RESOURCE_TRANSITION_BARRIER rtb = ZI;
@ -1601,6 +1699,7 @@ INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandL
INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority) INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority)
{ {
__prof;
struct command_queue *cq = NULL; struct command_queue *cq = NULL;
{ {
struct arena *arena = arena_alloc(GIGABYTE(64)); struct arena *arena = arena_alloc(GIGABYTE(64));
@ -1629,6 +1728,7 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE
INTERNAL void command_queue_release(struct command_queue *cq) INTERNAL void command_queue_release(struct command_queue *cq)
{ {
__prof;
/* TODO */ /* TODO */
(UNUSED)cq; (UNUSED)cq;
//ID3D12CommandQueue_Release(G.cq_copy_background->cq); //ID3D12CommandQueue_Release(G.cq_copy_background->cq);
@ -1640,6 +1740,7 @@ INTERNAL void command_queue_release(struct command_queue *cq)
INTERNAL struct command_list *command_list_open(struct command_queue *cq) INTERNAL struct command_list *command_list_open(struct command_queue *cq)
{ {
__prof;
u64 queue_fence_value = ID3D12Fence_GetCompletedValue(cq->fence); u64 queue_fence_value = ID3D12Fence_GetCompletedValue(cq->fence);
struct command_list *cl = NULL; struct command_list *cl = NULL;
@ -1717,6 +1818,7 @@ INTERNAL struct command_list *command_list_open(struct command_queue *cq)
/* TODO: Allow multiple command list submissions */ /* TODO: Allow multiple command list submissions */
INTERNAL u64 command_list_close(struct command_list *cl) INTERNAL u64 command_list_close(struct command_list *cl)
{ {
__prof;
struct command_queue *cq = cl->cq; struct command_queue *cq = cl->cq;
/* Close & execute */ /* Close & execute */
@ -1786,6 +1888,7 @@ INTERNAL u64 command_list_close(struct command_list *cl)
INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struct command_list *cl, struct cpu_descriptor_heap *dh_cpu) INTERNAL struct command_descriptor_heap *command_list_push_descriptor_heap(struct command_list *cl, struct cpu_descriptor_heap *dh_cpu)
{ {
__prof;
ASSERT(dh_cpu->type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); /* Src heap must have expected type */ ASSERT(dh_cpu->type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); /* Src heap must have expected type */
/* Allocate GPU heap */ /* Allocate GPU heap */
@ -1888,6 +1991,8 @@ INTERNAL u64 align_up_pow2(u64 v)
INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl, struct string data) INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl, struct string data)
{ {
__prof;
/* Determine size */ /* Determine size */
u64 size = max_u64(DX12_COMMAND_BUFFER_MIN_SIZE, align_up_pow2(data.len)); u64 size = max_u64(DX12_COMMAND_BUFFER_MIN_SIZE, align_up_pow2(data.len));
@ -1942,6 +2047,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl
cb->group = cb_group; cb->group = cb_group;
cb->size = data.len; cb->size = data.len;
/* Create upload heap */
if (resource) { if (resource) {
cb->resource = resource; cb->resource = resource;
} else { } else {
@ -1995,6 +2101,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl
INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, u32 size) INTERNAL void command_list_set_root_constant(struct command_list *cl, void *src, u32 size)
{ {
__prof;
if (size % 4 == 0) { if (size % 4 == 0) {
u32 num32bit = size / 4; u32 num32bit = size / 4;
for (u32 i = 0; i < num32bit; ++i) { for (u32 i = 0; i < num32bit; ++i) {
@ -2030,12 +2137,31 @@ INTERNAL D3D12_RECT scissor_from_rect(struct rect r)
return scissor; return scissor;
} }
INTERNAL D3D12_VERTEX_BUFFER_VIEW vbv_from_command_buffer(struct command_buffer *cb, u32 vertex_size)
{
D3D12_VERTEX_BUFFER_VIEW vbv = ZI;
vbv.BufferLocation = cb->resource->gpu_address;
vbv.SizeInBytes = cb->size;
vbv.StrideInBytes = vertex_size;
return vbv;
}
INTERNAL D3D12_INDEX_BUFFER_VIEW ibv_from_command_buffer(struct command_buffer *cb, DXGI_FORMAT format)
{
D3D12_INDEX_BUFFER_VIEW ibv = ZI;
ibv.BufferLocation = cb->resource->gpu_address;
ibv.Format = format;
ibv.SizeInBytes = cb->size;
return ibv;
}
/* ========================== * /* ========================== *
* Texture * Texture
* ========================== */ * ========================== */
struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data) struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
{ {
__prof;
struct dxgi_format_info { DXGI_FORMAT format; u32 size; }; struct dxgi_format_info { DXGI_FORMAT format; u32 size; };
LOCAL_PERSIST const struct dxgi_format_info formats[] = { LOCAL_PERSIST const struct dxgi_format_info formats[] = {
[GP_TEXTURE_FORMAT_R8G8B8A8_UNORM] = { DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, [GP_TEXTURE_FORMAT_R8G8B8A8_UNORM] = { DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
@ -2215,7 +2341,7 @@ void gp_dispatch(struct gp_dispatch_params params)
struct pipeline_scope *pipeline_scope = pipeline_scope_begin(); struct pipeline_scope *pipeline_scope = pipeline_scope_begin();
struct pipeline *material_pipeline = pipeline_from_name(pipeline_scope, LIT("material")); struct pipeline *material_pipeline = pipeline_from_name(pipeline_scope, LIT("material"));
if (material_pipeline->success) { struct pipeline *shape_pipeline = pipeline_from_name(pipeline_scope, LIT("shape"));
struct command_list *cl = command_list_open(G.cq_direct); struct command_list *cl = command_list_open(G.cq_direct);
{ {
struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE); struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE);
@ -2226,16 +2352,13 @@ void gp_dispatch(struct gp_dispatch_params params)
LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 };
struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0)); struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0));
struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices)); struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices));
D3D12_VERTEX_BUFFER_VIEW dummy_vertex_buffer_view = ZI;
dummy_vertex_buffer_view.BufferLocation = dummy_vertex_buffer->resource->gpu_address;
D3D12_INDEX_BUFFER_VIEW quad_index_buffer_view = ZI;
quad_index_buffer_view.BufferLocation = quad_index_buffer->resource->gpu_address;
quad_index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
quad_index_buffer_view.SizeInBytes = sizeof(quad_indices);
/* Upload buffers */ /* Upload buffers */
struct command_buffer *instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena)); struct command_buffer *material_instance_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_instances_arena));
struct command_buffer *grid_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_grids_arena)); struct command_buffer *material_grid_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->material_grids_arena));
struct command_buffer *shape_verts_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->shape_verts_arena));
struct command_buffer *shape_indices_buffer = command_list_push_buffer(cl, STRING_FROM_ARENA(flow->shape_indices_arena));
/* Upload descriptor heap */ /* Upload descriptor heap */
struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap);
@ -2257,8 +2380,9 @@ void gp_dispatch(struct gp_dispatch_params params)
} }
/* Material pass */ /* Material pass */
{ if (material_pipeline->success) {
u32 instance_count = instance_buffer->size / sizeof(struct sh_material_instance); __profscope(Material pass);
u32 instance_count = material_instance_buffer->size / sizeof(struct sh_material_instance);
/* Bind pipeline */ /* Bind pipeline */
ID3D12GraphicsCommandList_SetPipelineState(cl->cl, material_pipeline->pso); ID3D12GraphicsCommandList_SetPipelineState(cl->cl, material_pipeline->pso);
@ -2270,10 +2394,10 @@ void gp_dispatch(struct gp_dispatch_params params)
command_list_set_root_constant(cl, &constants, sizeof(constants)); command_list_set_root_constant(cl, &constants, sizeof(constants));
/* Bind instance buffer */ /* Bind instance buffer */
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, instance_buffer->resource->gpu_address); ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 1, material_instance_buffer->resource->gpu_address);
/* Bind grid buffer */ /* Bind grid buffer */
ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 2, grid_buffer->resource->gpu_address); ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView(cl->cl, 2, material_grid_buffer->resource->gpu_address);
/* Bind descriptor heap */ /* Bind descriptor heap */
ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap };
@ -2287,19 +2411,53 @@ void gp_dispatch(struct gp_dispatch_params params)
ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor); ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor);
/* Draw */ /* Draw */
D3D12_VERTEX_BUFFER_VIEW vbv = vbv_from_command_buffer(dummy_vertex_buffer, 0);
D3D12_INDEX_BUFFER_VIEW ibv = ibv_from_command_buffer(quad_index_buffer, DXGI_FORMAT_R16_UINT);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &dummy_vertex_buffer_view); ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &vbv);
ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &quad_index_buffer_view); ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv);
ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, instance_count, 0, 0, 0); ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, instance_count, 0, 0, 0);
} }
/* Shape pass */
if (shape_pipeline->success) {
__profscope(Shape pass);
/* Bind pipeline */
ID3D12GraphicsCommandList_SetPipelineState(cl->cl, material_pipeline->pso);
ID3D12GraphicsCommandList_SetGraphicsRootSignature(cl->cl, material_pipeline->rootsig);
/* Set root constants */
struct sh_shape_constants constants = ZI;
constants.projection = sh_float4x4_from_mat4x4(vp_matrix);
command_list_set_root_constant(cl, &constants, sizeof(constants));
/* Bind descriptor heap */
ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap };
ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, ARRAY_COUNT(heaps), heaps);
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(cl->cl, 3, descriptor_heap->gp_handle);
/* Setup Rasterizer State */
D3D12_VIEWPORT viewport = viewport_from_rect(params.draw_target_viewport);
D3D12_RECT scissor = scissor_from_rect(params.draw_target_viewport);
ID3D12GraphicsCommandList_RSSetViewports(cl->cl, 1, &viewport);
ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor);
/* Draw */
D3D12_VERTEX_BUFFER_VIEW vbv = vbv_from_command_buffer(shape_verts_buffer, sizeof(struct sh_shape_vert));
D3D12_INDEX_BUFFER_VIEW ibv = ibv_from_command_buffer(shape_indices_buffer, DXGI_FORMAT_R32_UINT);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &vbv);
ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv);
ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, 1, 0, 0, 0);
}
/* Reset render target */ /* Reset render target */
{ {
dx12_resource_barrier(cl->cl, target, target_old_state); dx12_resource_barrier(cl->cl, target, target_old_state);
} }
} }
command_list_close(cl); command_list_close(cl);
}
pipeline_scope_end(pipeline_scope); pipeline_scope_end(pipeline_scope);
flow_reset(flow); flow_reset(flow);
} }
@ -2308,54 +2466,6 @@ void gp_dispatch(struct gp_dispatch_params params)
* Memory info * Memory info
* ========================== */ * ========================== */
#if 0
struct gp_memory_info gp_query_memory_info(void)
{
struct gp_memory_info res = ZI;
HRESULT hr = 0;
IDXGIAdapter3 *dxgiAdapter3 = NULL;
struct DXGI_QUERY_VIDEO_MEMORY_INFO info = ZI;
if (SUCCEEDED(hr)) {
hr = IDXGIAdapter_QueryInterface(G.adapter, &IID_IDXGIAdapter3, (void **)&dxgiAdapter3);
ASSERT(SUCCEEDED(hr));
}
if (SUCCEEDED(hr)) {
IDXGIAdapter3_QueryVideoMemoryInfo(dxgiAdapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info);
{
u64 vram = info.CurrentUsage;
u64 budget = info.Budget;
(UNUSED)vram;
(UNUSED)budget;
#if GSTAT_ENABLED
{
gstat_set(GSTAT_VRAM_USAGE, vram);
gstat_set(GSTAT_VRAM_BUDGET, budget);
}
#endif
#if PROFILING
{
LOCAL_PERSIST char *vram_plot_name = NULL;
LOCAL_PERSIST u64 prev_vram = 0;
if (!vram_plot_name) {
vram_plot_name = "Video memory usage";
__prof_plot_init(vram_plot_name, __prof_plot_type_memory, 1, 1, 0);
}
if (vram != prev_vram) {
__prof_plot_i(vram_plot_name, vram);
}
prev_vram = vram;
}
#endif
}
}
if (dxgiAdapter3) {
IDXGIAdapter_Release(dxgiAdapter3);
}
return res;
}
#else
struct gp_memory_info gp_query_memory_info(void) struct gp_memory_info gp_query_memory_info(void)
{ {
struct gp_memory_info res = ZI; struct gp_memory_info res = ZI;
@ -2383,8 +2493,6 @@ struct gp_memory_info gp_query_memory_info(void)
} }
return res; return res;
} }
#endif
/* ========================== * /* ========================== *
* Present * Present
@ -2476,12 +2584,6 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 }; LOCAL_PERSIST u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 };
struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0)); struct command_buffer *dummy_vertex_buffer = command_list_push_buffer(cl, STRING(0, 0));
struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices)); struct command_buffer *quad_index_buffer = command_list_push_buffer(cl, STRING_FROM_ARRAY(quad_indices));
D3D12_VERTEX_BUFFER_VIEW dummy_vertex_buffer_view = ZI;
dummy_vertex_buffer_view.BufferLocation = dummy_vertex_buffer->resource->gpu_address;
D3D12_INDEX_BUFFER_VIEW quad_index_buffer_view = ZI;
quad_index_buffer_view.BufferLocation = quad_index_buffer->resource->gpu_address;
quad_index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
quad_index_buffer_view.SizeInBytes = sizeof(quad_indices);
/* Upload descriptor heap */ /* Upload descriptor heap */
struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap); struct command_descriptor_heap *descriptor_heap = command_list_push_descriptor_heap(cl, G.cbv_srv_uav_heap);
@ -2520,9 +2622,11 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor); ID3D12GraphicsCommandList_RSSetScissorRects(cl->cl, 1, &scissor);
/* Draw */ /* Draw */
D3D12_VERTEX_BUFFER_VIEW vbv = vbv_from_command_buffer(dummy_vertex_buffer, 0);
D3D12_INDEX_BUFFER_VIEW ibv = ibv_from_command_buffer(quad_index_buffer, DXGI_FORMAT_R16_UINT);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetPrimitiveTopology(cl->cl, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &dummy_vertex_buffer_view); ID3D12GraphicsCommandList_IASetVertexBuffers(cl->cl, 0, 1, &vbv);
ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &quad_index_buffer_view); ID3D12GraphicsCommandList_IASetIndexBuffer(cl->cl, &ibv);
ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, 1, 0, 0, 0); ID3D12GraphicsCommandList_DrawIndexedInstanced(cl->cl, 6, 1, 0, 0, 0);
/* Set dst to presentable */ /* Set dst to presentable */
@ -2535,6 +2639,7 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
{ {
__prof;
//sys_sleep(0.1); //sys_sleep(0.1);
struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution); struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution);
@ -2547,10 +2652,14 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
/* Present */ /* Present */
/* FIXME: Resource barrier */ /* FIXME: Resource barrier */
{
__profscope(Present);
HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0); HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0);
if (!SUCCEEDED(hr)) { if (!SUCCEEDED(hr)) {
ASSERT(false); ASSERT(false);
} }
__profframe(0);
}
(UNUSED)backbuffer_resolution; (UNUSED)backbuffer_resolution;
(UNUSED)texture; (UNUSED)texture;

View File

@ -974,7 +974,6 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_from_tag(struct sprite_scope
} }
} }
return scope_ref; return scope_ref;
} }

View File

@ -1195,6 +1195,11 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str
}; };
SetWindowPlacement(hwnd, &wp); SetWindowPlacement(hwnd, &wp);
/* Make window always on top when debugging */
#if RTC
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
#endif
{ {
struct arena_temp scratch = scratch_begin_no_conflict(); struct arena_temp scratch = scratch_begin_no_conflict();
wchar_t *title_wstr = wstr_from_string(scratch.arena, string_from_cstr_no_limit(settings->title)); wchar_t *title_wstr = wstr_from_string(scratch.arena, string_from_cstr_no_limit(settings->title));

View File

@ -1053,19 +1053,6 @@ INTERNAL void user_update(void)
draw_grid(G.world_gp_flow, xform_from_rect(RECT_FROM_V2(pos, size)), color0, color1, RGBA32(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset); draw_grid(G.world_gp_flow, xform_from_rect(RECT_FROM_V2(pos, size)), color0, color1, RGBA32(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset);
} }
/* ========================== *
* Draw test
* ========================== */
{
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);
struct gp_cmd_desc cmd = ZI;
cmd.kind = GP_CMD_KIND_TEST;
cmd.test.xf = xform_from_rect(RECT_FROM_V2(pos, size));
gp_push_cmd(G.world_gp_flow, cmd);
}
#if 0 #if 0
/* ========================== * /* ========================== *
* Alloc / release tile cache entries * Alloc / release tile cache entries

View File

@ -548,11 +548,12 @@ struct work_handle work_slate_end(struct work_slate *ws, enum work_priority prio
struct work_handle work_slate_end_and_help(struct work_slate *ws, enum work_priority priority) struct work_handle work_slate_end_and_help(struct work_slate *ws, enum work_priority priority)
{ {
__prof; __prof;
struct work_handle handle = ZI;
if (ws->num_tasks > 0) {
struct sys_lock lock = sys_mutex_lock_e(G.mutex); struct sys_lock lock = sys_mutex_lock_e(G.mutex);
struct work_handle handle = work_push_from_slate_locked(&lock, ws, true, priority); handle = work_push_from_slate_locked(&lock, ws, true, priority);
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
}
return handle; return handle;
} }
@ -566,7 +567,7 @@ INTERNAL struct work *work_from_handle_locked(struct sys_lock *lock, struct work
(UNUSED)lock; (UNUSED)lock;
struct work *work = handle.work; struct work *work = handle.work;
if (work->gen != handle.gen) { if (work && work->gen != handle.gen) {
work = NULL; work = NULL;
} }
return work; return work;