light testing setup. backbuffer resize delay.

This commit is contained in:
jacob 2025-06-02 22:54:50 -05:00
parent c6e70e201e
commit fae10387cd
12 changed files with 537 additions and 350 deletions

View File

@ -957,7 +957,7 @@ void OnBuild(StringList cli_args)
BuildStepSimpleCommandArg *bs_arg = ArenaPush(&perm, BuildStepSimpleCommandArg);
bs_arg->cmd = StringF(&perm, link_args_fmt, FmtStr(link_files_str), FmtStr(executable_file.full_path));
bs_arg->skip_flag = &src_success_flag;
String step_name = Lit("Linking");
String step_name = Lit("Link");
AddStep(step_name, &BuildStepSimpleCommand, bs_arg);
}
}

View File

@ -5,6 +5,7 @@ struct vs_instance {
float2 uv0;
float2 uv1;
uint tint_srgb;
float emittance;
};
struct ps_input {

View File

@ -83,5 +83,5 @@
/* TODO: Move these to user-configurable settings */
#define AUDIO_ENABLED 0
#define VSYNC_ENABLED 0
#define VSYNC_ENABLED 1
#define USER_FPS_LIMIT 300

View File

@ -49,6 +49,7 @@ void draw_texture(struct gpu_cmd_store store, struct draw_texture_params params)
cmd.texture.texture = params.texture;
cmd.texture.clip = params.clip;
cmd.texture.tint = params.tint;
cmd.texture.emittance = params.emittance;
gpu_push_cmd(store, cmd);
}

View File

@ -32,6 +32,7 @@ struct draw_texture_params {
struct sprite_tag sprite;
struct clip_rect clip;
u32 tint;
f32 emittance;
};
void draw_texture(struct gpu_cmd_store store, struct draw_texture_params params);

View File

@ -42,16 +42,6 @@ void gpu_texture_clear(struct gpu_texture target_texture, u32 clear_color);
struct v2i32 gpu_texture_get_size(struct gpu_texture texture);
/* ========================== *
* Backbuffer
* ========================== */
/* Returns a texture representing the internal backbuffer. Lifetime is managed by gpu layer. */
struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size);
/* Presents the backbuffer to the screen */
void gpu_swap_backbuffer(i32 vsync);
/* ========================== *
* Cmd buffer
* ========================== */
@ -89,6 +79,7 @@ struct gpu_cmd_params {
struct gpu_texture texture;
struct clip_rect clip;
u32 tint;
f32 emittance;
} texture;
struct {
struct xform xf;
@ -144,4 +135,14 @@ void gpu_pass_state_release(struct gpu_pass_state gpu_pass_state);
void gpu_run_pass(struct gpu_pass_state gpu_pass_state, struct gpu_pass_params params);
/* ========================== *
* Backbuffer
* ========================== */
/* Returns a texture representing the internal backbuffer. Lifetime is managed by gpu layer. */
struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size);
/* Presents the backbuffer to the screen */
void gpu_swap_backbuffer(i32 vsync);
#endif

View File

@ -26,18 +26,21 @@
#pragma comment(lib, "dxguid")
#pragma comment(lib, "d3dcompiler")
#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
# define DX11_SHADER_DEBUG 0
#endif
#define DX11_SWAPCHAIN_FLAGS (DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING | DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)
#define DX11_BACKBUFFER_RECREATION_DELAY (1.0 / 30.0)
#define DX11_WAIT_FRAME_LATENCY 1
#define DX11_ALLOW_TEARING 1
#define DX11_SWAPCHAIN_FLAGS ((DX11_ALLOW_TEARING * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | (DX11_WAIT_FRAME_LATENCY * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
#define DX11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM)
#define DX11_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
@ -61,6 +64,7 @@ struct dx11_shader {
};
struct dx11_pass_state {
struct dx11_texture *albedo;
struct dx11_pass_state *next_free;
};
@ -157,16 +161,12 @@ struct dx11_cmd_store {
struct dx11_cmd_store *next_free;
};
struct dx11_format {
DXGI_FORMAT format;
u32 pixel_size;
};
struct dx11_texture {
ID3D11Texture2D *texture;
ID3D11ShaderResourceView *srv;
ID3D11RenderTargetView *rtv;
b32 is_backbuffer;
struct v2i32 size;
struct dx11_texture *next_free;
};
@ -202,6 +202,7 @@ GLOBAL struct {
IDXGISwapChain2 *swapchain;
HANDLE swapchain_waitable;
struct dx11_texture backbuffer_texture;
i64 last_backbuffer_resize_ns;
ID3D11BlendState *blend_state;
ID3D11RasterizerState *rasterizer_state;
@ -358,12 +359,12 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window)
DXGI_SWAP_CHAIN_DESC1 desc = {
.Format = DX11_SWAPCHAIN_FORMAT,
.SampleDesc = { 1, 0 },
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
.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,
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD
};
IDXGISwapChain1 *swapchain1 = NULL;
@ -393,11 +394,13 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window)
G.backbuffer_texture.is_backbuffer = true;
/* 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");
(UNUSED)prof_ctx_name;
@ -543,6 +546,7 @@ PACK(struct dx11_texture_instance {
struct v2 uv0;
struct v2 uv1;
u32 tint_srgb;
f32 emittance;
});
/* ========================== *
@ -939,6 +943,162 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name)
}
#endif
/* ========================== *
* Texture
* ========================== */
INTERNAL enum DXGI_FORMAT dx11_format_from_gpu_format(enum gpu_texture_format gpu_format)
{
LOCAL_PERSIST const enum DXGI_FORMAT dx11_formats[NUM_GPU_TEXTURE_FORMATS] = {
[GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM] = DXGI_FORMAT_R8G8B8A8_UNORM,
[GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
};
enum DXGI_FORMAT res = DXGI_FORMAT_UNKNOWN;
if ((u32)gpu_format < ARRAY_COUNT(dx11_formats)) {
res = dx11_formats[gpu_format];
}
return res;
}
INTERNAL u32 pixel_size_from_dx11_format(enum DXGI_FORMAT dx11_format)
{
LOCAL_PERSIST const u32 pixel_sizes[] = {
[DXGI_FORMAT_R8G8B8A8_UNORM] = 4,
[DXGI_FORMAT_R8G8B8A8_UNORM_SRGB] = 4
};
u32 res = 0;
if ((u32)dx11_format < ARRAY_COUNT(pixel_sizes)) {
res = pixel_sizes[dx11_format];
}
return res;
}
INTERNAL struct dx11_texture *dx11_texture_alloc(enum DXGI_FORMAT format, u32 flags, struct v2i32 size, void *initial_data)
{
struct dx11_texture *t = NULL;
{
struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex);
if (G.first_free_texture) {
t = G.first_free_texture;
G.first_free_texture = t->next_free;
} else {
t = arena_push_no_zero(&G.textures_arena, struct dx11_texture);
}
sys_mutex_unlock(&lock);
}
MEMZERO_STRUCT(t);
D3D11_TEXTURE2D_DESC desc = ZI;
desc.Width = max_i32(size.x, 1);
desc.Height = max_i32(size.y, 1);
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.BindFlags = flags;
desc.Format = format;
/* Create texture */
ID3D11Texture2D *texture = NULL;
if (initial_data) {
u32 pixel_size = pixel_size_from_dx11_format(format);
D3D11_SUBRESOURCE_DATA subresource_data = { .pSysMem = initial_data, .SysMemPitch = size.x * pixel_size, .SysMemSlicePitch = 0 };
ID3D11Device_CreateTexture2D(G.dev, &desc, &subresource_data, &texture);
} else {
ID3D11Device_CreateTexture2D(G.dev, &desc, NULL, &texture);
}
ASSERT(texture != NULL);
t->texture = texture;
/* Create SRV */
if (t->texture && (flags & D3D11_BIND_SHADER_RESOURCE)) {
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = ZI;
srv_desc.Format = desc.Format;
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MipLevels = desc.MipLevels;
ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)texture, &srv_desc, &t->srv);
}
/* Create RTV */
if (t->texture && (flags & D3D11_BIND_RENDER_TARGET)) {
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &t->rtv);
}
t->size = size;
return t;
}
INTERNAL void dx11_texture_release(struct dx11_texture *t)
{
if (!t->is_backbuffer) {
{
struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex);
t->next_free = G.first_free_texture;
G.first_free_texture = t;
sys_mutex_unlock(&lock);
}
if (t->rtv) {
ID3D11RenderTargetView_Release(t->rtv);
}
if (t->srv) {
ID3D11ShaderResourceView_Release(t->srv);
}
if (t->texture) {
ID3D11Texture2D_Release(t->texture);
}
}
}
struct gpu_texture gpu_texture_alloc(enum gpu_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
{
__prof;
struct gpu_texture res = ZI;
/* Convert format to dx11 format */
enum DXGI_FORMAT dx11_format = dx11_format_from_gpu_format(format);
if (dx11_format == DXGI_FORMAT_UNKNOWN) {
/* Unknown format */
ASSERT(false);
sys_panic(LIT("Unknown dx11 texture format during texture allocation"));
}
/* Convert flags to dx11 flags */
u32 dx11_flags = D3D11_BIND_SHADER_RESOURCE;
if (flags & GPU_TEXTURE_FLAG_TARGETABLE) {
dx11_flags |= D3D11_BIND_RENDER_TARGET;
}
struct dx11_texture *t = dx11_texture_alloc(dx11_format, dx11_flags, size, initial_data);
res.handle = (u64)t;
return res;
}
void gpu_texture_release(struct gpu_texture t)
{
__prof;
dx11_texture_release((struct dx11_texture *)t.handle);
}
void gpu_texture_clear(struct gpu_texture target_texture, u32 clear_color)
{
__prof;
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, t->rtv, fill);
}
}
struct v2i32 gpu_texture_get_size(struct gpu_texture texture)
{
return ((struct dx11_texture *)texture.handle)->size;
}
/* ========================== *
* Dx11 buffer
* ========================== */
@ -1273,6 +1433,7 @@ void gpu_push_cmd(struct gpu_cmd_store gpu_cmd_store, struct gpu_cmd_params para
instance->uv0 = params.texture.clip.p0;
instance->uv1 = params.texture.clip.p1;
instance->tint_srgb = params.texture.tint;
instance->emittance = params.texture.emittance;
} break;
case GPU_CMD_KIND_DRAW_GRID:
@ -1474,15 +1635,11 @@ void gpu_run_pass(struct gpu_pass_state gpu_pass_state, struct gpu_pass_params p
__prof;
__profscope_dx11(G.profiling_ctx, Run pass, RGB_F(0.5, 0.2, 0.2));
struct sprite_scope *sprite_scope = sprite_scope_begin();
struct dx11_pass_state *pass_state = (struct dx11_pass_state *)gpu_pass_state.handle;
(UNUSED)pass_state;
struct dx11_pass_state *state = (struct dx11_pass_state *)gpu_pass_state.handle;
struct dx11_texture *draw_target = (struct dx11_texture *)params.draw_target.handle;
struct rect viewport = params.draw_target_viewport;
/* Set render targets */
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &draw_target->rtv, NULL);
/* Set viewport */
D3D11_VIEWPORT d3d11_viewport = ZI;
d3d11_viewport.Width = viewport.width;
d3d11_viewport.Height = viewport.height;
@ -1493,92 +1650,252 @@ void gpu_run_pass(struct gpu_pass_state gpu_pass_state, struct gpu_pass_params p
ID3D11DeviceContext_RSSetViewports(G.devcon, 1, &d3d11_viewport);
struct mat4x4 vp_matrix = calculate_vp(XFORM_IDENT, viewport.width, viewport.height);
for (u64 cmd_stores_array_index = 0; cmd_stores_array_index < params.cmds_array.count; ++cmd_stores_array_index) {
struct dx11_cmd_store *store = (struct dx11_cmd_store *)params.cmds_array.cmds[cmd_stores_array_index]->handle;
for (struct dx11_cmd *cmd = store->gpu_first_cmd; cmd; cmd = cmd->next) {
enum gpu_cmd_kind cmd_kind = cmd->kind;
switch (cmd_kind) {
default:
{
/* Unknown cmd kind */
ASSERT(false);
} break;
#if 0
/* GI pass */
{
__profscope(GI pass);
__profscope_dx11(G.profiling_ctx, GI pass, RGB_F(0.5, 0.5, 0.5));
for (u64 cmd_stores_array_index = 0; cmd_stores_array_index < params.cmds_array.count; ++cmd_stores_array_index) {
struct dx11_cmd_store *store = (struct dx11_cmd_store *)params.cmds_array.cmds[cmd_stores_array_index]->handle;
for (struct dx11_cmd *cmd = store->gpu_first_cmd; cmd; cmd = cmd->next) {
enum gpu_cmd_kind cmd_kind = cmd->kind;
case GPU_CMD_KIND_DRAW_VIEW:
{
__profscope(Set draw view);
vp_matrix = calculate_vp(cmd->view.xf, viewport.width, viewport.height);
} break;
switch (cmd_kind) {
default: break;
case GPU_CMD_KIND_DRAW_MESH:
{
__profscope(Draw mesh);
__profscope_dx11(G.profiling_ctx, Draw mesh, RGB_F(0.5, 0.2, 0.2));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_MESH];
if (shader->valid) {
struct dx11_buffer *constant_buffer = store->buffers.constant_buffer;
struct dx11_buffer *vertex_buffer = store->buffers.mesh.vertex_buffer;
struct dx11_buffer *index_buffer = store->buffers.mesh.index_buffer;
case GPU_CMD_KIND_DRAW_VIEW:
{
__profscope(Set draw view);
vp_matrix = calculate_vp(cmd->view.xf, viewport.width, viewport.height);
} break;
u32 vertex_offset = cmd->mesh.vertex_offset;
u32 index_offset = cmd->mesh.index_offset;
u32 index_count = cmd->mesh.index_count;
case GPU_CMD_KIND_DRAW_TEXTURE:
{
__profscope(Draw texture emittance);
__profscope_dx11(G.profiling_ctx, Draw texture emittance, RGB_F(0.2, 0.5, 0.2));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE];
if (shader->valid) {
struct dx11_texture *texture = NULL;
if (cmd->texture.texture.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;
}
}
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
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 input layout */
ID3D11DeviceContext_IASetInputLayout(G.devcon, shader->input_layout);
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
/* Fill & bind constant buffer */
{
struct dx11_mesh_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_mesh_uniform));
uniform->vp = vp_matrix;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Fill & bind constant buffer */
{
struct dx11_texture_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_texture_uniform));
uniform->vp = vp_matrix;
uniform->instance_offset = instance_offset;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind vertex buffer */
u32 zero = 0;
u32 stride = sizeof(struct dx11_mesh_vertex);
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &vertex_buffer->gpu_buffer, &stride, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* 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);
/* Draw */
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset);
/* Bind instance buffer */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
/* Unbind */
dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_IA | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF);
}
} break;
/* Bind texture */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 1, 1, &texture->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 1, 1, &texture->srv);
case GPU_CMD_KIND_DRAW_TEXTURE:
{
__profscope(Draw texture);
__profscope_dx11(G.profiling_ctx, Draw texture, RGB_F(0.2, 0.5, 0.2));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE];
if (shader->valid) {
struct dx11_texture *texture = NULL;
if (cmd->texture.texture.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;
/* Bind RTV */
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &draw_target->rtv, 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;
}
}
}
}
#endif
if (texture && texture->srv && shader->valid) {
struct dx11_texture *final_tex = (struct dx11_texture *)params.draw_target.handle;
struct v2i32 final_tex_size = final_tex->size;
/* Allocate / resize albedo */
struct dx11_texture *albedo_tex = state->albedo;
if (!albedo_tex || !v2i32_eq(albedo_tex->size, final_tex->size)) {
if (albedo_tex) {
dx11_texture_release(albedo_tex);
}
albedo_tex = dx11_texture_alloc(DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, final_tex_size, NULL);
state->albedo = albedo_tex;
}
/* Regular pass */
{
__profscope(Regular pass);
__profscope_dx11(G.profiling_ctx, Regular pass, RGB_F(0.2, 0.5, 0.5));
for (u64 cmd_stores_array_index = 0; cmd_stores_array_index < params.cmds_array.count; ++cmd_stores_array_index) {
struct dx11_cmd_store *store = (struct dx11_cmd_store *)params.cmds_array.cmds[cmd_stores_array_index]->handle;
for (struct dx11_cmd *cmd = store->gpu_first_cmd; cmd; cmd = cmd->next) {
enum gpu_cmd_kind cmd_kind = cmd->kind;
switch (cmd_kind) {
default:
{
/* Unknown cmd kind */
ASSERT(false);
} break;
case GPU_CMD_KIND_DRAW_VIEW:
{
__profscope(Set draw view);
vp_matrix = calculate_vp(cmd->view.xf, viewport.width, viewport.height);
} break;
case GPU_CMD_KIND_DRAW_MESH:
{
__profscope(Draw mesh);
__profscope_dx11(G.profiling_ctx, Draw mesh, RGB_F(0.5, 0.2, 0.2));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_MESH];
if (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;
struct dx11_buffer *vertex_buffer = store->buffers.mesh.vertex_buffer;
struct dx11_buffer *index_buffer = store->buffers.mesh.index_buffer;
u32 vertex_offset = cmd->mesh.vertex_offset;
u32 index_offset = cmd->mesh.index_offset;
u32 index_count = cmd->mesh.index_count;
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
/* Bind input layout */
ID3D11DeviceContext_IASetInputLayout(G.devcon, shader->input_layout);
/* Fill & bind constant buffer */
{
struct dx11_mesh_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_mesh_uniform));
uniform->vp = vp_matrix;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind vertex buffer */
u32 zero = 0;
u32 stride = sizeof(struct dx11_mesh_vertex);
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &vertex_buffer->gpu_buffer, &stride, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* Bind RTV */
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &final_tex->rtv, NULL);
/* Draw */
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset);
/* Unbind */
dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_IA | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_RTV);
}
} break;
case GPU_CMD_KIND_DRAW_TEXTURE:
{
__profscope(Draw texture);
__profscope_dx11(G.profiling_ctx, Draw texture, RGB_F(0.2, 0.5, 0.2));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEXTURE];
if (shader->valid) {
struct dx11_texture *texture = NULL;
if (cmd->texture.texture.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 (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);
/* Fill & bind constant buffer */
{
struct dx11_texture_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_texture_uniform));
uniform->vp = vp_matrix;
uniform->instance_offset = instance_offset;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind dummy vertex buffer */
u32 zero = 0;
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* Bind instance buffer */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
/* Bind texture */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 1, 1, &texture->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 1, 1, &texture->srv);
/* Bind RTV */
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &final_tex->rtv, NULL);
/* Draw */
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_DrawIndexedInstanced(G.devcon, 6, instance_count, 0, 0, 0);
/* Unbind */
dx11_unbind(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV);
}
}
} break;
case GPU_CMD_KIND_DRAW_GRID:
{
__profscope(Draw grid);
__profscope_dx11(G.profiling_ctx, Draw grid, RGB_F(0.2, 0.2, 0.5));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID];
if (shader->valid) {
struct dx11_buffer *constant_buffer = store->buffers.constant_buffer;
struct dx11_buffer *instance_buffer = store->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);
@ -1586,7 +1903,7 @@ void gpu_run_pass(struct gpu_pass_state gpu_pass_state, struct gpu_pass_params p
/* Fill & bind constant buffer */
{
struct dx11_texture_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_texture_uniform));
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);
@ -1603,268 +1920,71 @@ void gpu_run_pass(struct gpu_pass_state gpu_pass_state, struct gpu_pass_params p
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
/* Bind texture */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 1, 1, &texture->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 1, 1, &texture->srv);
/* Bind RTV */
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &final_tex->rtv, 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(DX11_UNBIND_VS | DX11_UNBIND_PS | DX11_UNBIND_CBUFF | DX11_UNBIND_VBUFF | DX11_UNBIND_IBUFF | DX11_UNBIND_SRV | DX11_UNBIND_RTV);
}
}
} break;
} break;
case GPU_CMD_KIND_DRAW_GRID:
{
__profscope(Draw grid);
__profscope_dx11(G.profiling_ctx, Draw grid, RGB_F(0.2, 0.2, 0.5));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_GRID];
if (shader->valid) {
struct dx11_buffer *constant_buffer = store->buffers.constant_buffer;
struct dx11_buffer *instance_buffer = store->buffers.grid.instance_buffer;
u32 instance_offset = cmd->grid.instance_offset;
u32 instance_count = cmd->grid.instance_count;
case GPU_CMD_KIND_TEST:
{
__profscope(Test);
__profscope_dx11(G.profiling_ctx, Test, RGB_F(1, 0.2, 1));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEST];
if (shader->valid) {
struct dx11_buffer *constant_buffer = store->buffers.constant_buffer;
struct dx11_buffer *instance_buffer = store->buffers.test.instance_buffer;
u32 instance_offset = cmd->test.instance_offset;
u32 instance_count = cmd->test.instance_count;
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
/* 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);
/* Fill & bind constant buffer */
{
struct dx11_test_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_test_uniform));
uniform->vp = vp_matrix;
uniform->instance_offset = instance_offset;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind dummy vertex buffer */
u32 zero = 0;
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* Bind instance buffer */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
/* Bind RTV */
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &final_tex->rtv, 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);
}
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 instance buffer */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
/* 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);
}
} break;
case GPU_CMD_KIND_TEST:
{
__profscope(Test);
__profscope_dx11(G.profiling_ctx, Test, RGB_F(1, 0.2, 1));
struct dx11_shader *shader = &G.shaders[DX11_SHADER_KIND_TEST];
if (shader->valid) {
struct dx11_buffer *constant_buffer = store->buffers.constant_buffer;
struct dx11_buffer *instance_buffer = store->buffers.test.instance_buffer;
u32 instance_offset = cmd->test.instance_offset;
u32 instance_count = cmd->test.instance_count;
/* Bind shader */
ID3D11DeviceContext_VSSetShader(G.devcon, shader->vs, 0, 0);
ID3D11DeviceContext_PSSetShader(G.devcon, shader->ps, 0, 0);
/* Fill & bind constant buffer */
{
struct dx11_test_uniform *uniform = dx11_buffer_push(constant_buffer, sizeof(struct dx11_test_uniform));
uniform->vp = vp_matrix;
uniform->instance_offset = instance_offset;
dx11_buffer_submit(constant_buffer);
}
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
ID3D11DeviceContext_PSSetConstantBuffers(G.devcon, 0, 1, &constant_buffer->gpu_buffer);
/* Bind dummy vertex buffer */
u32 zero = 0;
ID3D11DeviceContext_IASetVertexBuffers(G.devcon, 0, 1, &G.dummy_vertex_buffer->gpu_buffer, &zero, &zero);
ID3D11DeviceContext_IASetIndexBuffer(G.devcon, G.quad_index_buffer->gpu_buffer, DXGI_FORMAT_R16_UINT, zero);
/* Bind instance buffer */
ID3D11DeviceContext_VSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &instance_buffer->srv);
/* 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);
}
} break;
} break;
}
}
}
}
/* Unbind render target */
dx11_unbind(DX11_UNBIND_RTV);
sprite_scope_end(sprite_scope);
}
/* ========================== *
* Texture
* ========================== */
INTERNAL struct dx11_format dx11_format_from_gpu_format(enum gpu_texture_format format)
{
LOCAL_PERSIST struct dx11_format dx11_formats[NUM_GPU_TEXTURE_FORMATS] = {
[GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM] = {
.format = DXGI_FORMAT_R8G8B8A8_UNORM,
.pixel_size = 4
},
[GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB] = {
.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
.pixel_size = 4
}
};
struct dx11_format res = ZI;
if ((u32)format < ARRAY_COUNT(dx11_formats)) {
res = dx11_formats[format];
}
return res;
}
INTERNAL struct dx11_texture *dx11_texture_alloc(struct dx11_format format, u32 flags, struct v2i32 size, void *initial_data)
{
struct dx11_texture *t = NULL;
{
struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex);
if (G.first_free_texture) {
t = G.first_free_texture;
G.first_free_texture = t->next_free;
} else {
t = arena_push_no_zero(&G.textures_arena, struct dx11_texture);
}
sys_mutex_unlock(&lock);
}
MEMZERO_STRUCT(t);
D3D11_TEXTURE2D_DESC desc = ZI;
desc.Width = max_i32(size.x, 1);
desc.Height = max_i32(size.y, 1);
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.BindFlags = flags;
desc.Format = format.format;
/* Create texture */
ID3D11Texture2D *texture = NULL;
if (initial_data) {
D3D11_SUBRESOURCE_DATA subresource_data = { .pSysMem = initial_data, .SysMemPitch = size.x * format.pixel_size, .SysMemSlicePitch = 0 };
ID3D11Device_CreateTexture2D(G.dev, &desc, &subresource_data, &texture);
} else {
ID3D11Device_CreateTexture2D(G.dev, &desc, NULL, &texture);
}
ASSERT(texture != NULL);
t->texture = texture;
/* Create SRV */
if (t->texture && (flags & D3D11_BIND_SHADER_RESOURCE)) {
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = ZI;
srv_desc.Format = desc.Format;
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MipLevels = desc.MipLevels;
ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)texture, &srv_desc, &t->srv);
}
/* Create RTV */
if (t->texture && (flags & D3D11_BIND_RENDER_TARGET)) {
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &t->rtv);
}
return t;
}
INTERNAL void dx11_texture_release(struct dx11_texture *t)
{
if (!t->is_backbuffer) {
{
struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex);
t->next_free = G.first_free_texture;
G.first_free_texture = t;
sys_mutex_unlock(&lock);
}
if (t->rtv) {
ID3D11RenderTargetView_Release(t->rtv);
}
if (t->srv) {
ID3D11ShaderResourceView_Release(t->srv);
}
if (t->texture) {
ID3D11Texture2D_Release(t->texture);
}
}
}
struct gpu_texture gpu_texture_alloc(enum gpu_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
{
__prof;
struct gpu_texture res = ZI;
/* Convert format to dx11 format */
struct dx11_format dx11_format = dx11_format_from_gpu_format(format);
if (dx11_format.format == DXGI_FORMAT_UNKNOWN) {
/* Unknown format */
ASSERT(false);
sys_panic(LIT("Unknown dx11 texture format during texture allocation"));
}
/* Convert flags to dx11 flags */
u32 dx11_flags = D3D11_BIND_SHADER_RESOURCE;
if (flags & GPU_TEXTURE_FLAG_TARGETABLE) {
dx11_flags |= D3D11_BIND_RENDER_TARGET;
}
struct dx11_texture *t = dx11_texture_alloc(dx11_format, dx11_flags, size, initial_data);
res.handle = (u64)t;
return res;
}
void gpu_texture_release(struct gpu_texture t)
{
__prof;
dx11_texture_release((struct dx11_texture *)t.handle);
}
void gpu_texture_clear(struct gpu_texture target_texture, u32 clear_color)
{
__prof;
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, t->rtv, fill);
}
}
struct v2i32 gpu_texture_get_size(struct gpu_texture texture)
{
struct v2i32 res = ZI;
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D_GetDesc(((struct dx11_texture *)texture.handle)->texture, &desc);
res.x = desc.Width;
res.y = desc.Height;
return res;
}
/* ========================== *
* Backbuffer
* ========================== */
@ -1911,6 +2031,20 @@ struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size)
{
struct gpu_texture res = ZI;
/* Delay backbuffer recreation so that we don't recreate it too quickly.
* It seems that doing this without a delay too often will cause windows
* to eventually just display a blackscreen rather than the backbuffer
* (e.g. when resizing for more than a few seconds). */
i64 now_ns = sys_time_ns();
if (G.last_backbuffer_resize_ns != 0) {
i64 next_resize_ns = G.last_backbuffer_resize_ns + NS_FROM_SECONDS(DX11_BACKBUFFER_RECREATION_DELAY);
if (now_ns < next_resize_ns) {
sys_sleep_precise(SECONDS_FROM_NS(next_resize_ns - now_ns));
now_ns = sys_time_ns();
}
}
G.last_backbuffer_resize_ns = now_ns;
/* Release */
if (G.backbuffer_texture.texture != 0) {
ID3D11RenderTargetView_Release(G.backbuffer_texture.rtv);
@ -1920,6 +2054,7 @@ struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size)
/* Resize */
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, size.x, size.y, DXGI_FORMAT_UNKNOWN, DX11_SWAPCHAIN_FLAGS);
IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&G.backbuffer_texture.texture);
G.backbuffer_texture.size = size;
/* Create rtv */
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = ZI;
@ -1982,7 +2117,9 @@ void gpu_swap_backbuffer(i32 vsync)
WaitForSingleObjectEx(G.swapchain_waitable, 1000, TRUE);
}
} else {
#if DX11_ALLOW_TEARING
flags = DXGI_PRESENT_ALLOW_TEARING;
#endif
}
gpu_capture_image_for_profiler();

View File

@ -145,10 +145,11 @@ enum sim_control_flag {
SIM_CONTROL_FLAG_SPAWN1_TEST = 1 << 5,
SIM_CONTROL_FLAG_SPAWN2_TEST = 1 << 6,
SIM_CONTROL_FLAG_SPAWN3_TEST = 1 << 7,
SIM_CONTROL_FLAG_WALLS_TEST = 1 << 8,
SIM_CONTROL_FLAG_TILE_TEST = 1 << 9,
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 10,
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 11,
SIM_CONTROL_FLAG_SPAWN4_TEST = 1 << 8,
SIM_CONTROL_FLAG_WALLS_TEST = 1 << 9,
SIM_CONTROL_FLAG_TILE_TEST = 1 << 10,
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 11,
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 12,
};
struct sim_control {

View File

@ -66,6 +66,7 @@ enum sim_ent_prop {
SEPROP_TEST,
SEPROP_TEST_SOUND_EMITTER,
SEPROP_LIGHT_TEST,
SEPROP_COUNT
};

View File

@ -327,6 +327,26 @@ INTERNAL void test_spawn_entities3(struct sim_ent *parent, struct v2 pos)
}
}
INTERNAL void test_spawn_entities4(struct sim_ent *parent, struct v2 pos)
{
(UNUSED)pos;
/* Light box */
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
f32 r = 0;
struct v2 size = V2(2, 1);
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
sim_ent_set_xform(e, xf);
e->sprite = sprite_tag_from_path(LIT("sprites/box.ase"));
e->layer = SIM_LAYER_SHOULDERS;
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
e->sprite_tint = RGB_F(1, 0, 1);
}
INTERNAL void test_spawn_tile(struct sim_snapshot *world, struct v2 world_pos)
{
#if 0
@ -1026,6 +1046,16 @@ void sim_step(struct sim_step_ctx *ctx)
test_spawn_entities3(root, pos);
}
}
if (flags & SIM_CONTROL_FLAG_SPAWN4_TEST) {
logf_debug("Spawn test 4");
u32 count = 1;
f32 spread = 0;
for (u32 j = 0; j < count; ++j) {
struct v2 pos = player->player_cursor_pos;
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
test_spawn_entities4(root, pos);
}
}
if (flags & SIM_CONTROL_FLAG_WALLS_TEST) {
test_generate_walls(world);
}

View File

@ -174,6 +174,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
[SYS_BTN_1] = USER_BIND_KIND_DEBUG_SPAWN1,
[SYS_BTN_2] = USER_BIND_KIND_DEBUG_SPAWN2,
[SYS_BTN_3] = USER_BIND_KIND_DEBUG_SPAWN3,
[SYS_BTN_4] = USER_BIND_KIND_DEBUG_SPAWN4,
[SYS_BTN_G] = USER_BIND_KIND_DEBUG_WALLS,
[SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP,
[SYS_BTN_Q] = USER_BIND_KIND_DEBUG_FOLLOW,
@ -596,6 +597,12 @@ INTERNAL SORT_COMPARE_FUNC_DEF(ent_draw_order_cmp, arg_a, arg_b, udata)
i32 res = 0;
if (res == 0) {
/* Sort by light */
b32 a_cmp = sim_ent_has_prop(a, SEPROP_LIGHT_TEST);
b32 b_cmp = sim_ent_has_prop(b, SEPROP_LIGHT_TEST);
res = (a_cmp > b_cmp) - (a_cmp < b_cmp);
}
if (res == 0) {
/* Sort by layer */
i32 a_cmp = a->layer;
@ -1272,9 +1279,11 @@ INTERNAL void user_update(void)
/* TODO: Fade in placeholder if texture isn't loaded */
if (sheet->loaded) {
b32 is_light = sim_ent_has_prop(ent, SEPROP_LIGHT_TEST);
f32 emittance = is_light ? 1.0 : 0.0;
u32 tint = ent->sprite_tint;
struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = sprite_xform, .sprite = sprite, .tint = tint, .clip = frame.clip);
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = sprite_xform, .sprite = sprite, .tint = tint, .clip = frame.clip, .emittance = emittance);
draw_texture(G.world_gpu_cmd_store, params);
}
}
@ -1823,6 +1832,7 @@ INTERNAL void user_update(void)
struct bind_state spawn1_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN1];
struct bind_state spawn2_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN2];
struct bind_state spawn3_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN3];
struct bind_state spawn4_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN4];
struct bind_state walls_state = G.bind_states[USER_BIND_KIND_DEBUG_WALLS];
struct bind_state pause_state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
@ -1854,6 +1864,9 @@ INTERNAL void user_update(void)
if (spawn3_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_SPAWN3_TEST;
}
if (spawn4_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_SPAWN4_TEST;
}
if (walls_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_WALLS_TEST;
}

View File

@ -32,6 +32,7 @@ enum user_bind_kind {
USER_BIND_KIND_DEBUG_SPAWN1,
USER_BIND_KIND_DEBUG_SPAWN2,
USER_BIND_KIND_DEBUG_SPAWN3,
USER_BIND_KIND_DEBUG_SPAWN4,
USER_BIND_KIND_DEBUG_WALLS,
USER_BIND_KIND_DEBUG_FOLLOW,
USER_BIND_KIND_DEBUG_DRAW,