move shared frame state to single struct

This commit is contained in:
jacob 2026-02-04 06:48:08 -06:00
parent 8745cb4da7
commit 3e62de78b1
12 changed files with 418 additions and 479 deletions

View File

@ -423,6 +423,9 @@
#define Enum(name) enum name #define Enum(name) enum name
#endif #endif
//- Embed
#define Embed(type, name) union { type; type name; }
//- alignof //- alignof
#if IsLanguageC && (IsCompilerMsvc || __STDC_VERSION__ < 202311L) #if IsLanguageC && (IsCompilerMsvc || __STDC_VERSION__ < 202311L)
#define alignof(type) __alignof(type) #define alignof(type) __alignof(type)

View File

@ -174,7 +174,7 @@ GC_Run GC_RunFromString32(Arena *arena, String32 str32, GC_FontKey font, f32 fon
f32 advance = RoundF32(glyph->advance); f32 advance = RoundF32(glyph->advance);
Rng2 bounds = glyph->bounds; Rng2 bounds = glyph->bounds;
rect->tex = glyph->atlas->tex_ref; rect->tex = glyph->atlas->tex;
rect->tex_slice = glyph->atlas_slice; rect->tex_slice = glyph->atlas_slice;
rect->tex_slice_uv = glyph->atlas_slice_uv; rect->tex_slice_uv = glyph->atlas_slice_uv;
@ -312,14 +312,14 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
atlas->dims = VEC2I32(1024, 1024); atlas->dims = VEC2I32(1024, 1024);
{ {
G_ArenaHandle gpu_perm = G_PermArena(); G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex = G_PushTexture2D( atlas->tex_res = G_PushTexture2D(
gpu_perm, cl, gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb, G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims, atlas->dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
.name = Lit("Glyph atlas") .name = Lit("Glyph atlas")
); );
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex); atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res);
} }
SllStackPush(GC.first_atlas, atlas); SllStackPush(GC.first_atlas, atlas);
++GC.atlases_count; ++GC.atlases_count;
@ -358,7 +358,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
{ {
G_CopyCpuToTexture( G_CopyCpuToTexture(
cl, cl,
glyph->atlas->tex, VEC3I32(glyph->atlas_slice.p0.x, glyph->atlas_slice.p0.y, 0), glyph->atlas->tex_res, VEC3I32(glyph->atlas_slice.p0.x, glyph->atlas_slice.p0.y, 0),
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1), image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
RNG3I32( RNG3I32(
VEC3I32(0, 0, 0), VEC3I32(0, 0, 0),

View File

@ -14,8 +14,8 @@ Struct(GC_Atlas)
GC_Atlas *next; GC_Atlas *next;
Vec2I32 dims; Vec2I32 dims;
G_ResourceHandle tex; G_ResourceHandle tex_res;
G_Texture2DRef tex_ref; G_Texture2DRef tex;
Vec2I32 cur_pos; Vec2I32 cur_pos;
i32 cur_row_height; i32 cur_row_height;
}; };

View File

@ -1,21 +1,21 @@
#include "meta.h" #include "meta.h"
BuildCtx Build = Zi; M_Ctx M = Zi;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Helpers //~ Helpers
i32 GetBuildStatus(void) i32 M_GetBuildStatus(void)
{ {
return Atomic32Fetch(&Build.status); return Atomic32Fetch(&M.status);
} }
void SetBuildStatus(i32 code) void M_SetBuildStatus(i32 code)
{ {
Atomic32FetchTestSet(&Build.status, 0, code); Atomic32FetchTestSet(&M.status, 0, code);
} }
void EchoLine(String msg) void M_EchoLine(String msg)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
{ {
@ -25,19 +25,19 @@ void EchoLine(String msg)
EndScratch(scratch); EndScratch(scratch);
} }
void EchoLineOrNothing(String msg) void M_EchoLineOrNothing(String msg)
{ {
String trimmed_msg = TrimWhitespace(msg); String trimmed_msg = TrimWhitespace(msg);
if (trimmed_msg.len > 0) if (trimmed_msg.len > 0)
{ {
EchoLine(trimmed_msg); M_EchoLine(trimmed_msg);
} }
} }
LineCol LineColFromPos(String data, i64 pos) M_LineCol M_LineColFromPos(String data, i64 pos)
{ {
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
LineCol result = Zi; M_LineCol result = Zi;
for (u64 cur = 0; cur < data.len && cur <= (u64)pos; ++cur) for (u64 cur = 0; cur < data.len && cur <= (u64)pos; ++cur)
{ {
u8 c = data.text[cur]; u8 c = data.text[cur];
@ -56,7 +56,7 @@ LineCol LineColFromPos(String data, i64 pos)
return result; return result;
} }
String StringFromMetaErrors(Arena *arena, M_ErrorList errors) String M_StringFromMetaErrors(Arena *arena, M_ErrorList errors)
{ {
TempArena scratch = BeginScratch(arena); TempArena scratch = BeginScratch(arena);
@ -78,10 +78,10 @@ String StringFromMetaErrors(Arena *arena, M_ErrorList errors)
{ {
token_pos = token->s.text - token_file_data.text; token_pos = token->s.text - token_file_data.text;
} }
LineCol line_col = Zi; M_LineCol line_col = Zi;
if (token_pos >= 0) if (token_pos >= 0)
{ {
line_col = LineColFromPos(token_file_data, token_pos); line_col = M_LineColFromPos(token_file_data, token_pos);
} }
String formatted = StringF( String formatted = StringF(
scratch.arena, scratch.arena,
@ -105,10 +105,10 @@ String StringFromMetaErrors(Arena *arena, M_ErrorList errors)
return result; return result;
} }
EmbedObj Embed(String store_name, String dir_path) M_EmbedObj M_Embed(String store_name, String dir_path)
{ {
Arena *perm = PermArena(); Arena *perm = PermArena();
EmbedObj result = Zi; M_EmbedObj result = Zi;
// Generate resource archive contents // Generate resource archive contents
u64 store_hash = HashString(store_name); u64 store_hash = HashString(store_name);
@ -239,7 +239,7 @@ EmbedObj Embed(String store_name, String dir_path)
result.return_code = cmd_result.code; result.return_code = cmd_result.code;
} }
SetBuildStatus(result.return_code); M_SetBuildStatus(result.return_code);
} }
else else
{ {
@ -251,9 +251,9 @@ EmbedObj Embed(String store_name, String dir_path)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Build //~ M
void BuildEntryPoint(WaveLaneCtx *lane) void M_BuildEntryPoint(WaveLaneCtx *lane)
{ {
Arena *perm = PermArena(); Arena *perm = PermArena();
@ -297,8 +297,8 @@ void BuildEntryPoint(WaveLaneCtx *lane)
} }
else else
{ {
EchoLine(Lit("Metaprogram is dirty")); M_EchoLine(Lit("Metaprogram is dirty"));
ExitNow(MetaRebuildCode); ExitNow(M_RebuildCode);
} }
} }
@ -326,7 +326,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
layer_name = Lit("pp"); layer_name = Lit("pp");
if (lane->idx == 0) if (lane->idx == 0)
{ {
EchoLine(Lit("No layer specified, assuming \"pp\" build")); M_EchoLine(Lit("No layer specified, assuming \"pp\" build"));
} }
} }
cmdline.leaf_layer_name = layer_name; cmdline.leaf_layer_name = layer_name;
@ -334,13 +334,13 @@ void BuildEntryPoint(WaveLaneCtx *lane)
if (lane->idx == 0) if (lane->idx == 0)
{ {
EchoLine(StringF(perm, "Building layer \"%F\"", FmtString(cmdline.leaf_layer_name))); M_EchoLine(StringF(perm, "Building layer \"%F\"", FmtString(cmdline.leaf_layer_name)));
} }
////////////////////////////// //////////////////////////////
//- Generate compiler params //- Generate compiler params
CompilerParams cp = Zi; M_CompilerParams cp = Zi;
{ {
//- Common //- Common
{ {
@ -452,7 +452,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
// Phase 2/3: Compile (wide) // Phase 2/3: Compile (wide)
// - Compile C // - Compile C
// - Compile & embed shaders // - Compile & embed shaders
// - Embed resource dirs // - M_Embed resource dirs
// //
// Phase 3/3: Link (narrow) // Phase 3/3: Link (narrow)
// - Link // - Link
@ -464,7 +464,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
String gpu_out_file = F_GetFull(perm, StringF(perm, "%F_gen.g", FmtString(cmdline.leaf_layer_name))); String gpu_out_file = F_GetFull(perm, StringF(perm, "%F_gen.g", FmtString(cmdline.leaf_layer_name)));
u64 shader_store_hash = HashString(shader_store_name); u64 shader_store_hash = HashString(shader_store_name);
if (lane->idx == 0 && GetBuildStatus() == 0) if (lane->idx == 0 && M_GetBuildStatus() == 0)
{ {
//- Parse layers //- Parse layers
{ {
@ -479,9 +479,9 @@ void BuildEntryPoint(WaveLaneCtx *lane)
// Flatten // Flatten
StringList starting_layer_names = Zi; StringList starting_layer_names = Zi;
PushStringToList(perm, &starting_layer_names, cmdline.leaf_layer_name); PushStringToList(perm, &starting_layer_names, cmdline.leaf_layer_name);
Build.layers_parse = M_FlattenEntries(perm, parsed, starting_layer_names); M.layers_parse = M_FlattenEntries(perm, parsed, starting_layer_names);
SetBuildStatus(Build.layers_parse.errors.count > 0); M_SetBuildStatus(M.layers_parse.errors.count > 0);
} }
//- Generate C file //- Generate C file
@ -491,7 +491,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
StringList c_include_lines = Zi; StringList c_include_lines = Zi;
StringList c_bootstrap_lines = Zi; StringList c_bootstrap_lines = Zi;
{ {
for (M_Entry *entry = Build.layers_parse.first; entry->valid; entry = entry->next) for (M_Entry *entry = M.layers_parse.first; entry->valid; entry = entry->next)
{ {
M_EntryKind kind = entry->kind; M_EntryKind kind = entry->kind;
M_Token *entry_tok = entry->name_token; M_Token *entry_tok = entry->name_token;
@ -518,12 +518,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
else else
{ {
String err = StringF(perm, "Directory '%F' not found", FmtString(full)); String err = StringF(perm, "Directory '%F' not found", FmtString(full));
M_PushError(perm, &Build.c_parse.errors, arg1_tok, err); M_PushError(perm, &M.c_parse.errors, arg1_tok, err);
} }
} }
else else
{ {
M_PushError(perm, &Build.c_parse.errors, entry_tok, Lit("Expected resource store & directory name")); M_PushError(perm, &M.c_parse.errors, entry_tok, Lit("Expected resource store & directory name"));
} }
} break; } break;
case M_EntryKind_VertexShader: case M_EntryKind_VertexShader:
@ -543,7 +543,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
} }
else else
{ {
M_PushError(perm, &Build.c_parse.errors, entry_tok, Lit("Expected shader name")); M_PushError(perm, &M.c_parse.errors, entry_tok, Lit("Expected shader name"));
} }
} break; } break;
case M_EntryKind_IncludeC: case M_EntryKind_IncludeC:
@ -562,12 +562,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
else else
{ {
String err = StringF(perm, "File '%F' not found", FmtString(full)); String err = StringF(perm, "File '%F' not found", FmtString(full));
M_PushError(perm, &Build.c_parse.errors, arg0_tok, err); M_PushError(perm, &M.c_parse.errors, arg0_tok, err);
} }
} }
else else
{ {
M_PushError(perm, &Build.c_parse.errors, entry_tok, Lit("Expected file name")); M_PushError(perm, &M.c_parse.errors, entry_tok, Lit("Expected file name"));
} }
} break; } break;
case M_EntryKind_Bootstrap: case M_EntryKind_Bootstrap:
@ -580,13 +580,13 @@ void BuildEntryPoint(WaveLaneCtx *lane)
} }
else else
{ {
M_PushError(perm, &Build.c_parse.errors, entry_tok, Lit("Expected bootstrap function name")); M_PushError(perm, &M.c_parse.errors, entry_tok, Lit("Expected bootstrap function name"));
} }
} break; } break;
} }
} }
} }
if (Build.c_parse.errors.count == 0) if (M.c_parse.errors.count == 0)
{ {
StringList c_out_lines = Zi; StringList c_out_lines = Zi;
PushStringToList(perm, &c_out_lines, Lit("// Auto generated file")); PushStringToList(perm, &c_out_lines, Lit("// Auto generated file"));
@ -645,7 +645,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
F_ClearWrite(c_out_file, c_out); F_ClearWrite(c_out_file, c_out);
} }
SetBuildStatus(Build.c_parse.errors.count > 0); M_SetBuildStatus(M.c_parse.errors.count > 0);
} }
//- Generate HLSL file //- Generate HLSL file
@ -677,7 +677,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
{ {
StringList gpu_include_lines = Zi; StringList gpu_include_lines = Zi;
{ {
for (M_Entry *entry = Build.layers_parse.first; entry->valid; entry = entry->next) for (M_Entry *entry = M.layers_parse.first; entry->valid; entry = entry->next)
{ {
M_EntryKind kind = entry->kind; M_EntryKind kind = entry->kind;
M_Token *entry_tok = entry->name_token; M_Token *entry_tok = entry->name_token;
@ -702,12 +702,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
else else
{ {
String err = StringF(perm, "File '%F' not found", FmtString(full)); String err = StringF(perm, "File '%F' not found", FmtString(full));
M_PushError(perm, &Build.gpu_parse.errors, arg0_tok, err); M_PushError(perm, &M.gpu_parse.errors, arg0_tok, err);
} }
} }
else else
{ {
M_PushError(perm, &Build.gpu_parse.errors, entry_tok, Lit("Expected file name")); M_PushError(perm, &M.gpu_parse.errors, entry_tok, Lit("Expected file name"));
} }
} break; } break;
case M_EntryKind_VertexShader: case M_EntryKind_VertexShader:
@ -716,26 +716,26 @@ void BuildEntryPoint(WaveLaneCtx *lane)
{ {
if (arg0_tok->valid) if (arg0_tok->valid)
{ {
ShaderEntryKind shader_kind = kind == M_EntryKind_VertexShader ? ShaderEntryKind_VS M_ShaderEntryKind shader_kind = kind == M_EntryKind_VertexShader ? ShaderEntryKind_VS
: kind == M_EntryKind_PixelShader ? ShaderEntryKind_PS : kind == M_EntryKind_PixelShader ? ShaderEntryKind_PS
: kind == M_EntryKind_ComputeShader ? ShaderEntryKind_CS : kind == M_EntryKind_ComputeShader ? ShaderEntryKind_CS
: ShaderEntryKind_VS; : ShaderEntryKind_VS;
String shader_name = arg0_tok->s; String shader_name = arg0_tok->s;
ShaderEntry *e = PushStruct(perm, ShaderEntry); M_ShaderEntry *e = PushStruct(perm, M_ShaderEntry);
e->kind = shader_kind; e->kind = shader_kind;
e->name = shader_name; e->name = shader_name;
SllQueuePush(Build.gpu_parse.first_shader_entry, Build.gpu_parse.last_shader_entry, e); SllQueuePush(M.gpu_parse.first_shader_entry, M.gpu_parse.last_shader_entry, e);
++Build.gpu_parse.shader_entries_count; ++M.gpu_parse.shader_entries_count;
} }
else else
{ {
M_PushError(perm, &Build.gpu_parse.errors, entry_tok, Lit("Expected shader name")); M_PushError(perm, &M.gpu_parse.errors, entry_tok, Lit("Expected shader name"));
} }
} break; } break;
} }
} }
} }
if (Build.gpu_parse.errors.count == 0) if (M.gpu_parse.errors.count == 0)
{ {
StringList gpu_out_lines = Zi; StringList gpu_out_lines = Zi;
PushStringToList(perm, &gpu_out_lines, Lit("// Auto generated file")); PushStringToList(perm, &gpu_out_lines, Lit("// Auto generated file"));
@ -763,13 +763,13 @@ void BuildEntryPoint(WaveLaneCtx *lane)
} }
} }
SetBuildStatus(Build.gpu_parse.errors.count > 0); M_SetBuildStatus(M.gpu_parse.errors.count > 0);
} }
//- Generate archive info //- Generate archive info
{ {
// Push embedded archive dirs // Push embedded archive dirs
for (M_Entry *entry = Build.layers_parse.first; entry->valid; entry = entry->next) for (M_Entry *entry = M.layers_parse.first; entry->valid; entry = entry->next)
{ {
M_EntryKind kind = entry->kind; M_EntryKind kind = entry->kind;
M_Token *entry_tok = entry->name_token; M_Token *entry_tok = entry->name_token;
@ -789,41 +789,41 @@ void BuildEntryPoint(WaveLaneCtx *lane)
String full = F_GetFullCrossPlatform(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir))); String full = F_GetFullCrossPlatform(perm, StringF(perm, "%F/%F", FmtString(token_parent_dir), FmtString(arg_dir)));
if (F_IsDir(full)) if (F_IsDir(full))
{ {
ResDir *rd = PushStruct(perm, ResDir); M_ResDir *rd = PushStruct(perm, M_ResDir);
rd->store_name = store_name; rd->store_name = store_name;
rd->dir_path = full; rd->dir_path = full;
SllQueuePush(Build.res_dir_parse.first_res_dir, Build.res_dir_parse.last_res_dir, rd); SllQueuePush(M.res_dir_parse.first_res_dir, M.res_dir_parse.last_res_dir, rd);
++Build.res_dir_parse.res_dirs_count; ++M.res_dir_parse.res_dirs_count;
} }
else else
{ {
String err = StringF(perm, "Directory '%F' not found", FmtString(full)); String err = StringF(perm, "Directory '%F' not found", FmtString(full));
M_PushError(perm, &Build.res_dir_parse.errors, arg1_tok, err); M_PushError(perm, &M.res_dir_parse.errors, arg1_tok, err);
} }
} }
else else
{ {
M_PushError(perm, &Build.res_dir_parse.errors, entry_tok, Lit("Expected resource store & directory name")); M_PushError(perm, &M.res_dir_parse.errors, entry_tok, Lit("Expected resource store & directory name"));
} }
} break; } break;
} }
} }
SetBuildStatus(Build.res_dir_parse.errors.count > 0); M_SetBuildStatus(M.res_dir_parse.errors.count > 0);
} }
//- Prep obj arrays //- Prep obj arrays
{ {
// Gpu objs // Gpu objs
Build.gpu_objs.count = Build.gpu_parse.shader_entries_count; M.gpu_objs.count = M.gpu_parse.shader_entries_count;
Build.gpu_objs.array = PushStructs(perm, GpuObj, Build.gpu_objs.count); M.gpu_objs.array = PushStructs(perm, M_GpuObj, M.gpu_objs.count);
// Embed objs // M_Embed objs
Build.embed_objs.count += Build.res_dir_parse.res_dirs_count; M.embed_objs.count += M.res_dir_parse.res_dirs_count;
if (Build.gpu_parse.shader_entries_count > 0) if (M.gpu_parse.shader_entries_count > 0)
{ {
Build.embed_objs.count += 1; M.embed_objs.count += 1;
} }
Build.embed_objs.array = PushStructs(perm, EmbedObj, Build.embed_objs.count); M.embed_objs.array = PushStructs(perm, M_EmbedObj, M.embed_objs.count);
} }
} }
@ -838,14 +838,14 @@ void BuildEntryPoint(WaveLaneCtx *lane)
//- Compile C //- Compile C
{ {
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx++) && GetBuildStatus() == 0) if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx++) && M_GetBuildStatus() == 0)
{ {
Build.c_obj.obj_file = StringF(perm, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name)); M.c_obj.obj_file = StringF(perm, "%F_gen_c.obj", FmtString(cmdline.leaf_layer_name));
String cmd = StringF( String cmd = StringF(
perm, perm,
"cl.exe /c %F -Fo:%F %F %F %F %F", "cl.exe /c %F -Fo:%F %F %F %F %F",
FmtString(c_out_file), FmtString(c_out_file),
FmtString(Build.c_obj.obj_file), FmtString(M.c_obj.obj_file),
FmtString(StringFromList(perm, cp.flags_msvc, Lit(" "))), FmtString(StringFromList(perm, cp.flags_msvc, Lit(" "))),
FmtString(StringFromList(perm, cp.compiler_only_flags_msvc, Lit(" "))), FmtString(StringFromList(perm, cp.compiler_only_flags_msvc, Lit(" "))),
FmtString(StringFromList(perm, cp.warnings_msvc, Lit(" "))), FmtString(StringFromList(perm, cp.warnings_msvc, Lit(" "))),
@ -853,33 +853,34 @@ void BuildEntryPoint(WaveLaneCtx *lane)
); );
OS_CommandResult cmd_result = OS_RunCommand(perm, cmd); OS_CommandResult cmd_result = OS_RunCommand(perm, cmd);
String cmd_output = TrimWhitespace(cmd_result.output); String cmd_output = TrimWhitespace(cmd_result.output);
Build.c_obj.output = cmd_output; M.c_obj.output = cmd_output;
Build.c_obj.return_code = cmd_result.code; M.c_obj.return_code = cmd_result.code;
// Ignore MSVC file-name echo // Ignore MSVC file-name echo
if (MatchString(TrimWhitespace(Build.c_obj.output), F_GetFileName(c_out_file))) if (MatchString(TrimWhitespace(M.c_obj.output), F_GetFileName(c_out_file)))
{ {
Build.c_obj.output = Zstr; M.c_obj.output = Zstr;
} }
SetBuildStatus(Build.c_obj.return_code); M_SetBuildStatus(M.c_obj.return_code);
} }
} }
//- Compile shaders //- Compile shaders
{ {
u32 gpu_obj_idx = 0; u32 gpu_obj_idx = 0;
for (ShaderEntry *e = Build.gpu_parse.first_shader_entry; e; e = e->next) for (M_ShaderEntry *e = M.gpu_parse.first_shader_entry; e; e = e->next)
{ {
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx++) && GetBuildStatus() == 0) if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx++) && M_GetBuildStatus() == 0)
{ {
String shader_name = e->name; String shader_name = e->name;
GpuObj *gpu_obj = &Build.gpu_objs.array[gpu_obj_idx]; M_GpuObj *gpu_obj = &M.gpu_objs.array[gpu_obj_idx];
String out_file = StringF(perm, "%F/%F.dxil", FmtString(shader_store_name), FmtString(e->name)); String out_file = StringF(perm, "%F/%F.dxil", FmtString(shader_store_name), FmtString(e->name));
String target = e->kind == ShaderEntryKind_VS ? Lit("vs_6_6") String target = (
: e->kind == ShaderEntryKind_PS ? Lit("ps_6_6") e->kind == ShaderEntryKind_VS ? Lit("vs_6_6") :
: e->kind == ShaderEntryKind_CS ? Lit("cs_6_6") e->kind == ShaderEntryKind_PS ? Lit("ps_6_6") :
: Lit("vs_6_6"); Lit("cs_6_6")
);
String compile_cmd = StringF( String compile_cmd = StringF(
perm, perm,
"dxc.exe -T %F -E %F -Fo %F %F %F %F %F", "dxc.exe -T %F -E %F -Fo %F %F %F %F %F",
@ -896,34 +897,34 @@ void BuildEntryPoint(WaveLaneCtx *lane)
gpu_obj->output = cmd_result.output; gpu_obj->output = cmd_result.output;
gpu_obj->return_code = cmd_result.code; gpu_obj->return_code = cmd_result.code;
SetBuildStatus(gpu_obj->return_code); M_SetBuildStatus(gpu_obj->return_code);
// Final shader compilation lane embeds shader archive // Final shader compilation lane embeds shader archive
u32 finished_count = Atomic32FetchAdd(&Build.gpu_objs.finished_count, 1) + 1; u32 finished_count = Atomic32FetchAdd(&M.gpu_objs.finished_count, 1) + 1;
if (finished_count == Build.gpu_objs.count && GetBuildStatus() == 0) if (finished_count == M.gpu_objs.count && M_GetBuildStatus() == 0)
{ {
EmbedObj *embed = &Build.embed_objs.array[embed_idx]; M_EmbedObj *embed = &M.embed_objs.array[embed_idx];
*embed = Embed(shader_store_name, shader_store_name); *embed = M_Embed(shader_store_name, shader_store_name);
} }
} }
++gpu_obj_idx; ++gpu_obj_idx;
} }
if (Build.gpu_parse.shader_entries_count > 0) if (M.gpu_parse.shader_entries_count > 0)
{ {
++embed_idx; ++embed_idx;
} }
} }
//- Embed resource dirs //- M_Embed resource dirs
{ {
for (ResDir *rd = Build.res_dir_parse.first_res_dir; rd; rd = rd->next) for (M_ResDir *rd = M.res_dir_parse.first_res_dir; rd; rd = rd->next)
{ {
if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx++) && GetBuildStatus() == 0) if (lane->idx == WaveLaneIdxFromTaskIdx(lane, task_idx++) && M_GetBuildStatus() == 0)
{ {
String dir_path = rd->dir_path; String dir_path = rd->dir_path;
String store_name = rd->store_name; String store_name = rd->store_name;
EmbedObj *embed = &Build.embed_objs.array[embed_idx]; M_EmbedObj *embed = &M.embed_objs.array[embed_idx];
*embed = Embed(store_name, dir_path); *embed = M_Embed(store_name, dir_path);
} }
++embed_idx; ++embed_idx;
} }
@ -935,7 +936,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Phase 3/3: Link //- Phase 3/3: Link
if (lane->idx == 0 && GetBuildStatus() == 0) if (lane->idx == 0 && M_GetBuildStatus() == 0)
{ {
String exe_file = StringF(perm, "%F.exe", FmtString(cmdline.leaf_layer_name)); String exe_file = StringF(perm, "%F.exe", FmtString(cmdline.leaf_layer_name));
{ {
@ -950,10 +951,10 @@ void BuildEntryPoint(WaveLaneCtx *lane)
String obj_files_str = Zi; String obj_files_str = Zi;
{ {
StringList obj_files = Zi; StringList obj_files = Zi;
PushStringToList(perm, &obj_files, Build.c_obj.obj_file); PushStringToList(perm, &obj_files, M.c_obj.obj_file);
for (u64 embed_obj_idx = 0; embed_obj_idx < Build.embed_objs.count; ++embed_obj_idx) for (u64 embed_obj_idx = 0; embed_obj_idx < M.embed_objs.count; ++embed_obj_idx)
{ {
EmbedObj *embed_obj = &Build.embed_objs.array[embed_obj_idx]; M_EmbedObj *embed_obj = &M.embed_objs.array[embed_obj_idx];
PushStringToList(perm, &obj_files, embed_obj->obj_file); PushStringToList(perm, &obj_files, embed_obj->obj_file);
} }
obj_files_str = StringFromList(perm, obj_files, Lit(" ")); obj_files_str = StringFromList(perm, obj_files, Lit(" "));
@ -968,12 +969,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
FmtString(StringFromList(perm, cp.linker_only_flags_msvc, Lit(" "))) FmtString(StringFromList(perm, cp.linker_only_flags_msvc, Lit(" ")))
); );
OS_CommandResult result = OS_RunCommand(perm, cmd); OS_CommandResult result = OS_RunCommand(perm, cmd);
Build.link.output = TrimWhitespace(result.output); M.link.output = TrimWhitespace(result.output);
Build.link.return_code = result.code; M.link.return_code = result.code;
i64 link_elapsed_ns = TimeNs() - start_ns; i64 link_elapsed_ns = TimeNs() - start_ns;
// EchoLine(StringF(perm, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns)))); // M_EchoLine(StringF(perm, ">>>>> Linked in %Fs", FmtFloat(SecondsFromNs(link_elapsed_ns))));
SetBuildStatus(Build.link.return_code); M_SetBuildStatus(M.link.return_code);
} }
////////////////////////////// //////////////////////////////
@ -983,10 +984,10 @@ void BuildEntryPoint(WaveLaneCtx *lane)
{ {
String gpu_obj_output = Zi; String gpu_obj_output = Zi;
{ {
GpuObj *disp_obj = 0; M_GpuObj *disp_obj = 0;
for (u32 gpu_obj_idx = 0; gpu_obj_idx < Build.gpu_objs.count; ++gpu_obj_idx) for (u32 gpu_obj_idx = 0; gpu_obj_idx < M.gpu_objs.count; ++gpu_obj_idx)
{ {
GpuObj *gpu_obj = &Build.gpu_objs.array[gpu_obj_idx]; M_GpuObj *gpu_obj = &M.gpu_objs.array[gpu_obj_idx];
if (!disp_obj || TrimWhitespace(disp_obj->output).len == 0 || gpu_obj->return_code != 0) if (!disp_obj || TrimWhitespace(disp_obj->output).len == 0 || gpu_obj->return_code != 0)
{ {
disp_obj = gpu_obj; disp_obj = gpu_obj;
@ -1000,22 +1001,22 @@ void BuildEntryPoint(WaveLaneCtx *lane)
String embed_obj_output = Zi; String embed_obj_output = Zi;
{ {
StringList embed_obj_outputs = Zi; StringList embed_obj_outputs = Zi;
for (u32 embed_obj_idx = 0; embed_obj_idx < Build.embed_objs.count; ++embed_obj_idx) for (u32 embed_obj_idx = 0; embed_obj_idx < M.embed_objs.count; ++embed_obj_idx)
{ {
EmbedObj *embed_obj = &Build.embed_objs.array[embed_obj_idx]; M_EmbedObj *embed_obj = &M.embed_objs.array[embed_obj_idx];
PushStringToList(perm, &embed_obj_outputs, embed_obj->output); PushStringToList(perm, &embed_obj_outputs, embed_obj->output);
} }
embed_obj_output = StringFromList(perm, embed_obj_outputs, Lit("\n")); embed_obj_output = StringFromList(perm, embed_obj_outputs, Lit("\n"));
} }
EchoLineOrNothing(StringFromMetaErrors(perm, Build.layers_parse.errors)); M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.layers_parse.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, Build.c_parse.errors)); M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.c_parse.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, Build.gpu_parse.errors)); M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.gpu_parse.errors));
EchoLineOrNothing(Build.c_obj.output); M_EchoLineOrNothing(M.c_obj.output);
EchoLineOrNothing(gpu_obj_output); M_EchoLineOrNothing(gpu_obj_output);
EchoLineOrNothing(StringFromMetaErrors(perm, Build.res_dir_parse.errors)); M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.res_dir_parse.errors));
EchoLineOrNothing(embed_obj_output); M_EchoLineOrNothing(embed_obj_output);
EchoLineOrNothing(Build.link.output); M_EchoLineOrNothing(M.link.output);
} }
////////////////////////////// //////////////////////////////
@ -1023,8 +1024,8 @@ void BuildEntryPoint(WaveLaneCtx *lane)
if (lane->idx == 0) if (lane->idx == 0)
{ {
EchoLine(StringF(perm, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs()), .p = 3))); M_EchoLine(StringF(perm, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs()), .p = 3)));
ExitNow(GetBuildStatus()); ExitNow(M_GetBuildStatus());
} }
} }
@ -1036,5 +1037,5 @@ void BootstrapLayers(void)
OS_Bootstrap(); OS_Bootstrap();
CpuTopologyInfo cpu_info = GetCpuTopologyInfo(); CpuTopologyInfo cpu_info = GetCpuTopologyInfo();
i32 meta_lanes_count = cpu_info.num_logical_cores - 1; i32 meta_lanes_count = cpu_info.num_logical_cores - 1;
DispatchWave(Lit("Meta"), MaxI32(meta_lanes_count, 1), BuildEntryPoint, 0); DispatchWave(Lit("Meta"), MaxI32(meta_lanes_count, 1), M_BuildEntryPoint, 0);
} }

View File

@ -1,4 +1,4 @@
#define MetaRebuildCode 1317212284 #define M_RebuildCode 1317212284
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Base layer definitions //~ Base layer definitions
@ -58,7 +58,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Helper types //~ Helper types
Struct(LineCol) Struct(M_LineCol)
{ {
i64 line; i64 line;
i64 col; i64 col;
@ -67,7 +67,7 @@ Struct(LineCol)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Build ctx types //~ Build ctx types
Struct(CompilerParams) Struct(M_CompilerParams)
{ {
StringList defs; StringList defs;
@ -86,41 +86,44 @@ Struct(CompilerParams)
StringList linker_only_flags_clang; StringList linker_only_flags_clang;
}; };
Enum(ShaderEntryKind) Enum(M_ShaderEntryKind)
{ {
ShaderEntryKind_VS, ShaderEntryKind_VS,
ShaderEntryKind_PS, ShaderEntryKind_PS,
ShaderEntryKind_CS, ShaderEntryKind_CS,
}; };
Struct(ShaderEntry) Struct(M_ShaderEntry)
{ {
ShaderEntry *next; M_ShaderEntry *next;
ShaderEntryKind kind; M_ShaderEntryKind kind;
String name; String name;
}; };
Struct(ResDir) Struct(M_ResDir)
{ {
ResDir *next; M_ResDir *next;
String dir_path; String dir_path;
String store_name; String store_name;
}; };
Struct(GpuObj) Struct(M_GpuObj)
{ {
String output; String output;
i32 return_code; i32 return_code;
}; };
Struct(EmbedObj) Struct(M_EmbedObj)
{ {
String obj_file; String obj_file;
String output; String output;
i32 return_code; i32 return_code;
}; };
Struct(BuildCtx) ////////////////////////////////////////////////////////////
//~ State types
Struct(M_Ctx)
{ {
Atomic32 status; Atomic32 status;
@ -134,16 +137,16 @@ Struct(BuildCtx)
struct struct
{ {
M_ErrorList errors; M_ErrorList errors;
ShaderEntry *first_shader_entry; M_ShaderEntry *first_shader_entry;
ShaderEntry *last_shader_entry; M_ShaderEntry *last_shader_entry;
u64 shader_entries_count; u64 shader_entries_count;
} gpu_parse; } gpu_parse;
struct struct
{ {
M_ErrorList errors; M_ErrorList errors;
ResDir *first_res_dir; M_ResDir *first_res_dir;
ResDir *last_res_dir; M_ResDir *last_res_dir;
u64 res_dirs_count; u64 res_dirs_count;
} res_dir_parse; } res_dir_parse;
@ -156,14 +159,14 @@ Struct(BuildCtx)
struct struct
{ {
GpuObj *array; M_GpuObj *array;
u32 count; u32 count;
Atomic32 finished_count; Atomic32 finished_count;
} gpu_objs; } gpu_objs;
struct struct
{ {
EmbedObj *array; M_EmbedObj *array;
u32 count; u32 count;
} embed_objs; } embed_objs;
@ -174,20 +177,20 @@ Struct(BuildCtx)
} link; } link;
}; };
extern BuildCtx Build; extern M_Ctx M;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Helpers //~ Helpers
i32 GetBuildStatus(void); i32 M_GetBuildStatus(void);
void SetBuildStatus(i32 code); void M_SetBuildStatus(i32 code);
void EchoLine(String msg); void M_EchoLine(String msg);
void EchoLineOrNothing(String msg); void M_EchoLineOrNothing(String msg);
LineCol LineColFromPos(String data, i64 pos); M_LineCol M_LineColFromPos(String data, i64 pos);
String StringFromMetaErrors(Arena *arena, M_ErrorList errors); String M_StringFromMetaErrors(Arena *arena, M_ErrorList errors);
EmbedObj Embed(String store_name, String dir_path); M_EmbedObj M_Embed(String store_name, String dir_path);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Build //~ Build
void BuildEntryPoint(WaveLaneCtx *lane); void M_BuildEntryPoint(WaveLaneCtx *lane);

View File

@ -390,35 +390,23 @@ void V_TickForever(WaveLaneCtx *lane)
Vec2I32 cells_dims = VEC2I32(P_CellsPerMeter * P_WorldPitch, P_CellsPerMeter * P_WorldPitch); Vec2I32 cells_dims = VEC2I32(P_CellsPerMeter * P_WorldPitch, P_CellsPerMeter * P_WorldPitch);
// Init gpu state // Init gpu state
G_ResourceHandle gpu_state = Zi; G_ResourceHandle gpu_tiles_res = Zi;
G_ResourceHandle gpu_tiles = Zi; G_ResourceHandle gpu_particles_res = Zi;
G_ResourceHandle gpu_particles = Zi; G_ResourceHandle gpu_cells_res = Zi;
G_ResourceHandle gpu_cells = Zi; G_ResourceHandle gpu_stains_res = Zi;
G_ResourceHandle gpu_stains = Zi; G_ResourceHandle gpu_drynesses_res = Zi;
G_ResourceHandle gpu_drynesses = Zi;
G_RWStructuredBufferRef gpu_state_ref = Zi; G_Texture2DRef gpu_tiles = Zi;
G_Texture2DRef gpu_tiles_ref = Zi; G_RWStructuredBufferRef gpu_particles = Zi;
G_RWStructuredBufferRef gpu_particles_ref = Zi; G_RWTexture2DRef gpu_cells = Zi;
G_RWTexture2DRef gpu_cells_ref = Zi; G_RWTexture2DRef gpu_stains = Zi;
G_RWTexture2DRef gpu_stains_ref = Zi; G_RWTexture2DRef gpu_drynesses = Zi;
G_RWTexture2DRef gpu_drynesses_ref = Zi;
{ {
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct); G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
{ {
// Init state buffer
{
gpu_state = G_PushBuffer(
gpu_perm, cl,
V_GpuState,
1,
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Gpu state")
);
gpu_state_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_state, V_GpuState);
}
// Init tile map texture // Init tile map texture
{ {
gpu_tiles = G_PushTexture2D( gpu_tiles_res = G_PushTexture2D(
gpu_perm, cl, gpu_perm, cl,
G_Format_R8_Uint, G_Format_R8_Uint,
tiles_dims, tiles_dims,
@ -426,22 +414,22 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory, .flags = G_ResourceFlag_ZeroMemory,
.name = Lit("Tiles") .name = Lit("Tiles")
); );
gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles); gpu_tiles = G_PushTexture2DRef(gpu_perm, gpu_tiles_res);
} }
// Init particle buffer // Init particle buffer
{ {
gpu_particles = G_PushBuffer( gpu_particles_res = G_PushBuffer(
gpu_perm, cl, gpu_perm, cl,
V_Particle, V_Particle,
V_ParticlesCap, V_ParticlesCap,
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Particles") .name = Lit("Particles")
); );
gpu_particles_ref = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles, V_Particle); gpu_particles = G_PushRWStructuredBufferRef(gpu_perm, gpu_particles_res, V_Particle);
} }
// Init cells texture // Init cells texture
{ {
gpu_cells = G_PushTexture2D( gpu_cells_res = G_PushTexture2D(
gpu_perm, cl, gpu_perm, cl,
// G_Format_R8_Uint, // G_Format_R8_Uint,
// G_Format_R11G11B10_Float, // G_Format_R11G11B10_Float,
@ -452,11 +440,11 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Cells") .name = Lit("Cells")
); );
gpu_cells_ref = G_PushRWTexture2DRef(gpu_perm, gpu_cells); gpu_cells = G_PushRWTexture2DRef(gpu_perm, gpu_cells_res);
} }
// Init stain texture // Init stain texture
{ {
gpu_stains = G_PushTexture2D( gpu_stains_res = G_PushTexture2D(
gpu_perm, cl, gpu_perm, cl,
// G_Format_R8_Uint, // G_Format_R8_Uint,
// G_Format_R11G11B10_Float, // G_Format_R11G11B10_Float,
@ -467,11 +455,11 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Stains") .name = Lit("Stains")
); );
gpu_stains_ref = G_PushRWTexture2DRef(gpu_perm, gpu_stains); gpu_stains = G_PushRWTexture2DRef(gpu_perm, gpu_stains_res);
} }
// Init drynesses texture // Init drynesses texture
{ {
gpu_drynesses = G_PushTexture2D( gpu_drynesses_res = G_PushTexture2D(
gpu_perm, cl, gpu_perm, cl,
// G_Format_R8_Uint, // G_Format_R8_Uint,
// G_Format_R11G11B10_Float, // G_Format_R11G11B10_Float,
@ -483,7 +471,7 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite, .flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Drynesses") .name = Lit("Drynesses")
); );
gpu_drynesses_ref = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses); gpu_drynesses = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses_res);
} }
} }
G_CommitCommandList(cl); G_CommitCommandList(cl);
@ -542,9 +530,6 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Begin frame //- Begin frame
b32 tiles_dirty = 0;
b32 should_clear_particles = 0;
V.current_frame_tick += 1; V.current_frame_tick += 1;
V_Frame *prev_frame = V_PrevFrame(); V_Frame *prev_frame = V_PrevFrame();
V_Frame *frame = V_CurrentFrame(); V_Frame *frame = V_CurrentFrame();
@ -596,6 +581,21 @@ void V_TickForever(WaveLaneCtx *lane)
TrueRand(StringFromStruct(&V.player_key)); TrueRand(StringFromStruct(&V.player_key));
} }
//////////////////////////////
//- Initialize persistent gpu resources
{
// Persistent resources
frame->tiles = gpu_tiles;
frame->pt_clamp_sampler = G_BasicPointClampSampler();
frame->pt_wrap_sampler = G_BasicPointWrapSampler();
frame->particles = gpu_particles;
frame->cells = gpu_cells;
frame->stains = gpu_stains;
frame->drynesses = gpu_drynesses;
}
////////////////////////////// //////////////////////////////
//- Swap //- Swap
@ -741,14 +741,14 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Process controller events into vis cmds //- Process controller events into vis cmds
b32 has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box); frame->has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box);
b32 has_keyboard_focus = 1; frame->has_keyboard_focus = 1;
Vec2 mouse_delta = Zi; Vec2 mouse_delta = Zi;
{ {
if (!window_frame.has_focus) if (!window_frame.has_focus)
{ {
has_mouse_focus = 0; frame->has_mouse_focus = 0;
has_keyboard_focus = 0; frame->has_keyboard_focus = 0;
} }
//- Reset held buttons //- Reset held buttons
@ -756,14 +756,14 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
if (btn == Button_M1 || btn == Button_M2 || btn == Button_M3) if (btn == Button_M1 || btn == Button_M2 || btn == Button_M3)
{ {
if (!has_mouse_focus) if (!frame->has_mouse_focus)
{ {
frame->held_buttons[btn] = 0; frame->held_buttons[btn] = 0;
} }
} }
else else
{ {
if (!has_keyboard_focus) if (!frame->has_keyboard_focus)
{ {
frame->held_buttons[btn] = 0; frame->held_buttons[btn] = 0;
} }
@ -782,14 +782,14 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
if (cev.button == Button_M1 || cev.button == Button_M2 || cev.button == Button_M3) if (cev.button == Button_M1 || cev.button == Button_M2 || cev.button == Button_M3)
{ {
if (!has_mouse_focus) if (!frame->has_mouse_focus)
{ {
ignore = 1; ignore = 1;
} }
} }
else else
{ {
if (!has_keyboard_focus) if (!frame->has_keyboard_focus)
{ {
ignore = 1; ignore = 1;
} }
@ -860,7 +860,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
// TODO: Adjustable sensitivity // TODO: Adjustable sensitivity
f32 mouse_sensitivity = TweakFloat("Mouse sensitivity", 1.0, 0.1, 5.0); f32 mouse_sensitivity = TweakFloat("Mouse sensitivity", 1.0, 0.1, 5.0);
f32 mouse_scale_factor = 0.005; f32 mouse_scale_factor = 0.007;
look = frame->look; look = frame->look;
look = AddVec2(look, MulVec2(mouse_delta, mouse_sensitivity * mouse_scale_factor)); look = AddVec2(look, MulVec2(mouse_delta, mouse_sensitivity * mouse_scale_factor));
look = ClampVec2Len(look, look_radius); look = ClampVec2Len(look, look_radius);
@ -1903,7 +1903,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
local_world->tiles_hash = predict_world->tiles_hash; local_world->tiles_hash = predict_world->tiles_hash;
CopyStructs(local_world->tiles, predict_world->tiles, P_TilesCount); CopyStructs(local_world->tiles, predict_world->tiles, P_TilesCount);
tiles_dirty = 1; frame->tiles_dirty = 1;
} }
local_world->seed = predict_world->seed; local_world->seed = predict_world->seed;
@ -4428,7 +4428,7 @@ void V_TickForever(WaveLaneCtx *lane)
case V_CmdKind_clear_particles: case V_CmdKind_clear_particles:
{ {
should_clear_particles = 1; frame->should_clear_particles = 1;
} break; } break;
case V_CmdKind_test: case V_CmdKind_test:
@ -4444,7 +4444,41 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
////////////////////////////// //////////////////////////////
//- Setup gpu data //- Build gpu data
// Tiles
{
for (P_TileKind tile_kind = 0; tile_kind < P_TileKind_COUNT; ++tile_kind)
{
SPR_Sprite tile_sprite = Zi;
{
String tile_name = P_TileNameFromKind(tile_kind);
String sheet_name = StringF(frame->arena, "tile/%F.ase", FmtString(tile_name));
ResourceKey sheet_resource = ResourceKeyFromStore(&P_Resources, sheet_name);
SPR_SheetKey sheet = SPR_SheetKeyFromResource(sheet_resource);
tile_sprite = SPR_SpriteFromSheet(sheet, SPR_NilSpanKey, 0);
}
V_TileDesc tile_desc = Zi;
{
tile_desc.tex = tile_sprite.tex;
tile_desc.tex_slice_uv = DivRng2Vec2(tile_sprite.tex_rect, tile_sprite.tex_dims);
}
frame->tile_descs[tile_kind] = tile_desc;
}
}
// Upload tiles
if (frame->tiles_dirty)
{
// LogDebugF("Uploading tiles to gpu");
G_DumbMemoryLayoutSync(frame->cl, gpu_tiles_res, G_Layout_DirectQueue_CopyWrite);
G_CopyCpuToTexture(
frame->cl,
gpu_tiles_res, VEC3I32(0, 0, 0),
local_world->tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1),
RNG3I32(VEC3I32(0, 0, 0), VEC3I32(tiles_dims.x, tiles_dims.y, 1))
);
G_DumbMemoryLayoutSync(frame->cl, gpu_tiles_res, G_Layout_DirectQueue_ShaderRead);
}
// Screen texture // Screen texture
G_ResourceHandle screen_target = G_PushTexture2D( G_ResourceHandle screen_target = G_PushTexture2D(
@ -4455,7 +4489,7 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_AllowRenderTarget, .flags = G_ResourceFlag_AllowRenderTarget,
.name = StringF(frame->arena, "Screen target [%F]", FmtSint(frame->tick)) .name = StringF(frame->arena, "Screen target [%F]", FmtSint(frame->tick))
); );
G_Texture2DRef screen_target_ro = G_PushTexture2DRef(frame->gpu_arena, screen_target); frame->screen_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)); Rng3 screen_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->screen_dims.x, frame->screen_dims.y, 1));
Rng2 screen_scissor = RNG2(VEC2(screen_viewport.p0.x, screen_viewport.p0.y), VEC2(screen_viewport.p1.x, screen_viewport.p1.y)); Rng2 screen_scissor = RNG2(VEC2(screen_viewport.p0.x, screen_viewport.p0.y), VEC2(screen_viewport.p1.x, screen_viewport.p1.y));
@ -4468,7 +4502,7 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_AllowRenderTarget, .flags = G_ResourceFlag_AllowRenderTarget,
.name = StringF(frame->arena, "Albedo target [%F]", FmtSint(frame->tick)) .name = StringF(frame->arena, "Albedo target [%F]", FmtSint(frame->tick))
); );
G_Texture2DRef albedo_target_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target); frame->albedo_ro = G_PushTexture2DRef(frame->gpu_arena, albedo_target);
// Shade texture // Shade texture
G_ResourceHandle shade_target = G_PushTexture2D( G_ResourceHandle shade_target = G_PushTexture2D(
@ -4481,8 +4515,8 @@ void V_TickForever(WaveLaneCtx *lane)
// .flags = G_ResourceFlag_AllowShaderReadWrite | G_ResourceFlag_ForceNoReuse, // .flags = G_ResourceFlag_AllowShaderReadWrite | G_ResourceFlag_ForceNoReuse,
.name = StringF(frame->arena, "Shade target [%F]", FmtSint(frame->tick)) .name = StringF(frame->arena, "Shade target [%F]", FmtSint(frame->tick))
); );
G_Texture2DRef shade_target_ro = G_PushTexture2DRef(frame->gpu_arena, shade_target); frame->shade_ro = G_PushTexture2DRef(frame->gpu_arena, shade_target);
G_RWTexture2DRef shade_target_rw = G_PushRWTexture2DRef(frame->gpu_arena, shade_target); frame->shade_rw = G_PushRWTexture2DRef(frame->gpu_arena, shade_target);
Rng3 shade_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->shade_dims.x, frame->shade_dims.y, 1)); Rng3 shade_viewport = RNG3(VEC3(0, 0, 0), VEC3(frame->shade_dims.x, frame->shade_dims.y, 1));
Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y)); Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y));
@ -4492,7 +4526,7 @@ void V_TickForever(WaveLaneCtx *lane)
StringFromArena(frame->quads_arena), StringFromArena(frame->quads_arena),
.name = StringF(frame->arena, "quads [%F]", FmtSint(frame->tick)) .name = StringF(frame->arena, "quads [%F]", FmtSint(frame->tick))
); );
G_StructuredBufferRef quads_ref = G_PushStructuredBufferRef(frame->gpu_arena, quads_buff, V_Quad); frame->quads = G_PushStructuredBufferRef(frame->gpu_arena, quads_buff, V_Quad);
// Debug shape buffers // Debug shape buffers
G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy( G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy(
@ -4505,10 +4539,10 @@ void V_TickForever(WaveLaneCtx *lane)
StringFromArena(frame->dvert_idxs_arena), StringFromArena(frame->dvert_idxs_arena),
.name = StringF(frame->arena, "dvert idxs [%F]", FmtSint(frame->tick)) .name = StringF(frame->arena, "dvert idxs [%F]", FmtSint(frame->tick))
); );
G_StructuredBufferRef dverts_ref = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert); frame->dverts = G_PushStructuredBufferRef(frame->gpu_arena, dverts_buff, V_DVert);
G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff); G_IndexBufferDesc dvert_idxs_ib = G_IdxBuff32(dvert_idxs_buff);
// Emitters // Particles
G_ResourceHandle gpu_emitters = Zi; G_ResourceHandle gpu_emitters = Zi;
{ {
// Flatten emitters list // Flatten emitters list
@ -4527,113 +4561,30 @@ void V_TickForever(WaveLaneCtx *lane)
.name = StringF(frame->arena, "emitters [%F]", FmtSint(frame->tick)) .name = StringF(frame->arena, "emitters [%F]", FmtSint(frame->tick))
); );
} }
G_StructuredBufferRef gpu_emitters_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_emitters, V_Emitter); frame->emitters = G_PushStructuredBufferRef(frame->gpu_arena, gpu_emitters, V_Emitter);
// Params // Upload gpu frame data
V_GpuParams params = Zi;
{ {
params.dt = frame->dt; // Gpu frame
params.tick = frame->tick; G_ResourceHandle gpu_frame = G_PushBufferFromCpuCopy(
params.seed = RandU64FromState(&frame->rand); frame->gpu_arena, frame->cl,
params.af = frame->af; StringFromStruct(&frame->shared_frame),
.name = StringF(frame->arena, "Gpu frame [%F]", FmtSint(frame->tick))
params.selection_mode = frame->selection_mode;
params.equipped_tile = frame->equipped_tile;
params.has_mouse_focus = has_mouse_focus;
params.has_keyboard_focus = has_keyboard_focus;
params.screen_cursor = frame->screen_cursor;
params.shade_cursor = frame->shade_cursor;
params.world_cursor = frame->world_cursor;
params.screen_selection = frame->screen_selection;
params.shade_selection = frame->shade_selection;
params.world_selection = frame->world_selection;
params.screen_crosshair = frame->screen_crosshair;
params.shade_crosshair = frame->shade_crosshair;
params.world_crosshair = frame->world_crosshair;
params.camera_pos = frame->camera_pos;
params.camera_zoom = frame->camera_zoom;
params.pt_clamp_sampler = G_BasicPointClampSampler();
params.pt_wrap_sampler = G_BasicPointWrapSampler();
params.shade_dims = frame->shade_dims;
params.shade_ro = shade_target_ro;
params.shade_rw = shade_target_rw;
params.screen_dims = frame->screen_dims;
params.albedo_ro = albedo_target_ro;
params.tiles = gpu_tiles_ref;
params.quads = quads_ref;
params.shape_verts = dverts_ref;
params.emitters_count = frame->emitters_count;
params.emitters = gpu_emitters_ref;
params.particles = gpu_particles_ref;
params.should_clear_stains = should_clear_particles;
params.cells = gpu_cells_ref;
params.stains = gpu_stains_ref;
params.drynesses = gpu_drynesses_ref;
// Fill tile textures
{
for (P_TileKind tile_kind = 0; tile_kind < P_TileKind_COUNT; ++tile_kind)
{
SPR_Sprite tile_sprite = Zi;
{
String tile_name = P_TileNameFromKind(tile_kind);
String sheet_name = StringF(frame->arena, "tile/%F.ase", FmtString(tile_name));
ResourceKey sheet_resource = ResourceKeyFromStore(&P_Resources, sheet_name);
SPR_SheetKey sheet = SPR_SheetKeyFromResource(sheet_resource);
tile_sprite = SPR_SpriteFromSheet(sheet, SPR_NilSpanKey, 0);
}
V_TileDesc tile_desc = Zi;
{
tile_desc.tex = tile_sprite.tex;
tile_desc.tex_slice_uv = DivRng2Vec2(tile_sprite.tex_rect, tile_sprite.tex_dims);
}
params.tile_descs[tile_kind] = tile_desc;
}
}
}
G_ResourceHandle gpu_params = G_PushBufferFromCpuCopy(
frame->gpu_arena, frame->cl,
StringFromStruct(&params),
.name = 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
if (tiles_dirty)
{
// LogDebugF("Uploading tiles to gpu");
G_DumbMemoryLayoutSync(frame->cl, gpu_tiles, G_Layout_DirectQueue_CopyWrite);
G_CopyCpuToTexture(
frame->cl,
gpu_tiles, VEC3I32(0, 0, 0),
local_world->tiles, VEC3I32(tiles_dims.x, tiles_dims.y, 1),
RNG3I32(VEC3I32(0, 0, 0), VEC3I32(tiles_dims.x, tiles_dims.y, 1))
); );
G_DumbMemoryLayoutSync(frame->cl, gpu_tiles, G_Layout_DirectQueue_ShaderRead); G_StructuredBufferRef gpu_frame_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_frame, V_SharedFrame);
}
// Flags // Gpu flags
V_GpuFlag gpu_flags = 0; V_GpuFlag gpu_flags = 0;
if (frame->show_console) if (frame->show_console)
{ {
gpu_flags |= V_GpuFlag_DebugDraw; gpu_flags |= V_GpuFlag_DebugDraw;
} }
// Constants // Set constants
G_SetConstant(frame->cl, V_ShaderConst_GpuFlags, gpu_flags); G_SetConstant(frame->cl, V_ShaderConst_GpuFlags, gpu_flags);
G_SetConstant(frame->cl, V_ShaderConst_State, gpu_state_ref); G_SetConstant(frame->cl, V_ShaderConst_Frame, gpu_frame_ref);
G_SetConstant(frame->cl, V_ShaderConst_Params, gpu_params_ref); G_SetConstant(frame->cl, V_ShaderConst_NoiseTex, G_BasicNoiseTexture());
G_SetConstant(frame->cl, V_ShaderConst_NoiseTex, G_BasicNoiseTexture()); }
// Sync // Sync
G_DumbGlobalMemorySync(frame->cl); G_DumbGlobalMemorySync(frame->cl);
@ -4649,7 +4600,7 @@ void V_TickForever(WaveLaneCtx *lane)
G_Compute(frame->cl, V_PrepareCellsCS, V_ThreadGroupSizeFromTexSize(cells_dims)); G_Compute(frame->cl, V_PrepareCellsCS, V_ThreadGroupSizeFromTexSize(cells_dims));
// Clear particles // Clear particles
if (should_clear_particles) if (frame->should_clear_particles)
{ {
G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap)); G_Compute(frame->cl, V_ClearParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap));
} }
@ -4686,7 +4637,7 @@ void V_TickForever(WaveLaneCtx *lane)
G_Compute(frame->cl, V_EmitParticlesCS, V_ThreadGroupSizeFromBufferSize(frame->emitters_count)); G_Compute(frame->cl, V_EmitParticlesCS, V_ThreadGroupSizeFromBufferSize(frame->emitters_count));
// Barrier particles buffer // Barrier particles buffer
G_DumbMemorySync(frame->cl, gpu_particles); G_DumbMemorySync(frame->cl, gpu_particles_res);
// Simulate particles // Simulate particles
G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap)); G_Compute(frame->cl, V_SimParticlesCS, V_ThreadGroupSizeFromBufferSize(V_ParticlesCap));
@ -4749,7 +4700,7 @@ void V_TickForever(WaveLaneCtx *lane)
uv.p0 = Vec2FromVec(screen_viewport.p0); uv.p0 = Vec2FromVec(screen_viewport.p0);
uv.p1 = Vec2FromVec(screen_viewport.p1); uv.p1 = Vec2FromVec(screen_viewport.p1);
uv = DivRng2Vec2(uv, Vec2FromVec(frame->screen_dims)); uv = DivRng2Vec2(uv, Vec2FromVec(frame->screen_dims));
UI_SetRawTexture(vis_box, screen_target_ro, uv); UI_SetRawTexture(vis_box, frame->screen_ro, uv);
} }
} }

View File

@ -215,12 +215,6 @@ Enum(V_DrawFlag)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ State types //~ State types
Enum(V_EditMode)
{
V_EditMode_None,
V_EditMode_Tile,
};
Struct(V_Frame) Struct(V_Frame)
{ {
Arena *arena; Arena *arena;
@ -230,77 +224,25 @@ Struct(V_Frame)
G_ArenaHandle gpu_arena; G_ArenaHandle gpu_arena;
G_CommandListHandle cl; G_CommandListHandle cl;
i64 tick; Embed(V_SharedFrame, shared_frame);
i64 time_ns;
i64 dt_ns;
f64 dt;
RandState rand; RandState rand;
NET_Key sim_key; NET_Key sim_key;
NET_Key desired_sim_key; NET_Key desired_sim_key;
f64 predict_tick_accum;
Button held_buttons[Button_COUNT]; Button held_buttons[Button_COUNT];
V_Palette palette; V_Palette palette;
String window_restore; String window_restore;
i32 zooms;
Vec2 screen_dims;
Vec2 shade_dims;
// Modes
b32 is_editing;
b32 ui_debug;
b32 show_console;
// Editor state
V_EditMode edit_mode;
P_TileKind equipped_tile;
// Editor
b32 is_selecting;
b32 is_panning;
V_SelectionMode selection_mode;
Vec2 world_selection_start;
Vec2 edit_camera_pos;
f32 edit_camera_zoom;
// Camera
f32 camera_lerp_rate;
Vec2 camera_pos;
f32 camera_zoom;
// affines;
V_Affines af;
// Cursor
Vec2 screen_cursor;
Vec2 shade_cursor;
Vec2 world_cursor;
Rng2 screen_selection;
Rng2 shade_selection;
Rng2 world_selection;
// Crosshair
Vec2 screen_crosshair;
Vec2 shade_crosshair;
Vec2 world_crosshair;
// Vis commands // Vis commands
i64 cmds_count; i64 cmds_count;
V_CmdNode *first_cmd_node; V_CmdNode *first_cmd_node;
V_CmdNode *last_cmd_node; V_CmdNode *last_cmd_node;
f64 predict_tick_accum; // Unflattened emitters list
// Control
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
// Emitters
i64 emitters_count;
V_EmitterNode *first_emitter_node; V_EmitterNode *first_emitter_node;
V_EmitterNode *last_emitter_node; V_EmitterNode *last_emitter_node;
}; };
@ -320,7 +262,7 @@ Struct(V_Ctx)
V_Notif *first_notif; V_Notif *first_notif;
V_Notif *last_notif; V_Notif *last_notif;
// Atomic monotonically increasing allocation counter sequence for GPU particle ring buffer // Monotonically increasing allocation counter sequence for GPU particle ring buffer
u32 particle_seq; u32 particle_seq;
Atomic32 shutdown; Atomic32 shutdown;

View File

@ -23,8 +23,8 @@ Vec4 V_DryColor(Vec4 color, f32 dryness)
//- Prepare shade //- Prepare shade
ComputeShader2D(V_PrepareShadeCS, 8, 8) ComputeShader2D(V_PrepareShadeCS, 8, 8)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWTexture2D<Vec4> shade = G_Dereference<Vec4>(params.shade_rw); RWTexture2D<Vec4> shade = G_Dereference<Vec4>(frame.shade_rw);
Vec2 shade_pos = SV_DispatchThreadID; Vec2 shade_pos = SV_DispatchThreadID;
if (all(shade_pos < countof(shade))) if (all(shade_pos < countof(shade)))
@ -37,9 +37,9 @@ ComputeShader2D(V_PrepareShadeCS, 8, 8)
//- Prepare cells //- Prepare cells
ComputeShader2D(V_PrepareCellsCS, 8, 8) ComputeShader2D(V_PrepareCellsCS, 8, 8)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells); RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses); RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
Vec2 cells_pos = SV_DispatchThreadID; Vec2 cells_pos = SV_DispatchThreadID;
if (all(cells_pos < countof(cells))) if (all(cells_pos < countof(cells)))
{ {
@ -47,7 +47,8 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
cells[cells_pos] = 0; cells[cells_pos] = 0;
// Increase dryness // Increase dryness
f32 dry_rate = params.dt * 0.1; // TODO: Use simulation dt
f32 dry_rate = frame.dt * 0.1;
{ {
f32 old_dryness = drynesses[cells_pos]; f32 old_dryness = drynesses[cells_pos];
f32 new_dryness = lerp(old_dryness, 1, dry_rate); f32 new_dryness = lerp(old_dryness, 1, dry_rate);
@ -55,9 +56,9 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
} }
// Clear stain // Clear stain
if (params.should_clear_stains) if (frame.should_clear_stains)
{ {
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains); RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
stains[cells_pos] = 0; stains[cells_pos] = 0;
drynesses[cells_pos] = 0; drynesses[cells_pos] = 0;
} }
@ -67,8 +68,8 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
//- Clear particles //- Clear particles
ComputeShader(V_ClearParticlesCS, 64) ComputeShader(V_ClearParticlesCS, 64)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles); RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
u32 particle_idx = SV_DispatchThreadID; u32 particle_idx = SV_DispatchThreadID;
if (particle_idx < V_ParticlesCap) if (particle_idx < V_ParticlesCap)
{ {
@ -84,8 +85,8 @@ ComputeShader(V_ClearParticlesCS, 64)
VertexShader(V_QuadVS, V_QuadPSInput) VertexShader(V_QuadVS, V_QuadPSInput)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(params.quads); StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(frame.quads);
V_Quad quad = quads[SV_InstanceID]; V_Quad quad = quads[SV_InstanceID];
@ -95,7 +96,7 @@ VertexShader(V_QuadVS, V_QuadPSInput)
Vec2 samp_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv); Vec2 samp_uv = lerp(quad.tex_slice_uv.p0, quad.tex_slice_uv.p1, rect_uv);
V_QuadPSInput result; V_QuadPSInput result;
result.sv_position = Vec4(NdcFromPos(screen_pos, params.screen_dims).xy, 0, 1); result.sv_position = Vec4(NdcFromPos(screen_pos, frame.screen_dims).xy, 0, 1);
result.quad_idx = SV_InstanceID; result.quad_idx = SV_InstanceID;
result.samp_uv = samp_uv; result.samp_uv = samp_uv;
return result; return result;
@ -106,9 +107,9 @@ VertexShader(V_QuadVS, V_QuadPSInput)
PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input) PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(params.quads); StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(frame.quads);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler); SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
V_Quad quad = quads[input.quad_idx]; V_Quad quad = quads[input.quad_idx];
@ -130,13 +131,12 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
ComputeShader(V_EmitParticlesCS, 64) ComputeShader(V_EmitParticlesCS, 64)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWStructuredBuffer<V_GpuState> state_buff = G_Dereference<V_GpuState>(V_ShaderConst_State); StructuredBuffer<V_Emitter> emitters = G_Dereference<V_Emitter>(frame.emitters);
StructuredBuffer<V_Emitter> emitters = G_Dereference<V_Emitter>(params.emitters); RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
u32 emitter_idx = SV_DispatchThreadID; u32 emitter_idx = SV_DispatchThreadID;
if (emitter_idx < params.emitters_count) if (emitter_idx < frame.emitters_count)
{ {
V_Emitter emitter = emitters[emitter_idx]; V_Emitter emitter = emitters[emitter_idx];
for (u32 i = 0; i < emitter.count; ++i) for (u32 i = 0; i < emitter.count; ++i)
@ -155,11 +155,11 @@ ComputeShader(V_EmitParticlesCS, 64)
ComputeShader(V_SimParticlesCS, 64) ComputeShader(V_SimParticlesCS, 64)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles); RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells); RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains); RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses); RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
u32 particle_idx = SV_DispatchThreadID; u32 particle_idx = SV_DispatchThreadID;
if (particle_idx < V_ParticlesCap) if (particle_idx < V_ParticlesCap)
@ -172,7 +172,7 @@ ComputeShader(V_SimParticlesCS, 64)
if (particle.emitter_init_num != 0) if (particle.emitter_init_num != 0)
{ {
V_Emitter emitter = G_Dereference<V_Emitter>(params.emitters)[particle.emitter_init_num - 1]; V_Emitter emitter = G_Dereference<V_Emitter>(frame.emitters)[particle.emitter_init_num - 1];
u64 seed0 = MixU64(particle.seq); u64 seed0 = MixU64(particle.seq);
u64 seed1 = MixU64(seed0); u64 seed1 = MixU64(seed0);
@ -214,14 +214,15 @@ ComputeShader(V_SimParticlesCS, 64)
f32 prev_exists = particle.exists; f32 prev_exists = particle.exists;
{ {
Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(particle.pos, 1)); Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells)); b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells));
// Simulate // Simulate
{ {
particle.pos += particle.velocity * params.dt; // TODO: Use simulation dt
particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * params.dt); particle.pos += particle.velocity * frame.dt;
particle.exists -= params.dt / particle.lifetime; particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * frame.dt);
particle.exists -= frame.dt / particle.lifetime;
if ((particle.flags & V_ParticleFlag_PruneWhenStill) && (dot(particle.velocity, particle.velocity) < (0.1 * 0.1))) if ((particle.flags & V_ParticleFlag_PruneWhenStill) && (dot(particle.velocity, particle.velocity) < (0.1 * 0.1)))
{ {
particle.exists = 0; particle.exists = 0;
@ -239,10 +240,10 @@ ComputeShader(V_SimParticlesCS, 64)
// FIXME: Atomic writes // FIXME: Atomic writes
{ {
Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(particle.pos, 1)); Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(particle.pos, 1));
Vec2 screen_pos = mul(params.af.world_to_screen, Vec3(particle.pos, 1)); Vec2 screen_pos = mul(frame.af.world_to_screen, Vec3(particle.pos, 1));
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells)); 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); b32 is_in_screen = all(screen_pos >= 0) && all(screen_pos < frame.screen_dims);
Vec4 color = particle.color; Vec4 color = particle.color;
color.a *= prev_exists; color.a *= prev_exists;
@ -295,18 +296,18 @@ ComputeShader(V_SimParticlesCS, 64)
ComputeShader2D(V_ShadeCS, 8, 8) ComputeShader2D(V_ShadeCS, 8, 8)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_rw); RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_rw);
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro); Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles); Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains); RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses); RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler); SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
Vec2 shade_pos = SV_DispatchThreadID + Vec2(0.5, 0.5); Vec2 shade_pos = SV_DispatchThreadID + Vec2(0.5, 0.5);
Vec2 world_pos = mul(params.af.shade_to_world, Vec3(shade_pos, 1)); Vec2 world_pos = mul(frame.af.shade_to_world, Vec3(shade_pos, 1));
Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(world_pos, 1)); Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 1));
Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); P_TileKind tile = tiles.Load(Vec3(tile_pos, 0));
@ -351,28 +352,28 @@ VertexShader(V_CompositeVS, V_CompositePSInput)
PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
// Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_ro); // Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_ro);
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro); Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains); RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells); RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses); RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles); Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler); SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
Vec2 screen_pos = input.sv_position.xy; Vec2 screen_pos = input.sv_position.xy;
Vec2 world_pos = mul(params.af.screen_to_world, Vec3(screen_pos, 1)); Vec2 world_pos = mul(frame.af.screen_to_world, Vec3(screen_pos, 1));
Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1)); Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
Vec2 cell_pos = mul(params.af.world_to_cell, Vec3(world_pos, 1)); Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 1));
Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1)); Vec2 shade_pos = mul(frame.af.screen_to_shade, Vec3(screen_pos.xy, 1));
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; 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_p0 = mul(frame.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)); Vec2 world_bounds_screen_p1 = mul(frame.af.world_to_screen, Vec3(half_world_dims.xy, 1));
b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells)); b32 is_in_world = all(cell_pos >= 0) && all(cell_pos < countof(cells));
P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); P_TileKind tile = tiles.Load(Vec3(tile_pos, 0));
P_TileKind equipped_tile = params.equipped_tile; P_TileKind equipped_tile = frame.equipped_tile;
////////////////////////////// //////////////////////////////
//- World color //- World color
@ -432,7 +433,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
} }
else if (tile != P_TileKind_Empty) else if (tile != P_TileKind_Empty)
{ {
V_TileDesc tile_desc = params.tile_descs[tile]; V_TileDesc tile_desc = frame.tile_descs[tile];
Texture2D<Vec4> tile_tex = G_Dereference<Vec4>(tile_desc.tex); Texture2D<Vec4> tile_tex = G_Dereference<Vec4>(tile_desc.tex);
Vec2 tile_samp_uv = lerp(tile_desc.tex_slice_uv.p0, tile_desc.tex_slice_uv.p1, frac(world_pos)); 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); tile_color = tile_tex.SampleLevel(clamp_sampler, tile_samp_uv, 0);
@ -525,18 +526,18 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
//- Tile selection overlay //- Tile selection overlay
Vec4 selection_color = 0; Vec4 selection_color = 0;
if (params.has_mouse_focus && params.selection_mode == V_SelectionMode_Tile) if (frame.has_mouse_focus && frame.selection_mode == V_SelectionMode_Tile)
{ {
Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1)); 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.4, 0.4, 0.25));
Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6)); Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6));
Rng2 screen_selection = params.screen_selection; Rng2 screen_selection = frame.screen_selection;
Rng2 world_selection = params.world_selection; Rng2 world_selection = frame.world_selection;
Rng2 tile_selection; Rng2 tile_selection;
tile_selection.p0 = floor(mul(params.af.world_to_tile, Vec3(world_selection.p0, 1))); tile_selection.p0 = floor(mul(frame.af.world_to_tile, Vec3(world_selection.p0, 1)));
tile_selection.p1 = ceil(mul(params.af.world_to_tile, Vec3(world_selection.p1, 1))); tile_selection.p1 = ceil(mul(frame.af.world_to_tile, Vec3(world_selection.p1, 1)));
f32 dist = 100000000; f32 dist = 100000000;
dist = min(dist, screen_pos.x - screen_selection.p0.x); dist = min(dist, screen_pos.x - screen_selection.p0.x);
@ -580,8 +581,8 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw)
{ {
const Vec4 line_color = LinearFromSrgb(Vec4(1, 1, 1, 0.1)); 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_p0 = mul(frame.af.world_to_screen, Vec3(floor(world_pos), 1));
Vec2 line_screen_p1 = mul(params.af.world_to_screen, Vec3(ceil(world_pos), 1)); Vec2 line_screen_p1 = mul(frame.af.world_to_screen, Vec3(ceil(world_pos), 1));
f32 line_dist = 100000; 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_p0.x));
line_dist = min(line_dist, abs(screen_pos.x - line_screen_p1.x)); line_dist = min(line_dist, abs(screen_pos.x - line_screen_p1.x));
@ -599,7 +600,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1)); const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1));
const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 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)); Vec2 zero_screen = mul(frame.af.world_to_screen, Vec3(0, 0, 1));
f32 x_dist = abs(screen_pos.x - zero_screen.x); f32 x_dist = abs(screen_pos.x - zero_screen.x);
f32 y_dist = abs(screen_pos.y - zero_screen.y); f32 y_dist = abs(screen_pos.y - zero_screen.y);
if (y_dist <= half_thickness) if (y_dist <= half_thickness)
@ -637,7 +638,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
Vec4 crosshair_color = 0; Vec4 crosshair_color = 0;
{ {
f32 dist = length(params.screen_crosshair - screen_pos); f32 dist = length(frame.screen_crosshair - screen_pos);
if (dist < 4) if (dist < 4)
{ {
// Adaptive crosshair color based on underlying luminance // Adaptive crosshair color based on underlying luminance
@ -686,15 +687,15 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
VertexShader(V_DVertVS, V_DVertPSInput) VertexShader(V_DVertVS, V_DVertPSInput)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(params.shape_verts); StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(frame.dverts);
V_DVert vert = verts[SV_VertexID]; V_DVert vert = verts[SV_VertexID];
Vec2 screen_pos = vert.pos; Vec2 screen_pos = vert.pos;
V_DVertPSInput result; V_DVertPSInput result;
result.sv_position = Vec4(NdcFromPos(screen_pos, params.screen_dims).xy, 0, 1); result.sv_position = Vec4(NdcFromPos(screen_pos, frame.screen_dims).xy, 0, 1);
result.color_lin = vert.color_lin; result.color_lin = vert.color_lin;
return result; return result;
} }

View File

@ -4,7 +4,7 @@
// #define V_ParticlesCap Mebi(16) // #define V_ParticlesCap Mebi(16)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Constant types //~ State types
Enum(V_GpuFlag) Enum(V_GpuFlag)
{ {
@ -13,9 +13,14 @@ Enum(V_GpuFlag)
}; };
G_DeclConstant(V_GpuFlag, V_ShaderConst_GpuFlags, 0); G_DeclConstant(V_GpuFlag, V_ShaderConst_GpuFlags, 0);
G_DeclConstant(G_RWStructuredBufferRef, V_ShaderConst_State, 1); G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Frame, 1);
G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 2); G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 2);
G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 3);
Struct(V_TileDesc)
{
G_Texture2DRef tex;
Rng2 tex_slice_uv;
};
Enum(V_SelectionMode) Enum(V_SelectionMode)
{ {
@ -23,6 +28,12 @@ Enum(V_SelectionMode)
V_SelectionMode_Tile, V_SelectionMode_Tile,
}; };
Enum(V_EditMode)
{
V_EditMode_None,
V_EditMode_Tile,
};
Struct(V_Affines) Struct(V_Affines)
{ {
// World <-> screen // World <-> screen
@ -46,64 +57,91 @@ Struct(V_Affines)
Affine tile_to_world; Affine tile_to_world;
}; };
Struct(V_TileDesc) Struct(V_SharedFrame)
{ {
G_Texture2DRef tex; //- Time
Rng2 tex_slice_uv;
};
Struct(V_GpuState) i64 tick;
{ i64 time_ns;
// u32 particle_seq; // Atomic monotonically increasing allocation counter sequence for particle ring buffer i64 dt_ns;
i32 _;
};
Struct(V_GpuParams)
{
// TODO: Use simulation dt
f32 dt; f32 dt;
u64 tick;
u64 seed;
V_Affines af;
V_SelectionMode selection_mode; //- Modes
P_TileKind equipped_tile;
b32 tiles_dirty;
b32 should_clear_particles;
b32 is_editing;
b32 ui_debug;
b32 show_console;
b32 is_selecting;
b32 is_panning;
b32 has_mouse_focus; b32 has_mouse_focus;
b32 has_keyboard_focus; b32 has_keyboard_focus;
//- Editor state
V_EditMode edit_mode;
P_TileKind equipped_tile;
V_SelectionMode selection_mode;
Vec2 world_selection_start;
Vec2 edit_camera_pos;
f32 edit_camera_zoom;
//- Camera
i32 zooms;
f32 camera_lerp_rate;
Vec2 camera_pos;
f32 camera_zoom;
//- Dims
Vec2 screen_dims;
Vec2 shade_dims;
//- Affines
V_Affines af;
//- Cursor
Vec2 screen_cursor; Vec2 screen_cursor;
Vec2 shade_cursor; Vec2 shade_cursor;
Vec2 world_cursor; Vec2 world_cursor;
Rng2 screen_selection; Rng2 screen_selection;
Rng2 shade_selection; Rng2 shade_selection;
Rng2 world_selection; Rng2 world_selection;
//- Crosshair
Vec2 screen_crosshair; Vec2 screen_crosshair;
Vec2 shade_crosshair; Vec2 shade_crosshair;
Vec2 world_crosshair; Vec2 world_crosshair;
Vec2 camera_pos; //- Control
f32 camera_zoom;
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
//- Gpu data
G_SamplerStateRef pt_clamp_sampler; G_SamplerStateRef pt_clamp_sampler;
G_SamplerStateRef pt_wrap_sampler; G_SamplerStateRef pt_wrap_sampler;
Vec2 screen_dims; V_TileDesc tile_descs[P_TileKind_COUNT];
G_Texture2DRef tiles;
Vec2 shade_dims; G_Texture2DRef screen_ro;
G_Texture2DRef shade_ro; G_Texture2DRef shade_ro;
G_RWTexture2DRef shade_rw; G_RWTexture2DRef shade_rw;
G_Texture2DRef albedo_ro; G_Texture2DRef albedo_ro;
G_RWTexture2DRef albedo_rw; G_RWTexture2DRef albedo_rw;
G_Texture2DRef tiles;
G_StructuredBufferRef quads;
G_StructuredBufferRef shape_verts;
u32 emitters_count; u32 emitters_count;
G_StructuredBufferRef emitters; G_StructuredBufferRef emitters;
G_RWStructuredBufferRef particles; G_RWStructuredBufferRef particles;
b32 should_clear_stains; b32 should_clear_stains;
@ -111,7 +149,8 @@ Struct(V_GpuParams)
G_RWTexture2DRef stains; G_RWTexture2DRef stains;
G_RWTexture2DRef drynesses; G_RWTexture2DRef drynesses;
V_TileDesc tile_descs[P_TileKind_COUNT]; G_StructuredBufferRef dverts;
G_StructuredBufferRef quads;
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -202,7 +241,6 @@ Struct(V_DVert)
Vec4 color_lin; Vec4 color_lin;
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Helpers //~ Helpers

View File

@ -313,7 +313,7 @@ SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64
if (slice_ready) if (slice_ready)
{ {
result.tex_dims = Vec2FromVec(slice->atlas->dims); result.tex_dims = Vec2FromVec(slice->atlas->dims);
result.tex = slice->atlas->tex_ref; result.tex = slice->atlas->tex;
result.tex_rect = RNG2(slice->atlas_pos, AddVec2(slice->atlas_pos, DimsFromRng2(slice->canvas_rect))); result.tex_rect = RNG2(slice->atlas_pos, AddVec2(slice->atlas_pos, DimsFromRng2(slice->canvas_rect)));
} }
else else
@ -425,14 +425,14 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
atlas->dims = VEC2I32(atlas_size, atlas_size); atlas->dims = VEC2I32(atlas_size, atlas_size);
{ {
G_ArenaHandle gpu_perm = G_PermArena(); G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex = G_PushTexture2D( atlas->tex_res = G_PushTexture2D(
gpu_perm, cl, gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb, G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims, atlas->dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
.name = Lit("Sprite atlas") .name = Lit("Sprite atlas")
); );
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex); atlas->tex = G_PushTexture2DRef(gpu_perm, atlas->tex_res);
} }
SllStackPush(SPR.first_atlas, atlas); SllStackPush(SPR.first_atlas, atlas);
++SPR.atlases_count; ++SPR.atlases_count;
@ -466,7 +466,7 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
// Copy to atlas // Copy to atlas
G_CopyCpuToTexture( G_CopyCpuToTexture(
cl, cl,
atlas->tex, VEC3I32(atlas_pos.x, atlas_pos.y, 0), atlas->tex_res, VEC3I32(atlas_pos.x, atlas_pos.y, 0),
composite.pixels, VEC3I32(slice_dims.x, slice_dims.y, 1), composite.pixels, VEC3I32(slice_dims.x, slice_dims.y, 1),
RNG3I32( RNG3I32(
VEC3I32(0, 0, 0), VEC3I32(0, 0, 0),

View File

@ -15,8 +15,8 @@ Struct(SPR_Atlas)
SPR_Atlas *next; SPR_Atlas *next;
Vec2I32 dims; Vec2I32 dims;
G_ResourceHandle tex; G_ResourceHandle tex_res;
G_Texture2DRef tex_ref; G_Texture2DRef tex;
Vec2I32 cur_pos; Vec2I32 cur_pos;
i32 cur_row_height; i32 cur_row_height;
}; };

View File

@ -380,7 +380,7 @@ Struct(UI_Frame)
i64 tick; i64 tick;
i64 time_ns; i64 time_ns;
i64 dt_ns; i64 dt_ns;
f64 dt; f32 dt;
// Control // Control
Vec2 cursor_pos; Vec2 cursor_pos;