G_Ctx G = Zi; ThreadLocal G_ThreadLocalCtx G_tl = Zi; //////////////////////////////////////////////////////////// //~ Bootstrap void G_BootstrapCommon(void) { G_ArenaHandle gpu_perm = G_PermArena(); G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct); { // Init quad index buffer { G_ResourceHandle quad_indices = Zi; u16 quad_data[6] = { 0, 1, 2, 0, 2, 3 }; quad_indices = G_PushBuffer(gpu_perm, cl, u16, countof(quad_data)); G_CopyCpuToBuffer(cl, quad_indices, 0, quad_data, RNGU64(0, sizeof(quad_data))); G.quad_indices = G_IdxBuff16(quad_indices); } // Init blank texture { G_ResourceHandle blank_tex = G_PushTexture2D( gpu_perm, cl, G_Format_R8G8B8A8_Unorm, VEC2I32(8, 8), G_Layout_Common, .flags = G_ResourceFlag_ZeroMemory, .name = Lit("Blank texture") ); G.blank_tex = G_PushTexture2DRef(gpu_perm, blank_tex); } // Init noise texture { G_ResourceHandle noise_tex = Zi; String noise_data = DataFromResource(ResourceKeyFromStore(&G_Resources, Lit("noise_128x128x64_16.dat"))); Vec3I32 noise_dims = VEC3I32(128, 128, 64); if (noise_data.len != noise_dims.x * noise_dims.y * noise_dims.z * 2) { Panic(Lit("Unexpected noise texture size")); } noise_tex = G_PushTexture3D( gpu_perm, cl, G_Format_R16_Uint, noise_dims, G_Layout_Common, .name = Lit("Noise texture") ); G_CopyCpuToTexture( cl, noise_tex, VEC3I32(0, 0, 0), noise_data.text, noise_dims, RNG3I32(VEC3I32(0, 0, 0), noise_dims) ); G.basic_noise = G_PushTexture3DRef(gpu_perm, noise_tex); } // Init basic samplers for (G_BasicSamplerKind sampler_kind = 0; sampler_kind < countof(G.basic_samplers); ++sampler_kind) { G_SamplerStateRef sampler = Zi; switch (sampler_kind) { default: { // Sampler unspecified Assert(0); } FALLTHROUGH; case G_BasicSamplerKind_PointClamp: { G_Filter filter = G_Filter_MinMagMipPoint; G_AddressMode address_mode = G_AddressMode_Clamp; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_PointWrap: { G_Filter filter = G_Filter_MinMagMipPoint; G_AddressMode address_mode = G_AddressMode_Wrap; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_PointMirror: { G_Filter filter = G_Filter_MinMagMipPoint; G_AddressMode address_mode = G_AddressMode_Mirror; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_BilinearClamp: { G_Filter filter = G_Filter_MinMagLinearMipPoint; G_AddressMode address_mode = G_AddressMode_Clamp; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_BilinearWrap: { G_Filter filter = G_Filter_MinMagLinearMipPoint; G_AddressMode address_mode = G_AddressMode_Wrap; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_BilinearMirror: { G_Filter filter = G_Filter_MinMagLinearMipPoint; G_AddressMode address_mode = G_AddressMode_Mirror; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_TrilinearClamp: { G_Filter filter = G_Filter_MinMagMipLinear; G_AddressMode address_mode = G_AddressMode_Clamp; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_TrilinearWrap: { G_Filter filter = G_Filter_MinMagMipLinear; G_AddressMode address_mode = G_AddressMode_Wrap; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; case G_BasicSamplerKind_TrilinearMirror: { G_Filter filter = G_Filter_MinMagMipLinear; G_AddressMode address_mode = G_AddressMode_Mirror; G_ResourceHandle sampler_res = G_PushSampler(gpu_perm, cl, .filter = filter, .x = address_mode, .y = address_mode, .z = address_mode); sampler = G_PushSamplerStateRef(gpu_perm, sampler_res); } break; } G.basic_samplers[sampler_kind] = sampler; } } G_CommitCommandList(cl); G_QueueSync(G_QueueMask_Direct, G_QueueMask_All); } //////////////////////////////////////////////////////////// //~ Utils //- Arena G_ArenaHandle G_PermArena(void) { if (G_IsArenaNil(G_tl.gpu_perm)) { G_tl.gpu_perm = G_AcquireArena(); } return G_tl.gpu_perm; } //- Push resource from cpu G_ResourceHandle G_PushBufferFromCpuCopy_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc) { G_ResourceHandle buffer = G_PushResource(gpu_arena, cl, (G_ResourceDesc) { .kind = G_ResourceKind_Buffer, .buffer = desc }); G_CopyCpuToBuffer(cl, buffer, 0, src.text, RNGU64(0, src.len)); return buffer; } //- Mip i32 G_DimsFromMip1D(i32 mip0_dims, i32 mip) { mip = ClampI32(mip, -31, 31); i32 result = 0; if (mip >= 0) { result = MaxI32(result >> mip, 1); } else { result = MaxI32(result << -mip, 1); } return result; } Vec2I32 G_DimsFromMip2D(Vec2I32 mip0_dims, i32 mip) { mip = ClampI32(mip, -31, 31); Vec2I32 result = Zi; if (mip >= 0) { result.x = MaxI32(mip0_dims.x >> mip, 1); result.y = MaxI32(mip0_dims.y >> mip, 1); } else { result.x = MaxI32(mip0_dims.x << -mip, 1); result.y = MaxI32(mip0_dims.y << -mip, 1); } return result; } Vec3I32 G_DimsFromMip3D(Vec3I32 mip0_dims, i32 mip) { mip = ClampI32(mip, -31, 31); Vec3I32 result = Zi; if (mip >= 0) { result.x = MaxI32(mip0_dims.x >> mip, 1); result.y = MaxI32(mip0_dims.y >> mip, 1); result.z = MaxI32(mip0_dims.z >> mip, 1); } else { result.x = MaxI32(mip0_dims.x << -mip, 1); result.y = MaxI32(mip0_dims.y << -mip, 1); result.z = MaxI32(mip0_dims.z << -mip, 1); } return result; } //- Thread count Vec3I32 G_GroupCountFromThreadCount(ComputeShaderDesc cs, Vec3I32 threads) { return VEC3I32( (threads.x + cs.x - 1) / cs.x, (threads.y + cs.y - 1) / cs.y, (threads.z + cs.z - 1) / cs.z ); } //- Viewport / scissor Rng3 G_ViewportFromTexture(G_ResourceHandle texture) { Vec2I32 dims = G_Count2D(texture); return RNG3(VEC3(0, 0, 0), VEC3(dims.x, dims.y, 1)); } Rng2 G_ScissorFromTexture(G_ResourceHandle texture) { Vec2I32 dims = G_Count2D(texture); return RNG2(VEC2(0, 0), VEC2(dims.x, dims.y)); } //- Shared resources G_SamplerStateRef G_BasicSamplerFromKind(G_BasicSamplerKind kind) { return G.basic_samplers[kind]; } G_IndexBufferDesc G_QuadIndices(void) { return G.quad_indices; } G_Texture2DRef G_BlankTexture2D(void) { return G.blank_tex; } G_Texture3DRef G_BasicNoiseTexture(void) { return G.basic_noise; }