unify gpu resource creation codepath

This commit is contained in:
jacob 2025-12-13 16:04:21 -06:00
parent 50be264a77
commit f241379dba
9 changed files with 427 additions and 420 deletions

View File

@ -1199,6 +1199,14 @@ Rng2 AddRng2Vec2(Rng2 r, Vec2 v)
return result;
}
Rng2 MulRng2Vec2(Rng2 r, Vec2 v)
{
Rng2 result = ZI;
result.p0 = MulVec2Vec2(r.p0, v);
result.p1 = MulVec2Vec2(r.p1, v);
return result;
}
Rng2 DivRng2Vec2(Rng2 r, Vec2 v)
{
Rng2 result = ZI;
@ -1235,6 +1243,14 @@ Rng2I32 AddRng2I32Vec2I32(Rng2I32 r, Vec2I32 v)
return result;
}
Rng2I32 MulRng2I32Vec2I32(Rng2I32 r, Vec2I32 v)
{
Rng2I32 result = ZI;
result.p0 = MulVec2I32Vec2I32(r.p0, v);
result.p1 = MulVec2I32Vec2I32(r.p1, v);
return result;
}
Rng2I32 DivRng2I32Vec2I32(Rng2I32 r, Vec2I32 v)
{
Rng2I32 result = ZI;
@ -1243,7 +1259,6 @@ Rng2I32 DivRng2I32Vec2I32(Rng2I32 r, Vec2I32 v)
return result;
}
////////////////////////////////////////////////////////////
//~ Xform

View File

@ -394,12 +394,14 @@ u32 U32FromVec4(Vec4 v);
Vec2 DimsFromRng2(Rng2 r);
Rng2 UnionRng2(Rng2 a, Rng2 b);
Rng2 AddRng2Vec2(Rng2 r, Vec2 v);
Rng2 MulRng2Vec2(Rng2 a, Vec2 v);
Rng2 DivRng2Vec2(Rng2 a, Vec2 v);
//- Rng2I32
Vec2I32 DimsFromRng2I32(Rng2I32 r);
Rng2I32 UnionRng2I32(Rng2I32 a, Rng2I32 b);
Rng2I32 AddRng2I32Vec2I32(Rng2I32 r, Vec2I32 v);
Rng2I32 MulRng2I32Vec2I32(Rng2I32 a, Vec2I32 v);
Rng2I32 DivRng2I32Vec2I32(Rng2I32 a, Vec2I32 v);
////////////////////////////////////////////////////////////

View File

@ -23,7 +23,7 @@ void G_BootstrapCommon(void)
/* Init point sampler */
{
G_ResourceHandle pt_sampler = G_PushSampler(gpu_perm, (G_SamplerResourceDesc) { .filter = G_Filter_MinMagMipPoint });
G_ResourceHandle pt_sampler = G_PushSampler(gpu_perm, .filter = G_Filter_MinMagMipPoint);
g->basic_sampler = G_PushSamplerStateRef(gpu_perm, pt_sampler);
}
@ -37,9 +37,9 @@ void G_BootstrapCommon(void)
Panic(Lit("Unexpected noise texture size"));
}
noise_tex = G_PushTexture3D(gpu_perm,
G_Format_R16_Uint,
noise_dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present);
G_Format_R16_Uint,
noise_dims,
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present);
G_CopyCpuToTexture(cl,
noise_tex, VEC3I32(0, 0, 0),
noise_data.text, noise_dims,
@ -73,9 +73,9 @@ G_ArenaHandle G_PermArena(void)
//- Cpu -> Gpu upload
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferResourceDesc desc)
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc)
{
G_ResourceHandle buffer = G_PushBufferEx(gpu_arena, desc);
G_ResourceHandle buffer = G_PushResource(gpu_arena, (G_ResourceDesc) { .kind = G_ResourceKind_Buffer, .buffer = desc });
G_CopyCpuToBuffer(cl, buffer, 0, src.text, RNGU64(0, src.len));
G_MemorySync(
cl, buffer,

View File

@ -25,9 +25,9 @@ G_ArenaHandle G_PermArena(void);
//- Cpu -> Gpu upload
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferResourceDesc desc);
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc);
#define G_PushBufferFromString(_arena, _cl, _src, ...) \
G_PushBufferFromString_((_arena), (_cl), (_src), (G_BufferResourceDesc) { .size = (_src).len, __VA_ARGS__ })
G_PushBufferFromString_((_arena), (_cl), (_src), (G_BufferDesc) { .size = (_src).len, __VA_ARGS__ })
//- Viewport / scissor

View File

@ -316,52 +316,7 @@ Struct(G_MemoryBarrierDesc)
};
////////////////////////////////////////////////////////////
//~ Resource types
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 automatically be mapped into the cpu's address space */
G_ResourceFlag_WriteCombined = (1 << 4), /* Writes into the mapped resource will be combined. Fast for linear memcpy, slow for everything else */
};
////////////////////////////////////////////////////////////
//~ Buffer types
Struct(G_BufferResourceDesc)
{
u64 size;
G_ResourceFlag flags;
};
////////////////////////////////////////////////////////////
//~ Texture types
#define G_MaxRenderTargets 8
Enum(G_TextureKind)
{
G_TextureKind_1D,
G_TextureKind_2D,
G_TextureKind_3D,
};
Struct(G_TextureResourceDesc)
{
G_TextureKind kind;
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;
};
////////////////////////////////////////////////////////////
//~ Sampler types
//~ Filter types
/* NOTE: Matches DirectX D3D12_FILTER */
Enum(G_Filter)
@ -439,8 +394,47 @@ Enum(G_ComparisonFunc)
G_ComparisonFunc_Always = 8
};
Struct(G_SamplerResourceDesc)
////////////////////////////////////////////////////////////
//~ 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;
@ -453,6 +447,14 @@ Struct(G_SamplerResourceDesc)
f32 max_lod;
};
Struct(G_ResourceDesc)
{
G_ResourceKind kind;
G_BufferDesc buffer;
G_TextureDesc texture;
G_SamplerDesc sampler;
};
////////////////////////////////////////////////////////////
//~ Ref types
@ -466,6 +468,8 @@ Struct(G_RefDesc)
////////////////////////////////////////////////////////////
//~ Rasterization types
#define G_MaxRenderTargets 8
Enum(G_RasterMode)
{
G_RasterMode_None,
@ -519,47 +523,65 @@ void G_ReleaseArena(G_ArenaHandle arena);
//- Resource creation
G_ResourceHandle G_PushBufferEx(G_ArenaHandle arena, G_BufferResourceDesc desc);
G_ResourceHandle G_PushTextureEx(G_ArenaHandle arena, G_TextureResourceDesc desc);
G_ResourceHandle G_PushSampler(G_ArenaHandle arena, G_SamplerResourceDesc desc);
G_ResourceHandle G_PushResource(G_ArenaHandle arena, G_ResourceDesc desc);
#define G_PushBuffer(arena, type, count, ...) G_PushBufferEx((arena), \
(G_BufferResourceDesc) { \
.size = sizeof(type) * (count), \
__VA_ARGS__ \
} \
#define G_PushBuffer(arena, _type, _count, ...) G_PushResource((arena), \
(G_ResourceDesc) { \
.kind = G_ResourceKind_Buffer, \
.buffer = { \
.size = sizeof(_type) * (_count), \
__VA_ARGS__ \
} \
} \
)
#define G_PushTexture1D(arena, _format, _size, _initial_layout, ...) G_PushTextureEx((arena), \
(G_TextureResourceDesc) { \
.kind = G_TextureKind_1D, \
.format = (_format), \
.dims = VEC3I32((_size), 1, 1), \
.initial_layout = (_initial_layout), \
__VA_ARGS__ \
} \
#define G_PushTexture1D(arena, _format, _size, _initial_layout, ...) G_PushResource((arena), \
(G_ResourceDesc) { \
.kind = G_ResourceKind_Texture1D, \
.texture = { \
.format = (_format), \
.dims = VEC3I32((_size), 1, 1), \
.initial_layout = (_initial_layout), \
__VA_ARGS__ \
} \
} \
)
#define G_PushTexture2D(arena, _format, _size, _initial_layout, ...) G_PushTextureEx((arena), \
(G_TextureResourceDesc) { \
.kind = G_TextureKind_2D, \
.format = (_format), \
.dims = VEC3I32((_size).x, (_size).y, 1), \
.initial_layout = (_initial_layout), \
__VA_ARGS__ \
} \
#define G_PushTexture2D(arena, _format, _size, _initial_layout, ...) G_PushResource((arena), \
(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, _format, _size, _initial_layout, ...) G_PushTextureEx((arena), \
(G_TextureResourceDesc) { \
.kind = G_TextureKind_3D, \
.format = (_format), \
.dims = (_size), \
.initial_layout = (_initial_layout), \
__VA_ARGS__ \
} \
#define G_PushTexture3D(arena, _format, _size, _initial_layout, ...) G_PushResource((arena), \
(G_ResourceDesc) { \
.kind = G_ResourceKind_Texture3D, \
.texture = { \
.format = (_format), \
.dims = (_size), \
.initial_layout = (_initial_layout), \
__VA_ARGS__ \
} \
} \
)
#define G_PushSampler(arena, ...) G_PushResource((arena), \
(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)) })

View File

@ -743,111 +743,6 @@ i64 G_D12_CommitRawCommandList(G_D12_RawCommandList *cl)
return completion;
}
////////////////////////////////////////////////////////////
//~ Arena
G_D12_ResourceHeap *G_D12_ResourceHeapFromArena(G_D12_Arena *gpu_arena, G_D12_ResourceHeapKind kind)
{
G_D12_SharedState *g = &G_D12_shared_state;
G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[kind];
b32 is_mappable = 0;
/* Initialize heap */
/* FIXME: Dynamic size */
if (heap->d3d_heap == 0)
{
HRESULT hr = 0;
/* Create d3d heap */
{
D3D12_HEAP_DESC d3d_desc = ZI;
d3d_desc.SizeInBytes = Mebi(512);
if (kind == G_D12_ResourceHeapKind_Cpu)
{
d3d_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
d3d_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
d3d_desc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
is_mappable = 1;
}
else if (kind == G_D12_ResourceHeapKind_CpuWriteCombined)
{
d3d_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
d3d_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
d3d_desc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
is_mappable = 1;
}
else
{
d3d_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT;
}
d3d_desc.Flags |= D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
d3d_desc.Flags |= D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; /* TODO: Remove this and support tier 1 resource heaps */
hr = ID3D12Device_CreateHeap(g->device, &d3d_desc, &IID_ID3D12Heap, (void **)&heap->d3d_heap);
heap->size = d3d_desc.SizeInBytes;
}
/* Map resource */
if (is_mappable)
{
/* Create heap-sized resource for mapping */
if (SUCCEEDED(hr))
{
D3D12_RESOURCE_DESC1 d3d_desc = ZI;
d3d_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
d3d_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
d3d_desc.Format = DXGI_FORMAT_UNKNOWN;
d3d_desc.Width = heap->size;
d3d_desc.Height = 1;
d3d_desc.DepthOrArraySize = 1;
d3d_desc.MipLevels = 1;
d3d_desc.SampleDesc.Count = 1;
d3d_desc.SampleDesc.Quality = 0;
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
u64 alloc_size = 0;
u64 alloc_align = 0;
{
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = ZI;
ID3D12Device_GetResourceAllocationInfo(g->device, &alloc_info, 0, 1, (D3D12_RESOURCE_DESC *)&d3d_desc);
alloc_size = alloc_info.SizeInBytes;
alloc_align = alloc_info.Alignment;
}
if (alloc_size > heap->size)
{
Panic(Lit("Gpu heap overflow"));
}
hr = ID3D12Device10_CreatePlacedResource2(g->device,
heap->d3d_heap,
0,
&d3d_desc,
D3D12_BARRIER_LAYOUT_UNDEFINED,
0,
0,
0,
&IID_ID3D12Resource,
(void **)&heap->d3d_mapped_resource);
}
if (SUCCEEDED(hr))
{
D3D12_RANGE read_range = ZI;
hr = ID3D12Resource_Map(heap->d3d_mapped_resource, 0, &read_range, &heap->mapped);
}
}
if (!SUCCEEDED(hr))
{
/* TODO: Don't panic */
Panic(Lit("Failed to create D3D12 resource heap"));
}
}
return heap;
}
////////////////////////////////////////////////////////////
//~ @hookimpl Arena
@ -876,7 +771,272 @@ void G_ReleaseArena(G_ArenaHandle arena)
}
////////////////////////////////////////////////////////////
//~ Resource
//~ Arena
void G_D12_ResetArena(G_D12_CmdList *cl, G_D12_Arena *gpu_arena)
{
/* TODO */
/* FIXME: Move descriptors into committed lists */
/* FIXME: Release id3d12 resource com object references */
for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
{
G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
heap->pos = 0;
}
}
////////////////////////////////////////////////////////////
//~ @hookimpl Resource
G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc)
{
G_D12_SharedState *g = &G_D12_shared_state;
G_D12_Arena *gpu_arena = G_D12_ArenaFromHandle(arena_handle);
G_D12_Resource *resource = 0;
HRESULT hr = 0;
b32 is_buffer = desc.kind == G_ResourceKind_Buffer;
b32 is_texture = desc.kind == G_ResourceKind_Texture1D ||
desc.kind == G_ResourceKind_Texture2D ||
desc.kind == G_ResourceKind_Texture3D;
b32 is_sampler = desc.kind == G_ResourceKind_Sampler;
G_ResourceFlag flags = is_buffer ? desc.buffer.flags :
is_texture ? desc.texture.flags :
desc.sampler.flags;
if (is_buffer || is_texture)
{
//////////////////////////////
//- Initialize heap
G_D12_ResourceHeap *heap = 0;
if (is_buffer || is_texture)
{
G_D12_ResourceHeapKind heap_kind = G_D12_ResourceHeapKind_Gpu;
if (flags & G_ResourceFlag_HostMemory)
{
heap_kind = G_D12_ResourceHeapKind_Cpu;
if (flags & G_ResourceFlag_Uncached)
{
heap_kind = G_D12_ResourceHeapKind_CpuWriteCombined;
}
}
heap = &gpu_arena->resource_heaps[heap_kind];
if (heap->d3d_heap == 0)
{
b32 is_mappable = 0;
/* Initialize heap */
/* FIXME: Dynamic size */
if (heap->d3d_heap == 0)
{
/* Create d3d heap */
{
D3D12_HEAP_DESC d3d_desc = ZI;
d3d_desc.SizeInBytes = Mebi(256);
if (heap_kind == G_D12_ResourceHeapKind_Cpu)
{
d3d_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
d3d_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
d3d_desc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
is_mappable = 1;
}
else if (heap_kind == G_D12_ResourceHeapKind_CpuWriteCombined)
{
d3d_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
d3d_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
d3d_desc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
is_mappable = 1;
}
else
{
d3d_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT;
}
d3d_desc.Flags |= D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
d3d_desc.Flags |= D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; /* TODO: Remove this and support tier 1 resource heaps */
hr = ID3D12Device_CreateHeap(g->device, &d3d_desc, &IID_ID3D12Heap, (void **)&heap->d3d_heap);
heap->size = d3d_desc.SizeInBytes;
}
/* Map heap resource */
if (is_mappable)
{
if (SUCCEEDED(hr))
{
D3D12_RESOURCE_DESC1 d3d_desc = ZI;
d3d_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
d3d_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
d3d_desc.Format = DXGI_FORMAT_UNKNOWN;
d3d_desc.Width = heap->size;
d3d_desc.Height = 1;
d3d_desc.DepthOrArraySize = 1;
d3d_desc.MipLevels = 1;
d3d_desc.SampleDesc.Count = 1;
d3d_desc.SampleDesc.Quality = 0;
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
u64 alloc_size = 0;
u64 alloc_align = 0;
{
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = ZI;
ID3D12Device_GetResourceAllocationInfo(g->device, &alloc_info, 0, 1, (D3D12_RESOURCE_DESC *)&d3d_desc);
alloc_size = alloc_info.SizeInBytes;
alloc_align = alloc_info.Alignment;
}
if (alloc_size > heap->size)
{
Panic(Lit("Gpu heap overflow"));
}
hr = ID3D12Device10_CreatePlacedResource2(g->device,
heap->d3d_heap,
0,
&d3d_desc,
D3D12_BARRIER_LAYOUT_UNDEFINED,
0,
0,
0,
&IID_ID3D12Resource,
(void **)&heap->d3d_mapped_resource);
}
if (SUCCEEDED(hr))
{
D3D12_RANGE read_range = ZI;
hr = ID3D12Resource_Map(heap->d3d_mapped_resource, 0, &read_range, &heap->mapped);
}
}
if (!SUCCEEDED(hr))
{
/* TODO: Don't panic */
Panic(Lit("Failed to create D3D12 resource heap"));
}
}
}
}
//////////////////////////////
//- Create buffer / texture
D3D12_BARRIER_LAYOUT initial_layout = D3D12_BARRIER_LAYOUT_UNDEFINED;
D3D12_CLEAR_VALUE clear_value = ZI;
D3D12_RESOURCE_DESC1 d3d_desc = ZI;
{
if (is_buffer)
{
d3d_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
d3d_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
d3d_desc.Format = DXGI_FORMAT_UNKNOWN;
d3d_desc.Width = AlignU64(MaxU64(desc.buffer.size, 1), 4);
d3d_desc.Height = 1;
d3d_desc.DepthOrArraySize = 1;
d3d_desc.MipLevels = 1;
d3d_desc.SampleDesc.Count = 1;
d3d_desc.SampleDesc.Quality = 0;
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS * AnyBit(flags, G_ResourceFlag_AllowShaderReadWrite);
}
if (is_texture)
{
initial_layout = G_D12_BarrierLayoutFromLayout(desc.texture.initial_layout);
d3d_desc.Dimension = desc.kind == G_ResourceKind_Texture1D ? D3D12_RESOURCE_DIMENSION_TEXTURE1D :
desc.kind == G_ResourceKind_Texture2D ? D3D12_RESOURCE_DIMENSION_TEXTURE2D :
D3D12_RESOURCE_DIMENSION_TEXTURE3D;
d3d_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
d3d_desc.Format = G_D12_DxgiFormatFromGpuFormat(desc.texture.format);
d3d_desc.Width = MaxI32(desc.texture.dims.x, 1);
d3d_desc.Height = MaxI32(desc.texture.dims.y, 1);
d3d_desc.DepthOrArraySize = MaxI32(desc.texture.dims.z, 1);
d3d_desc.MipLevels = MaxI32(desc.texture.mip_levels, 1);
d3d_desc.SampleDesc.Count = 1;
d3d_desc.SampleDesc.Quality = 0;
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS * AnyBit(flags, G_ResourceFlag_AllowShaderReadWrite);
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET * AnyBit(flags, G_ResourceFlag_AllowRenderTarget);
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL * AnyBit(flags, G_ResourceFlag_AllowDepthStencil);
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS * (desc.texture.initial_layout == G_Layout_Simultaneous);
clear_value.Color[0] = desc.texture.clear_color.x,
clear_value.Color[1] = desc.texture.clear_color.y,
clear_value.Color[2] = desc.texture.clear_color.z,
clear_value.Color[3] = desc.texture.clear_color.w,
clear_value.Format = d3d_desc.Format;
}
}
u64 alloc_size = 0;
u64 alloc_align = 0;
{
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = ZI;
ID3D12Device_GetResourceAllocationInfo(g->device, &alloc_info, 0, 1, (D3D12_RESOURCE_DESC *)&d3d_desc);
alloc_size = alloc_info.SizeInBytes;
alloc_align = alloc_info.Alignment;
}
u64 pos_in_heap = 0;
{
pos_in_heap = heap->pos;
pos_in_heap = AlignU64(pos_in_heap, alloc_align);
heap->pos = pos_in_heap + alloc_size;
if (pos_in_heap + alloc_size > heap->size)
{
Panic(Lit("Gpu arena overflow"));
}
}
ID3D12Resource *d3d_resource = 0;
{
hr = ID3D12Device10_CreatePlacedResource2(
g->device,
heap->d3d_heap,
pos_in_heap,
&d3d_desc,
D3D12_BARRIER_LAYOUT_UNDEFINED,
(d3d_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ? &clear_value : 0,
0,
0,
&IID_ID3D12Resource,
(void **)&d3d_resource
);
}
resource = PushStruct(gpu_arena->arena, G_D12_Resource);
resource->heap = heap;
resource->pos_in_heap = pos_in_heap;
resource->d3d_resource = d3d_resource;
resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
resource->flags = flags;
if (is_buffer)
{
resource->buffer_size = desc.buffer.size;
resource->buffer_size_actual = d3d_desc.Width;
resource->buffer_gpu_address = ID3D12Resource_GetGPUVirtualAddress(d3d_resource);
}
if (is_texture)
{
resource->is_texture = 1;
resource->texture_format = desc.texture.format;
resource->texture_dims = desc.texture.dims;
resource->texture_mip_levels = desc.texture.mip_levels;
resource->texture_layout = initial_layout;
}
}
//////////////////////////////
//- Create sampler
if (is_sampler)
{
resource = PushStruct(gpu_arena->arena, G_D12_Resource);
resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
resource->sampler_desc = desc.sampler;
}
return G_D12_MakeHandle(G_ResourceHandle, resource);
}
////////////////////////////////////////////////////////////
//~ Descriptor
G_D12_Descriptor *G_D12_DescriptorFromIndex(G_D12_DescriptorHeapKind heap_kind, u32 index)
{
@ -951,194 +1111,6 @@ G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorH
return descriptor;
}
////////////////////////////////////////////////////////////
//~ @hookimpl Resource
//- Resource creation
G_ResourceHandle G_PushBufferEx(G_ArenaHandle arena_handle, G_BufferResourceDesc desc)
{
G_D12_SharedState *g = &G_D12_shared_state;
G_D12_Arena *gpu_arena = G_D12_ArenaFromHandle(arena_handle);
/* Fetch heap */
G_D12_ResourceHeapKind heap_kind = G_D12_ResourceHeapKind_Gpu;
if (desc.flags & G_ResourceFlag_HostMemory)
{
heap_kind = G_D12_ResourceHeapKind_Cpu;
if (desc.flags & G_ResourceFlag_WriteCombined)
{
heap_kind = G_D12_ResourceHeapKind_CpuWriteCombined;
}
}
G_D12_ResourceHeap *heap = G_D12_ResourceHeapFromArena(gpu_arena, heap_kind);
/* Create d3d resource */
ID3D12Resource *d3d_resource = 0;
u64 pos_in_heap = 0;
u64 aligned_size = AlignU64(MaxU64(desc.size, 1), 4);
{
D3D12_RESOURCE_DESC1 d3d_desc = ZI;
d3d_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
d3d_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
d3d_desc.Format = DXGI_FORMAT_UNKNOWN;
d3d_desc.Width = aligned_size;
d3d_desc.Height = 1;
d3d_desc.DepthOrArraySize = 1;
d3d_desc.MipLevels = 1;
d3d_desc.SampleDesc.Count = 1;
d3d_desc.SampleDesc.Quality = 0;
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS * AnyBit(desc.flags, G_ResourceFlag_AllowShaderReadWrite);
u64 alloc_size = 0;
u64 alloc_align = 0;
{
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = ZI;
ID3D12Device_GetResourceAllocationInfo(g->device, &alloc_info, 0, 1, (D3D12_RESOURCE_DESC *)&d3d_desc);
alloc_size = alloc_info.SizeInBytes;
alloc_align = alloc_info.Alignment;
}
pos_in_heap = heap->pos;
pos_in_heap = AlignU64(pos_in_heap, alloc_align);
heap->pos = pos_in_heap + alloc_size;
if (pos_in_heap + alloc_size > heap->size)
{
Panic(Lit("Gpu arena overflow"));
}
HRESULT hr = ID3D12Device10_CreatePlacedResource2(g->device,
heap->d3d_heap,
pos_in_heap,
&d3d_desc,
D3D12_BARRIER_LAYOUT_UNDEFINED,
0,
0,
0,
&IID_ID3D12Resource,
(void **)&d3d_resource);
}
G_D12_Resource *resource = PushStruct(gpu_arena->arena, G_D12_Resource);
resource->heap = heap;
resource->pos_in_heap = pos_in_heap;
resource->d3d_resource = d3d_resource;
resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
resource->flags = desc.flags;
resource->buffer_size = desc.size;
resource->buffer_size_aligned = aligned_size;
resource->buffer_gpu_address = ID3D12Resource_GetGPUVirtualAddress(d3d_resource);
return G_D12_MakeHandle(G_ResourceHandle, resource);
}
G_ResourceHandle G_PushTextureEx(G_ArenaHandle arena_handle, G_TextureResourceDesc desc)
{
G_D12_SharedState *g = &G_D12_shared_state;
G_D12_Arena *gpu_arena = G_D12_ArenaFromHandle(arena_handle);
D3D12_BARRIER_LAYOUT initial_layout = G_D12_BarrierLayoutFromLayout(desc.initial_layout);
/* Fetch heap */
G_D12_ResourceHeapKind heap_kind = G_D12_ResourceHeapKind_Gpu;
if (desc.flags & G_ResourceFlag_HostMemory)
{
heap_kind = G_D12_ResourceHeapKind_Cpu;
if (desc.flags & G_ResourceFlag_WriteCombined)
{
heap_kind = G_D12_ResourceHeapKind_CpuWriteCombined;
}
}
G_D12_ResourceHeap *heap = G_D12_ResourceHeapFromArena(gpu_arena, heap_kind);
/* Create d3d resource */
ID3D12Resource *d3d_resource = 0;
u64 pos_in_heap;
{
D3D12_RESOURCE_DESC1 d3d_desc = ZI;
d3d_desc.Dimension = desc.kind == G_TextureKind_1D ? D3D12_RESOURCE_DIMENSION_TEXTURE1D :
desc.kind == G_TextureKind_2D ? D3D12_RESOURCE_DIMENSION_TEXTURE2D :
D3D12_RESOURCE_DIMENSION_TEXTURE3D;
d3d_desc.Format = G_D12_DxgiFormatFromGpuFormat(desc.format);
d3d_desc.Width = MaxI32(desc.dims.x, 1);
d3d_desc.Height = MaxI32(desc.dims.y, 1);
d3d_desc.DepthOrArraySize = MaxI32(desc.dims.z, 1);
d3d_desc.MipLevels = MaxI32(desc.mip_levels, 1);
d3d_desc.SampleDesc.Count = 1;
d3d_desc.SampleDesc.Quality = 0;
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS * AnyBit(desc.flags, G_ResourceFlag_AllowShaderReadWrite);
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET * AnyBit(desc.flags, G_ResourceFlag_AllowRenderTarget);
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL * AnyBit(desc.flags, G_ResourceFlag_AllowDepthStencil);
d3d_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS * (desc.initial_layout == G_Layout_Simultaneous);
u64 alloc_size = 0;
u64 alloc_align = 0;
{
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = ZI;
ID3D12Device_GetResourceAllocationInfo(g->device, &alloc_info, 0, 1, (D3D12_RESOURCE_DESC *)&d3d_desc);
alloc_size = alloc_info.SizeInBytes;
alloc_align = alloc_info.Alignment;
}
pos_in_heap = heap->pos;
pos_in_heap = AlignU64(pos_in_heap, alloc_align);
heap->pos = pos_in_heap + alloc_size;
if (pos_in_heap + alloc_size > heap->size)
{
Panic(Lit("Gpu arena overflow"));
}
D3D12_CLEAR_VALUE clear_value = {
.Color[0] = desc.clear_color.x,
.Color[1] = desc.clear_color.y,
.Color[2] = desc.clear_color.z,
.Color[3] = desc.clear_color.w,
.Format = d3d_desc.Format
};
HRESULT hr = ID3D12Device10_CreatePlacedResource2(g->device,
heap->d3d_heap,
pos_in_heap,
&d3d_desc,
initial_layout,
(d3d_desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ? &clear_value : 0,
0,
0,
&IID_ID3D12Resource,
(void **)&d3d_resource);
}
G_D12_Resource *resource = PushStruct(gpu_arena->arena, G_D12_Resource);
resource->heap = heap;
resource->pos_in_heap = pos_in_heap;
resource->d3d_resource = d3d_resource;
resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
resource->flags = desc.flags;
resource->is_texture = 1;
resource->texture_format = desc.format;
resource->texture_dims = desc.dims;
resource->texture_mip_levels = desc.mip_levels;
resource->texture_layout = initial_layout;
return G_D12_MakeHandle(G_ResourceHandle, resource);
}
G_ResourceHandle G_PushSampler(G_ArenaHandle arena_handle, G_SamplerResourceDesc desc)
{
G_D12_SharedState *g = &G_D12_shared_state;
G_D12_Arena *gpu_arena = G_D12_ArenaFromHandle(arena_handle);
G_D12_Resource *resource = PushStruct(gpu_arena->arena, G_D12_Resource);
resource->uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
resource->sampler_desc = desc;
return G_D12_MakeHandle(G_ResourceHandle, resource);
}
////////////////////////////////////////////////////////////
//~ @hookimpl Shader resource reference
@ -1185,8 +1157,8 @@ u32 G_PushRef(G_ArenaHandle arena_handle, G_ResourceHandle resource_handle, G_Re
}
descriptor = G_D12_PushDescriptor(gpu_arena, G_D12_DescriptorHeapKind_CbvSrvUav);
u64 buffer_size_aligned = resource->buffer_size_aligned;
u64 num_elements_in_buffer = buffer_size_aligned / ref_desc.element_size;
u64 buffer_size_actual = resource->buffer_size_actual;
u64 num_elements_in_buffer = buffer_size_actual / ref_desc.element_size;
u64 num_elements_after_offset = num_elements_in_buffer > ref_desc.element_offset ? num_elements_in_buffer - ref_desc.element_offset : 0;
if (num_elements_after_offset > 0)
@ -1247,7 +1219,7 @@ u32 G_PushRef(G_ArenaHandle arena_handle, G_ResourceHandle resource_handle, G_Re
else if (is_sampler)
{
descriptor = G_D12_PushDescriptor(gpu_arena, G_D12_DescriptorHeapKind_Sampler);
G_SamplerResourceDesc sampler_desc = resource->sampler_desc;
G_SamplerDesc sampler_desc = resource->sampler_desc;
D3D12_SAMPLER_DESC d3d_desc = ZI;
{
d3d_desc.Filter = (D3D12_FILTER)sampler_desc.filter;
@ -1523,7 +1495,7 @@ G_D12_StagingRegionNode *G_D12_PushStagingRegion(G_D12_CmdList *cl, u64 size)
heap->resource.d3d_resource = d3d_resource;
heap->resource.uid = Atomic64FetchAdd(&g->resource_creation_gen.v, 1) + 1;
heap->resource.buffer_size = new_heap_size;
heap->resource.buffer_size_aligned = new_heap_size;
heap->resource.buffer_size_actual = new_heap_size;
heap->resource.buffer_gpu_address = ID3D12Resource_GetGPUVirtualAddress(d3d_resource);
/* Map */
@ -2240,18 +2212,9 @@ i64 G_CommitCommandList(G_CommandListHandle cl_handle)
void G_ResetArena(G_CommandListHandle cl_handle, G_ArenaHandle arena_handle)
{
G_D12_CmdList *cl = G_D12_CmdListFromHandle(cl_handle);
G_D12_Arena *gpu_arena = G_D12_ArenaFromHandle(arena_handle);
/* TODO */
/* FIXME: Move descriptors into committed lists */
/* FIXME: Release id3d12 resource com object references */
for (u64 heap_idx = 0; heap_idx < countof(gpu_arena->resource_heaps); ++heap_idx)
{
G_D12_ResourceHeap *heap = &gpu_arena->resource_heaps[heap_idx];
heap->pos = 0;
}
G_D12_ResetArena(cl, gpu_arena);
}
//- Cpu -> Gpu copy
@ -2935,7 +2898,7 @@ void G_D12_CollectionWorkerEntryPoint(WaveLaneCtx *lane)
switch (gpu_kind)
{
/* Translate unsigned args */
/* Translate unsigned integer args */
case G_FmtArgKind_Uint:
{
u32 gpu_value = *(u32 *)at;
@ -2961,7 +2924,7 @@ void G_D12_CollectionWorkerEntryPoint(WaveLaneCtx *lane)
at += 16;
} break;
/* Translate signed args */
/* Translate signed integer args */
case G_FmtArgKind_Sint:
{
i32 gpu_value = *(i32 *)at;

View File

@ -99,7 +99,7 @@ Struct(G_D12_DescriptorList)
};
////////////////////////////////////////////////////////////
//~ Resource heap types
//~ Arena types
/* TODO:
* To support D3D12_RESOURCE_HEAP_TIER_1 devices, create separate heaps for:
@ -124,13 +124,18 @@ Struct(G_D12_ResourceHeap)
ID3D12Resource *d3d_mapped_resource;
void *mapped;
u64 resources_count;
struct G_D12_Resource *first_resource;
struct G_D12_Resource *last_resource;
u64 reset_resources_count;
struct G_D12_Resource *first_reset_resource;
struct G_D12_Resource *last_reset_resource;
u64 pos;
u64 size;
};
////////////////////////////////////////////////////////////
//~ Arena types
Struct(G_D12_Arena)
{
Arena *arena;
@ -144,7 +149,7 @@ Struct(G_D12_Arena)
Struct(G_D12_Resource)
{
G_D12_Resource *next_free;
G_D12_Resource *next;
G_D12_ResourceHeap *heap;
u64 pos_in_heap;
@ -155,7 +160,7 @@ Struct(G_D12_Resource)
/* Buffer info */
u64 buffer_size;
u64 buffer_size_aligned;
u64 buffer_size_actual;
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address;
/* Texture info */
@ -166,7 +171,7 @@ Struct(G_D12_Resource)
D3D12_BARRIER_LAYOUT texture_layout;
/* Sampler info */
G_SamplerResourceDesc sampler_desc;
G_SamplerDesc sampler_desc;
/* Backbuffer info */
struct G_D12_Swapchain *swapchain;
@ -445,23 +450,23 @@ G_D12_Pipeline *G_D12_PipelineFromDesc(G_D12_PipelineDesc desc);
G_D12_Queue *G_D12_QueueFromKind(G_QueueKind kind);
////////////////////////////////////////////////////////////
//~ Arena
G_D12_ResourceHeap *G_D12_ResourceHeapFromArena(G_D12_Arena *gpu_arena, G_D12_ResourceHeapKind kind);
////////////////////////////////////////////////////////////
//~ Resource
G_D12_Descriptor *G_D12_DescriptorFromIndex(G_D12_DescriptorHeapKind heap_kind, u32 index);
G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorHeapKind heap_kind);
////////////////////////////////////////////////////////////
//~ Raw command list
G_D12_RawCommandList *G_D12_PrepareRawCommandList(G_QueueKind queue_kind);
i64 G_D12_CommitRawCommandList(G_D12_RawCommandList *cl);
////////////////////////////////////////////////////////////
//~ Arena
void G_D12_ResetArena(G_D12_CmdList *cl, G_D12_Arena *gpu_arena);
////////////////////////////////////////////////////////////
//~ Descriptor
G_D12_Descriptor *G_D12_DescriptorFromIndex(G_D12_DescriptorHeapKind heap_kind, u32 index);
G_D12_Descriptor *G_D12_PushDescriptor(G_D12_Arena *gpu_arena, G_D12_DescriptorHeapKind heap_kind);
////////////////////////////////////////////////////////////
//~ Command helpers

View File

@ -111,7 +111,7 @@ TTF_GlyphResult TTF_RasterizeGlyphFromCodepoint(Arena *arena, u32 codepoint, Res
/* Best-guess a position in the middle of the render target based on metrics */
Vec2I32 rt_baseline = ZI;
rt_baseline.x = (rt_dims.x / 2) - (advance / 2);
rt_baseline.y = (rt_dims.y / 2) - (font_cap / 2);
rt_baseline.y = (rt_dims.y / 2) + (font_cap / 2);
/* Create render target */
IDWriteBitmapRenderTarget *render_target = 0;

View File

@ -1263,7 +1263,7 @@ void UI_EndFrame(UI_Frame *frame)
for (u64 rect_idx = 0; rect_idx < raw_run.rects_count; ++rect_idx)
{
GC_RunRect rr = raw_run.rects[rect_idx];
if ((rr.baseline_pos + rr.advance) <= elipses_start_pos)
if (rr.baseline_pos + rr.advance <= elipses_start_pos)
{
final_rects[final_rects_count] = rr;
final_rects_count += 1;
@ -1275,7 +1275,7 @@ void UI_EndFrame(UI_Frame *frame)
{
GC_RunRect rr = elipses_run.rects[rect_idx];
rr.baseline_pos += elipses_start_pos;
if ((rr.baseline_pos + rr.advance) <= max_baseline)
if (rr.baseline_pos > 0)
{
final_rects[final_rects_count] = rr;
final_rects_count += 1;