From 201d0c2bf0d2a3c8719ca4a74a06bb04aecf5f5b Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 2 Feb 2026 22:29:14 -0600 Subject: [PATCH] fix oob resource access during composition pass --- src/base/base_async.c | 1 - src/base/base_crum.c | 1 - src/base/base_math.c | 1 - src/base/base_resource.c | 1 - src/base/base_shader.gh | 81 +- src/base/base_string.h | 1 - src/glyph_cache/glyph_cache.c | 1 + src/gpu/gpu_core.h | 4 + src/gpu/gpu_dx12/gpu_dx12_core.c | 336 +++++--- src/gpu/gpu_dx12/gpu_dx12_core.h | 13 +- src/meta/meta.c | 2 + src/net/net_win32/net_win32.c | 1 - src/platform/platform_win32/platform_win32.c | 1 - src/pp/pp_vis/pp_vis_core.c | 63 +- src/pp/pp_vis/pp_vis_gpu.g | 850 ++++++++----------- src/sprite/sprite.c | 1 + src/ttf/ttf_dwrite/ttf_dwrite.h | 1 - src/ui/ui_core.c | 15 +- 18 files changed, 669 insertions(+), 705 deletions(-) diff --git a/src/base/base_async.c b/src/base/base_async.c index 639b3099..12db3ce8 100644 --- a/src/base/base_async.c +++ b/src/base/base_async.c @@ -81,7 +81,6 @@ void AsyncWorkerEntryPoint(WaveLaneCtx *lane) } } - WaveSync(lane); ////////////////////////////// diff --git a/src/base/base_crum.c b/src/base/base_crum.c index 9cec3800..f80a6db3 100644 --- a/src/base/base_crum.c +++ b/src/base/base_crum.c @@ -439,7 +439,6 @@ CR_Item *CR_ItemFromString(Arena *arena, String str) } } - EndScratch(scratch); return result; } diff --git a/src/base/base_math.c b/src/base/base_math.c index ebb11a39..cdfef495 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -29,7 +29,6 @@ u64 ClampU64(u64 v, u64 min, u64 max) { return v < min ? min : v > max ? max : v i64 ClampI64(i64 v, i64 min, i64 max) { return v < min ? min : v > max ? max : v; } f64 ClampF64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; } - //- Saturate u32 SaturateU32(u32 v) { return v < 0 ? 0 : v > 1 ? 1 : v; } i32 SaturateI32(i32 v) { return v < 0 ? 0 : v > 1 ? 1 : v; } diff --git a/src/base/base_resource.c b/src/base/base_resource.c index f538c46a..d21ed9a2 100644 --- a/src/base/base_resource.c +++ b/src/base/base_resource.c @@ -39,7 +39,6 @@ void BootstrapResources(u64 archive_strings_count, String *archive_strings) } } - //////////////////////////////////////////////////////////// //~ Resource ops diff --git a/src/base/base_shader.gh b/src/base/base_shader.gh index 2b52504c..9d2f3f47 100644 --- a/src/base/base_shader.gh +++ b/src/base/base_shader.gh @@ -49,66 +49,65 @@ u32 countof(T arr[N]) //~ C -> HLSL interoperability stubs //- Min -#define MinU8 min -#define MinI8 min -#define MinU32 min -#define MinI32 min -#define MinF32 min -#define MinU64 min -#define MinI64 min -#define MinF64 min +#define MinU8 (u8)min +#define MinI8 (i8)min +#define MinU32 (u32)min +#define MinI32 (i32)min +#define MinF32 (f32)min +#define MinU64 (u64)min +#define MinI64 (i64)min +#define MinF64 (f64)min //- Max -#define MaxU8 max -#define MaxI8 max -#define MaxU32 max -#define MaxI32 max -#define MaxF32 max -#define MaxU64 max -#define MaxI64 max -#define MaxF64 max +#define MaxU8 (u8)max +#define MaxI8 (i8)max +#define MaxU32 (u32)max +#define MaxI32 (i32)max +#define MaxF32 (f32)max +#define MaxU64 (u64)max +#define MaxI64 (i64)max +#define MaxF64 (f64)max //- Clamp -#define ClampU32 clamp -#define ClampI32 clamp -#define ClampF32 clamp -#define ClampU64 clamp -#define ClampI64 clamp -#define ClampF64 clamp +#define ClampU32 (u32)clamp +#define ClampI32 (i32)clamp +#define ClampF32 (f32)clamp +#define ClampU64 (u64)clamp +#define ClampI64 (i64)clamp +#define ClampF64 (f64)clamp //- Round -#define RoundF32 round -#define RoundF64 round +#define RoundF32 (f32)round +#define RoundF64 (f64)round //- Floor -#define FloorF32 floor -#define FloorF64 floor +#define FloorF32 (f32)floor +#define FloorF64 (f64)floor //- Ceil -#define CeilF32 ceil -#define CeilF64 ceil +#define CeilF32 (f32)ceil +#define CeilF64 (f64)ceil //- Trunc -#define TruncF32 trunc -#define TruncF64 trunc +#define TruncF32 (f32)trunc +#define TruncF64 (f64)trunc //- Mod -#define ModF32 fmod -#define ModF64 fmod +#define ModF32 (f32)fmod +#define ModF64 (f64)fmod //- Abs -#define AbsF32 abs -#define AbsF64 abs +#define AbsF32 (f32)abs +#define AbsF64 (f64)abs //- Sign -#define SignF32 sign -#define SignF64 sign +#define SignF32 (f32)sign +#define SignF64 (f64)sign //- Smoothstep -#define SmoothstepF32 smoothstep -#define SmoothstepF64 smoothstep +#define SmoothstepF32 (f32)smoothstep +#define SmoothstepF64 (f64)smoothstep -//- Matchfloor #define MatchFloor(a, b) all(floor(a) == floor(b)) //////////////////////////////////////////////////////////// @@ -166,12 +165,12 @@ Inline Vec4 LinearFromSrgb(Vec4 srgb) Inline f32 LuminanceFromColor(Vec4 v) { return 0.2126 * v.r + 0.7152 * v.g + 0.0722 * v.b; -}; +} Inline Vec4 InvertColor(Vec4 v) { return Vec4(Vec3(1, 1, 1) - v.rgb, v.a); -}; +} Inline Vec4 Premul(Vec4 v) { diff --git a/src/base/base_string.h b/src/base/base_string.h index 55213546..4488ccc0 100644 --- a/src/base/base_string.h +++ b/src/base/base_string.h @@ -132,7 +132,6 @@ String StringFromList(Arena *arena, StringList l, String separator); #define FmtChar(v, ...) FMTARG(FmtArgKind_Char, .value.c = (v), __VA_ARGS__) #define FmtString(v, ...) FMTARG(FmtArgKind_String, .value.string = (v), __VA_ARGS__) - #define FmtUint(v, ...) FMTARG(FmtArgKind_Uint, .value.uints = VEC4U64((v), 0, 0, 0), __VA_ARGS__) #define FmtUint2(v, ...) FMTARG(FmtArgKind_Uint2, .value.uints = VEC4U64((v).x, (v).y, 0, 0), __VA_ARGS__) #define FmtUint3(v, ...) FMTARG(FmtArgKind_Uint3, .value.uints = VEC4U64((v).x, (v).y, (v).z, 0), __VA_ARGS__) diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index da456c01..995ccd75 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -317,6 +317,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame) G_Format_R8G8B8A8_Unorm_Srgb, atlas->dims, G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, + .debug = Lit("Glyph atlas") ); atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex); } diff --git a/src/gpu/gpu_core.h b/src/gpu/gpu_core.h index f9a8e3b9..62adadd2 100644 --- a/src/gpu/gpu_core.h +++ b/src/gpu/gpu_core.h @@ -415,12 +415,14 @@ Enum(G_ResourceFlag) G_ResourceFlag_ZeroMemory = (1 << 3), G_ResourceFlag_HostMemory = (1 << 4), // Resource will be mapped into the cpu's address space G_ResourceFlag_Uncached = (1 << 5), // Cpu writes will be combined & reads will be uncached + G_ResourceFlag_ForceNoReuse = (1 << 6), }; Struct(G_BufferDesc) { G_ResourceFlag flags; u64 size; + String debug; }; Struct(G_TextureDesc) @@ -431,6 +433,7 @@ Struct(G_TextureDesc) G_Layout initial_layout; i32 mip_levels; // Will be clamped to range [1, inf) Vec4 clear_color; + String debug; }; Struct(G_SamplerDesc) @@ -446,6 +449,7 @@ Struct(G_SamplerDesc) Vec4 border_color; f32 min_lod; f32 max_lod; + String debug; }; Struct(G_ResourceDesc) diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index 7e081408..e830a05b 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -450,6 +450,34 @@ D3D12_BARRIER_LAYOUT G_D12_BarrierLayoutFromLayout(G_Layout layout) return result; }; +void G_D12_SetObjectName(ID3D12Object *object, String name) +{ + TempArena scratch = BeginScratchNoConflict(); + { + wchar_t *name_wstr = WstrFromString(scratch.arena, name); + ID3D12Resource_SetName(object, name_wstr); + } + EndScratch(scratch); +} + +String G_D12_NameFromObject(Arena *arena, ID3D12Object *object) +{ + String result = Zi; + { + wchar_t dbg_text[G_D12_MaxDebugTextLen] = Zi; + u32 dbg_text_sz = sizeof(dbg_text); + ID3D12Object_GetPrivateData(object, &WKPDID_D3DDebugObjectNameW, &dbg_text_sz, dbg_text); + if (dbg_text_sz > 2) + { + String16 str16 = Zi; + str16.len = (dbg_text_sz / 2) - 1; + str16.text = dbg_text; + result = StringFromString16(arena, str16); + } + } + return result; +} + //////////////////////////////////////////////////////////// //~ Pipeline @@ -497,163 +525,197 @@ G_D12_Pipeline *G_D12_PipelineFromDesc(G_D12_PipelineDesc desc) // Create pipeline if (is_pipeline_new) { + TempArena scratch = BeginScratchNoConflict(); HRESULT hr = 0; b32 ok = 1; String error_str = Zi; + b32 is_compute = IsResourceNil(desc.vs.resource) || IsResourceNil(desc.ps.resource); + + String pipeline_name = Zi; + if (is_compute) + { + pipeline_name = StringF( + scratch.arena, + "%F%F", + FmtHandle(desc.cs.resource.v), + FmtString(NameFromResource(desc.cs.resource)) + ); + } + else + { + pipeline_name = StringF( + scratch.arena, + "%F%F-%F%F", + FmtHandle(desc.vs.resource.v), + FmtString(NameFromResource(desc.vs.resource)), + FmtHandle(desc.ps.resource.v), + FmtString(NameFromResource(desc.ps.resource)) + ); + } // Create PSO ID3D12PipelineState *pso = 0; - if (ok && (!IsResourceNil(desc.vs.resource) || !IsResourceNil(desc.ps.resource))) + if (ok) { - i32 rts_count = 0; - b32 has_multiple_blend_modes = 0; + if (!is_compute) { - G_BlendMode last_blend_mode = 0; - for (i32 rt_idx = 0; rt_idx < countof(desc.render_target_formats); ++rt_idx) + i32 rts_count = 0; + b32 has_multiple_blend_modes = 0; { - G_BlendMode blend_mode = desc.render_target_blend_modes[rt_idx]; - DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(desc.render_target_formats[rt_idx]); - if (format == DXGI_FORMAT_UNKNOWN) + G_BlendMode last_blend_mode = 0; + for (i32 rt_idx = 0; rt_idx < countof(desc.render_target_formats); ++rt_idx) { - break; + G_BlendMode blend_mode = desc.render_target_blend_modes[rt_idx]; + DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(desc.render_target_formats[rt_idx]); + if (format == DXGI_FORMAT_UNKNOWN) + { + break; + } + else + { + if (rt_idx > 0 && blend_mode != last_blend_mode) + { + has_multiple_blend_modes = 1; + } + last_blend_mode = blend_mode; + rts_count += 1; + } + } + } + + D3D12_RASTERIZER_DESC raster_desc = Zi; + { + if (desc.is_wireframe) + { + raster_desc.FillMode = D3D12_FILL_MODE_WIREFRAME; } else { - if (rt_idx > 0 && blend_mode != last_blend_mode) - { - has_multiple_blend_modes = 1; - } - last_blend_mode = blend_mode; - rts_count += 1; + raster_desc.FillMode = D3D12_FILL_MODE_SOLID; } + raster_desc.CullMode = D3D12_CULL_MODE_NONE; + raster_desc.FrontCounterClockwise = 0; + raster_desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + raster_desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + raster_desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + raster_desc.DepthClipEnable = 1; + raster_desc.MultisampleEnable = 0; + raster_desc.AntialiasedLineEnable = 0; + raster_desc.ForcedSampleCount = 0; + raster_desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; } - } - D3D12_RASTERIZER_DESC raster_desc = Zi; - { - if (desc.is_wireframe) + D3D12_BLEND_DESC blend_desc = Zi; { - raster_desc.FillMode = D3D12_FILL_MODE_WIREFRAME; - } - else - { - raster_desc.FillMode = D3D12_FILL_MODE_SOLID; - } - raster_desc.CullMode = D3D12_CULL_MODE_NONE; - raster_desc.FrontCounterClockwise = 0; - raster_desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; - raster_desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; - raster_desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; - raster_desc.DepthClipEnable = 1; - raster_desc.MultisampleEnable = 0; - raster_desc.AntialiasedLineEnable = 0; - raster_desc.ForcedSampleCount = 0; - raster_desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; - } - - D3D12_BLEND_DESC blend_desc = Zi; - { - blend_desc.IndependentBlendEnable = has_multiple_blend_modes; - blend_desc.AlphaToCoverageEnable = 0; - for (i32 rt_idx = 0; rt_idx < rts_count; ++rt_idx) - { - G_BlendMode blend_mode = desc.render_target_blend_modes[rt_idx]; - D3D12_RENDER_TARGET_BLEND_DESC *rt = &blend_desc.RenderTarget[rt_idx]; - switch (blend_mode) + blend_desc.IndependentBlendEnable = has_multiple_blend_modes; + blend_desc.AlphaToCoverageEnable = 0; + for (i32 rt_idx = 0; rt_idx < rts_count; ++rt_idx) { - default: + G_BlendMode blend_mode = desc.render_target_blend_modes[rt_idx]; + D3D12_RENDER_TARGET_BLEND_DESC *rt = &blend_desc.RenderTarget[rt_idx]; + switch (blend_mode) { - rt->BlendEnable = 0; - rt->RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - } break; + default: + { + rt->BlendEnable = 0; + rt->RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } break; - case G_BlendMode_CompositeStraightAlpha: - { - rt->BlendEnable = 1; + case G_BlendMode_CompositeStraightAlpha: + { + rt->BlendEnable = 1; - rt->SrcBlend = D3D12_BLEND_SRC_ALPHA; - rt->BlendOp = D3D12_BLEND_OP_ADD; - rt->DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + rt->SrcBlend = D3D12_BLEND_SRC_ALPHA; + rt->BlendOp = D3D12_BLEND_OP_ADD; + rt->DestBlend = D3D12_BLEND_INV_SRC_ALPHA; - rt->SrcBlendAlpha = D3D12_BLEND_ONE; - rt->BlendOpAlpha = D3D12_BLEND_OP_ADD; - rt->DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + rt->SrcBlendAlpha = D3D12_BLEND_ONE; + rt->BlendOpAlpha = D3D12_BLEND_OP_ADD; + rt->DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; - rt->RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - } break; + rt->RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } break; - case G_BlendMode_CompositePremultipliedAlpha: - { - rt->BlendEnable = 1; + case G_BlendMode_CompositePremultipliedAlpha: + { + rt->BlendEnable = 1; - rt->SrcBlend = D3D12_BLEND_ONE; - rt->BlendOp = D3D12_BLEND_OP_ADD; - rt->DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + rt->SrcBlend = D3D12_BLEND_ONE; + rt->BlendOp = D3D12_BLEND_OP_ADD; + rt->DestBlend = D3D12_BLEND_INV_SRC_ALPHA; - rt->SrcBlendAlpha = D3D12_BLEND_ONE; - rt->BlendOpAlpha = D3D12_BLEND_OP_ADD; - rt->DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + rt->SrcBlendAlpha = D3D12_BLEND_ONE; + rt->BlendOpAlpha = D3D12_BLEND_OP_ADD; + rt->DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; - rt->RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - } break; + rt->RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + } break; + } } } - } - D3D12_DEPTH_STENCIL_DESC ds_desc = Zi; - { - ds_desc.DepthEnable = 0; - ds_desc.StencilEnable = 0; - } - - String vs = DataFromResource(desc.vs.resource); - String ps = DataFromResource(desc.ps.resource); - D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = Zi; - { - pso_desc.pRootSignature = G_D12.bindless_rootsig; - pso_desc.VS.pShaderBytecode = vs.text; - pso_desc.VS.BytecodeLength = vs.len; - pso_desc.PS.pShaderBytecode = ps.text; - pso_desc.PS.BytecodeLength = ps.len; - pso_desc.RasterizerState = raster_desc; - pso_desc.BlendState = blend_desc; - pso_desc.DepthStencilState = ds_desc; - pso_desc.PrimitiveTopologyType = desc.topology_type; - pso_desc.SampleMask = UINT_MAX; - pso_desc.SampleDesc.Count = 1; - pso_desc.SampleDesc.Quality = 0; - pso_desc.NumRenderTargets = rts_count; - for (i32 rt_idx = 0; rt_idx < rts_count; ++rt_idx) + D3D12_DEPTH_STENCIL_DESC ds_desc = Zi; { - DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(desc.render_target_formats[rt_idx]); - pso_desc.RTVFormats[rt_idx] = format; + ds_desc.DepthEnable = 0; + ds_desc.StencilEnable = 0; + } + + String vs = DataFromResource(desc.vs.resource); + String ps = DataFromResource(desc.ps.resource); + D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = Zi; + { + pso_desc.pRootSignature = G_D12.bindless_rootsig; + pso_desc.VS.pShaderBytecode = vs.text; + pso_desc.VS.BytecodeLength = vs.len; + pso_desc.PS.pShaderBytecode = ps.text; + pso_desc.PS.BytecodeLength = ps.len; + pso_desc.RasterizerState = raster_desc; + pso_desc.BlendState = blend_desc; + pso_desc.DepthStencilState = ds_desc; + pso_desc.PrimitiveTopologyType = desc.topology_type; + pso_desc.SampleMask = UINT_MAX; + pso_desc.SampleDesc.Count = 1; + pso_desc.SampleDesc.Quality = 0; + pso_desc.NumRenderTargets = rts_count; + for (i32 rt_idx = 0; rt_idx < rts_count; ++rt_idx) + { + DXGI_FORMAT format = G_D12_DxgiFormatFromGpuFormat(desc.render_target_formats[rt_idx]); + pso_desc.RTVFormats[rt_idx] = format; + } + } + hr = ID3D12Device_CreateGraphicsPipelineState(G_D12.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); + if (FAILED(hr)) + { + error_str = StringF(scratch.arena, "Failed to create graphics pipeline \"%F\"", FmtString(pipeline_name)); + ok = 0; } } - hr = ID3D12Device_CreateGraphicsPipelineState(G_D12.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); - if (FAILED(hr)) + else { - error_str = Lit("Failed to create graphics pipeline"); - ok = 0; - } - } - else if (ok) - { - String cs = DataFromResource(desc.cs.resource); - D3D12_COMPUTE_PIPELINE_STATE_DESC pso_desc = Zi; - { - pso_desc.pRootSignature = G_D12.bindless_rootsig; - pso_desc.CS.pShaderBytecode = cs.text; - pso_desc.CS.BytecodeLength = cs.len; - } - hr = ID3D12Device_CreateComputePipelineState(G_D12.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); - if (FAILED(hr)) - { - error_str = Lit("Failed to create compute pipeline"); - ok = 0; + String cs = DataFromResource(desc.cs.resource); + D3D12_COMPUTE_PIPELINE_STATE_DESC pso_desc = Zi; + { + pso_desc.pRootSignature = G_D12.bindless_rootsig; + pso_desc.CS.pShaderBytecode = cs.text; + pso_desc.CS.BytecodeLength = cs.len; + } + hr = ID3D12Device_CreateComputePipelineState(G_D12.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); + if (FAILED(hr)) + { + error_str = StringF(scratch.arena, "Failed to create compute pipeline \"%F\"", FmtString(pipeline_name)); + ok = 0; + } } } - if (!ok) + if (ok) + { + if (GPU_DEBUG) + { + G_D12_SetObjectName((ID3D12Object *)pso, pipeline_name); + } + } + else { // TOOD: Don't panic Panic(error_str); @@ -662,6 +724,7 @@ G_D12_Pipeline *G_D12_PipelineFromDesc(G_D12_PipelineDesc desc) pipeline->pso = pso; pipeline->error = error_str; pipeline->ok = ok; + EndScratch(scratch); } return pipeline; @@ -900,15 +963,22 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_CommandListHandle desc.kind == G_ResourceKind_Texture2D || desc.kind == G_ResourceKind_Texture3D; b32 is_sampler = desc.kind == G_ResourceKind_Sampler; + G_ResourceFlag flags = is_buffer ? desc.buffer.flags : is_texture ? desc.texture.flags : desc.sampler.flags; + String new_debug_text = + is_buffer ? desc.buffer.debug : + is_texture ? desc.texture.debug : + desc.sampler.debug; + new_debug_text.len = MinU64(new_debug_text.len, countof(resource->debug_text)); + ////////////////////////////// //- Initialize heap info - b32 can_reuse = 1; + b32 can_reuse = !AnyBit(flags, G_ResourceFlag_ForceNoReuse); D3D12_HEAP_FLAGS heap_flags = 0; D3D12_HEAP_PROPERTIES heap_props = Zi; @@ -1047,8 +1117,14 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_CommandListHandle Unlock(&lock); } ZeroStruct(release); - release->d3d_resource = resource->d3d_resource; SllQueuePush(cl->releases.first, cl->releases.last, release); + release->d3d_resource = resource->d3d_resource; + if (GPU_DEBUG) + { + StaticAssert(countof(release->debug_text) == countof(resource->debug_text)); + release->debug_text_len = resource->debug_text_len; + CopyBytes(release->debug_text, resource->debug_text, resource->debug_text_len); + } } ZeroStruct(resource); } @@ -1146,6 +1222,20 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_CommandListHandle } } + ////////////////////////////// + //- Set debug information + + if (GPU_DEBUG) + { + String old_debug_text = STRING(resource->debug_text_len, resource->debug_text); + if (!MatchString(old_debug_text, new_debug_text)) + { + resource->debug_text_len = new_debug_text.len; + CopyBytes(resource->debug_text, new_debug_text.text, new_debug_text.len); + G_D12_SetObjectName((ID3D12Object *)resource->d3d_resource, new_debug_text); + } + } + ////////////////////////////// //- Barrier if reusing @@ -1221,7 +1311,7 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH { Panic(Lit("Max descriptors reached in heap")); } - descriptor = PushStruct(heap->descriptors_arena, G_D12_Descriptor); + descriptor = PushStructNoZero(heap->descriptors_arena, G_D12_Descriptor); index = descriptors_count; } } diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.h b/src/gpu/gpu_dx12/gpu_dx12_core.h index 21011813..45933035 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.h +++ b/src/gpu/gpu_dx12/gpu_dx12_core.h @@ -11,7 +11,7 @@ #pragma comment(lib, "dxgi") //////////////////////////////////////////////////////////// -//~ Tweakable defines +//~ Tweakable definitions #define G_D12_TearingIsAllowed 1 #define G_D12_FrameLatency 1 @@ -25,6 +25,8 @@ #define G_D12_MaxSamplerDescriptors (1024 * 1) #define G_D12_MaxRtvDescriptors (1024 * 64) +#define G_D12_MaxDebugTextLen 64 + //////////////////////////////////////////////////////////// //~ Pipeline types @@ -90,6 +92,9 @@ Struct(G_D12_Resource) // Backbuffer info struct G_D12_Swapchain *swapchain; + + u64 debug_text_len; + u8 debug_text[G_D12_MaxDebugTextLen]; }; Struct(G_D12_ResourceList) @@ -273,6 +278,9 @@ Struct(G_D12_Releasable) i64 completion_queue_target; ID3D12Resource *d3d_resource; + + u64 debug_text_len; + u8 debug_text[G_D12_MaxDebugTextLen]; }; Struct(G_D12_ReleasableList) @@ -495,6 +503,9 @@ D3D12_BARRIER_SYNC G_D12_BarrierSyncFromStages(G_Stage stages); D3D12_BARRIER_ACCESS G_D12_BarrierAccessFromAccesses(G_Access accesses); D3D12_BARRIER_LAYOUT G_D12_BarrierLayoutFromLayout(G_Layout layout); +void G_D12_SetObjectName(ID3D12Object *object, String name); +String G_D12_NameFromObject(Arena *arena, ID3D12Object *object); + //////////////////////////////////////////////////////////// //~ Pipeline diff --git a/src/meta/meta.c b/src/meta/meta.c index e0b3753e..3ee0560c 100644 --- a/src/meta/meta.c +++ b/src/meta/meta.c @@ -426,11 +426,13 @@ void BuildEntryPoint(WaveLaneCtx *lane) //- Dxc { PushStringToList(perm, &cp.flags_dxc, Lit("-O3")); + // PushStringToList(perm, &cp.flags_dxc, Lit("-Od")); PushStringToList(perm, &cp.flags_dxc, Lit("-Zi -Qembed_debug")); // Enable warnings PushStringToList(perm, &cp.warnings_dxc, Lit("-Wall")); PushStringToList(perm, &cp.warnings_dxc, Lit("-WX")); + PushStringToList(perm, &cp.warnings_dxc, Lit("-Wshadow")); // Disable warnings PushStringToList(perm, &cp.warnings_dxc, Lit("-Wno-unused-variable")); diff --git a/src/net/net_win32/net_win32.c b/src/net/net_win32/net_win32.c index 4c2e7d26..5e2801fa 100644 --- a/src/net/net_win32/net_win32.c +++ b/src/net/net_win32/net_win32.c @@ -815,7 +815,6 @@ void NET_W32_TickForever(WaveLaneCtx *lane) // Post initial recv CreateIoCompletionPort((HANDLE)sock, NET_W32.iocp, 0, 0); - NET_W32_PostRecv(pipe); } else diff --git a/src/platform/platform_win32/platform_win32.c b/src/platform/platform_win32/platform_win32.c index ca48d1f7..ada3d4ea 100644 --- a/src/platform/platform_win32/platform_win32.c +++ b/src/platform/platform_win32/platform_win32.c @@ -392,7 +392,6 @@ PLT_FileMap PLT_OpenFileMap(PLT_File file) map.mapped_memory = STRING(size, base_ptr); map.valid = map_handle != INVALID_HANDLE_VALUE && base_ptr != 0; - return map; } diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 5cc3f42a..d039a299 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -411,7 +411,8 @@ void V_TickForever(WaveLaneCtx *lane) gpu_perm, cl, V_GpuState, 1, - .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite + .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, + .debug = Lit("Gpu state") ); gpu_state_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_state, V_GpuState); } @@ -422,7 +423,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R8_Uint, tiles_dims, G_Layout_DirectQueue_ShaderRead, - .flags = G_ResourceFlag_ZeroMemory + .flags = G_ResourceFlag_ZeroMemory, + .debug = Lit("Tiles") ); gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles); } @@ -432,7 +434,8 @@ void V_TickForever(WaveLaneCtx *lane) gpu_perm, cl, V_Particle, V_ParticlesCap, - .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite + .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, + .debug = Lit("Particles") ); gpu_particles_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles, V_Particle); } @@ -446,7 +449,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R16G16B16A16_Float, cells_dims, G_Layout_DirectQueue_ShaderReadWrite, - .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite + .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, + .debug = Lit("Cells") ); gpu_cells_ref = G_PushRWTexture2DRef(gpu_perm, gpu_cells); } @@ -460,7 +464,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R16G16B16A16_Float, cells_dims, G_Layout_DirectQueue_ShaderReadWrite, - .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite + .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, + .debug = Lit("Stains") ); gpu_stains_ref = G_PushRWTexture2DRef(gpu_perm, gpu_stains); } @@ -475,7 +480,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R32_Float, cells_dims, G_Layout_DirectQueue_ShaderReadWrite, - .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite + .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, + .debug = Lit("Drynesses") ); gpu_drynesses_ref = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses); } @@ -853,9 +859,10 @@ void V_TickForever(WaveLaneCtx *lane) f32 fire_presses = fire_held && !prev_frame->held_buttons[Button_M1]; { // TODO: Adjustable sensitivity + f32 mouse_sensitivity = TweakFloat("Mouse sensitivity", 1.0, 0.1, 5.0); f32 mouse_scale_factor = 0.005; look = frame->look; - look = AddVec2(look, MulVec2(mouse_delta, mouse_scale_factor)); + look = AddVec2(look, MulVec2(mouse_delta, mouse_sensitivity * mouse_scale_factor)); look = ClampVec2Len(look, look_radius); } if (frame->is_editing) @@ -4445,7 +4452,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R16G16B16A16_Float, frame->screen_dims, G_Layout_DirectQueue_RenderTargetWrite, - .flags = G_ResourceFlag_AllowRenderTarget + .flags = G_ResourceFlag_AllowRenderTarget, + .debug = StringF(frame->arena, "Screen target [%F]", FmtSint(frame->tick)) ); G_Texture2DRef screen_target_ro = G_PushTexture2DRef(frame->gpu_arena, screen_target); Rng3 screen_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1)); @@ -4457,7 +4465,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R16G16B16A16_Float, frame->screen_dims, G_Layout_DirectQueue_RenderTargetWrite, - .flags = G_ResourceFlag_AllowRenderTarget + .flags = G_ResourceFlag_AllowRenderTarget, + .debug = StringF(frame->arena, "Albedo target [%F]", FmtSint(frame->tick)) ); G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target); @@ -4467,7 +4476,8 @@ void V_TickForever(WaveLaneCtx *lane) G_Format_R16G16B16A16_Float, frame->shade_dims, G_Layout_DirectQueue_ShaderReadWrite, - .flags = G_ResourceFlag_AllowShaderReadWrite + .flags = G_ResourceFlag_AllowShaderReadWrite, + .debug = StringF(frame->arena, "Shade target [%F]", FmtSint(frame->tick)) ); G_Texture2DRef shade_target_ro = G_PushTexture2DRef(frame->gpu_arena, shade_target); G_RWTexture2DRef shade_target_rw = G_PushRWTexture2DRef(frame->gpu_arena, shade_target); @@ -4475,12 +4485,24 @@ void V_TickForever(WaveLaneCtx *lane) Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y)); // Quad buffers - G_ResourceHandle quads_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->quads_arena)); + G_ResourceHandle quads_buff = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromArena(frame->quads_arena), + .debug = StringF(frame->arena, "quads [%F]", FmtSint(frame->tick)) + ); G_StructuredBufferRef quads_ref = G_PushStructuredBufferRef(frame->gpu_arena, quads_buff, V_Quad); // Debug shape buffers - G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->dverts_arena)); - G_ResourceHandle dvert_idxs_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->dvert_idxs_arena)); + G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromArena(frame->dverts_arena), + .debug = StringF(frame->arena, "dverts [%F]", FmtSint(frame->tick)) + ); + G_ResourceHandle dvert_idxs_buff = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromArena(frame->dvert_idxs_arena), + .debug = StringF(frame->arena, "dvert idxs [%F]", FmtSint(frame->tick)) + ); G_StructuredBufferRef dverts_ref = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert); G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff); @@ -4497,7 +4519,11 @@ void V_TickForever(WaveLaneCtx *lane) ++emitter_idx; } } - gpu_emitters = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromStructs(flattened_emitters, frame->emitters_count)); + gpu_emitters = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromStructs(flattened_emitters, frame->emitters_count), + .debug = StringF(frame->arena, "emitters [%F]", FmtSint(frame->tick)) + ); } G_StructuredBufferRef gpu_emitters_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_emitters, V_Emitter); @@ -4573,7 +4599,11 @@ void V_TickForever(WaveLaneCtx *lane) } } } - G_ResourceHandle gpu_params = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromStruct(¶ms)); + G_ResourceHandle gpu_params = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromStruct(¶ms), + .debug = StringF(frame->arena, "Gpu params [%F]", FmtSint(frame->tick)) + ); G_StructuredBufferRef gpu_params_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_params, V_GpuParams); // Upload tiles @@ -4680,12 +4710,9 @@ void V_TickForever(WaveLaneCtx *lane) G_DumbMemoryLayoutSync(frame->cl, shade_target, G_Layout_DirectQueue_ShaderRead); } - ////////////////////////////// //- Composite pass - G_DumbMemoryLayoutSync(frame->cl, screen_target, G_Layout_DirectQueue_RenderTargetWrite); - { G_Rasterize( frame->cl, diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index 644df199..abcd81f0 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -25,11 +25,12 @@ ComputeShader2D(V_PrepareShadeCS, 8, 8) { V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; RWTexture2D shade = G_Dereference(params.shade_rw); - Vec2 shade_idx = SV_DispatchThreadID; - if (all(shade_idx < countof(shade))) + Vec2 shade_pos = SV_DispatchThreadID; + + if (all(shade_pos < countof(shade))) { // Clear shade - shade[shade_idx] = 0; + shade[shade_pos] = 0; } } @@ -39,26 +40,26 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8) V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; RWTexture2D cells = G_Dereference(params.cells); RWTexture2D drynesses = G_Dereference(params.drynesses); - Vec2 cells_idx = SV_DispatchThreadID; - if (all(cells_idx < countof(cells))) + Vec2 cells_pos = SV_DispatchThreadID; + if (all(cells_pos < countof(cells))) { // Clear cell - cells[cells_idx] = 0; + cells[cells_pos] = 0; // Increase dryness f32 dry_rate = params.dt * 0.1; { - f32 old_dryness = drynesses[cells_idx]; + f32 old_dryness = drynesses[cells_pos]; f32 new_dryness = lerp(old_dryness, 1, dry_rate); - drynesses[cells_idx] = new_dryness; + drynesses[cells_pos] = new_dryness; } // Clear stain if (params.should_clear_stains) { RWTexture2D stains = G_Dereference(params.stains); - stains[cells_idx] = 0; - drynesses[cells_idx] = 0; + stains[cells_pos] = 0; + drynesses[cells_pos] = 0; } } } @@ -114,223 +115,11 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input) Texture2D tex = G_Dereference(quad.tex); Vec4 albedo = tex.Sample(clamp_sampler, input.samp_uv); - // Vec4 albedo = Color_Cyan; - V_QuadPSOutput output; output.sv_target0 = albedo; return output; } -//////////////////////////////////////////////////////////// -//~ Backdrop - -// ComputeShader2D(V_BackdropCS, 8, 8) -// { -// V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; -// RWTexture2D screen = G_Dereference(params.screen_rw); -// Texture2D tiles = G_Dereference(params.tiles); -// SamplerState wrap_sampler = G_Dereference(params.pt_wrap_sampler); - -// const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)); -// const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); - -// Vec2 screen_pos = SV_DispatchThreadID + Vec2(0.5, 0.5); - -// Vec4 result = Vec4(0.025, 0.025, 0.025, 1); -// Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1)); -// Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(world_pos, 1))); -// Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); - -// P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); - -// f32 half_thickness = 1; -// f32 half_world_bounds_size = P_WorldPitch * 0.5; -// Vec2 world_bounds_screen_p0 = mul(params.af.world_to_screen, Vec3(-half_world_bounds_size, -half_world_bounds_size, 1)); -// Vec2 world_bounds_screen_p1 = mul(params.af.world_to_screen, Vec3(half_world_bounds_size, half_world_bounds_size, 1)); -// b32 is_in_world_bounds = -// screen_pos.x > (world_bounds_screen_p0.x - half_thickness) && -// screen_pos.y > (world_bounds_screen_p0.y - half_thickness) && -// screen_pos.x < (world_bounds_screen_p1.x + half_thickness) && -// screen_pos.y < (world_bounds_screen_p1.y + half_thickness); - -// if (is_in_world_bounds) -// { -// // // Checkered grid -// // { -// // i32 color_idx = 0; -// // Vec4 colors[2] = { -// // background_color_a, -// // background_color_b -// // }; -// // const f32 checker_size = 0.5; -// // Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); -// // if (world_pos_modded.x < checker_size) -// // { -// // color_idx = !color_idx; -// // } -// // if (world_pos_modded.y < checker_size) -// // { -// // color_idx = !color_idx; -// // } -// // if (world_pos.x < 0) -// // { -// // color_idx = !color_idx; -// // } -// // if (world_pos.y < 0) -// // { -// // color_idx = !color_idx; -// // } -// // result = colors[color_idx]; -// // } - -// // Tile test -// // TODO: Remove this -// { -// P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); -// P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); -// P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); -// P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); -// P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); -// P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); -// P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); -// P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); - -// f32 tile_edge_dist = Inf; -// P_TileKind edge_tile = tile; -// if (tile_tl != tile) { edge_tile = tile_tl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), floor(tile_pos.y)))); } -// if (tile_tr != tile) { edge_tile = tile_tr; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), floor(tile_pos.y)))); } -// if (tile_br != tile) { edge_tile = tile_br; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), ceil(tile_pos.y)))); } -// if (tile_bl != tile) { edge_tile = tile_bl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), ceil(tile_pos.y)))); } -// if (tile_l != tile) { edge_tile = tile_l; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.x)); } -// if (tile_r != tile) { edge_tile = tile_r; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.x)); } -// if (tile_t != tile) { edge_tile = tile_t; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.y)); } -// if (tile_b != tile) { edge_tile = tile_b; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.y)); } - -// if (tile == P_TileKind_Wall) -// { -// Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); -// Vec4 inner = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); -// result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375)); -// // result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.5)); -// } -// else if (tile != P_TileKind_Empty) -// { -// SPR_Slice slice = params.tile_slices[tile]; -// Texture2D tile_tex = G_Dereference(slice.tex); -// Vec4 tile_col = tile_tex.SampleLevel(wrap_sampler, world_pos, 0); - -// result = tile_col; -// } - -// // switch (tile) -// // { -// // default: break; - -// // case P_TileKind_Floor: -// // { -// // result = Color_Blue; -// // } break; - -// // case P_TileKind_Wall: -// // { -// // // result = Color_Red; -// // result = Color_Black; -// // } break; -// // } -// } - - - - - -// // TODO: Remove this -// // Cells test -// { -// RWTexture2D stains = G_Dereference(params.stains); -// RWTexture2D cells = G_Dereference(params.cells); -// RWTexture2D drynesses = G_Dereference(params.drynesses); - -// Vec4 stain = stains.Load(cell_pos); -// Vec4 cell = cells.Load(cell_pos); -// f32 dryness = drynesses[cell_pos]; - -// stain = V_DryColor(stain, dryness); - -// // cell.rgb *= cell.a; -// // stain.rgb *= stain.a; - -// result.rgb = (stain.rgb * stain.a) + (result.rgb * (1.0 - stain.a)); -// result.a = (stain.a * 1) + (result.a * (1.0 - stain.a)); - -// result.rgb = (cell.rgb * cell.a) + (result.rgb * (1.0 - cell.a)); -// result.a = (cell.a * 1) + (result.a * (1.0 - cell.a)); - -// // Vec4 cell = cells.Load(cell_pos); -// // if (cell.a != 0) -// // { -// // result = cell; -// // } -// // else -// // { -// // Vec4 stain = stains.Load(cell_pos); -// // if (stain.a != 0) -// // { -// // result = stain; -// // } -// // } -// } - - - - - - -// // // TODO: Remove this -// // // Cells test -// // { -// // RWTexture2D cells = G_Dereference(params.cells); -// // Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(world_pos, 1))); -// // Vec4 cell = cells.Load(cell_pos); -// // if (cell.a != 0) -// // { -// // result = cell; -// // } -// // else -// // { -// // RWTexture2D stains = G_Dereference(params.stains); -// // Vec4 stain = stains.Load(cell_pos); -// // if (stain.a != 0) -// // { -// // result = stain; -// // } -// // } -// // } - - - -// // TODO: Remove this -// // Stains test -// // { -// // RWTexture2D stains = G_Dereference(params.stains); -// // Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(world_pos, 1)); -// // V_ParticleKind stain = stains.Load(cell_pos); - -// // if (stain == V_ParticleKind_Test) -// // { -// // // result = Color_Yellow; -// // // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1)); -// // // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1)); -// // } -// // } - -// } - -// if (all(screen_pos < countof(screen))) -// { -// screen[screen_pos] = result; -// } -// } - //////////////////////////////////////////////////////////// //~ Particle simulation @@ -378,7 +167,9 @@ ComputeShader(V_SimParticlesCS, 64) V_Particle particle = particles[particle_idx]; if (particle.exists > 0) { - // Initialize + ////////////////////////////// + //- Initialize particle + if (particle.emitter_init_num != 0) { V_Emitter emitter = G_Dereference(params.emitters)[particle.emitter_init_num - 1]; @@ -418,63 +209,81 @@ ComputeShader(V_SimParticlesCS, 64) particle.emitter_init_num = 0; } - Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(particle.pos, 1))); - b32 is_in_world_bounds = cell_pos.x >= 0 && cell_pos.y >= 0 && cell_pos.x < countof(stains).x && cell_pos.y < countof(stains).y; + ////////////////////////////// + //- Simulate particle - // Simulate - f32 old_exists = particle.exists; + f32 prev_exists = particle.exists; { - particle.pos += particle.velocity * params.dt; - particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * params.dt); - particle.exists -= params.dt / particle.lifetime; - if ((particle.flags & V_ParticleFlag_PruneWhenStill) && (dot(particle.velocity, particle.velocity) < (0.1 * 0.1))) + Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(particle.pos, 1)); + b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells)); + + // Simulate { - particle.exists = 0; - } - if (particle.exists < 0.000001) - { - particle.exists = 0; - } - if (!is_in_world_bounds) - { - particle.exists = 0; + particle.pos += particle.velocity * params.dt; + particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * params.dt); + particle.exists -= params.dt / particle.lifetime; + if ((particle.flags & V_ParticleFlag_PruneWhenStill) && (dot(particle.velocity, particle.velocity) < (0.1 * 0.1))) + { + particle.exists = 0; + } + if (particle.exists < 0.000001) + { + particle.exists = 0; + } } } - // Commit + ////////////////////////////// + //- Commit particle + // FIXME: Atomic writes + { - b32 should_stain = is_in_world_bounds && ( - AnyBit(particle.flags, V_ParticleFlag_StainTrail) || - (AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0) - ); - b32 should_draw = is_in_world_bounds; + Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(particle.pos, 1)); + Vec2 screen_pos = mul(params.af.world_to_screen, Vec3(particle.pos, 1)); + b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells)); + b32 is_in_screen = all(screen_pos >= 0) && all(screen_pos < params.screen_dims); Vec4 color = particle.color; - color.a *= old_exists; + color.a *= prev_exists; // Stain - if (should_stain) + if (is_in_world) { - f32 old_dryness = drynesses[cell_pos]; - Vec4 old_stain = stains[cell_pos]; - // old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5); - // old_stain = V_DryColor(old_stain, old_dryness); - Vec4 new_stain = 0; - new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a)); - new_stain.a = color.a + (old_stain.a * (1.0 - color.a)); - // new_stain = V_DryColor(new_stain, old_dryness * 0.1); - // new_stain = V_DryColor(new_stain, old_dryness * 0.5); + b32 should_stain = ( + AnyBit(particle.flags, V_ParticleFlag_StainTrail) || + (AnyBit(particle.flags, V_ParticleFlag_StainOnPrune) && particle.exists == 0) + ); - stains[cell_pos] = new_stain; - drynesses[cell_pos] = 0; + + // Stain + if (should_stain) + { + f32 old_dryness = drynesses[cell_pos]; + Vec4 old_stain = stains[cell_pos]; + // old_stain = V_DryColor(old_stain, drynesses[cell_pos] * 0.5); + // old_stain = V_DryColor(old_stain, old_dryness); + Vec4 new_stain = 0; + new_stain.rgb = (color.rgb * color.a) + (old_stain.rgb * (1.0 - color.a)); + new_stain.a = color.a + (old_stain.a * (1.0 - color.a)); + // new_stain = V_DryColor(new_stain, old_dryness * 0.1); + // new_stain = V_DryColor(new_stain, old_dryness * 0.5); + + stains[cell_pos] = new_stain; + drynesses[cell_pos] = 0; + } } // Draw - if (should_draw) { - cells[cell_pos] = color; + b32 should_draw = is_in_world; + + if (should_draw) + { + cells[cell_pos] = color; + } } + } particles[particle_idx] = particle; } @@ -488,7 +297,7 @@ ComputeShader2D(V_ShadeCS, 8, 8) { V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; RWTexture2D shade_tex = G_Dereference(params.shade_rw); - // Texture2D albedo_tex = G_Dereference(params.albedo_ro); + Texture2D albedo_tex = G_Dereference(params.albedo_ro); Texture2D tiles = G_Dereference(params.tiles); RWTexture2D stains = G_Dereference(params.stains); RWTexture2D drynesses = G_Dereference(params.drynesses); @@ -496,13 +305,13 @@ ComputeShader2D(V_ShadeCS, 8, 8) Vec2 shade_pos = SV_DispatchThreadID + Vec2(0.5, 0.5); Vec2 world_pos = mul(params.af.shade_to_world, Vec3(shade_pos, 1)); - Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(world_pos, 1))); + Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(world_pos, 1)); Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; - b32 is_in_world_bounds = all(world_pos > -half_world_dims) && all(world_pos < half_world_dims); + b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(stains)); ////////////////////////////// //- Compute albedo @@ -543,7 +352,7 @@ VertexShader(V_CompositeVS, V_CompositePSInput) PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) { V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; - Texture2D shade_tex = G_Dereference(params.shade_ro); + // Texture2D shade_tex = G_Dereference(params.shade_ro); Texture2D albedo_tex = G_Dereference(params.albedo_ro); RWTexture2D stains = G_Dereference(params.stains); RWTexture2D cells = G_Dereference(params.cells); @@ -554,294 +363,313 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) Vec2 screen_pos = input.sv_position.xy; Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1)); Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); - Vec2 cell_pos = floor(mul(params.af.world_to_cell, Vec3(world_pos, 1))); + Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(world_pos, 1)); Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1)); - f32 half_thickness = 1; Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; Vec2 world_bounds_screen_p0 = mul(params.af.world_to_screen, Vec3(-half_world_dims.xy, 1)); Vec2 world_bounds_screen_p1 = mul(params.af.world_to_screen, Vec3(half_world_dims.xy, 1)); - b32 is_in_world_bounds = ( - screen_pos.x > (world_bounds_screen_p0.x - half_thickness) && - screen_pos.y > (world_bounds_screen_p0.y - half_thickness) && - screen_pos.x < (world_bounds_screen_p1.x + half_thickness) && - screen_pos.y < (world_bounds_screen_p1.y + half_thickness) - ); + b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells)); P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); P_TileKind equipped_tile = params.equipped_tile; ////////////////////////////// - //- Shade color + //- World color - // Vec4 shade_color = 0; - // if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex))) - // { - // Vec2 shade_uv = shade_pos / countof(shade_tex); - // shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0); - // } - - ////////////////////////////// - //- Albedo color - - Vec4 albedo_color = 0; + Vec4 world_color = Vec4(0.025, 0.025, 0.025, 1); + if (is_in_world) { ////////////////////////////// - //- Tile color + //- Shade color + + Vec4 shade_color = 0; + // if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex))) + // { + // Vec2 shade_uv = shade_pos / countof(shade_tex); + // shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0); + // } + + ////////////////////////////// + //- Albedo + + Vec4 albedo_color = 0; + { + ////////////////////////////// + //- Tile + + // TODO: Remove this + + b32 tile_is_wall = 0; + Vec4 tile_color = 0; + { + P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); + P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); + P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); + P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); + P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); + P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); + P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); + P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); + + f32 tile_edge_dist = Inf; + P_TileKind edge_tile = tile; + if (tile_tl != tile) { edge_tile = tile_tl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), floor(tile_pos.y)))); } + if (tile_tr != tile) { edge_tile = tile_tr; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), floor(tile_pos.y)))); } + if (tile_br != tile) { edge_tile = tile_br; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), ceil(tile_pos.y)))); } + if (tile_bl != tile) { edge_tile = tile_bl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), ceil(tile_pos.y)))); } + if (tile_l != tile) { edge_tile = tile_l; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.x)); } + if (tile_r != tile) { edge_tile = tile_r; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.x)); } + if (tile_t != tile) { edge_tile = tile_t; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.y)); } + if (tile_b != tile) { edge_tile = tile_b; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.y)); } + + if (tile == P_TileKind_Wall) + { + Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); + Vec4 inner = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); + tile_color = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375)); + tile_is_wall = 1; + } + else if (tile != P_TileKind_Empty) + { + V_TileDesc tile_desc = params.tile_descs[tile]; + Texture2D tile_tex = G_Dereference(tile_desc.tex); + Vec2 tile_samp_uv = lerp(tile_desc.tex_slice_uv.p0, tile_desc.tex_slice_uv.p1, frac(world_pos)); + tile_color = tile_tex.SampleLevel(clamp_sampler, tile_samp_uv, 0); + } + // Checkered grid + else if (tile == P_TileKind_Empty) + { + i32 color_idx = 0; + Vec4 colors[2] = { + LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)), + LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)) + }; + const f32 checker_size = 0.5; + Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); + if (world_pos_modded.x < checker_size) + { + color_idx = !color_idx; + } + if (world_pos_modded.y < checker_size) + { + color_idx = !color_idx; + } + if (world_pos.x < 0) + { + color_idx = !color_idx; + } + if (world_pos.y < 0) + { + color_idx = !color_idx; + } + tile_color = colors[color_idx]; + } + } + + ////////////////////////////// + //- Stain + + Vec4 stain_color = 0; + { + f32 dryness = drynesses.Load(cell_pos); + Vec4 stain = stains.Load(cell_pos); + stain_color = V_DryColor(stain, dryness); + stain_color.rgb *= 1.0 - (0.75 * tile_is_wall); // Darken wall stains + } + + ////////////////////////////// + //- Albedo tex + + Vec4 albedo_tex_color = albedo_tex.Load(Vec3(screen_pos, 0)); + + ////////////////////////////// + //- Compose albedo + + if (!tile_is_wall) + { + albedo_color = BlendPremul(tile_color, albedo_color); // Blend floor tile + albedo_color = BlendPremul(stain_color, albedo_color); // Blend floor stain + } + albedo_color = BlendPremul(albedo_tex_color, albedo_color); + if (tile_is_wall) + { + albedo_color = BlendPremul(tile_color, albedo_color); // Blend wall tile + albedo_color = BlendPremul(stain_color, albedo_color); // Blend wall stain + } + } + + ////////////////////////////// + //- Particle // TODO: Remove this - b32 tile_is_wall = 0; - Vec4 tile_color = Vec4(0.025, 0.025, 0.025, 1); - if (is_in_world_bounds) + Vec4 particle_color = cells.Load(cell_pos); + + ////////////////////////////// + //- Compose world + + // world_color = BlendPremul(shade_color, world_color); + world_color = BlendPremul(albedo_color, world_color); + world_color = BlendPremul(particle_color, world_color); + } + + ////////////////////////////// + //- Overlay color + + Vec4 overlay_color = 0; + { + f32 half_thickness = 1; + + ////////////////////////////// + //- Tile selection overlay + + Vec4 selection_color = 0; + if (params.has_mouse_focus && params.selection_mode == V_SelectionMode_Tile) { - P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); - P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); - P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); - P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); - P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); - P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); - P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); - P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); + Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1)); + // Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25)); + Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6)); - f32 tile_edge_dist = Inf; - P_TileKind edge_tile = tile; - if (tile_tl != tile) { edge_tile = tile_tl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), floor(tile_pos.y)))); } - if (tile_tr != tile) { edge_tile = tile_tr; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), floor(tile_pos.y)))); } - if (tile_br != tile) { edge_tile = tile_br; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), ceil(tile_pos.y)))); } - if (tile_bl != tile) { edge_tile = tile_bl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), ceil(tile_pos.y)))); } - if (tile_l != tile) { edge_tile = tile_l; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.x)); } - if (tile_r != tile) { edge_tile = tile_r; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.x)); } - if (tile_t != tile) { edge_tile = tile_t; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.y)); } - if (tile_b != tile) { edge_tile = tile_b; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.y)); } + Rng2 screen_selection = params.screen_selection; + Rng2 world_selection = params.world_selection; - if (tile == P_TileKind_Wall) + Rng2 tile_selection; + tile_selection.p0 = floor(mul(params.af.world_to_tile, Vec3(world_selection.p0, 1))); + tile_selection.p1 = ceil(mul(params.af.world_to_tile, Vec3(world_selection.p1, 1))); + + f32 dist = 100000000; + dist = min(dist, screen_pos.x - screen_selection.p0.x); + dist = min(dist, screen_pos.y - screen_selection.p0.y); + dist = min(dist, screen_selection.p1.x - screen_pos.x); + dist = min(dist, screen_selection.p1.y - screen_pos.y); + dist = -dist; + + // if (dist >= -half_thickness && dist <= half_thickness) + // { + // selection_color = border_color; + // } + // else { - Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); - Vec4 inner = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); - tile_color = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375)); - // tile_color = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.5)); - tile_is_wall = 1; + if ( + world_pos.x > -(P_WorldPitch / 2) && + world_pos.y > -(P_WorldPitch / 2) && + world_pos.x < (P_WorldPitch / 2) && + world_pos.y < (P_WorldPitch / 2) && + tile_pos.x >= tile_selection.p0.x && + tile_pos.x <= tile_selection.p1.x && + tile_pos.y >= tile_selection.p0.y && + tile_pos.y <= tile_selection.p1.y + ) + { + selection_color = inner_color; + } } - else if (tile != P_TileKind_Empty) + + // Premultiply + selection_color.rgb *= selection_color.a; + } + + ////////////////////////////// + //- Grid + + Vec4 grid_color = 0; + if (is_in_world) + { + // Grid outline + if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) { - V_TileDesc tile_desc = params.tile_descs[tile]; - Texture2D tile_tex = G_Dereference(tile_desc.tex); - Vec2 tile_samp_uv = lerp(tile_desc.tex_slice_uv.p0, tile_desc.tex_slice_uv.p1, frac(world_pos)); - tile_color = tile_tex.SampleLevel(clamp_sampler, tile_samp_uv, 0); + const Vec4 line_color = LinearFromSrgb(Vec4(1, 1, 1, 0.1)); + Vec2 line_screen_p0 = mul(params.af.world_to_screen, Vec3(floor(world_pos), 1)); + Vec2 line_screen_p1 = mul(params.af.world_to_screen, Vec3(ceil(world_pos), 1)); + f32 line_dist = 100000; + line_dist = min(line_dist, abs(screen_pos.x - line_screen_p0.x)); + line_dist = min(line_dist, abs(screen_pos.x - line_screen_p1.x)); + line_dist = min(line_dist, abs(screen_pos.y - line_screen_p0.y)); + line_dist = min(line_dist, abs(screen_pos.y - line_screen_p1.y)); + if (line_dist <= half_thickness * 0.5) + { + grid_color = line_color; + } } - // Checkered grid - else if (tile == P_TileKind_Empty) + + // Axis + if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) { - i32 color_idx = 0; - Vec4 colors[2] = { - LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)), - LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)) - }; - const f32 checker_size = 0.5; - Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); - if (world_pos_modded.x < checker_size) + const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1)); + const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1)); + + Vec2 zero_screen = mul(params.af.world_to_screen, Vec3(0, 0, 1)); + f32 x_dist = abs(screen_pos.x - zero_screen.x); + f32 y_dist = abs(screen_pos.y - zero_screen.y); + if (y_dist <= half_thickness) { - color_idx = !color_idx; + grid_color = x_axis_color; } - if (world_pos_modded.y < checker_size) + else if (x_dist <= half_thickness) { - color_idx = !color_idx; + grid_color = y_axis_color; } - if (world_pos.x < 0) + } + + // World bounds + { + const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1)); + f32 bounds_dist = 100000; + bounds_dist = min(bounds_dist, abs(screen_pos.x - world_bounds_screen_p0.x)); + bounds_dist = min(bounds_dist, abs(screen_pos.x - world_bounds_screen_p1.x)); + bounds_dist = min(bounds_dist, abs(screen_pos.y - world_bounds_screen_p0.y)); + bounds_dist = min(bounds_dist, abs(screen_pos.y - world_bounds_screen_p1.y)); + if (bounds_dist <= half_thickness) { - color_idx = !color_idx; + grid_color = bounds_color; } - if (world_pos.y < 0) + } + + // Premultiply + grid_color.rgb *= grid_color.a; + } + + ////////////////////////////// + //- Crosshair + + // TODO: Remove this + + Vec4 crosshair_color = 0; + { + f32 dist = length(params.screen_crosshair - screen_pos); + if (dist < 4) + { + // Adaptive crosshair color based on underlying luminance + f32 world_luminance = LuminanceFromColor(world_color); + f32 adaptive_threshold = 0.5; + Vec4 adapted_crosshair_color = crosshair_color; + if (world_luminance <= adaptive_threshold) { - color_idx = !color_idx; + crosshair_color = Color_White; } - tile_color = colors[color_idx]; + else + { + crosshair_color = InvertColor(Color_White); + } + crosshair_color = Premul(crosshair_color); } } ////////////////////////////// - //- Stain color + //- Compose overlay - Vec4 stain_color = 0; - { - f32 dryness = drynesses.Load(cell_pos); - stain_color = V_DryColor(stains.Load(cell_pos), dryness); - stain_color.rgb *= 1.0 - (0.75 * tile_is_wall); // Darken wall stains - } - - ////////////////////////////// - //- Albedo tex - - Vec4 albedo_tex_color = albedo_tex.Load(Vec3(screen_pos, 0)); - - ////////////////////////////// - //- Compose albedo - - albedo_color = BlendPremul(!tile_is_wall * tile_color, albedo_color); // Blend floor tile - albedo_color = BlendPremul(!tile_is_wall * stain_color, albedo_color); // Blend floor stain - albedo_color = BlendPremul(albedo_tex_color, albedo_color); - albedo_color = BlendPremul(tile_is_wall * tile_color, albedo_color); // Blend wall tile - albedo_color = BlendPremul(tile_is_wall * stain_color, albedo_color); // Blend wall stain + overlay_color = BlendPremul(selection_color, overlay_color); + overlay_color = BlendPremul(grid_color, overlay_color); + overlay_color = BlendPremul(crosshair_color, overlay_color); } ////////////////////////////// - //- Particle color - - // TODO: Remove this - - Vec4 particle_color = 0; - if (is_in_world_bounds) - { - particle_color = cells.Load(cell_pos); - } - - ////////////////////////////// - //- Tile selection overlay - - Vec4 selection_color = 0; - if (params.has_mouse_focus && params.selection_mode == V_SelectionMode_Tile) - { - Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1)); - // Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25)); - Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6)); - - Rng2 screen_selection = params.screen_selection; - Rng2 world_selection = params.world_selection; - - Rng2 tile_selection; - tile_selection.p0 = floor(mul(params.af.world_to_tile, Vec3(world_selection.p0, 1))); - tile_selection.p1 = ceil(mul(params.af.world_to_tile, Vec3(world_selection.p1, 1))); - - f32 dist = 100000000; - dist = min(dist, screen_pos.x - screen_selection.p0.x); - dist = min(dist, screen_pos.y - screen_selection.p0.y); - dist = min(dist, screen_selection.p1.x - screen_pos.x); - dist = min(dist, screen_selection.p1.y - screen_pos.y); - dist = -dist; - - // if (dist >= -half_thickness && dist <= half_thickness) - // { - // selection_color = border_color; - // } - // else - { - if ( - world_pos.x > -(P_WorldPitch / 2) && - world_pos.y > -(P_WorldPitch / 2) && - world_pos.x < (P_WorldPitch / 2) && - world_pos.y < (P_WorldPitch / 2) && - tile_pos.x >= tile_selection.p0.x && - tile_pos.x <= tile_selection.p1.x && - tile_pos.y >= tile_selection.p0.y && - tile_pos.y <= tile_selection.p1.y - ) - { - selection_color = inner_color; - } - } - - // Premultiply - selection_color.rgb *= selection_color.a; - } - - ////////////////////////////// - //- Grid - - Vec4 grid_color = 0; - if (is_in_world_bounds) - { - // Grid outline - if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) - { - const Vec4 line_color = LinearFromSrgb(Vec4(1, 1, 1, 0.1)); - Vec2 line_screen_p0 = mul(params.af.world_to_screen, Vec3(floor(world_pos), 1)); - Vec2 line_screen_p1 = mul(params.af.world_to_screen, Vec3(ceil(world_pos), 1)); - f32 line_dist = 100000; - line_dist = min(line_dist, abs(screen_pos.x - line_screen_p0.x)); - line_dist = min(line_dist, abs(screen_pos.x - line_screen_p1.x)); - line_dist = min(line_dist, abs(screen_pos.y - line_screen_p0.y)); - line_dist = min(line_dist, abs(screen_pos.y - line_screen_p1.y)); - if (line_dist <= half_thickness * 0.5) - { - grid_color = line_color; - } - } - - // Axis - if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) - { - const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1)); - const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1)); - - Vec2 zero_screen = mul(params.af.world_to_screen, Vec3(0, 0, 1)); - f32 x_dist = abs(screen_pos.x - zero_screen.x); - f32 y_dist = abs(screen_pos.y - zero_screen.y); - if (y_dist <= half_thickness) - { - grid_color = x_axis_color; - } - else if (x_dist <= half_thickness) - { - grid_color = y_axis_color; - } - } - - // World bounds - { - const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1)); - f32 bounds_dist = 100000; - bounds_dist = min(bounds_dist, abs(screen_pos.x - world_bounds_screen_p0.x)); - bounds_dist = min(bounds_dist, abs(screen_pos.x - world_bounds_screen_p1.x)); - bounds_dist = min(bounds_dist, abs(screen_pos.y - world_bounds_screen_p0.y)); - bounds_dist = min(bounds_dist, abs(screen_pos.y - world_bounds_screen_p1.y)); - if (bounds_dist <= half_thickness) - { - grid_color = bounds_color; - } - } - - // Premultiply - grid_color.rgb *= grid_color.a; - } - - ////////////////////////////// - //- Crosshair - - Vec4 crosshair_color = 0; - { - f32 screen_dist = length(params.screen_crosshair - screen_pos); - - if (screen_dist < 5) - { - crosshair_color = Color_White; - } - - crosshair_color.rgb *= crosshair_color.a; - } - - ////////////////////////////// - //- Blend + //- Compose result Vec4 result = Vec4(0, 0, 0, 1); - // result = BlendPremul(shade_color, result); - result = BlendPremul(albedo_color, result); - result = BlendPremul(particle_color, result); - result = BlendPremul(selection_color, result); - result = BlendPremul(grid_color, result); - - // Adaptively blend crosshair - { - f32 luminance = LuminanceFromColor(result); - f32 adaptive_threshold = 0.5; - Vec4 adapted_crosshair_color = crosshair_color; - if (luminance > adaptive_threshold) - { - adapted_crosshair_color = InvertColor(Unpremul(crosshair_color)); - adapted_crosshair_color = Premul(adapted_crosshair_color); - } - result = BlendPremul(adapted_crosshair_color, result); - } + result = BlendPremul(world_color, result); + result = BlendPremul(overlay_color, result); result = Unpremul(result); diff --git a/src/sprite/sprite.c b/src/sprite/sprite.c index f8fbdd01..19b5cc38 100644 --- a/src/sprite/sprite.c +++ b/src/sprite/sprite.c @@ -430,6 +430,7 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame) G_Format_R8G8B8A8_Unorm_Srgb, atlas->dims, G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, + .debug = Lit("Sprite atlas") ); atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex); } diff --git a/src/ttf/ttf_dwrite/ttf_dwrite.h b/src/ttf/ttf_dwrite/ttf_dwrite.h index ff7fe4b9..08220b3a 100644 --- a/src/ttf/ttf_dwrite/ttf_dwrite.h +++ b/src/ttf/ttf_dwrite/ttf_dwrite.h @@ -89,7 +89,6 @@ typedef struct DWRITE_FONT_METRICS { UINT16 strikethroughThickness; } DWRITE_FONT_METRICS; - typedef enum DWRITE_GRID_FIT_MODE { DWRITE_GRID_FIT_MODE_DEFAULT = 0, DWRITE_GRID_FIT_MODE_DISABLED = 1, diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 1a0876b1..3723d653 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -1670,13 +1670,18 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) G_Format_R16G16B16A16_Float, monitor_size, G_Layout_DirectQueue_RenderTargetWrite, - .flags = G_ResourceFlag_AllowRenderTarget + .flags = G_ResourceFlag_AllowRenderTarget, + .debug = Lit("UI draw target") ); G_Texture2DRef draw_target_ro = G_PushTexture2DRef(frame->gpu_arena, draw_target); // Rects u64 rects_count = ArenaCount(frame->rects_arena, UI_GpuRect); - G_ResourceHandle rects_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromArena(frame->rects_arena)); + G_ResourceHandle rects_buff = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromArena(frame->rects_arena), + .debug = Lit("UI rects") + ); G_StructuredBufferRef rects_ro = G_PushStructuredBufferRef(frame->gpu_arena, rects_buff, UI_GpuRect); // Params @@ -1689,7 +1694,11 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) params.cursor_pos = frame->cursor_pos; params.aa = TweakFloat("UI anti-aliasing", 1, 0, 1); } - G_ResourceHandle params_buff = G_PushBufferFromCpuCopy(frame->gpu_arena, frame->cl, StringFromStruct(¶ms)); + G_ResourceHandle params_buff = G_PushBufferFromCpuCopy( + frame->gpu_arena, frame->cl, + StringFromStruct(¶ms), + .debug = Lit("UI gpu params") + ); G_StructuredBufferRef params_ro = G_PushStructuredBufferRef(frame->gpu_arena, params_buff, UI_GpuParams); // Constants