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
#endif
//- Embed
#define Embed(type, name) union { type; type name; }
//- alignof
#if IsLanguageC && (IsCompilerMsvc || __STDC_VERSION__ < 202311L)
#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);
Rng2 bounds = glyph->bounds;
rect->tex = glyph->atlas->tex_ref;
rect->tex = glyph->atlas->tex;
rect->tex_slice = glyph->atlas_slice;
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);
{
G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex = G_PushTexture2D(
atlas->tex_res = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
.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);
++GC.atlases_count;
@ -358,7 +358,7 @@ void GC_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
{
G_CopyCpuToTexture(
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),
RNG3I32(
VEC3I32(0, 0, 0),

View File

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

View File

@ -1,21 +1,21 @@
#include "meta.h"
BuildCtx Build = Zi;
M_Ctx M = Zi;
////////////////////////////////////////////////////////////
//~ 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();
{
@ -25,19 +25,19 @@ void EchoLine(String msg)
EndScratch(scratch);
}
void EchoLineOrNothing(String msg)
void M_EchoLineOrNothing(String msg)
{
String trimmed_msg = TrimWhitespace(msg);
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();
LineCol result = Zi;
M_LineCol result = Zi;
for (u64 cur = 0; cur < data.len && cur <= (u64)pos; ++cur)
{
u8 c = data.text[cur];
@ -56,7 +56,7 @@ LineCol LineColFromPos(String data, i64 pos)
return result;
}
String StringFromMetaErrors(Arena *arena, M_ErrorList errors)
String M_StringFromMetaErrors(Arena *arena, M_ErrorList errors)
{
TempArena scratch = BeginScratch(arena);
@ -78,10 +78,10 @@ String StringFromMetaErrors(Arena *arena, M_ErrorList errors)
{
token_pos = token->s.text - token_file_data.text;
}
LineCol line_col = Zi;
M_LineCol line_col = Zi;
if (token_pos >= 0)
{
line_col = LineColFromPos(token_file_data, token_pos);
line_col = M_LineColFromPos(token_file_data, token_pos);
}
String formatted = StringF(
scratch.arena,
@ -105,10 +105,10 @@ String StringFromMetaErrors(Arena *arena, M_ErrorList errors)
return result;
}
EmbedObj Embed(String store_name, String dir_path)
M_EmbedObj M_Embed(String store_name, String dir_path)
{
Arena *perm = PermArena();
EmbedObj result = Zi;
M_EmbedObj result = Zi;
// Generate resource archive contents
u64 store_hash = HashString(store_name);
@ -239,7 +239,7 @@ EmbedObj Embed(String store_name, String dir_path)
result.return_code = cmd_result.code;
}
SetBuildStatus(result.return_code);
M_SetBuildStatus(result.return_code);
}
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();
@ -297,8 +297,8 @@ void BuildEntryPoint(WaveLaneCtx *lane)
}
else
{
EchoLine(Lit("Metaprogram is dirty"));
ExitNow(MetaRebuildCode);
M_EchoLine(Lit("Metaprogram is dirty"));
ExitNow(M_RebuildCode);
}
}
@ -326,7 +326,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
layer_name = Lit("pp");
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;
@ -334,13 +334,13 @@ void BuildEntryPoint(WaveLaneCtx *lane)
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
CompilerParams cp = Zi;
M_CompilerParams cp = Zi;
{
//- Common
{
@ -452,7 +452,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
// Phase 2/3: Compile (wide)
// - Compile C
// - Compile & embed shaders
// - Embed resource dirs
// - M_Embed resource dirs
//
// Phase 3/3: Link (narrow)
// - 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)));
u64 shader_store_hash = HashString(shader_store_name);
if (lane->idx == 0 && GetBuildStatus() == 0)
if (lane->idx == 0 && M_GetBuildStatus() == 0)
{
//- Parse layers
{
@ -479,9 +479,9 @@ void BuildEntryPoint(WaveLaneCtx *lane)
// Flatten
StringList starting_layer_names = Zi;
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
@ -491,7 +491,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
StringList c_include_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_Token *entry_tok = entry->name_token;
@ -518,12 +518,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
else
{
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
{
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;
case M_EntryKind_VertexShader:
@ -543,7 +543,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
}
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;
case M_EntryKind_IncludeC:
@ -562,12 +562,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
else
{
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
{
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;
case M_EntryKind_Bootstrap:
@ -580,13 +580,13 @@ void BuildEntryPoint(WaveLaneCtx *lane)
}
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;
}
}
}
if (Build.c_parse.errors.count == 0)
if (M.c_parse.errors.count == 0)
{
StringList c_out_lines = Zi;
PushStringToList(perm, &c_out_lines, Lit("// Auto generated file"));
@ -645,7 +645,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
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
@ -677,7 +677,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
{
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_Token *entry_tok = entry->name_token;
@ -702,12 +702,12 @@ void BuildEntryPoint(WaveLaneCtx *lane)
else
{
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
{
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;
case M_EntryKind_VertexShader:
@ -716,26 +716,26 @@ void BuildEntryPoint(WaveLaneCtx *lane)
{
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_ComputeShader ? ShaderEntryKind_CS
: ShaderEntryKind_VS;
String shader_name = arg0_tok->s;
ShaderEntry *e = PushStruct(perm, ShaderEntry);
M_ShaderEntry *e = PushStruct(perm, M_ShaderEntry);
e->kind = shader_kind;
e->name = shader_name;
SllQueuePush(Build.gpu_parse.first_shader_entry, Build.gpu_parse.last_shader_entry, e);
++Build.gpu_parse.shader_entries_count;
SllQueuePush(M.gpu_parse.first_shader_entry, M.gpu_parse.last_shader_entry, e);
++M.gpu_parse.shader_entries_count;
}
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;
}
}
}
if (Build.gpu_parse.errors.count == 0)
if (M.gpu_parse.errors.count == 0)
{
StringList gpu_out_lines = Zi;
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
{
// 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_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)));
if (F_IsDir(full))
{
ResDir *rd = PushStruct(perm, ResDir);
M_ResDir *rd = PushStruct(perm, M_ResDir);
rd->store_name = store_name;
rd->dir_path = full;
SllQueuePush(Build.res_dir_parse.first_res_dir, Build.res_dir_parse.last_res_dir, rd);
++Build.res_dir_parse.res_dirs_count;
SllQueuePush(M.res_dir_parse.first_res_dir, M.res_dir_parse.last_res_dir, rd);
++M.res_dir_parse.res_dirs_count;
}
else
{
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
{
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;
}
}
SetBuildStatus(Build.res_dir_parse.errors.count > 0);
M_SetBuildStatus(M.res_dir_parse.errors.count > 0);
}
//- Prep obj arrays
{
// Gpu objs
Build.gpu_objs.count = Build.gpu_parse.shader_entries_count;
Build.gpu_objs.array = PushStructs(perm, GpuObj, Build.gpu_objs.count);
M.gpu_objs.count = M.gpu_parse.shader_entries_count;
M.gpu_objs.array = PushStructs(perm, M_GpuObj, M.gpu_objs.count);
// Embed objs
Build.embed_objs.count += Build.res_dir_parse.res_dirs_count;
if (Build.gpu_parse.shader_entries_count > 0)
// M_Embed objs
M.embed_objs.count += M.res_dir_parse.res_dirs_count;
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
{
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(
perm,
"cl.exe /c %F -Fo:%F %F %F %F %F",
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.compiler_only_flags_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);
String cmd_output = TrimWhitespace(cmd_result.output);
Build.c_obj.output = cmd_output;
Build.c_obj.return_code = cmd_result.code;
M.c_obj.output = cmd_output;
M.c_obj.return_code = cmd_result.code;
// 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
{
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;
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 target = e->kind == ShaderEntryKind_VS ? Lit("vs_6_6")
: e->kind == ShaderEntryKind_PS ? Lit("ps_6_6")
: e->kind == ShaderEntryKind_CS ? Lit("cs_6_6")
: Lit("vs_6_6");
String target = (
e->kind == ShaderEntryKind_VS ? Lit("vs_6_6") :
e->kind == ShaderEntryKind_PS ? Lit("ps_6_6") :
Lit("cs_6_6")
);
String compile_cmd = StringF(
perm,
"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->return_code = cmd_result.code;
SetBuildStatus(gpu_obj->return_code);
M_SetBuildStatus(gpu_obj->return_code);
// Final shader compilation lane embeds shader archive
u32 finished_count = Atomic32FetchAdd(&Build.gpu_objs.finished_count, 1) + 1;
if (finished_count == Build.gpu_objs.count && GetBuildStatus() == 0)
u32 finished_count = Atomic32FetchAdd(&M.gpu_objs.finished_count, 1) + 1;
if (finished_count == M.gpu_objs.count && M_GetBuildStatus() == 0)
{
EmbedObj *embed = &Build.embed_objs.array[embed_idx];
*embed = Embed(shader_store_name, shader_store_name);
M_EmbedObj *embed = &M.embed_objs.array[embed_idx];
*embed = M_Embed(shader_store_name, shader_store_name);
}
}
++gpu_obj_idx;
}
if (Build.gpu_parse.shader_entries_count > 0)
if (M.gpu_parse.shader_entries_count > 0)
{
++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 store_name = rd->store_name;
EmbedObj *embed = &Build.embed_objs.array[embed_idx];
*embed = Embed(store_name, dir_path);
M_EmbedObj *embed = &M.embed_objs.array[embed_idx];
*embed = M_Embed(store_name, dir_path);
}
++embed_idx;
}
@ -935,7 +936,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
//////////////////////////////
//- 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));
{
@ -950,10 +951,10 @@ void BuildEntryPoint(WaveLaneCtx *lane)
String obj_files_str = Zi;
{
StringList obj_files = Zi;
PushStringToList(perm, &obj_files, Build.c_obj.obj_file);
for (u64 embed_obj_idx = 0; embed_obj_idx < Build.embed_objs.count; ++embed_obj_idx)
PushStringToList(perm, &obj_files, M.c_obj.obj_file);
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);
}
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(" ")))
);
OS_CommandResult result = OS_RunCommand(perm, cmd);
Build.link.output = TrimWhitespace(result.output);
Build.link.return_code = result.code;
M.link.output = TrimWhitespace(result.output);
M.link.return_code = result.code;
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;
{
GpuObj *disp_obj = 0;
for (u32 gpu_obj_idx = 0; gpu_obj_idx < Build.gpu_objs.count; ++gpu_obj_idx)
M_GpuObj *disp_obj = 0;
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)
{
disp_obj = gpu_obj;
@ -1000,22 +1001,22 @@ void BuildEntryPoint(WaveLaneCtx *lane)
String embed_obj_output = 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);
}
embed_obj_output = StringFromList(perm, embed_obj_outputs, Lit("\n"));
}
EchoLineOrNothing(StringFromMetaErrors(perm, Build.layers_parse.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, Build.c_parse.errors));
EchoLineOrNothing(StringFromMetaErrors(perm, Build.gpu_parse.errors));
EchoLineOrNothing(Build.c_obj.output);
EchoLineOrNothing(gpu_obj_output);
EchoLineOrNothing(StringFromMetaErrors(perm, Build.res_dir_parse.errors));
EchoLineOrNothing(embed_obj_output);
EchoLineOrNothing(Build.link.output);
M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.layers_parse.errors));
M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.c_parse.errors));
M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.gpu_parse.errors));
M_EchoLineOrNothing(M.c_obj.output);
M_EchoLineOrNothing(gpu_obj_output);
M_EchoLineOrNothing(M_StringFromMetaErrors(perm, M.res_dir_parse.errors));
M_EchoLineOrNothing(embed_obj_output);
M_EchoLineOrNothing(M.link.output);
}
//////////////////////////////
@ -1023,8 +1024,8 @@ void BuildEntryPoint(WaveLaneCtx *lane)
if (lane->idx == 0)
{
EchoLine(StringF(perm, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs()), .p = 3)));
ExitNow(GetBuildStatus());
M_EchoLine(StringF(perm, "Runtime: %Fs", FmtFloat(SecondsFromNs(TimeNs()), .p = 3)));
ExitNow(M_GetBuildStatus());
}
}
@ -1036,5 +1037,5 @@ void BootstrapLayers(void)
OS_Bootstrap();
CpuTopologyInfo cpu_info = GetCpuTopologyInfo();
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
@ -58,7 +58,7 @@
////////////////////////////////////////////////////////////
//~ Helper types
Struct(LineCol)
Struct(M_LineCol)
{
i64 line;
i64 col;
@ -67,7 +67,7 @@ Struct(LineCol)
////////////////////////////////////////////////////////////
//~ Build ctx types
Struct(CompilerParams)
Struct(M_CompilerParams)
{
StringList defs;
@ -86,41 +86,44 @@ Struct(CompilerParams)
StringList linker_only_flags_clang;
};
Enum(ShaderEntryKind)
Enum(M_ShaderEntryKind)
{
ShaderEntryKind_VS,
ShaderEntryKind_PS,
ShaderEntryKind_CS,
};
Struct(ShaderEntry)
Struct(M_ShaderEntry)
{
ShaderEntry *next;
ShaderEntryKind kind;
M_ShaderEntry *next;
M_ShaderEntryKind kind;
String name;
};
Struct(ResDir)
Struct(M_ResDir)
{
ResDir *next;
M_ResDir *next;
String dir_path;
String store_name;
};
Struct(GpuObj)
Struct(M_GpuObj)
{
String output;
i32 return_code;
};
Struct(EmbedObj)
Struct(M_EmbedObj)
{
String obj_file;
String output;
i32 return_code;
};
Struct(BuildCtx)
////////////////////////////////////////////////////////////
//~ State types
Struct(M_Ctx)
{
Atomic32 status;
@ -134,16 +137,16 @@ Struct(BuildCtx)
struct
{
M_ErrorList errors;
ShaderEntry *first_shader_entry;
ShaderEntry *last_shader_entry;
M_ShaderEntry *first_shader_entry;
M_ShaderEntry *last_shader_entry;
u64 shader_entries_count;
} gpu_parse;
struct
{
M_ErrorList errors;
ResDir *first_res_dir;
ResDir *last_res_dir;
M_ResDir *first_res_dir;
M_ResDir *last_res_dir;
u64 res_dirs_count;
} res_dir_parse;
@ -156,14 +159,14 @@ Struct(BuildCtx)
struct
{
GpuObj *array;
M_GpuObj *array;
u32 count;
Atomic32 finished_count;
} gpu_objs;
struct
{
EmbedObj *array;
M_EmbedObj *array;
u32 count;
} embed_objs;
@ -174,20 +177,20 @@ Struct(BuildCtx)
} link;
};
extern BuildCtx Build;
extern M_Ctx M;
////////////////////////////////////////////////////////////
//~ Helpers
i32 GetBuildStatus(void);
void SetBuildStatus(i32 code);
void EchoLine(String msg);
void EchoLineOrNothing(String msg);
LineCol LineColFromPos(String data, i64 pos);
String StringFromMetaErrors(Arena *arena, M_ErrorList errors);
EmbedObj Embed(String store_name, String dir_path);
i32 M_GetBuildStatus(void);
void M_SetBuildStatus(i32 code);
void M_EchoLine(String msg);
void M_EchoLineOrNothing(String msg);
M_LineCol M_LineColFromPos(String data, i64 pos);
String M_StringFromMetaErrors(Arena *arena, M_ErrorList errors);
M_EmbedObj M_Embed(String store_name, String dir_path);
////////////////////////////////////////////////////////////
//~ 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);
// Init gpu state
G_ResourceHandle gpu_state = Zi;
G_ResourceHandle gpu_tiles = Zi;
G_ResourceHandle gpu_particles = Zi;
G_ResourceHandle gpu_cells = Zi;
G_ResourceHandle gpu_stains = Zi;
G_ResourceHandle gpu_drynesses = Zi;
G_RWStructuredBufferRef gpu_state_ref = Zi;
G_Texture2DRef gpu_tiles_ref = Zi;
G_RWStructuredBufferRef gpu_particles_ref = Zi;
G_RWTexture2DRef gpu_cells_ref = Zi;
G_RWTexture2DRef gpu_stains_ref = Zi;
G_RWTexture2DRef gpu_drynesses_ref = Zi;
G_ResourceHandle gpu_tiles_res = Zi;
G_ResourceHandle gpu_particles_res = Zi;
G_ResourceHandle gpu_cells_res = Zi;
G_ResourceHandle gpu_stains_res = Zi;
G_ResourceHandle gpu_drynesses_res = Zi;
G_Texture2DRef gpu_tiles = Zi;
G_RWStructuredBufferRef gpu_particles = Zi;
G_RWTexture2DRef gpu_cells = Zi;
G_RWTexture2DRef gpu_stains = Zi;
G_RWTexture2DRef gpu_drynesses = Zi;
{
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
{
gpu_tiles = G_PushTexture2D(
gpu_tiles_res = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8_Uint,
tiles_dims,
@ -426,22 +414,22 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory,
.name = Lit("Tiles")
);
gpu_tiles_ref = G_PushTexture2DRef(gpu_perm, gpu_tiles);
gpu_tiles = G_PushTexture2DRef(gpu_perm, gpu_tiles_res);
}
// Init particle buffer
{
gpu_particles = G_PushBuffer(
gpu_particles_res = G_PushBuffer(
gpu_perm, cl,
V_Particle,
V_ParticlesCap,
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.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
{
gpu_cells = G_PushTexture2D(
gpu_cells_res = G_PushTexture2D(
gpu_perm, cl,
// G_Format_R8_Uint,
// G_Format_R11G11B10_Float,
@ -452,11 +440,11 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Cells")
);
gpu_cells_ref = G_PushRWTexture2DRef(gpu_perm, gpu_cells);
gpu_cells = G_PushRWTexture2DRef(gpu_perm, gpu_cells_res);
}
// Init stain texture
{
gpu_stains = G_PushTexture2D(
gpu_stains_res = G_PushTexture2D(
gpu_perm, cl,
// G_Format_R8_Uint,
// G_Format_R11G11B10_Float,
@ -467,11 +455,11 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Stains")
);
gpu_stains_ref = G_PushRWTexture2DRef(gpu_perm, gpu_stains);
gpu_stains = G_PushRWTexture2DRef(gpu_perm, gpu_stains_res);
}
// Init drynesses texture
{
gpu_drynesses = G_PushTexture2D(
gpu_drynesses_res = G_PushTexture2D(
gpu_perm, cl,
// G_Format_R8_Uint,
// G_Format_R11G11B10_Float,
@ -483,7 +471,7 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_ZeroMemory | G_ResourceFlag_AllowShaderReadWrite,
.name = Lit("Drynesses")
);
gpu_drynesses_ref = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses);
gpu_drynesses = G_PushRWTexture2DRef(gpu_perm, gpu_drynesses_res);
}
}
G_CommitCommandList(cl);
@ -542,9 +530,6 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Begin frame
b32 tiles_dirty = 0;
b32 should_clear_particles = 0;
V.current_frame_tick += 1;
V_Frame *prev_frame = V_PrevFrame();
V_Frame *frame = V_CurrentFrame();
@ -596,6 +581,21 @@ void V_TickForever(WaveLaneCtx *lane)
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
@ -741,14 +741,14 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Process controller events into vis cmds
b32 has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box);
b32 has_keyboard_focus = 1;
frame->has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box);
frame->has_keyboard_focus = 1;
Vec2 mouse_delta = Zi;
{
if (!window_frame.has_focus)
{
has_mouse_focus = 0;
has_keyboard_focus = 0;
frame->has_mouse_focus = 0;
frame->has_keyboard_focus = 0;
}
//- Reset held buttons
@ -756,14 +756,14 @@ void V_TickForever(WaveLaneCtx *lane)
{
if (btn == Button_M1 || btn == Button_M2 || btn == Button_M3)
{
if (!has_mouse_focus)
if (!frame->has_mouse_focus)
{
frame->held_buttons[btn] = 0;
}
}
else
{
if (!has_keyboard_focus)
if (!frame->has_keyboard_focus)
{
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 (!has_mouse_focus)
if (!frame->has_mouse_focus)
{
ignore = 1;
}
}
else
{
if (!has_keyboard_focus)
if (!frame->has_keyboard_focus)
{
ignore = 1;
}
@ -860,7 +860,7 @@ void V_TickForever(WaveLaneCtx *lane)
{
// TODO: Adjustable sensitivity
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 = AddVec2(look, MulVec2(mouse_delta, mouse_sensitivity * mouse_scale_factor));
look = ClampVec2Len(look, look_radius);
@ -1903,7 +1903,7 @@ void V_TickForever(WaveLaneCtx *lane)
{
local_world->tiles_hash = predict_world->tiles_hash;
CopyStructs(local_world->tiles, predict_world->tiles, P_TilesCount);
tiles_dirty = 1;
frame->tiles_dirty = 1;
}
local_world->seed = predict_world->seed;
@ -4428,7 +4428,7 @@ void V_TickForever(WaveLaneCtx *lane)
case V_CmdKind_clear_particles:
{
should_clear_particles = 1;
frame->should_clear_particles = 1;
} break;
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
G_ResourceHandle screen_target = G_PushTexture2D(
@ -4455,7 +4489,7 @@ void V_TickForever(WaveLaneCtx *lane)
.flags = G_ResourceFlag_AllowRenderTarget,
.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));
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,
.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
G_ResourceHandle shade_target = G_PushTexture2D(
@ -4481,8 +4515,8 @@ void V_TickForever(WaveLaneCtx *lane)
// .flags = G_ResourceFlag_AllowShaderReadWrite | G_ResourceFlag_ForceNoReuse,
.name = 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);
frame->shade_ro = G_PushTexture2DRef(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));
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),
.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
G_ResourceHandle dverts_buff = G_PushBufferFromCpuCopy(
@ -4505,10 +4539,10 @@ void V_TickForever(WaveLaneCtx *lane)
StringFromArena(frame->dvert_idxs_arena),
.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);
// Emitters
// Particles
G_ResourceHandle gpu_emitters = Zi;
{
// Flatten emitters list
@ -4527,113 +4561,30 @@ void V_TickForever(WaveLaneCtx *lane)
.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
V_GpuParams params = Zi;
// Upload gpu frame data
{
params.dt = frame->dt;
params.tick = frame->tick;
params.seed = RandU64FromState(&frame->rand);
params.af = frame->af;
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(
// Gpu frame
G_ResourceHandle gpu_frame = G_PushBufferFromCpuCopy(
frame->gpu_arena, frame->cl,
StringFromStruct(&params),
.name = StringF(frame->arena, "Gpu params [%F]", FmtSint(frame->tick))
StringFromStruct(&frame->shared_frame),
.name = StringF(frame->arena, "Gpu frame [%F]", FmtSint(frame->tick))
);
G_StructuredBufferRef gpu_params_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_params, V_GpuParams);
G_StructuredBufferRef gpu_frame_ref = G_PushStructuredBufferRef(frame->gpu_arena, gpu_frame, V_SharedFrame);
// 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);
}
// Flags
// Gpu flags
V_GpuFlag gpu_flags = 0;
if (frame->show_console)
{
gpu_flags |= V_GpuFlag_DebugDraw;
}
// Constants
// Set constants
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_Params, gpu_params_ref);
G_SetConstant(frame->cl, V_ShaderConst_Frame, gpu_frame_ref);
G_SetConstant(frame->cl, V_ShaderConst_NoiseTex, G_BasicNoiseTexture());
}
// Sync
G_DumbGlobalMemorySync(frame->cl);
@ -4649,7 +4600,7 @@ void V_TickForever(WaveLaneCtx *lane)
G_Compute(frame->cl, V_PrepareCellsCS, V_ThreadGroupSizeFromTexSize(cells_dims));
// Clear particles
if (should_clear_particles)
if (frame->should_clear_particles)
{
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));
// Barrier particles buffer
G_DumbMemorySync(frame->cl, gpu_particles);
G_DumbMemorySync(frame->cl, gpu_particles_res);
// Simulate particles
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.p1 = Vec2FromVec(screen_viewport.p1);
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
Enum(V_EditMode)
{
V_EditMode_None,
V_EditMode_Tile,
};
Struct(V_Frame)
{
Arena *arena;
@ -230,77 +224,25 @@ Struct(V_Frame)
G_ArenaHandle gpu_arena;
G_CommandListHandle cl;
i64 tick;
i64 time_ns;
i64 dt_ns;
f64 dt;
Embed(V_SharedFrame, shared_frame);
RandState rand;
NET_Key sim_key;
NET_Key desired_sim_key;
f64 predict_tick_accum;
Button held_buttons[Button_COUNT];
V_Palette palette;
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
i64 cmds_count;
V_CmdNode *first_cmd_node;
V_CmdNode *last_cmd_node;
f64 predict_tick_accum;
// Control
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
// Emitters
i64 emitters_count;
// Unflattened emitters list
V_EmitterNode *first_emitter_node;
V_EmitterNode *last_emitter_node;
};
@ -320,7 +262,7 @@ Struct(V_Ctx)
V_Notif *first_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;
Atomic32 shutdown;

View File

@ -23,8 +23,8 @@ Vec4 V_DryColor(Vec4 color, f32 dryness)
//- Prepare shade
ComputeShader2D(V_PrepareShadeCS, 8, 8)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWTexture2D<Vec4> shade = G_Dereference<Vec4>(params.shade_rw);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWTexture2D<Vec4> shade = G_Dereference<Vec4>(frame.shade_rw);
Vec2 shade_pos = SV_DispatchThreadID;
if (all(shade_pos < countof(shade)))
@ -37,9 +37,9 @@ ComputeShader2D(V_PrepareShadeCS, 8, 8)
//- Prepare cells
ComputeShader2D(V_PrepareCellsCS, 8, 8)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
Vec2 cells_pos = SV_DispatchThreadID;
if (all(cells_pos < countof(cells)))
{
@ -47,7 +47,8 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
cells[cells_pos] = 0;
// 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 new_dryness = lerp(old_dryness, 1, dry_rate);
@ -55,9 +56,9 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
}
// 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;
drynesses[cells_pos] = 0;
}
@ -67,8 +68,8 @@ ComputeShader2D(V_PrepareCellsCS, 8, 8)
//- Clear particles
ComputeShader(V_ClearParticlesCS, 64)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
u32 particle_idx = SV_DispatchThreadID;
if (particle_idx < V_ParticlesCap)
{
@ -84,8 +85,8 @@ ComputeShader(V_ClearParticlesCS, 64)
VertexShader(V_QuadVS, V_QuadPSInput)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(params.quads);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(frame.quads);
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);
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.samp_uv = samp_uv;
return result;
@ -106,9 +107,9 @@ VertexShader(V_QuadVS, V_QuadPSInput)
PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(params.quads);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_Quad> quads = G_Dereference<V_Quad>(frame.quads);
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
V_Quad quad = quads[input.quad_idx];
@ -130,13 +131,12 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
ComputeShader(V_EmitParticlesCS, 64)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWStructuredBuffer<V_GpuState> state_buff = G_Dereference<V_GpuState>(V_ShaderConst_State);
StructuredBuffer<V_Emitter> emitters = G_Dereference<V_Emitter>(params.emitters);
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_Emitter> emitters = G_Dereference<V_Emitter>(frame.emitters);
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
u32 emitter_idx = SV_DispatchThreadID;
if (emitter_idx < params.emitters_count)
if (emitter_idx < frame.emitters_count)
{
V_Emitter emitter = emitters[emitter_idx];
for (u32 i = 0; i < emitter.count; ++i)
@ -155,11 +155,11 @@ ComputeShader(V_EmitParticlesCS, 64)
ComputeShader(V_SimParticlesCS, 64)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(params.particles);
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWStructuredBuffer<V_Particle> particles = G_Dereference<V_Particle>(frame.particles);
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
u32 particle_idx = SV_DispatchThreadID;
if (particle_idx < V_ParticlesCap)
@ -172,7 +172,7 @@ ComputeShader(V_SimParticlesCS, 64)
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 seed1 = MixU64(seed0);
@ -214,14 +214,15 @@ ComputeShader(V_SimParticlesCS, 64)
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));
// Simulate
{
particle.pos += particle.velocity * params.dt;
particle.velocity = lerp(particle.velocity, 0, particle.velocity_falloff * params.dt);
particle.exists -= params.dt / particle.lifetime;
// TODO: Use simulation dt
particle.pos += particle.velocity * frame.dt;
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)))
{
particle.exists = 0;
@ -239,10 +240,10 @@ ComputeShader(V_SimParticlesCS, 64)
// FIXME: Atomic writes
{
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));
Vec2 cell_pos = mul(frame.af.world_to_cell, 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_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;
color.a *= prev_exists;
@ -295,18 +296,18 @@ ComputeShader(V_SimParticlesCS, 64)
ComputeShader2D(V_ShadeCS, 8, 8)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_rw);
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
RWTexture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_rw);
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
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 = mul(params.af.world_to_cell, Vec3(world_pos, 1));
Vec2 tile_pos = mul(params.af.world_to_tile, Vec3(world_pos, 1));
Vec2 world_pos = mul(frame.af.shade_to_world, Vec3(shade_pos, 1));
Vec2 cell_pos = mul(frame.af.world_to_cell, 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));
@ -351,28 +352,28 @@ VertexShader(V_CompositeVS, V_CompositePSInput)
PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
// Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(params.shade_ro);
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(params.albedo_ro);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(params.cells);
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles);
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
// Texture2D<Vec4> shade_tex = G_Dereference<Vec4>(frame.shade_ro);
Texture2D<Vec4> albedo_tex = G_Dereference<Vec4>(frame.albedo_ro);
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(frame.stains);
RWTexture2D<Vec4> cells = G_Dereference<Vec4>(frame.cells);
RWTexture2D<f32> drynesses = G_Dereference<f32>(frame.drynesses);
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(frame.tiles);
SamplerState clamp_sampler = G_Dereference(frame.pt_clamp_sampler);
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 = mul(params.af.world_to_cell, Vec3(world_pos, 1));
Vec2 shade_pos = mul(params.af.screen_to_shade, Vec3(screen_pos.xy, 1));
Vec2 world_pos = mul(frame.af.screen_to_world, Vec3(screen_pos, 1));
Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 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 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));
Vec2 world_bounds_screen_p0 = mul(frame.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));
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
@ -432,7 +433,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
}
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);
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);
@ -525,18 +526,18 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
//- Tile selection overlay
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 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 screen_selection = frame.screen_selection;
Rng2 world_selection = frame.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)));
tile_selection.p0 = floor(mul(frame.af.world_to_tile, Vec3(world_selection.p0, 1)));
tile_selection.p1 = ceil(mul(frame.af.world_to_tile, Vec3(world_selection.p1, 1)));
f32 dist = 100000000;
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)
{
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));
Vec2 line_screen_p0 = mul(frame.af.world_to_screen, Vec3(floor(world_pos), 1));
Vec2 line_screen_p1 = mul(frame.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));
@ -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 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 y_dist = abs(screen_pos.y - zero_screen.y);
if (y_dist <= half_thickness)
@ -637,7 +638,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
Vec4 crosshair_color = 0;
{
f32 dist = length(params.screen_crosshair - screen_pos);
f32 dist = length(frame.screen_crosshair - screen_pos);
if (dist < 4)
{
// Adaptive crosshair color based on underlying luminance
@ -686,15 +687,15 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input)
VertexShader(V_DVertVS, V_DVertPSInput)
{
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(params.shape_verts);
V_SharedFrame frame = G_Dereference<V_SharedFrame>(V_ShaderConst_Frame)[0];
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(frame.dverts);
V_DVert vert = verts[SV_VertexID];
Vec2 screen_pos = vert.pos;
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;
return result;
}

View File

@ -4,7 +4,7 @@
// #define V_ParticlesCap Mebi(16)
////////////////////////////////////////////////////////////
//~ Constant types
//~ State types
Enum(V_GpuFlag)
{
@ -13,9 +13,14 @@ Enum(V_GpuFlag)
};
G_DeclConstant(V_GpuFlag, V_ShaderConst_GpuFlags, 0);
G_DeclConstant(G_RWStructuredBufferRef, V_ShaderConst_State, 1);
G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 2);
G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 3);
G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Frame, 1);
G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 2);
Struct(V_TileDesc)
{
G_Texture2DRef tex;
Rng2 tex_slice_uv;
};
Enum(V_SelectionMode)
{
@ -23,6 +28,12 @@ Enum(V_SelectionMode)
V_SelectionMode_Tile,
};
Enum(V_EditMode)
{
V_EditMode_None,
V_EditMode_Tile,
};
Struct(V_Affines)
{
// World <-> screen
@ -46,64 +57,91 @@ Struct(V_Affines)
Affine tile_to_world;
};
Struct(V_TileDesc)
Struct(V_SharedFrame)
{
G_Texture2DRef tex;
Rng2 tex_slice_uv;
};
//- Time
Struct(V_GpuState)
{
// u32 particle_seq; // Atomic monotonically increasing allocation counter sequence for particle ring buffer
i32 _;
};
Struct(V_GpuParams)
{
// TODO: Use simulation dt
i64 tick;
i64 time_ns;
i64 dt_ns;
f32 dt;
u64 tick;
u64 seed;
V_Affines af;
V_SelectionMode selection_mode;
P_TileKind equipped_tile;
//- Modes
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_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 shade_cursor;
Vec2 world_cursor;
Rng2 screen_selection;
Rng2 shade_selection;
Rng2 world_selection;
//- Crosshair
Vec2 screen_crosshair;
Vec2 shade_crosshair;
Vec2 world_crosshair;
Vec2 camera_pos;
f32 camera_zoom;
//- Control
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
//- Gpu data
G_SamplerStateRef pt_clamp_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_RWTexture2DRef shade_rw;
G_Texture2DRef albedo_ro;
G_RWTexture2DRef albedo_rw;
G_Texture2DRef tiles;
G_StructuredBufferRef quads;
G_StructuredBufferRef shape_verts;
u32 emitters_count;
G_StructuredBufferRef emitters;
G_RWStructuredBufferRef particles;
b32 should_clear_stains;
@ -111,7 +149,8 @@ Struct(V_GpuParams)
G_RWTexture2DRef stains;
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;
};
////////////////////////////////////////////////////////////
//~ Helpers

View File

@ -313,7 +313,7 @@ SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64
if (slice_ready)
{
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)));
}
else
@ -425,14 +425,14 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
atlas->dims = VEC2I32(atlas_size, atlas_size);
{
G_ArenaHandle gpu_perm = G_PermArena();
atlas->tex = G_PushTexture2D(
atlas->tex_res = G_PushTexture2D(
gpu_perm, cl,
G_Format_R8G8B8A8_Unorm_Srgb,
atlas->dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
.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);
++SPR.atlases_count;
@ -466,7 +466,7 @@ void SPR_TickAsync(WaveLaneCtx *lane, AsyncFrameLaneCtx *base_async_lane_frame)
// Copy to atlas
G_CopyCpuToTexture(
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),
RNG3I32(
VEC3I32(0, 0, 0),

View File

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

View File

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