diff --git a/build.c b/build.c index 56f613cb..cd7b5906 100644 --- a/build.c +++ b/build.c @@ -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); } } diff --git a/res/shaders/texture.hlsl b/res/shaders/texture.hlsl index 5f054343..18e0c717 100644 --- a/res/shaders/texture.hlsl +++ b/res/shaders/texture.hlsl @@ -5,6 +5,7 @@ struct vs_instance { float2 uv0; float2 uv1; uint tint_srgb; + float emittance; }; struct ps_input { diff --git a/src/config.h b/src/config.h index e3bee223..910c37b2 100644 --- a/src/config.h +++ b/src/config.h @@ -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 diff --git a/src/draw.c b/src/draw.c index 2ec4124a..ec59cc9b 100644 --- a/src/draw.c +++ b/src/draw.c @@ -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); } diff --git a/src/draw.h b/src/draw.h index c511f260..1948460d 100644 --- a/src/draw.h +++ b/src/draw.h @@ -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); diff --git a/src/gpu.h b/src/gpu.h index 2932f9f1..e639b24e 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -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 diff --git a/src/gpu_dx11.c b/src/gpu_dx11.c index 9b3b0813..51bca839 100644 --- a/src/gpu_dx11.c +++ b/src/gpu_dx11.c @@ -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(); diff --git a/src/sim.h b/src/sim.h index 119324f8..96078aa6 100644 --- a/src/sim.h +++ b/src/sim.h @@ -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 { diff --git a/src/sim_ent.h b/src/sim_ent.h index 6fe3f1d9..d4fc037f 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -66,6 +66,7 @@ enum sim_ent_prop { SEPROP_TEST, SEPROP_TEST_SOUND_EMITTER, + SEPROP_LIGHT_TEST, SEPROP_COUNT }; diff --git a/src/sim_step.c b/src/sim_step.c index c776cf84..ae861323 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -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); } diff --git a/src/user.c b/src/user.c index c84c57ee..38fe0303 100644 --- a/src/user.c +++ b/src/user.c @@ -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; } diff --git a/src/user.h b/src/user.h index ec1a989b..3b9c911f 100644 --- a/src/user.h +++ b/src/user.h @@ -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,