//////////////////////////////////////////////////////////// //~ Handle types Struct(G_ArenaHandle) { u64 v; }; Struct(G_CommandListHandle) { u64 v; }; Struct(G_ResourceHandle) { u64 v; }; Struct(G_SwapchainHandle) { u64 v; }; #define G_IsArenaNil(h) ((h).v == 0) #define G_IsCommandListNil(h) ((h).v == 0) #define G_IsResourceNil(h) ((h).v == 0) #define G_IsSwapchainNil(h) ((h).v == 0) //////////////////////////////////////////////////////////// //~ Queue types #define G_IsMultiQueueEnabled 1 Enum(G_QueueKind) { G_QueueKind_Direct = 0, #if G_IsMultiQueueEnabled G_QueueKind_AsyncCompute = 1, G_QueueKind_AsyncCopy = 2, #else G_QueueKind_AsyncCompute = G_QueueKind_Direct, G_QueueKind_AsyncCopy = G_QueueKind_Direct, #endif G_NumQueues }; Enum(G_QueueMask) { G_QueueMask_None = 0, G_QueueMask_Direct = (1 << 0), #if G_IsMultiQueueEnabled G_QueueMask_AsyncCompute = (1 << 1), G_QueueMask_AsyncCopy = (1 << 2), #else G_QueueMask_AsyncCompute = G_QueueMask_Direct, G_QueueMask_AsyncCopy = G_QueueMask_Direct, #endif G_QueueMask_All = (0xFFFFFFFF >> (32 - G_NumQueues)) }; #define G_MaskFromQueue(queue_kind) (1 << queue_kind) Struct(G_QueueCompletions) { i64 v[G_NumQueues]; // Array of completions indexed by queue kind }; // All waiters will wait until specified queues reach their value in the `completions` array Struct(G_QueueBarrierDesc) { G_QueueCompletions completions; // Completions that waiters should wait for G_QueueMask wait_queues; // Mask of queues that will wait for completions b32 wait_cpu; // Will the cpu wait for completion }; //////////////////////////////////////////////////////////// //~ Format types // NOTE: Matches DirectX DXGI_FORMAT Enum(G_Format) { G_Format_Unknown = 0, G_Format_R32G32B32A32_Typeless = 1, G_Format_R32G32B32A32_Float = 2, G_Format_R32G32B32A32_Uint = 3, G_Format_R32G32B32A32_Sint = 4, G_Format_R32G32B32_Typeless = 5, G_Format_R32G32B32_Float = 6, G_Format_R32G32B32_Uint = 7, G_Format_R32G32B32_Sint = 8, G_Format_R16G16B16A16_Typeless = 9, G_Format_R16G16B16A16_Float = 10, G_Format_R16G16B16A16_Unorm = 11, G_Format_R16G16B16A16_Uint = 12, G_Format_R16G16B16A16_Snorm = 13, G_Format_R16G16B16A16_Sint = 14, G_Format_R32G32_Typeless = 15, G_Format_R32G32_Float = 16, G_Format_R32G32_Uint = 17, G_Format_R32G32_Sint = 18, G_Format_R32G8X24_Typeless = 19, G_Format_D32_Float_S8X24_Uint = 20, G_Format_R32_Float_X8X24_Typeless = 21, G_Format_X32_Typeless_G8X24_Uint = 22, G_Format_R10G10B10A2_Typeless = 23, G_Format_R10G10B10A2_Unorm = 24, G_Format_R10G10B10A2_Uint = 25, G_Format_R11G11B10_Float = 26, G_Format_R8G8B8A8_Typeless = 27, G_Format_R8G8B8A8_Unorm = 28, G_Format_R8G8B8A8_Unorm_Srgb = 29, G_Format_R8G8B8A8_Uint = 30, G_Format_R8G8B8A8_Snorm = 31, G_Format_R8G8B8A8_Sint = 32, G_Format_R16G16_Typeless = 33, G_Format_R16G16_Float = 34, G_Format_R16G16_Unorm = 35, G_Format_R16G16_Uint = 36, G_Format_R16G16_Snorm = 37, G_Format_R16G16_Sint = 38, G_Format_R32_Typeless = 39, G_Format_D32_Float = 40, G_Format_R32_Float = 41, G_Format_R32_Uint = 42, G_Format_R32_Sint = 43, G_Format_R24G8_Typeless = 44, G_Format_D24_Unorm_S8_Uint = 45, G_Format_R24_Unorm_X8_Typeless = 46, G_Format_X24_Typeless_G8_Uint = 47, G_Format_R8G8_Typeless = 48, G_Format_R8G8_Unorm = 49, G_Format_R8G8_Uint = 50, G_Format_R8G8_Snorm = 51, G_Format_R8G8_Sint = 52, G_Format_R16_Typeless = 53, G_Format_R16_Float = 54, G_Format_D16_Unorm = 55, G_Format_R16_Unorm = 56, G_Format_R16_Uint = 57, G_Format_R16_Snorm = 58, G_Format_R16_Sint = 59, G_Format_R8_Typeless = 60, G_Format_R8_Unorm = 61, G_Format_R8_Uint = 62, G_Format_R8_Snorm = 63, G_Format_R8_Sint = 64, G_Format_A8_Unorm = 65, G_Format_R1_Unorm = 66, G_Format_R9G9B9E5_SharedXP = 67, G_Format_R8G8_B8G8_Unorm = 68, G_Format_G8R8_G8B8_Unorm = 69, G_Format_BC1_Typeless = 70, G_Format_BC1_Unorm = 71, G_Format_BC1_Unorm_Srgb = 72, G_Format_BC2_Typeless = 73, G_Format_BC2_Unorm = 74, G_Format_BC2_Unorm_Srgb = 75, G_Format_BC3_Typeless = 76, G_Format_BC3_Unorm = 77, G_Format_BC3_Unorm_Srgb = 78, G_Format_BC4_Typeless = 79, G_Format_BC4_Unorm = 80, G_Format_BC4_Snorm = 81, G_Format_BC5_Typeless = 82, G_Format_BC5_Unorm = 83, G_Format_BC5_Snorm = 84, G_Format_B5G6R5_Unorm = 85, G_Format_B5G5R5A1_Unorm = 86, G_Format_B8G8R8A8_Unorm = 87, G_Format_B8G8R8X8_Unorm = 88, G_Format_R10G10B10_XR_BIAS_A2_Unorm = 89, G_Format_B8G8R8A8_Typeless = 90, G_Format_B8G8R8A8_Unorm_Srgb = 91, G_Format_B8G8R8X8_Typeless = 92, G_Format_B8G8R8X8_Unorm_Srgb = 93, G_Format_BC6H_Typeless = 94, G_Format_BC6H_UF16 = 95, G_Format_BC6H_SF16 = 96, G_Format_BC7_Typeless = 97, G_Format_BC7_Unorm = 98, G_Format_BC7_Unorm_Srgb = 99, G_Format_AYUV = 100, G_Format_Y410 = 101, G_Format_Y416 = 102, G_Format_NV12 = 103, G_Format_P010 = 104, G_Format_P016 = 105, G_Format_420_Opaque = 106, G_Format_YUY2 = 107, G_Format_Y210 = 108, G_Format_Y216 = 109, G_Format_NV11 = 110, G_Format_AI44 = 111, G_Format_IA44 = 112, G_Format_P8 = 113, G_Format_A8P8 = 114, G_Format_B4G4R4A4_Unorm = 115, G_Format_P208 = 130, G_Format_V208 = 131, G_Format_V408 = 132, G_Format_SamplerFeedbackMinMipOpaque = 189, G_Format_SamplerFeedbackMipRegionUsedOpaque = 190, G_Format_A4B4G4R4_Unorm = 191, G_Format_COUNT = 192 }; //////////////////////////////////////////////////////////// //~ Memory sync types Enum(G_Stage) { G_Stage_None = 0, // Compute stages G_Stage_ComputeShading = (1 << 1), // Draw stages G_Stage_IndexAssembly = (1 << 2), G_Stage_VertexShading = (1 << 3), G_Stage_PixelShading = (1 << 4), G_Stage_DepthStencil = (1 << 5), G_Stage_RenderTarget = (1 << 6), // Copy stages G_Stage_Copy = (1 << 7), // Indirect stages G_Stage_Indirect = (1 << 8), // Aggregate stages G_Stage_AllDraw = G_Stage_IndexAssembly | G_Stage_VertexShading | G_Stage_PixelShading | G_Stage_DepthStencil | G_Stage_RenderTarget, G_Stage_AllShading = G_Stage_ComputeShading | G_Stage_VertexShading | G_Stage_PixelShading, G_Stage_All = 0xFFFFFFFF }; Enum(G_Access) { G_Access_None = 0, G_Access_ShaderReadWrite = (1 << 1), G_Access_ShaderRead = (1 << 2), G_Access_CopyWrite = (1 << 3), G_Access_CopyRead = (1 << 4), G_Access_DepthStencilRead = (1 << 5), G_Access_DepthStencilWrite = (1 << 6), G_Access_RenderTargetWrite = (1 << 7), G_Access_IndexBuffer = (1 << 8), G_Access_IndirectArgument = (1 << 9), G_Access_All = 0xFFFFFFFF }; Enum(G_Layout) { G_Layout_NoChange, // Allows a resource to be used on any queue with any access type, as long // as there is only one writer at a time, and the writer is not writing to // any texels currently being read. // Resources cannot transition to/from this layout. They must be created // with it and are locked to it. G_Layout_Simultaneous, // D3D12_BARRIER_LAYOUT_COMMON + D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS G_Layout_Undefined, // D3D12_BARRIER_LAYOUT_UNDEFINED ////////////////////////////// //- Queue-agnostic G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present, // D3D12_BARRIER_LAYOUT_COMMON ////////////////////////////// //- Direct & Compute queue G_Layout_DirectComputeQueue_ShaderRead_CopyRead, // D3D12_BARRIER_LAYOUT_GENERIC_READ G_Layout_DirectComputeQueue_ShaderReadWrite, // D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS G_Layout_DirectComputeQueue_ShaderRead, // D3D12_BARRIER_LAYOUT_SHADER_RESOURCE G_Layout_DirectComputeQueue_CopyRead, // D3D12_BARRIER_LAYOUT_COPY_SOURCE ////////////////////////////// //- Direct queue G_Layout_DirectQueue_ShaderRead_ShaderReadWrite_CopyRead_CopyWrite, // D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON G_Layout_DirectQueue_ShaderRead_CopyRead_DepthStencilRead, // D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ G_Layout_DirectQueue_ShaderReadWrite, // D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS G_Layout_DirectQueue_ShaderRead, // D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE G_Layout_DirectQueue_CopyRead, // D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE G_Layout_DirectQueue_DepthStencilRead_DepthStencilWrite, // D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE G_Layout_DirectQueue_DepthStencilRead, // D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_READ G_Layout_DirectQueue_RenderTargetWrite, // D3D12_BARRIER_LAYOUT_RENDER_TARGET ////////////////////////////// //- Compute queue G_Layout_ComputeQueue_ShaderRead_ShaderReadWrite_CopyRead_CopyWrite, // D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON G_Layout_ComputeQueue_ShaderRead_CopyRead, // D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ G_Layout_ComputeQueue_ShaderReadWrite, // D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_UNORDERED_ACCESS G_Layout_ComputeQueue_ShaderRead, // D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_SHADER_RESOURCE G_Layout_ComputeQueue_CopyRead, // D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_SOURCE }; // Barrier will execute after previous stages specified by `stage_prev`, and before next stages specified by `stage_next`. // When barrier executes: // - Necessary resource flushes will occur based on `access_prev` & `access_next` // - Texture layout will transition based on `layout` (if specified) Struct(G_MemoryBarrierDesc) { G_ResourceHandle resource; b32 is_global; G_Stage stage_prev; G_Stage stage_next; G_Access access_prev; G_Access access_next; G_Layout layout; }; //////////////////////////////////////////////////////////// //~ Filter types // NOTE: Matches DirectX D3D12_FILTER Enum(G_Filter) { // Standard filter G_Filter_MinMagMipPoint = 0, G_Filter_MinMagPointMipLinear = 0x1, G_Filter_MinPointMagLinearMipPoint = 0x4, G_Filter_MinPointMagMipLinear = 0x5, G_Filter_MinLinearMagMipPoint = 0x10, G_Filter_MinLinearMagPointMipLinear = 0x11, G_Filter_MinMagLinearMipPoint = 0x14, G_Filter_MinMagMipLinear = 0x15, G_Filter_MinMagAnisotropicMipPoint = 0x54, G_Filter_Anisotropic = 0x55, // Comparison filter G_Filter_Comparison_MinMagMipPoint = 0x80, G_Filter_Comparison_MinMagPointMipLinear = 0x81, G_Filter_Comparison_MinPointMagLinearMipPoint = 0x84, G_Filter_Comparison_MinPointMagMipLinear = 0x85, G_Filter_Comparison_MinLinearMagMipPoint = 0x90, G_Filter_Comparison_MinLinearMagPointMipLinear = 0x91, G_Filter_Comparison_MinMagLinearMipPoint = 0x94, G_Filter_Comparison_MinMagMipLinear = 0x95, G_Filter_Comparison_MinMagAnisotropicMipPoint = 0xd4, G_Filter_Comparison_Anisotropic = 0xd5, // Minimum filter G_Filter_Minimum_MinMagMipPoint = 0x100, G_Filter_Minimum_MinMagPointMipLinear = 0x101, G_Filter_Minimum_MinPointMagLinearMipPoint = 0x104, G_Filter_Minimum_MinPointMagMipLinear = 0x105, G_Filter_Minimum_MinLinearMagMipPoint = 0x110, G_Filter_Minimum_MinLinearMagPointMipLinear = 0x111, G_Filter_Minimum_MinMagLinearMipPoint = 0x114, G_Filter_Minimum_MinMagMipLinear = 0x115, G_Filter_Minimum_MinMagAnisotropicMipPoint = 0x155, G_Filter_Minimum_Anisotropic = 0x155, // Maximum filter G_Filter_Maximum_MinMagMipPoint = 0x180, G_Filter_Maximum_MinMagPointMipLinear = 0x181, G_Filter_Maximum_MinPointMagLinearMipPoint = 0x184, G_Filter_Maximum_MinPointMagMipLinear = 0x185, G_Filter_Maximum_MinLinearMagMipPoint = 0x190, G_Filter_Maximum_MinLinearMagPointMipLinear = 0x191, G_Filter_Maximum_MinMagLinearMipPoint = 0x194, G_Filter_Maximum_MinMagMipLinear = 0x195, G_Filter_Maximum_MinMagAnisotropicMipPoint = 0x1d4, G_Filter_Maximum_Anisotropic = 0x1d5 }; // NOTE: Matches DirectX D3D12_TEXTURE_ADDRESS_MODE Enum(G_AddressMode) { G_AddressMode_Wrap = 1, G_AddressMode_Mirror = 2, G_AddressMode_Clamp = 3, // Default G_AddressMode_Border = 4, G_AddressMode_MirrorOnce = 5 }; // NOTE: Matches DirectX D3D12_COMPARISON_FUNC Enum(G_ComparisonFunc) { G_ComparisonFunc_None = 0, G_ComparisonFunc_Never = 1, G_ComparisonFunc_Less = 2, G_ComparisonFunc_Equal = 3, G_ComparisonFunc_LessEqual = 4, G_ComparisonFunc_Greater = 5, G_ComparisonFunc_NotEqual = 6, G_ComparisonFunc_GreaterEqual = 7, G_ComparisonFunc_Always = 8 }; //////////////////////////////////////////////////////////// //~ Resource types Enum(G_ResourceKind) { G_ResourceKind_Buffer, G_ResourceKind_Texture1D, G_ResourceKind_Texture2D, G_ResourceKind_Texture3D, G_ResourceKind_Sampler, }; Enum(G_ResourceFlag) { G_ResourceFlag_None = 0, G_ResourceFlag_AllowShaderReadWrite = (1 << 0), G_ResourceFlag_AllowRenderTarget = (1 << 1), G_ResourceFlag_AllowDepthStencil = (1 << 2), G_ResourceFlag_HostMemory = (1 << 3), // Resource will be mapped into the cpu's address space G_ResourceFlag_Uncached = (1 << 4), // Cpu writes will be combined & reads will be uncached }; Struct(G_BufferDesc) { G_ResourceFlag flags; u64 size; }; Struct(G_TextureDesc) { G_ResourceFlag flags; G_Format format; Vec3I32 dims; G_Layout initial_layout; i32 mip_levels; // Will be clamped to range [1, inf) Vec4 clear_color; }; Struct(G_SamplerDesc) { G_ResourceFlag flags; G_Filter filter; G_AddressMode x; G_AddressMode y; G_AddressMode z; f32 mip_lod_bias; u32 max_anisotropy; G_ComparisonFunc comparison; Vec4 border_color; f32 min_lod; f32 max_lod; }; Struct(G_ResourceDesc) { G_ResourceKind kind; G_BufferDesc buffer; G_TextureDesc texture; G_SamplerDesc sampler; }; //////////////////////////////////////////////////////////// //~ Ref types Struct(G_RefDesc) { G_RefKind kind; u64 element_size; u64 element_offset; }; //////////////////////////////////////////////////////////// //~ Rasterization types #define G_MaxRenderTargets 8 Enum(G_RasterMode) { G_RasterMode_None, G_RasterMode_PointList, G_RasterMode_LineList, G_RasterMode_LineStrip, G_RasterMode_TriangleList, G_RasterMode_TriangleStrip, G_RasterMode_WireTriangleList, G_RasterMode_WireTriangleStrip, }; Struct(G_IndexBufferDesc) { G_ResourceHandle resource; u32 index_size; // Either 2 for u16 indices, or 4 for u32 indices u32 index_count; }; //////////////////////////////////////////////////////////// //~ Statistic types Struct(G_Stats) { // Memory usage u64 local_committed; u64 local_budget; u64 non_local_committed; u64 non_local_budget; // Resources u64 driver_resources_allocated; u64 driver_descriptors_allocated; // TODO: Arena stats (committed, reserved, etc) }; //////////////////////////////////////////////////////////// //~ @hookdecl Bootstrap void G_Bootstrap(void); //////////////////////////////////////////////////////////// //~ @hookdecl Arena G_ArenaHandle G_AcquireArena(void); void G_ReleaseArena(G_ArenaHandle arena); void G_ResetArena(G_CommandListHandle cl_handle, G_ArenaHandle arena_handle); //////////////////////////////////////////////////////////// //~ @hookdecl Resource //- Resource creation G_ResourceHandle G_PushResource(G_ArenaHandle arena, G_CommandListHandle cl, G_ResourceDesc desc); #define G_PushBuffer(arena, cl, _type, _count, ...) G_PushResource((arena), (cl), \ (G_ResourceDesc) { \ .kind = G_ResourceKind_Buffer, \ .buffer = { \ .size = sizeof(_type) * (_count), \ __VA_ARGS__ \ } \ } \ ) #define G_PushTexture1D(arena, cl, _format, _size, _initial_layout, ...) G_PushResource((arena), (cl), \ (G_ResourceDesc) { \ .kind = G_ResourceKind_Texture1D, \ .texture = { \ .format = (_format), \ .dims = VEC3I32((_size), 1, 1), \ .initial_layout = (_initial_layout), \ __VA_ARGS__ \ } \ } \ ) #define G_PushTexture2D(arena, cl, _format, _size, _initial_layout, ...) G_PushResource((arena), (cl), \ (G_ResourceDesc) { \ .kind = G_ResourceKind_Texture2D, \ .texture = { \ .format = (_format), \ .dims = VEC3I32((_size).x, (_size).y, 1), \ .initial_layout = (_initial_layout), \ __VA_ARGS__ \ } \ } \ ) #define G_PushTexture3D(arena, cl, _format, _size, _initial_layout, ...) G_PushResource((arena), (cl), \ (G_ResourceDesc) { \ .kind = G_ResourceKind_Texture3D, \ .texture = { \ .format = (_format), \ .dims = (_size), \ .initial_layout = (_initial_layout), \ __VA_ARGS__ \ } \ } \ ) #define G_PushSampler(arena, cl, ...) G_PushResource((arena), (cl), \ (G_ResourceDesc) { \ .kind = G_ResourceKind_Sampler, \ .sampler = { \ .filter = G_Filter_MinMagMipPoint, \ __VA_ARGS__ \ } \ } \ ) //- Index buffer helpers #define G_IdxBuff16(_res) ((G_IndexBufferDesc) { .resource = (_res), .index_size = 2, .index_count = (G_CountBuffer((_res), i16)) }) #define G_IdxBuff32(_res) ((G_IndexBufferDesc) { .resource = (_res), .index_size = 4, .index_count = (G_CountBuffer((_res), i32)) }) //- Count u64 G_CountBufferBytes(G_ResourceHandle buffer); i32 G_Count1D(G_ResourceHandle texture); Vec2I32 G_Count2D(G_ResourceHandle texture); Vec3I32 G_Count3D(G_ResourceHandle texture); i32 G_CountWidth(G_ResourceHandle texture); i32 G_CountHeight(G_ResourceHandle texture); i32 G_CountDepth(G_ResourceHandle texture); #define G_CountBuffer(buffer, type) G_CountBufferBytes(buffer) / sizeof(type) //- Map void *G_HostPointerFromResource(G_ResourceHandle resource); #define G_StructFromResource(resource, type) (type *)G_HostPointerFromResource(resource) //////////////////////////////////////////////////////////// //~ @hookdecl Shader resource reference u32 G_PushRef(G_ArenaHandle arena, G_ResourceHandle resource, G_RefDesc desc); #define G_PushStructuredBufferRef(arena, resource, type, ...)(G_StructuredBufferRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_StructuredBuffer, .element_size = sizeof(type), __VA_ARGS__ } \ ) \ } #define G_PushRWStructuredBufferRef(arena, resource, type, ...)(G_RWStructuredBufferRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_RWStructuredBuffer, .element_size = sizeof(type), __VA_ARGS__ } \ ) \ } #define G_PushByteAddressBufferRef(arena, resource, ...)(G_ByteAddressBufferRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_ByteAddressBuffer, __VA_ARGS__ } \ ) \ } #define G_PushRWByteAddressBufferRef(arena, resource, ...)(G_RWByteAddressBufferRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_RWByteAddressBuffer, __VA_ARGS__ } \ ) \ } #define G_PushTexture1DRef(arena, resource, ...)(G_Texture1DRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_Texture1D, __VA_ARGS__ } \ ) \ } #define G_PushRWTexture1DRef(arena, resource, ...)(G_RWTexture1DRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_RWTexture1D, __VA_ARGS__ } \ ) \ } #define G_PushTexture2DRef(arena, resource, ...)(G_Texture2DRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_Texture2D, __VA_ARGS__ } \ ) \ } #define G_PushRWTexture2DRef(arena, resource, ...)(G_RWTexture2DRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_RWTexture2D, __VA_ARGS__ } \ ) \ } #define G_PushTexture3DRef(arena, resource, ...)(G_Texture3DRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_Texture3D, __VA_ARGS__ } \ ) \ } #define G_PushRWTexture3DRef(arena, resource, ...)(G_RWTexture3DRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_RWTexture3D, __VA_ARGS__ } \ ) \ } #define G_PushSamplerStateRef(arena, resource, ...)(G_SamplerStateRef) { \ .v = G_PushRef( \ (arena), (resource), \ (G_RefDesc) { .kind = G_RefKind_SamplerState, __VA_ARGS__ } \ ) \ } //////////////////////////////////////////////////////////// //~ @hookdecl Command //- Command list G_CommandListHandle G_PrepareCommandList(G_QueueKind queue); i64 G_CommitCommandList(G_CommandListHandle cl); //- Cpu -> Gpu copy void G_CopyCpuToBuffer(G_CommandListHandle cl, G_ResourceHandle dst, u64 dst_offset, void *src, RngU64 src_copy_range); void G_CopyCpuToTexture(G_CommandListHandle cl, G_ResourceHandle dst, Vec3I32 dst_offset, void *src, Vec3I32 src_dims, Rng3I32 src_copy_range); //- Gpu <-> Gpu copy void G_CopyBufferToBuffer(G_CommandListHandle cl, G_ResourceHandle dst, u64 dst_offset, G_ResourceHandle src, RngU64 src_copy_range); void G_CopyBufferToTexture(G_CommandListHandle cl_handle, G_ResourceHandle dst_handle, Rng3I32 dst_copy_range, G_ResourceHandle src_handle, u64 src_offset); void G_CopyTextureToTexture(G_CommandListHandle cl, G_ResourceHandle dst, Vec3I32 dst_offset, G_ResourceHandle src, Rng3I32 src_copy_range); void G_CopyTextureToBuffer(G_CommandListHandle cl, G_ResourceHandle dst, Vec3I32 dst_offset, G_ResourceHandle src, Rng3I32 src_copy_range); //- Constant void G_SetConstant_(G_CommandListHandle cl, i32 slot, void *src_32bit, u32 size); #define G_SetConstant(cl, name, value) do { \ name##__shaderconstanttype __src; \ __src.v = value; \ G_SetConstant_((cl), (name), &__src, sizeof(__src)); \ } while (0) //- Memory sync void G_MemorySyncEx(G_CommandListHandle cl, G_MemoryBarrierDesc desc); #define G_MemorySync(_cl, _resource, _stage_prev, _access_prev, _stage_next, _access_next) \ G_MemorySyncEx((_cl), (G_MemoryBarrierDesc) { \ .resource = (_resource), \ .stage_prev = _stage_prev, \ .access_prev = _access_prev, \ .stage_next = _stage_next, \ .access_next = _access_next, \ }) #define G_MemoryLayoutSync(_cl, _resource, _stage_prev, _access_prev, _stage_next, _access_next, _layout) \ G_MemorySyncEx((_cl), (G_MemoryBarrierDesc) { \ .resource = (_resource), \ .stage_prev = _stage_prev, \ .access_prev = _access_prev, \ .stage_next = _stage_next, \ .access_next = _access_next, \ .layout = _layout, \ }) #define G_GlobalMemorySync(_cl, _stage_prev, _access_prev, _stage_next, _access_next) \ G_MemorySyncEx((_cl), (G_MemoryBarrierDesc) { \ .is_global = 1, \ .stage_prev = _stage_prev, \ .access_prev = _access_prev, \ .stage_next = _stage_next, \ .access_next = _access_next, \ }) #define G_DumbMemorySync(cl, resource) \ G_MemorySync((cl), (resource), G_Stage_All, G_Access_All, G_Stage_All, G_Access_All) #define G_DumbMemoryLayoutSync(cl, resource, layout) \ G_MemoryLayoutSync((cl), (resource), G_Stage_All, G_Access_All, G_Stage_All, G_Access_All, (layout)) #define G_DumbGlobalMemorySync(cl) \ G_GlobalMemorySync((cl), G_Stage_All, G_Access_All, G_Stage_All, G_Access_All) //- Compute void G_Compute(G_CommandListHandle cl, ComputeShader cs, Vec3I32 groups); //- Rasterize void G_Rasterize( G_CommandListHandle cl, VertexShader vs, PixelShader ps, u32 instances_count, G_IndexBufferDesc index_buffer, u32 render_targets_count, G_ResourceHandle *render_targets, Rng3 viewport, Rng2 scissor, G_RasterMode mode ); //- Clear void G_ClearRenderTarget(G_CommandListHandle cl, G_ResourceHandle render_target, Vec4 color); //- Discard void G_DiscardRenderTarget(G_CommandListHandle cl, G_ResourceHandle render_target); //////////////////////////////////////////////////////////// //~ @hookdecl Synchronization i64 G_CompletionValueFromQueue(G_QueueKind queue_kind); i64 G_CompletionTargetFromQueue(G_QueueKind queue_kind); G_QueueCompletions G_CompletionValuesFromQueues(G_QueueMask queue_mask); G_QueueCompletions G_CompletionTargetsFromQueues(G_QueueMask queue_mask); void G_SyncEx(G_QueueBarrierDesc desc); #define G_Sync(completion_mask, ...) \ G_SyncEx((G_QueueBarrierDesc) { \ .completions = G_CompletionTargetsFromQueues(completion_mask), \ __VA_ARGS__ \ }) #define G_SyncGpu(completion_mask, wait_mask) G_Sync((completion_mask), .wait_queues = (wait_mask)) #define G_SyncCpu(completion_mask) G_Sync((completion_mask), .wait_cpu = 1); //////////////////////////////////////////////////////////// //~ @hookdecl Statistics G_Stats G_QueryStats(void); //////////////////////////////////////////////////////////// //~ @hookdecl Swapchain G_SwapchainHandle G_AcquireSwapchain(u64 os_window_handle); void G_ReleaseSwapchain(G_SwapchainHandle swapchain); // Waits until a new backbuffer is ready from the swapchain. // This should be called before rendering for minimum latency. G_ResourceHandle G_PrepareBackbuffer(G_SwapchainHandle swapchain_handle, G_Format format, Vec2I32 size); void G_CommitBackbuffer(G_ResourceHandle backbuffer, i32 vsync);