gpu utils
This commit is contained in:
parent
fca8ba5a8d
commit
69a8f2e1a3
@ -398,7 +398,11 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
|||||||
#define AlignedBlock(n) struct alignas(n)
|
#define AlignedBlock(n) struct alignas(n)
|
||||||
|
|
||||||
//- Enum
|
//- Enum
|
||||||
#define Enum(name) typedef enum name name; enum name
|
#if !LanguageIsGpu
|
||||||
|
# define Enum(name) typedef enum name name; enum name
|
||||||
|
#else
|
||||||
|
# define Enum(name) enum name
|
||||||
|
#endif
|
||||||
|
|
||||||
//- alignof
|
//- alignof
|
||||||
#if LanguageIsC && (CompilerIsMsvc || __STDC_VERSION__ < 202311L)
|
#if LanguageIsC && (CompilerIsMsvc || __STDC_VERSION__ < 202311L)
|
||||||
|
|||||||
@ -51,3 +51,14 @@ Vec4 LinearFromSrgbU32(u32 srgb32)
|
|||||||
{
|
{
|
||||||
return LinearFromSrgbVec4(Vec4NormFromU32(srgb32));
|
return LinearFromSrgbVec4(Vec4NormFromU32(srgb32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Ndc helpers
|
||||||
|
|
||||||
|
Vec2 NdcFromViewport(Vec2 viewport_size, Vec2 viewport_coords)
|
||||||
|
{
|
||||||
|
Vec2 result;
|
||||||
|
result.x = ((viewport_coords.x + 0.5f) / viewport_size.x) * 2.0f - 1.0f;
|
||||||
|
result.y = 1.0f - ((viewport_coords.y + 0.5f) / viewport_size.y) * 2.0f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@ -384,6 +384,8 @@ Vec2I32 GPU_GetTextureSize2D(GPU_Resource *resource);
|
|||||||
Vec3I32 GPU_GetTextureSize3D(GPU_Resource *resource);
|
Vec3I32 GPU_GetTextureSize3D(GPU_Resource *resource);
|
||||||
u64 GPU_GetFootprintSize(GPU_Resource *resource);
|
u64 GPU_GetFootprintSize(GPU_Resource *resource);
|
||||||
|
|
||||||
|
u64 GPU_GetBufferCount(GPU_Resource *gpu_resource);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Resource index operations
|
//~ @hookdecl Resource index operations
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,17 @@
|
|||||||
|
|
||||||
//- Api
|
//- Api
|
||||||
@IncludeC gpu.h
|
@IncludeC gpu.h
|
||||||
|
@IncludeC gpu_util.h
|
||||||
|
|
||||||
|
//- Impl
|
||||||
|
@IncludeC gpu_util.c
|
||||||
|
|
||||||
//- Dx12 impl
|
//- Dx12 impl
|
||||||
@DefaultWindowsImpl gpu_dx12
|
@DefaultWindowsImpl gpu_dx12
|
||||||
|
|
||||||
|
//- Embeds
|
||||||
|
@EmbedDir GPU_Resources gpu_res
|
||||||
|
|
||||||
//- Startup
|
//- Startup
|
||||||
@Startup GPU_Startup
|
@Startup GPU_Startup
|
||||||
|
@Startup GPU_StartupUtils
|
||||||
|
|||||||
@ -1231,9 +1231,9 @@ GPU_Resource *GPU_AcquireResource(GPU_ResourceDesc desc)
|
|||||||
d3d_desc.MaxLOD = desc.sampler.max_lod;
|
d3d_desc.MaxLOD = desc.sampler.max_lod;
|
||||||
|
|
||||||
/* Defaults */
|
/* Defaults */
|
||||||
if (d3d_desc.AddressU == 0) d3d_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;;
|
if (d3d_desc.AddressU == 0) d3d_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
if (d3d_desc.AddressV == 0) d3d_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;;
|
if (d3d_desc.AddressV == 0) d3d_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
if (d3d_desc.AddressW == 0) d3d_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;;
|
if (d3d_desc.AddressW == 0) d3d_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||||
if (d3d_desc.MaxLOD >= F32Infinity)
|
if (d3d_desc.MaxLOD >= F32Infinity)
|
||||||
{
|
{
|
||||||
d3d_desc.MaxLOD = D3D12_FLOAT32_MAX;
|
d3d_desc.MaxLOD = D3D12_FLOAT32_MAX;
|
||||||
@ -1351,6 +1351,12 @@ u64 GPU_GetFootprintSize(GPU_Resource *gpu_resource)
|
|||||||
return footprint_size;
|
return footprint_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 GPU_GetBufferCount(GPU_Resource *gpu_resource)
|
||||||
|
{
|
||||||
|
GPU_D12_Resource *resource = (GPU_D12_Resource *)gpu_resource;
|
||||||
|
return resource->desc.buffer.count;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdef Resource index hooks
|
//~ @hookdef Resource index hooks
|
||||||
|
|
||||||
|
|||||||
236
src/gpu/gpu_util.c
Normal file
236
src/gpu/gpu_util.c
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
GPU_SharedUtilState GPU_shared_util_state = ZI;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Startup
|
||||||
|
|
||||||
|
void GPU_StartupUtils(void)
|
||||||
|
{
|
||||||
|
GPU_SharedUtilState *g = &GPU_shared_util_state;
|
||||||
|
|
||||||
|
GPU_QueueKind queue_kind = GPU_QueueKind_Direct;
|
||||||
|
Fence *queue_fence = GPU_FenceFromQueue(queue_kind);
|
||||||
|
i64 queue_fence_target = FetchFence(queue_fence);
|
||||||
|
|
||||||
|
GPU_Resource *noise_upload = 0;
|
||||||
|
GPU_Resource *quad_upload = 0;
|
||||||
|
GPU_Resource *noise = 0;
|
||||||
|
GPU_Resource *quad = 0;
|
||||||
|
|
||||||
|
GPU_CommandList *cl = GPU_BeginCommandList(queue_kind);
|
||||||
|
{
|
||||||
|
/* Upload noise */
|
||||||
|
{
|
||||||
|
Vec3I32 noise_size = VEC3I32(128, 128, 64);
|
||||||
|
Resource noise_resource = ResourceFromStore(&GPU_Resources, Lit("noise_128x128x64_16.dat"));
|
||||||
|
String noise_res_data = DataFromResource(noise_resource);
|
||||||
|
if (noise_res_data.len != noise_size.x * noise_size.y * noise_size.z * 2)
|
||||||
|
{
|
||||||
|
Panic(Lit("Unexpected noise texture size"));
|
||||||
|
}
|
||||||
|
GPU_ResourceDesc desc = ZI;
|
||||||
|
desc.kind = GPU_ResourceKind_Texture3D;
|
||||||
|
desc.texture.format = GPU_Format_R16_Uint;
|
||||||
|
desc.texture.size = noise_size;
|
||||||
|
noise = GPU_AcquireResource(desc);
|
||||||
|
{
|
||||||
|
u64 footprint_size = GPU_GetFootprintSize(noise);
|
||||||
|
GPU_ResourceDesc upload_desc = ZI;
|
||||||
|
upload_desc.kind = GPU_ResourceKind_Buffer;
|
||||||
|
upload_desc.buffer.heap_kind = GPU_HeapKind_Upload;
|
||||||
|
upload_desc.buffer.count = footprint_size;
|
||||||
|
noise_upload = GPU_AcquireResource(upload_desc);
|
||||||
|
GPU_Mapped mapped = GPU_Map(noise_upload);
|
||||||
|
GPU_CopyBytesToFootprint(mapped.mem, noise_res_data.text, noise);
|
||||||
|
GPU_Unmap(mapped);
|
||||||
|
}
|
||||||
|
GPU_TransitionToCopyDst(cl, noise);
|
||||||
|
GPU_CopyResource(cl, noise, noise_upload);
|
||||||
|
GPU_TransitionToReadable(cl, noise);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Upload quad indices */
|
||||||
|
{
|
||||||
|
u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 };
|
||||||
|
GPU_ResourceDesc desc = ZI;
|
||||||
|
desc.kind = GPU_ResourceKind_Buffer;
|
||||||
|
desc.buffer.count = countof(quad_indices);
|
||||||
|
desc.buffer.stride = sizeof(quad_indices[0]);
|
||||||
|
quad = GPU_AcquireResource(desc);
|
||||||
|
{
|
||||||
|
GPU_ResourceDesc upload_desc = ZI;
|
||||||
|
upload_desc.kind = GPU_ResourceKind_Buffer;
|
||||||
|
upload_desc.buffer.heap_kind = GPU_HeapKind_Upload;
|
||||||
|
upload_desc.buffer.count = desc.buffer.count * desc.buffer.stride;
|
||||||
|
quad_upload = GPU_AcquireResource(upload_desc);
|
||||||
|
GPU_Mapped mapped = GPU_Map(quad_upload);
|
||||||
|
CopyBytes(mapped.mem, quad_indices, sizeof(quad_indices));
|
||||||
|
GPU_Unmap(mapped);
|
||||||
|
}
|
||||||
|
GPU_TransitionToCopyDst(cl, quad);
|
||||||
|
GPU_CopyResource(cl, quad, quad_upload);
|
||||||
|
GPU_TransitionToReadable(cl, quad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue_fence_target = GPU_EndCommandList(cl);
|
||||||
|
|
||||||
|
/* Init point sampler */
|
||||||
|
g->pt_sampler = GPU_AcquireResource((GPU_ResourceDesc) { .kind = GPU_ResourceKind_Sampler, .sampler.filter = GPU_Filter_MinMagMipPoint });
|
||||||
|
|
||||||
|
/* Wait & cleanup */
|
||||||
|
YieldOnFence(queue_fence, queue_fence_target);
|
||||||
|
GPU_ReleaseResource(noise_upload, GPU_ReleaseFlag_None);
|
||||||
|
GPU_ReleaseResource(quad_upload, GPU_ReleaseFlag_None);
|
||||||
|
|
||||||
|
g->noise = noise;
|
||||||
|
g->quad_indices = quad;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Common resource helpers
|
||||||
|
|
||||||
|
GPU_Resource *GPU_GetCommonPointSampler(void)
|
||||||
|
{
|
||||||
|
return GPU_shared_util_state.pt_sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPU_Resource *GPU_GetCommonQuadIndices(void)
|
||||||
|
{
|
||||||
|
return GPU_shared_util_state.quad_indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPU_Resource *GPU_GetCommonNoise(void)
|
||||||
|
{
|
||||||
|
return GPU_shared_util_state.noise;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Transient buffer operations
|
||||||
|
|
||||||
|
GPU_TransientBuffer *GPU_AcquireTransientBuffer_(u64 reserve, GPU_QueueKind queue_kind, u32 max_in_flight, u32 element_size, u32 element_align)
|
||||||
|
{
|
||||||
|
element_size = MaxU32(element_size, 1);
|
||||||
|
element_align = MaxU32(element_align, 1);
|
||||||
|
max_in_flight = MaxU32(max_in_flight, 1);
|
||||||
|
|
||||||
|
GPU_TransientBuffer *tbuff = 0;
|
||||||
|
{
|
||||||
|
Arena *arena = AcquireArena(reserve);
|
||||||
|
tbuff = PushStruct(arena, GPU_TransientBuffer);
|
||||||
|
tbuff->arena = arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbuff->queue_kind = queue_kind;
|
||||||
|
tbuff->submitted_resources = PushStructs(tbuff->arena, GPU_SubmittedTransientBufferResource, max_in_flight);
|
||||||
|
tbuff->max_in_flight = max_in_flight;
|
||||||
|
for (u32 i = 0; i < max_in_flight; ++i)
|
||||||
|
{
|
||||||
|
/* Init free list */
|
||||||
|
StackPush(tbuff->first_free, &tbuff->submitted_resources[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
PushAlign(tbuff->arena, element_align);
|
||||||
|
tbuff->elements_start_pos = tbuff->arena->pos;
|
||||||
|
tbuff->element_size = element_size;
|
||||||
|
tbuff->element_align = element_align;
|
||||||
|
|
||||||
|
return tbuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_ReleaseTransientBuffer(GPU_TransientBuffer *tbuff)
|
||||||
|
{
|
||||||
|
Fence *queue_fence = GPU_FenceFromQueue(tbuff->queue_kind);
|
||||||
|
i64 queue_fence_value = FetchFence(queue_fence);
|
||||||
|
YieldOnFence(queue_fence, queue_fence_value);
|
||||||
|
|
||||||
|
for (GPU_SubmittedTransientBufferResource *submitted = tbuff->first_submitted;
|
||||||
|
submitted;
|
||||||
|
submitted = submitted->next)
|
||||||
|
{
|
||||||
|
GPU_ReleaseResource(submitted->resource, GPU_ReleaseFlag_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseArena(tbuff->arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
GPU_Resource *GPU_UploadTransientBuffer(GPU_TransientBuffer *tbuff)
|
||||||
|
{
|
||||||
|
GPU_Resource *resource = 0;
|
||||||
|
u32 element_count = (tbuff->arena->pos - tbuff->elements_start_pos) / tbuff->element_size;
|
||||||
|
|
||||||
|
Fence *queue_fence = GPU_FenceFromQueue(tbuff->queue_kind);
|
||||||
|
i64 queue_fence_value = FetchFence(queue_fence);
|
||||||
|
|
||||||
|
if (tbuff->uploaded != 0)
|
||||||
|
{
|
||||||
|
Panic(Lit("GPU transient buffer uploaded without a reset"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab resource */
|
||||||
|
GPU_SubmittedTransientBufferResource *upload = 0;
|
||||||
|
{
|
||||||
|
GPU_SubmittedTransientBufferResource *submitted = tbuff->first_submitted;
|
||||||
|
if (submitted && submitted->fence_target <= queue_fence_value)
|
||||||
|
{
|
||||||
|
upload = submitted;
|
||||||
|
QueuePop(tbuff->first_submitted, tbuff->last_submitted);
|
||||||
|
}
|
||||||
|
else if (tbuff->first_free)
|
||||||
|
{
|
||||||
|
/* Resource in upload, create new */
|
||||||
|
upload = tbuff->first_free;
|
||||||
|
StackPop(tbuff->first_free);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Resource in use and max_in_flight reached, wait for availability */
|
||||||
|
Assert(submitted != 0);
|
||||||
|
YieldOnFence(queue_fence, submitted->fence_target);
|
||||||
|
queue_fence_value = FetchFence(queue_fence);
|
||||||
|
upload = submitted;
|
||||||
|
QueuePop(tbuff->first_submitted, tbuff->last_submitted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upload->resource)
|
||||||
|
{
|
||||||
|
GPU_ReleaseResource(upload->resource, GPU_ReleaseFlag_Reuse);
|
||||||
|
upload->resource = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPU_ResourceDesc desc = ZI;
|
||||||
|
desc.kind = GPU_ResourceKind_Buffer;
|
||||||
|
desc.flags = GPU_ResourceFlag_None;
|
||||||
|
desc.buffer.heap_kind = GPU_HeapKind_Upload;
|
||||||
|
desc.buffer.count = element_count;
|
||||||
|
desc.buffer.stride = tbuff->element_size;
|
||||||
|
upload->resource = GPU_AcquireResource(desc);
|
||||||
|
|
||||||
|
{
|
||||||
|
__profn("Copy to transfer buffer");
|
||||||
|
GPU_Mapped m = GPU_Map(upload->resource);
|
||||||
|
CopyBytes(m.mem, ArenaBase(tbuff->arena) + tbuff->elements_start_pos, tbuff->element_size * element_count);
|
||||||
|
GPU_Unmap(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbuff->uploaded = upload;
|
||||||
|
tbuff->uploaded_element_count = element_count;
|
||||||
|
|
||||||
|
return upload->resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_ResetTransientBuffer(GPU_TransientBuffer *tbuff, i64 queue_fence_target)
|
||||||
|
{
|
||||||
|
PopTo(tbuff->arena, tbuff->elements_start_pos);
|
||||||
|
GPU_SubmittedTransientBufferResource *use = tbuff->uploaded;
|
||||||
|
if (use)
|
||||||
|
{
|
||||||
|
use->fence_target = queue_fence_target;
|
||||||
|
QueuePush(tbuff->first_submitted, tbuff->last_submitted, use);
|
||||||
|
tbuff->uploaded = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Arena *GPU_ArenaFromTransientBuffer(GPU_TransientBuffer *tbuff)
|
||||||
|
{
|
||||||
|
return tbuff->arena;
|
||||||
|
}
|
||||||
65
src/gpu/gpu_util.h
Normal file
65
src/gpu/gpu_util.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
////////////////////////////////
|
||||||
|
//~ Transient buffer types
|
||||||
|
|
||||||
|
Struct(GPU_SubmittedTransientBufferResource)
|
||||||
|
{
|
||||||
|
GPU_SubmittedTransientBufferResource *next;
|
||||||
|
|
||||||
|
i64 fence_target; /* Once the buffer's queue reaches the target, the resource can be freed or reused */
|
||||||
|
GPU_Resource *resource;
|
||||||
|
};
|
||||||
|
|
||||||
|
Struct(GPU_TransientBuffer)
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
GPU_QueueKind queue_kind;
|
||||||
|
u64 elements_start_pos;
|
||||||
|
u32 element_size;
|
||||||
|
u32 element_align;
|
||||||
|
|
||||||
|
GPU_SubmittedTransientBufferResource *submitted_resources; /* Pool of submitted resource structs */
|
||||||
|
|
||||||
|
u32 uploaded_element_count;
|
||||||
|
GPU_SubmittedTransientBufferResource *uploaded;
|
||||||
|
|
||||||
|
GPU_SubmittedTransientBufferResource *first_submitted;
|
||||||
|
GPU_SubmittedTransientBufferResource *last_submitted;
|
||||||
|
GPU_SubmittedTransientBufferResource *first_free;
|
||||||
|
u32 max_in_flight;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ State types
|
||||||
|
|
||||||
|
Struct(GPU_SharedUtilState)
|
||||||
|
{
|
||||||
|
/* Common shared resources */
|
||||||
|
GPU_Resource *pt_sampler;
|
||||||
|
GPU_Resource *quad_indices;
|
||||||
|
GPU_Resource *noise;
|
||||||
|
} extern GPU_shared_util_state;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Startup
|
||||||
|
|
||||||
|
void GPU_StartupUtils(void);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Common resource helpers
|
||||||
|
|
||||||
|
GPU_Resource *GPU_GetCommonPointSampler(void);
|
||||||
|
GPU_Resource *GPU_GetCommonQuadIndices(void);
|
||||||
|
GPU_Resource *GPU_GetCommonNoise(void);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Transient buffer operations
|
||||||
|
|
||||||
|
GPU_TransientBuffer *GPU_AcquireTransientBuffer_(u64 reserve, GPU_QueueKind queue_kind, u32 max_in_flight, u32 element_size, u32 element_align);
|
||||||
|
#define GPU_AcquireTransientBuffer(reserve, queue_kind, max_in_flight, type) GPU_AcquireTransientBuffer_((reserve), (queue_kind), (max_in_flight), sizeof(type), alignof(type))
|
||||||
|
void GPU_ReleaseTransientBuffer(GPU_TransientBuffer *tbuff);
|
||||||
|
|
||||||
|
GPU_Resource *GPU_UploadTransientBuffer(GPU_TransientBuffer *tbuff);
|
||||||
|
void GPU_ResetTransientBuffer(GPU_TransientBuffer *tbuff, i64 queue_fence_target);
|
||||||
|
|
||||||
|
Arena *GPU_ArenaFromTransientBuffer(GPU_TransientBuffer *tbuff);
|
||||||
235
src/pp/pp.c
235
src/pp/pp.c
@ -26,16 +26,6 @@ void StartupUser(void)
|
|||||||
g->user_blended_client = AcquireClient(g->user_client_store);
|
g->user_blended_client = AcquireClient(g->user_client_store);
|
||||||
g->ss_blended = NilSnapshot();
|
g->ss_blended = NilSnapshot();
|
||||||
|
|
||||||
/* Renderer sampler */
|
|
||||||
g->pt_sampler = GPU_AcquireResource((GPU_ResourceDesc) { .kind = GPU_ResourceKind_Sampler, .sampler.filter = GPU_Filter_MinMagMipPoint });
|
|
||||||
|
|
||||||
/* Renderer data arenas */
|
|
||||||
g->material_instances_arena = AcquireArena(Gibi(64));
|
|
||||||
g->ui_rect_instances_arena = AcquireArena(Gibi(64));
|
|
||||||
g->ui_shape_verts_arena = AcquireArena(Gibi(64));
|
|
||||||
g->ui_shape_indices_arena = AcquireArena(Gibi(64));
|
|
||||||
g->grids_arena = AcquireArena(Gibi(64));
|
|
||||||
|
|
||||||
/* Local to user client */
|
/* Local to user client */
|
||||||
g->local_to_user_client_store = AcquireClientStore();
|
g->local_to_user_client_store = AcquireClientStore();
|
||||||
g->local_to_user_client = AcquireClient(g->local_to_user_client_store);
|
g->local_to_user_client = AcquireClient(g->local_to_user_client_store);
|
||||||
@ -403,42 +393,6 @@ GPU_Resource *AcquireGbuffer(GPU_Format format, Vec2I32 size)
|
|||||||
return GPU_AcquireResource(desc);
|
return GPU_AcquireResource(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Upload buffer
|
|
||||||
|
|
||||||
GPU_Resource *AcquireUploadBuffer_(void *src, u32 element_size, u32 element_count)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
GPU_ResourceDesc desc = ZI;
|
|
||||||
desc.kind = GPU_ResourceKind_Buffer;
|
|
||||||
desc.flags = GPU_ResourceFlag_None;
|
|
||||||
desc.buffer.heap_kind = GPU_HeapKind_Upload;
|
|
||||||
desc.buffer.count = element_count;
|
|
||||||
desc.buffer.stride = element_size;
|
|
||||||
GPU_Resource *r = GPU_AcquireResource(desc);
|
|
||||||
{
|
|
||||||
__profn("Copy to transfer buffer");
|
|
||||||
GPU_Mapped m = GPU_Map(r);
|
|
||||||
CopyBytes(m.mem, src, element_size * element_count);
|
|
||||||
GPU_Unmap(m);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
GPU_Resource *AcquireUploadBufferFromArena_(Arena *arena, u32 element_size)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
u64 element_count = arena->pos / element_size;
|
|
||||||
GPU_Resource *r = AcquireUploadBuffer_(ArenaBase(arena), element_size, element_count);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
JobDef(DelayReleaseGpuResources, sig, id)
|
|
||||||
{
|
|
||||||
YieldOnFence(sig->begin_fence, sig->begin_fence_target);
|
|
||||||
GPU_Resource *resource = sig->resources[id];
|
|
||||||
GPU_ReleaseResource(resource, sig->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Sort entities
|
//~ Sort entities
|
||||||
|
|
||||||
@ -500,6 +454,21 @@ void UpdateUser(P_Window *window)
|
|||||||
UI_Box *pp_root_box = UI_BuildBox(UI_Flag_DrawImage, UI_NilKey);
|
UI_Box *pp_root_box = UI_BuildBox(UI_Flag_DrawImage, UI_NilKey);
|
||||||
UI_PushParent(pp_root_box);
|
UI_PushParent(pp_root_box);
|
||||||
|
|
||||||
|
//- Init render data buffers
|
||||||
|
if (!g->material_instances_tbuff)
|
||||||
|
{
|
||||||
|
g->material_instances_tbuff = GPU_AcquireTransientBuffer(Gibi(64), GPU_QueueKind_Direct, 8, MaterialInstance);
|
||||||
|
g->ui_rect_instances_tbuff = GPU_AcquireTransientBuffer(Gibi(64), GPU_QueueKind_Direct, 8, UiRectInstance);
|
||||||
|
g->ui_shape_verts_tbuff = GPU_AcquireTransientBuffer(Gibi(64), GPU_QueueKind_Direct, 8, UiShapeVert);
|
||||||
|
g->ui_shape_indices_tbuff = GPU_AcquireTransientBuffer(Gibi(64), GPU_QueueKind_Direct, 8, u32);
|
||||||
|
g->grids_tbuff = GPU_AcquireTransientBuffer(Gibi(64), GPU_QueueKind_Direct, 8, MaterialGrid);
|
||||||
|
}
|
||||||
|
Arena *material_instances_arena = GPU_ArenaFromTransientBuffer(g->material_instances_tbuff);
|
||||||
|
Arena *ui_rect_instances_arena = GPU_ArenaFromTransientBuffer(g->ui_rect_instances_tbuff);
|
||||||
|
Arena *ui_shape_verts_arena = GPU_ArenaFromTransientBuffer(g->ui_shape_verts_tbuff);
|
||||||
|
Arena *ui_shape_indices_arena = GPU_ArenaFromTransientBuffer(g->ui_shape_indices_tbuff);
|
||||||
|
Arena *grids_arena = GPU_ArenaFromTransientBuffer(g->grids_tbuff);
|
||||||
|
|
||||||
//- Pull latest local sim snapshot
|
//- Pull latest local sim snapshot
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1007,7 +976,6 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
//- Draw grid
|
//- Draw grid
|
||||||
|
|
||||||
/* FIXME: Enable this */
|
|
||||||
{
|
{
|
||||||
f32 thickness = 2;
|
f32 thickness = 2;
|
||||||
|
|
||||||
@ -1019,7 +987,7 @@ void UpdateUser(P_Window *window)
|
|||||||
u32 color0 = Rgba32F(0.17f, 0.17f, 0.17f, 1.f);
|
u32 color0 = Rgba32F(0.17f, 0.17f, 0.17f, 1.f);
|
||||||
u32 color1 = Rgba32F(0.15f, 0.15f, 0.15f, 1.f);
|
u32 color1 = Rgba32F(0.15f, 0.15f, 0.15f, 1.f);
|
||||||
|
|
||||||
MaterialGrid *grid = PushStruct(g->grids_arena, MaterialGrid);
|
MaterialGrid *grid = PushStruct(grids_arena, MaterialGrid);
|
||||||
*grid = DefaultMaterialGrid;
|
*grid = DefaultMaterialGrid;
|
||||||
grid->line_thickness = thickness;
|
grid->line_thickness = thickness;
|
||||||
grid->line_spacing = spacing;
|
grid->line_spacing = spacing;
|
||||||
@ -1030,9 +998,12 @@ void UpdateUser(P_Window *window)
|
|||||||
grid->x_srgb = ColorRed;
|
grid->x_srgb = ColorRed;
|
||||||
grid->y_srgb = ColorGreen;
|
grid->y_srgb = ColorGreen;
|
||||||
|
|
||||||
MaterialInstance *mat = PushStruct(g->material_instances_arena, MaterialInstance);
|
MaterialInstance *mat = PushStruct(material_instances_arena, MaterialInstance);
|
||||||
*mat = DefaultMaterialInstance;
|
*mat = DefaultMaterialInstance;
|
||||||
mat->grid_id = grid - (MaterialGrid *)ArenaBase(g->grids_arena);
|
// TODO
|
||||||
|
// BROKE
|
||||||
|
// FIXME
|
||||||
|
mat->grid_id = grid - (MaterialGrid *)ArenaBase(grids_arena);
|
||||||
mat->xf = XformFromRect(RectFromVec2(pos, size));
|
mat->xf = XformFromRect(RectFromVec2(pos, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,7 +1222,7 @@ void UpdateUser(P_Window *window)
|
|||||||
Vec3 emittance = ent->sprite_emittance;
|
Vec3 emittance = ent->sprite_emittance;
|
||||||
u32 tint = ent->sprite_tint;
|
u32 tint = ent->sprite_tint;
|
||||||
S_Frame frame = S_FrameFromIndex(sheet, ent->animation_frame);
|
S_Frame frame = S_FrameFromIndex(sheet, ent->animation_frame);
|
||||||
MaterialInstance *mat = PushStruct(g->material_instances_arena, MaterialInstance);
|
MaterialInstance *mat = PushStruct(material_instances_arena, MaterialInstance);
|
||||||
*mat = DefaultMaterialInstance;
|
*mat = DefaultMaterialInstance;
|
||||||
mat->xf = sprite_xform;
|
mat->xf = sprite_xform;
|
||||||
mat->tex = GPU_Texture2DRidFromResource(texture->gpu_texture);
|
mat->tex = GPU_Texture2DRidFromResource(texture->gpu_texture);
|
||||||
@ -1286,7 +1257,7 @@ void UpdateUser(P_Window *window)
|
|||||||
Vec2I32 world_tile_index = WorldTileIndexFromLocalTileIndex(chunk_index, local_tile_index);
|
Vec2I32 world_tile_index = WorldTileIndexFromLocalTileIndex(chunk_index, local_tile_index);
|
||||||
Vec2 pos = PosFromWorldTileIndex(world_tile_index);
|
Vec2 pos = PosFromWorldTileIndex(world_tile_index);
|
||||||
Xform tile_xf = XformFromRect(RectFromVec2(pos, VEC2(tile_size, tile_size)));
|
Xform tile_xf = XformFromRect(RectFromVec2(pos, VEC2(tile_size, tile_size)));
|
||||||
MaterialInstance *mat = PushStruct(g->material_instances_arena, MaterialInstance);
|
MaterialInstance *mat = PushStruct(material_instances_arena, MaterialInstance);
|
||||||
*mat = DefaultMaterialInstance;
|
*mat = DefaultMaterialInstance;
|
||||||
mat->xf = tile_xf;
|
mat->xf = tile_xf;
|
||||||
mat->tex = GPU_Texture2DRidFromResource(tile_texture->gpu_texture);
|
mat->tex = GPU_Texture2DRidFromResource(tile_texture->gpu_texture);
|
||||||
@ -2029,6 +2000,7 @@ void UpdateUser(P_Window *window)
|
|||||||
GPU_MemoryInfo vram = GPU_QueryMemoryInfo();
|
GPU_MemoryInfo vram = GPU_QueryMemoryInfo();
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
//~ Draw global debug info
|
//~ Draw global debug info
|
||||||
/* FIXME: Enable this */
|
/* FIXME: Enable this */
|
||||||
#if 1
|
#if 1
|
||||||
@ -2264,14 +2236,15 @@ void UpdateUser(P_Window *window)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
//~ Render
|
//~ Render
|
||||||
|
Rect ui_viewport = RectFromVec2(VEC2(0, 0), VEC2(g->ui_size.x, g->ui_size.y));
|
||||||
|
Rect render_viewport = RectFromVec2(VEC2(0, 0), VEC2(g->render_size.x, g->render_size.y));
|
||||||
|
GPU_QueueKind gpu_render_queue = GPU_QueueKind_Direct;
|
||||||
|
Fence *render_fence = GPU_FenceFromQueue(gpu_render_queue);
|
||||||
{
|
{
|
||||||
__profn("Render");
|
__profn("Render");
|
||||||
GPU_QueueKind gpu_render_queue = GPU_QueueKind_Direct;
|
|
||||||
Rect ui_viewport = RectFromVec2(VEC2(0, 0), VEC2(g->ui_size.x, g->ui_size.y));
|
|
||||||
Rect render_viewport = RectFromVec2(VEC2(0, 0), VEC2(g->render_size.x, g->render_size.y));
|
|
||||||
|
|
||||||
Fence *render_fence = GPU_FenceFromQueue(gpu_render_queue);
|
|
||||||
|
|
||||||
/* Acquire gbuffers */
|
/* Acquire gbuffers */
|
||||||
if (g->shade_target && !EqVec2I32(g->render_size, GPU_GetTextureSize2D(g->shade_target)))
|
if (g->shade_target && !EqVec2I32(g->render_size, GPU_GetTextureSize2D(g->shade_target)))
|
||||||
@ -2309,84 +2282,17 @@ void UpdateUser(P_Window *window)
|
|||||||
g->ui_target = AcquireGbuffer(GPU_Format_R8G8B8A8_Unorm, g->ui_size);
|
g->ui_target = AcquireGbuffer(GPU_Format_R8G8B8A8_Unorm, g->ui_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init renderer resources */
|
/* Upload transient buffers */
|
||||||
if (!g->gpu_noise || !g->gpu_quad)
|
GPU_Resource *material_instances_buffer = GPU_UploadTransientBuffer(g->material_instances_tbuff);
|
||||||
{
|
GPU_Resource *ui_rect_instances_buffer = GPU_UploadTransientBuffer(g->ui_rect_instances_tbuff);
|
||||||
GPU_Resource *noise_upload = 0;
|
GPU_Resource *ui_shape_verts_buffer = GPU_UploadTransientBuffer(g->ui_shape_verts_tbuff);
|
||||||
GPU_Resource *quad_upload = 0;
|
GPU_Resource *ui_shape_indices_buffer = GPU_UploadTransientBuffer(g->ui_shape_indices_tbuff);
|
||||||
GPU_Resource *noise = 0;
|
GPU_Resource *grids_buffer = GPU_UploadTransientBuffer(g->grids_tbuff);
|
||||||
GPU_Resource *quad = 0;
|
u64 material_instances_count = GPU_GetBufferCount(material_instances_buffer);
|
||||||
GPU_CommandList *cl = GPU_BeginCommandList(gpu_render_queue);
|
u64 ui_rect_instances_count = GPU_GetBufferCount(ui_rect_instances_buffer);
|
||||||
/* Upload noise */
|
u64 ui_shape_verts_count = GPU_GetBufferCount(ui_shape_verts_buffer);
|
||||||
{
|
u64 ui_shape_indices_count = GPU_GetBufferCount(ui_shape_indices_buffer);
|
||||||
Vec3I32 noise_size = VEC3I32(128, 128, 64);
|
u64 grids_count = GPU_GetBufferCount(grids_buffer);
|
||||||
Resource noise_resource = ResourceFromStore(&GameResources, Lit("noise_128x128x64_16.dat"));
|
|
||||||
String noise_res_data = DataFromResource(noise_resource);
|
|
||||||
if (noise_res_data.len != noise_size.x * noise_size.y * noise_size.z * 2)
|
|
||||||
{
|
|
||||||
Panic(Lit("Unexpected noise texture size"));
|
|
||||||
}
|
|
||||||
GPU_ResourceDesc desc = ZI;
|
|
||||||
desc.kind = GPU_ResourceKind_Texture3D;
|
|
||||||
desc.texture.format = GPU_Format_R16_Uint;
|
|
||||||
desc.texture.size = noise_size;
|
|
||||||
noise = GPU_AcquireResource(desc);
|
|
||||||
{
|
|
||||||
u64 footprint_size = GPU_GetFootprintSize(noise);
|
|
||||||
GPU_ResourceDesc upload_desc = ZI;
|
|
||||||
upload_desc.kind = GPU_ResourceKind_Buffer;
|
|
||||||
upload_desc.buffer.heap_kind = GPU_HeapKind_Upload;
|
|
||||||
upload_desc.buffer.count = footprint_size;
|
|
||||||
noise_upload = GPU_AcquireResource(upload_desc);
|
|
||||||
GPU_Mapped mapped = GPU_Map(noise_upload);
|
|
||||||
GPU_CopyBytesToFootprint(mapped.mem, noise_res_data.text, noise);
|
|
||||||
GPU_Unmap(mapped);
|
|
||||||
}
|
|
||||||
GPU_TransitionToCopyDst(cl, noise);
|
|
||||||
GPU_CopyResource(cl, noise, noise_upload);
|
|
||||||
GPU_TransitionToReadable(cl, noise);
|
|
||||||
}
|
|
||||||
/* Upload quad indices */
|
|
||||||
{
|
|
||||||
u16 quad_indices[6] = { 0, 1, 2, 0, 2, 3 };
|
|
||||||
GPU_ResourceDesc desc = ZI;
|
|
||||||
desc.kind = GPU_ResourceKind_Buffer;
|
|
||||||
desc.buffer.count = countof(quad_indices);
|
|
||||||
desc.buffer.stride = sizeof(quad_indices[0]);
|
|
||||||
quad = GPU_AcquireResource(desc);
|
|
||||||
{
|
|
||||||
GPU_ResourceDesc upload_desc = ZI;
|
|
||||||
upload_desc.kind = GPU_ResourceKind_Buffer;
|
|
||||||
upload_desc.buffer.heap_kind = GPU_HeapKind_Upload;
|
|
||||||
upload_desc.buffer.count = desc.buffer.count * desc.buffer.stride;
|
|
||||||
quad_upload = GPU_AcquireResource(upload_desc);
|
|
||||||
GPU_Mapped mapped = GPU_Map(quad_upload);
|
|
||||||
CopyBytes(mapped.mem, quad_indices, sizeof(quad_indices));
|
|
||||||
GPU_Unmap(mapped);
|
|
||||||
}
|
|
||||||
GPU_TransitionToCopyDst(cl, quad);
|
|
||||||
GPU_CopyResource(cl, quad, quad_upload);
|
|
||||||
GPU_TransitionToReadable(cl, quad);
|
|
||||||
}
|
|
||||||
g->gpu_render_fence_target = GPU_EndCommandList(cl);
|
|
||||||
YieldOnFence(render_fence, g->gpu_render_fence_target);
|
|
||||||
GPU_ReleaseResource(noise_upload, GPU_ReleaseFlag_None);
|
|
||||||
GPU_ReleaseResource(quad_upload, GPU_ReleaseFlag_None);
|
|
||||||
g->gpu_noise = noise;
|
|
||||||
g->gpu_quad = quad;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Acquire transfer buffers */
|
|
||||||
GPU_Resource *material_instance_buffer = AcquireUploadBufferFromArena(g->material_instances_arena, MaterialInstance);
|
|
||||||
GPU_Resource *ui_rect_instance_buffer = AcquireUploadBufferFromArena(g->ui_rect_instances_arena, UiRectInstance);
|
|
||||||
GPU_Resource *ui_shape_verts_buffer = AcquireUploadBufferFromArena(g->ui_shape_verts_arena, UiShapeVert);
|
|
||||||
GPU_Resource *ui_shape_indices_buffer = AcquireUploadBufferFromArena(g->ui_shape_indices_arena, u32);
|
|
||||||
GPU_Resource *grids_buffer = AcquireUploadBufferFromArena(g->grids_arena, MaterialGrid);
|
|
||||||
u64 material_instances_count = ArenaCount(g->material_instances_arena, MaterialInstance);
|
|
||||||
u64 ui_rect_instances_count = ArenaCount(g->ui_rect_instances_arena, UiRectInstance);
|
|
||||||
u64 ui_shape_verts_count = ArenaCount(g->ui_shape_verts_arena, UiShapeVert);
|
|
||||||
u64 ui_shape_indices_count = ArenaCount(g->ui_shape_indices_arena, u32);
|
|
||||||
u64 grids_count = ArenaCount(g->grids_arena, MaterialGrid);
|
|
||||||
|
|
||||||
GPU_CommandList *cl = GPU_BeginCommandList(gpu_render_queue);
|
GPU_CommandList *cl = GPU_BeginCommandList(gpu_render_queue);
|
||||||
{
|
{
|
||||||
@ -2423,8 +2329,8 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
MaterialSig sig = ZI;
|
MaterialSig sig = ZI;
|
||||||
sig.projection = world_to_render_vp_matrix;
|
sig.projection = world_to_render_vp_matrix;
|
||||||
sig.sampler = GPU_SamplerStateRidFromResource(g->pt_sampler);
|
sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler());
|
||||||
sig.instances = GPU_StructuredBufferRidFromResource(material_instance_buffer);
|
sig.instances = GPU_StructuredBufferRidFromResource(material_instances_buffer);
|
||||||
sig.grids = GPU_StructuredBufferRidFromResource(grids_buffer);
|
sig.grids = GPU_StructuredBufferRidFromResource(grids_buffer);
|
||||||
GPU_Rasterize(cl,
|
GPU_Rasterize(cl,
|
||||||
&sig,
|
&sig,
|
||||||
@ -2433,7 +2339,7 @@ void UpdateUser(P_Window *window)
|
|||||||
viewport,
|
viewport,
|
||||||
scissor,
|
scissor,
|
||||||
material_instances_count,
|
material_instances_count,
|
||||||
g->gpu_quad,
|
GPU_GetCommonQuadIndices(),
|
||||||
GPU_RasterizeMode_TriangleList);
|
GPU_RasterizeMode_TriangleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2504,7 +2410,7 @@ void UpdateUser(P_Window *window)
|
|||||||
{
|
{
|
||||||
__profn("Shade pass");
|
__profn("Shade pass");
|
||||||
GPU_ProfN(cl, Lit("Shade pass"));
|
GPU_ProfN(cl, Lit("Shade pass"));
|
||||||
Vec3I32 noise_size = GPU_GetTextureSize3D(g->gpu_noise);
|
Vec3I32 noise_size = GPU_GetTextureSize3D(GPU_GetCommonNoise());
|
||||||
|
|
||||||
u32 shade_flags = ShadeFlag_None;
|
u32 shade_flags = ShadeFlag_None;
|
||||||
if (effects_disabled)
|
if (effects_disabled)
|
||||||
@ -2522,7 +2428,7 @@ void UpdateUser(P_Window *window)
|
|||||||
(u32)(RandU64FromState(&g->frame_rand) & 0xFFFFFFFF));
|
(u32)(RandU64FromState(&g->frame_rand) & 0xFFFFFFFF));
|
||||||
sig.frame_index = g->frame_index;
|
sig.frame_index = g->frame_index;
|
||||||
sig.camera_offset = g->world_to_render_xf.og;
|
sig.camera_offset = g->world_to_render_xf.og;
|
||||||
sig.noise = GPU_Texture3DRidFromResource(g->gpu_noise);
|
sig.noise = GPU_Texture3DRidFromResource(GPU_GetCommonNoise());
|
||||||
sig.albedo = GPU_Texture2DRidFromResource(g->albedo);
|
sig.albedo = GPU_Texture2DRidFromResource(g->albedo);
|
||||||
sig.emittance = GPU_Texture2DRidFromResource(g->emittance);
|
sig.emittance = GPU_Texture2DRidFromResource(g->emittance);
|
||||||
sig.emittance_flood = GPU_Texture2DRidFromResource(g->emittance_flood_read);
|
sig.emittance_flood = GPU_Texture2DRidFromResource(g->emittance_flood_read);
|
||||||
@ -2557,7 +2463,7 @@ void UpdateUser(P_Window *window)
|
|||||||
GPU_Scissor scissor = GPU_ScissorFromRect(ui_viewport);
|
GPU_Scissor scissor = GPU_ScissorFromRect(ui_viewport);
|
||||||
|
|
||||||
UiBlitSig sig = ZI;
|
UiBlitSig sig = ZI;
|
||||||
sig.sampler = GPU_SamplerStateRidFromResource(g->pt_sampler);
|
sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler());
|
||||||
sig.src = GPU_Texture2DRidFromResource(g->shade_read);
|
sig.src = GPU_Texture2DRidFromResource(g->shade_read);
|
||||||
sig.projection = blit_vp_matrix;
|
sig.projection = blit_vp_matrix;
|
||||||
sig.flags = UiBlitFlag_ToneMap | UiBlitFlag_GammaCorrect;
|
sig.flags = UiBlitFlag_ToneMap | UiBlitFlag_GammaCorrect;
|
||||||
@ -2570,7 +2476,7 @@ void UpdateUser(P_Window *window)
|
|||||||
viewport,
|
viewport,
|
||||||
scissor,
|
scissor,
|
||||||
1,
|
1,
|
||||||
g->gpu_quad,
|
GPU_GetCommonQuadIndices(),
|
||||||
GPU_RasterizeMode_TriangleList);
|
GPU_RasterizeMode_TriangleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2584,8 +2490,8 @@ void UpdateUser(P_Window *window)
|
|||||||
|
|
||||||
UiRectSig sig = ZI;
|
UiRectSig sig = ZI;
|
||||||
sig.projection = ui_vp_matrix;
|
sig.projection = ui_vp_matrix;
|
||||||
sig.sampler = GPU_SamplerStateRidFromResource(g->pt_sampler);
|
sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler());
|
||||||
sig.instances = GPU_StructuredBufferRidFromResource(ui_rect_instance_buffer);
|
sig.instances = GPU_StructuredBufferRidFromResource(ui_rect_instances_buffer);
|
||||||
GPU_Rasterize(cl,
|
GPU_Rasterize(cl,
|
||||||
&sig,
|
&sig,
|
||||||
UiRectVS, UiRectPS,
|
UiRectVS, UiRectPS,
|
||||||
@ -2593,7 +2499,7 @@ void UpdateUser(P_Window *window)
|
|||||||
viewport,
|
viewport,
|
||||||
scissor,
|
scissor,
|
||||||
ui_rect_instances_count,
|
ui_rect_instances_count,
|
||||||
g->gpu_quad,
|
GPU_GetCommonQuadIndices(),
|
||||||
GPU_RasterizeMode_TriangleList);
|
GPU_RasterizeMode_TriangleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2618,44 +2524,25 @@ void UpdateUser(P_Window *window)
|
|||||||
ui_shape_indices_buffer,
|
ui_shape_indices_buffer,
|
||||||
GPU_RasterizeMode_TriangleList);
|
GPU_RasterizeMode_TriangleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Transition target to readable before UI pass
|
||||||
|
GPU_TransitionToReadable(cl, g->ui_target);
|
||||||
|
|
||||||
}
|
}
|
||||||
g->gpu_render_fence_target = GPU_EndCommandList(cl);
|
g->gpu_render_fence_target = GPU_EndCommandList(cl);
|
||||||
|
|
||||||
/* Reset transfer buffers & queue their release */
|
/* Reset transients */
|
||||||
{
|
GPU_ResetTransientBuffer(g->material_instances_tbuff, g->gpu_render_fence_target);
|
||||||
{
|
GPU_ResetTransientBuffer(g->ui_rect_instances_tbuff, g->gpu_render_fence_target);
|
||||||
GPU_Resource *release_resources[] = {
|
GPU_ResetTransientBuffer(g->ui_shape_verts_tbuff, g->gpu_render_fence_target);
|
||||||
material_instance_buffer,
|
GPU_ResetTransientBuffer(g->ui_shape_indices_tbuff, g->gpu_render_fence_target);
|
||||||
ui_rect_instance_buffer,
|
GPU_ResetTransientBuffer(g->grids_tbuff, g->gpu_render_fence_target);
|
||||||
ui_shape_verts_buffer,
|
|
||||||
ui_shape_indices_buffer,
|
|
||||||
grids_buffer,
|
|
||||||
};
|
|
||||||
Job *job = OpenJob(DelayReleaseGpuResources, JobPool_Inherit);
|
|
||||||
{
|
|
||||||
DelayReleaseGpuResources_Sig *sig = PushStruct(job->arena, DelayReleaseGpuResources_Sig);
|
|
||||||
job->count = countof(release_resources);
|
|
||||||
job->sig = sig;
|
|
||||||
sig->begin_fence = render_fence;
|
|
||||||
sig->begin_fence_target = g->gpu_render_fence_target;
|
|
||||||
sig->resources = PushStructsNoZero(job->arena, GPU_Resource *, job->count);
|
|
||||||
sig->flags = GPU_ReleaseFlag_Reuse;
|
|
||||||
CopyBytes(sig->resources, release_resources, sizeof(release_resources));
|
|
||||||
}
|
|
||||||
CloseJob(job);
|
|
||||||
}
|
|
||||||
ResetArena(g->material_instances_arena);
|
|
||||||
ResetArena(g->ui_rect_instances_arena);
|
|
||||||
ResetArena(g->ui_shape_verts_arena);
|
|
||||||
ResetArena(g->ui_shape_indices_arena);
|
|
||||||
ResetArena(g->grids_arena);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render UI */
|
/* Render UI */
|
||||||
UI_PopParent();
|
UI_PopParent();
|
||||||
UI_SetDisplayImage(pp_root_box, g->ui_target);
|
UI_SetDisplayImage(pp_root_box, g->ui_target);
|
||||||
GPU_Resource *ui_render = UI_EndBuild();
|
GPU_Resource *ui_render = UI_EndBuild(ui_viewport);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Present
|
//~ Present
|
||||||
|
|||||||
27
src/pp/pp.h
27
src/pp/pp.h
@ -172,11 +172,7 @@ Struct(SharedUserState)
|
|||||||
SecondsStat net_bytes_read;
|
SecondsStat net_bytes_read;
|
||||||
SecondsStat net_bytes_sent;
|
SecondsStat net_bytes_sent;
|
||||||
|
|
||||||
//- Gpu resources
|
//- Renderer gbuffers
|
||||||
GPU_Resource *pt_sampler;
|
|
||||||
GPU_Resource *gpu_noise;
|
|
||||||
GPU_Resource *gpu_quad;
|
|
||||||
|
|
||||||
GPU_Resource *albedo;
|
GPU_Resource *albedo;
|
||||||
GPU_Resource *emittance;
|
GPU_Resource *emittance;
|
||||||
GPU_Resource *emittance_flood_read;
|
GPU_Resource *emittance_flood_read;
|
||||||
@ -185,15 +181,16 @@ Struct(SharedUserState)
|
|||||||
GPU_Resource *shade_target;
|
GPU_Resource *shade_target;
|
||||||
GPU_Resource *ui_target;
|
GPU_Resource *ui_target;
|
||||||
|
|
||||||
|
//- Render transient buffers
|
||||||
|
GPU_TransientBuffer *material_instances_tbuff;
|
||||||
|
GPU_TransientBuffer *ui_rect_instances_tbuff;
|
||||||
|
GPU_TransientBuffer *ui_shape_verts_tbuff;
|
||||||
|
GPU_TransientBuffer *ui_shape_indices_tbuff;
|
||||||
|
GPU_TransientBuffer *grids_tbuff;
|
||||||
|
|
||||||
|
//- Renderer state
|
||||||
RandState frame_rand;
|
RandState frame_rand;
|
||||||
u64 frame_index;
|
u64 frame_index;
|
||||||
|
|
||||||
Arena *material_instances_arena;
|
|
||||||
Arena *ui_rect_instances_arena;
|
|
||||||
Arena *ui_shape_verts_arena;
|
|
||||||
Arena *ui_shape_indices_arena;
|
|
||||||
Arena *grids_arena;
|
|
||||||
|
|
||||||
i64 gpu_render_fence_target;
|
i64 gpu_render_fence_target;
|
||||||
|
|
||||||
//- Bind state
|
//- Bind state
|
||||||
@ -295,13 +292,7 @@ void DrawDebugConsole(i32 level, b32 minimized);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Gpu buffer helpers
|
//~ Gpu buffer helpers
|
||||||
|
|
||||||
#define AcquireUploadBuffer(src, type, count) AcquireUploadBuffer_((src), sizeof(type), (count))
|
|
||||||
#define AcquireUploadBufferFromArena(arena, type) AcquireUploadBufferFromArena_((arena), sizeof(type))
|
|
||||||
|
|
||||||
GPU_Resource *AcquireGbuffer(GPU_Format format, Vec2I32 size);
|
GPU_Resource *AcquireGbuffer(GPU_Format format, Vec2I32 size);
|
||||||
GPU_Resource *AcquireUploadBuffer_(void *src, u32 element_size, u32 element_count);
|
|
||||||
GPU_Resource *AcquireUploadBufferFromArena_(Arena *arena, u32 element_size);
|
|
||||||
JobDecl(DelayReleaseGpuResources, { Fence *begin_fence; u64 begin_fence_target; GPU_Resource **resources; GPU_ReleaseFlag flags; });
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Entity sorting
|
//~ Entity sorting
|
||||||
|
|||||||
186
src/ui/ui.c
186
src/ui/ui.c
@ -28,9 +28,9 @@ void UI_PushTagFromHash(u64 hash)
|
|||||||
{
|
{
|
||||||
hash = RandU64FromSeeds(hash, g->top_tag->hash);
|
hash = RandU64FromSeeds(hash, g->top_tag->hash);
|
||||||
}
|
}
|
||||||
UI_Tag *tag = PushStruct(g->build_arena, UI_Tag);
|
UI_TagNode *n = PushStruct(g->build_arena, UI_TagNode);
|
||||||
StackPush(g->top_tag, tag);
|
StackPush(g->top_tag, n);
|
||||||
tag->hash = hash;
|
n->hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_PushTagFromString(String str)
|
void UI_PushTagFromString(String str)
|
||||||
@ -42,9 +42,9 @@ void UI_PushTagFromString(String str)
|
|||||||
hash = g->top_tag->hash;
|
hash = g->top_tag->hash;
|
||||||
}
|
}
|
||||||
hash = HashFnv64(hash, str);
|
hash = HashFnv64(hash, str);
|
||||||
UI_Tag *tag = PushStruct(g->build_arena, UI_Tag);
|
UI_TagNode *n = PushStruct(g->build_arena, UI_TagNode);
|
||||||
StackPush(g->top_tag, tag);
|
n->hash = hash;
|
||||||
tag->hash = hash;
|
StackPush(g->top_tag, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_PushTagF_(char *fmt_cstr, ...)
|
void UI_PushTagF_(char *fmt_cstr, ...)
|
||||||
@ -63,8 +63,7 @@ void UI_PushTagF_(char *fmt_cstr, ...)
|
|||||||
|
|
||||||
void UI_PopTag(void)
|
void UI_PopTag(void)
|
||||||
{
|
{
|
||||||
UI_SharedState *g = &UI_shared_state;
|
StackPop(UI_shared_state.top_tag);
|
||||||
StackPop(g->top_tag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Parent
|
//- Parent
|
||||||
@ -72,15 +71,46 @@ void UI_PopTag(void)
|
|||||||
void UI_PushParent(UI_Box *box)
|
void UI_PushParent(UI_Box *box)
|
||||||
{
|
{
|
||||||
UI_SharedState *g = &UI_shared_state;
|
UI_SharedState *g = &UI_shared_state;
|
||||||
UI_Parent *parent = PushStruct(g->build_arena, UI_Parent);
|
UI_ParentNode *n = PushStruct(g->build_arena, UI_ParentNode);
|
||||||
parent->box = box;
|
n->box = box;
|
||||||
StackPush(g->top_parent, parent);
|
StackPush(g->top_parent, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_PopParent(void)
|
void UI_PopParent(void)
|
||||||
|
{
|
||||||
|
StackPop(UI_shared_state.top_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Size
|
||||||
|
|
||||||
|
void UI_PushSize(Axis axis, UI_SizeKind kind, f32 v, f32 strictness)
|
||||||
{
|
{
|
||||||
UI_SharedState *g = &UI_shared_state;
|
UI_SharedState *g = &UI_shared_state;
|
||||||
StackPop(g->top_parent);
|
UI_SizeNode *n = PushStruct(g->build_arena, UI_SizeNode);
|
||||||
|
n->size.kind = kind;
|
||||||
|
n->size.v = v;
|
||||||
|
n->size.strictness = strictness;
|
||||||
|
StackPush(g->top_size[axis], n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_PopSize(Axis axis)
|
||||||
|
{
|
||||||
|
StackPop(UI_shared_state.top_size[axis]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Layout dir
|
||||||
|
|
||||||
|
void UI_PushLayoutDir(Axis dir)
|
||||||
|
{
|
||||||
|
UI_SharedState *g = &UI_shared_state;
|
||||||
|
UI_AxisNode *n = PushStruct(g->build_arena, UI_AxisNode);
|
||||||
|
n->axis = dir;
|
||||||
|
StackPush(g->top_layout_dir, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_PopLayoutDir(void)
|
||||||
|
{
|
||||||
|
StackPop(UI_shared_state.top_layout_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -131,16 +161,21 @@ UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key)
|
|||||||
|
|
||||||
box->key = key;
|
box->key = key;
|
||||||
box->flags = flags;
|
box->flags = flags;
|
||||||
|
|
||||||
|
box->tint = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
/* Pull from stack */
|
||||||
box->parent = g->top_parent->box;
|
box->parent = g->top_parent->box;
|
||||||
|
box->pref_size[Axis_X] = g->top_size[Axis_X]->size;
|
||||||
|
box->pref_size[Axis_Y] = g->top_size[Axis_Y]->size;
|
||||||
|
box->layout_dir = g->top_layout_dir->axis;
|
||||||
|
|
||||||
DllPushBack(g->top_parent->box->first, g->top_parent->box->last, box);
|
DllPushBack(g->top_parent->box->first, g->top_parent->box->last, box);
|
||||||
++box->parent->count;
|
++box->parent->count;
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Text
|
|
||||||
|
|
||||||
void UI_SetDisplayText(UI_Box *box, String str)
|
void UI_SetDisplayText(UI_Box *box, String str)
|
||||||
{
|
{
|
||||||
UI_SharedState *g = &UI_shared_state;
|
UI_SharedState *g = &UI_shared_state;
|
||||||
@ -148,9 +183,6 @@ void UI_SetDisplayText(UI_Box *box, String str)
|
|||||||
box->display_text = text;
|
box->display_text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Image
|
|
||||||
|
|
||||||
void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img)
|
void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img)
|
||||||
{
|
{
|
||||||
box->display_image = img;
|
box->display_image = img;
|
||||||
@ -187,8 +219,6 @@ void UI_BeginBuild(void)
|
|||||||
/* Init root box */
|
/* Init root box */
|
||||||
g->root_box = PushStruct(g->build_arena, UI_Box);
|
g->root_box = PushStruct(g->build_arena, UI_Box);
|
||||||
g->root_box->key = UI_RootKey;
|
g->root_box->key = UI_RootKey;
|
||||||
g->root_box->pref_size[Axis_X].kind = UI_SizeKind_Absolute;
|
|
||||||
g->root_box->pref_size[Axis_Y].kind = UI_SizeKind_Absolute;
|
|
||||||
UI_BoxBin *bin = &g->box_bins[g->root_box->key.hash % UI_NumBoxLookupBins];
|
UI_BoxBin *bin = &g->box_bins[g->root_box->key.hash % UI_NumBoxLookupBins];
|
||||||
DllPushBackNP(bin->first, bin->last, g->root_box, next_in_bin, prev_in_bin);
|
DllPushBackNP(bin->first, bin->last, g->root_box, next_in_bin, prev_in_bin);
|
||||||
++g->boxes_count;
|
++g->boxes_count;
|
||||||
@ -196,6 +226,9 @@ void UI_BeginBuild(void)
|
|||||||
/* Init stacks */
|
/* Init stacks */
|
||||||
UI_PushTagF("root");
|
UI_PushTagF("root");
|
||||||
UI_PushParent(g->root_box);
|
UI_PushParent(g->root_box);
|
||||||
|
UI_PushSize(Axis_X, UI_SizeKind_Percent, 1, 0);
|
||||||
|
UI_PushSize(Axis_Y, UI_SizeKind_Percent, 1, 0);
|
||||||
|
UI_PushLayoutDir(Axis_X);
|
||||||
|
|
||||||
if (!g->back_build_arena)
|
if (!g->back_build_arena)
|
||||||
{
|
{
|
||||||
@ -207,7 +240,7 @@ void UI_BeginBuild(void)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ End build
|
//~ End build
|
||||||
|
|
||||||
GPU_Resource *UI_EndBuild(void)
|
GPU_Resource *UI_EndBuild(Rect render_viewport)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
UI_SharedState *g = &UI_shared_state;
|
UI_SharedState *g = &UI_shared_state;
|
||||||
@ -218,9 +251,10 @@ GPU_Resource *UI_EndBuild(void)
|
|||||||
//- Layout
|
//- Layout
|
||||||
|
|
||||||
/* Init root size */
|
/* Init root size */
|
||||||
Vec2I32 root_size = VEC2I32(500, 500);
|
g->root_box->pref_size[Axis_X].kind = UI_SizeKind_Pixel;
|
||||||
g->root_box->p0 = VEC2(0, 0);
|
g->root_box->pref_size[Axis_X].v = render_viewport.size.x;
|
||||||
g->root_box->p1 = VEC2(root_size.x, root_size.y);
|
g->root_box->pref_size[Axis_Y].kind = UI_SizeKind_Pixel;
|
||||||
|
g->root_box->pref_size[Axis_Y].v = render_viewport.size.y;
|
||||||
|
|
||||||
/* Build pre-order & post-order box arrays */
|
/* Build pre-order & post-order box arrays */
|
||||||
u64 boxes_count = g->boxes_count;
|
u64 boxes_count = g->boxes_count;
|
||||||
@ -263,21 +297,21 @@ GPU_Resource *UI_EndBuild(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate independent sizes */
|
/* Calculate independent sizes */
|
||||||
for (u64 box_index = 1; box_index < boxes_count; ++box_index)
|
for (u64 box_index = 0; box_index < boxes_count; ++box_index)
|
||||||
{
|
{
|
||||||
UI_Box *box = boxes_pre[box_index];
|
UI_Box *box = boxes_pre[box_index];
|
||||||
for (Axis axis = 0; axis < Axis_CountXY; ++axis)
|
for (Axis axis = 0; axis < Axis_CountXY; ++axis)
|
||||||
{
|
{
|
||||||
UI_Size pref_size = box->pref_size[axis];
|
UI_Size pref_size = box->pref_size[axis];
|
||||||
if (pref_size.kind == UI_SizeKind_Absolute)
|
if (pref_size.kind == UI_SizeKind_Pixel)
|
||||||
{
|
{
|
||||||
box->solved_size[axis].v = pref_size.v;
|
box->solved_dims[axis] = pref_size.v;
|
||||||
}
|
}
|
||||||
else if (pref_size.kind == UI_SizeKind_Text)
|
else if (pref_size.kind == UI_SizeKind_Text)
|
||||||
{
|
{
|
||||||
/* FIXME: Calculate actual text size here */
|
/* FIXME: Calculate actual text size here */
|
||||||
f32 text_size = 10;
|
f32 text_size = 10;
|
||||||
box->solved_size[axis].v = text_size;
|
box->solved_dims[axis] = text_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,21 +326,39 @@ GPU_Resource *UI_EndBuild(void)
|
|||||||
if (pref_size.kind == UI_SizeKind_Percent)
|
if (pref_size.kind == UI_SizeKind_Percent)
|
||||||
{
|
{
|
||||||
UI_Box *ancestor = box->parent;
|
UI_Box *ancestor = box->parent;
|
||||||
UI_Size ancestor_size = ZI;
|
f32 ancestor_size = 0;
|
||||||
for (; ancestor; ancestor = ancestor->parent)
|
for (; ancestor; ancestor = ancestor->parent)
|
||||||
{
|
{
|
||||||
UI_Size tmp = ancestor->solved_size[axis];
|
UI_Size tmp = ancestor->pref_size[axis];
|
||||||
if (tmp.kind == UI_SizeKind_Absolute || tmp.kind == UI_SizeKind_Text)
|
if (tmp.kind == UI_SizeKind_Pixel || tmp.kind == UI_SizeKind_Text)
|
||||||
{
|
{
|
||||||
ancestor_size = tmp;
|
ancestor_size = ancestor->solved_dims[axis];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// box->solved_size =
|
box->solved_dims[axis] = pref_size.v * ancestor_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate final positions */
|
||||||
|
for (u64 box_index = 0; box_index < boxes_count; ++box_index)
|
||||||
|
{
|
||||||
|
UI_Box *box = boxes_pre[box_index];
|
||||||
|
UI_Box *parent = box->parent;
|
||||||
|
Vec2 final_size = VEC2(box->solved_dims[0], box->solved_dims[1]);
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
b32 is_layout_x = parent->layout_dir == Axis_X;
|
||||||
|
f32 layout_cursor = parent->layout_cursor;
|
||||||
|
Vec2 offset = VEC2(layout_cursor * is_layout_x, layout_cursor * !is_layout_x);
|
||||||
|
parent->layout_cursor += final_size.x * is_layout_x + final_size.y * is_layout_x;
|
||||||
|
box->p0 = AddVec2(parent->p0, offset);
|
||||||
|
}
|
||||||
|
box->p1 = AddVec2(box->p0, final_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
@ -351,33 +403,46 @@ GPU_Resource *UI_EndBuild(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//- Build instances
|
//- Build render data
|
||||||
|
|
||||||
|
/* Init transient buffers */
|
||||||
|
if (!g->draw_rects_tbuff)
|
||||||
|
{
|
||||||
|
g->draw_rects_tbuff = GPU_AcquireTransientBuffer(Gibi(64), GPU_QueueKind_Direct, 8, UI_RectInstance);
|
||||||
|
}
|
||||||
|
Arena *draw_rects_arena = GPU_ArenaFromTransientBuffer(g->draw_rects_tbuff);
|
||||||
|
|
||||||
GPU_QueueKind render_queue = GPU_QueueKind_Direct;
|
GPU_QueueKind render_queue = GPU_QueueKind_Direct;
|
||||||
Fence *render_fence = GPU_FenceFromQueue(render_queue);
|
Fence *render_fence = GPU_FenceFromQueue(render_queue);
|
||||||
|
|
||||||
/* Init render state */
|
/* Init render state */
|
||||||
if (!g->draw_rects_arena)
|
if (!draw_rects_arena)
|
||||||
{
|
{
|
||||||
g->draw_rects_arena = AcquireArena(Gibi(64));
|
draw_rects_arena = AcquireArena(Gibi(64));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build rect instance data */
|
/* Build rect instance data */
|
||||||
for (u64 box_index = 0; box_index < boxes_count; ++box_index)
|
for (u64 box_index = 0; box_index < boxes_count; ++box_index)
|
||||||
{
|
{
|
||||||
UI_Box *box = boxes_pre[box_index];
|
UI_Box *box = boxes_pre[box_index];
|
||||||
UI_RectInstance *rect = PushStruct(g->draw_rects_arena, UI_RectInstance);
|
UI_RectInstance *rect = PushStruct(draw_rects_arena, UI_RectInstance);
|
||||||
|
|
||||||
|
rect->flags = box->flags;
|
||||||
rect->p0 = box->p0;
|
rect->p0 = box->p0;
|
||||||
rect->p1 = box->p1;
|
rect->p1 = box->p1;
|
||||||
rect->tint_srgb = 0xFFFFFFFF;
|
rect->tint_srgb = box->tint;
|
||||||
|
|
||||||
|
if (box->flags & UI_Flag_DrawImage, box->display_image)
|
||||||
|
{
|
||||||
|
rect->image_tex = GPU_Texture2DRidFromResource(box->display_image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//- Render
|
//- Render
|
||||||
|
|
||||||
/* Acquire render target */
|
/* Init render target */
|
||||||
if (g->render_target && !EqVec2I32(root_size, GPU_GetTextureSize2D(g->render_target)))
|
if (g->render_target && !EqVec2I32(VEC2I32(render_viewport.size.x, render_viewport.size.y), GPU_GetTextureSize2D(g->render_target)))
|
||||||
{
|
{
|
||||||
YieldOnFence(render_fence, g->render_fence_target);
|
YieldOnFence(render_fence, g->render_fence_target);
|
||||||
GPU_ReleaseResource(g->render_target, GPU_ReleaseFlag_None);
|
GPU_ReleaseResource(g->render_target, GPU_ReleaseFlag_None);
|
||||||
@ -389,18 +454,53 @@ GPU_Resource *UI_EndBuild(void)
|
|||||||
desc.kind = GPU_ResourceKind_Texture2D;
|
desc.kind = GPU_ResourceKind_Texture2D;
|
||||||
desc.flags = GPU_ResourceFlag_Renderable;
|
desc.flags = GPU_ResourceFlag_Renderable;
|
||||||
desc.texture.format = GPU_Format_R8G8B8A8_Unorm;
|
desc.texture.format = GPU_Format_R8G8B8A8_Unorm;
|
||||||
desc.texture.size = VEC3I32(root_size.x, root_size.y, 1);
|
desc.texture.size = VEC3I32(render_viewport.size.x, render_viewport.size.y, 1);
|
||||||
g->render_target = GPU_AcquireResource(desc);
|
g->render_target = GPU_AcquireResource(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Upload transient buffers */
|
||||||
|
GPU_Resource *draw_rects_buffer = GPU_UploadTransientBuffer(g->draw_rects_tbuff);
|
||||||
|
u32 draw_rects_count = GPU_GetBufferCount(draw_rects_buffer);
|
||||||
|
|
||||||
/* Build command list */
|
/* Build command list */
|
||||||
GPU_CommandList *cl = GPU_BeginCommandList(render_queue);
|
GPU_CommandList *cl = GPU_BeginCommandList(render_queue);
|
||||||
{
|
{
|
||||||
|
//- Prep rect pass
|
||||||
|
{
|
||||||
|
__profn("Clear target");
|
||||||
|
GPU_ProfN(cl, Lit("Clear target"));
|
||||||
|
GPU_TransitionToRenderable(cl, g->render_target, 0);
|
||||||
|
GPU_ClearRenderable(cl, g->render_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Rect pass
|
||||||
|
if (draw_rects_count > 0)
|
||||||
|
{
|
||||||
|
__profn("Rect pass");
|
||||||
|
GPU_ProfN(cl, Lit("Rect pass"));
|
||||||
|
|
||||||
|
GPU_Viewport viewport = GPU_ViewportFromRect(render_viewport);
|
||||||
|
GPU_Scissor scissor = GPU_ScissorFromRect(render_viewport);
|
||||||
|
|
||||||
|
UI_RectSig sig = ZI;
|
||||||
|
sig.viewport_size = RoundVec2ToVec2I32(render_viewport.size);
|
||||||
|
sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler());
|
||||||
|
sig.instances = GPU_StructuredBufferRidFromResource(draw_rects_buffer);
|
||||||
|
GPU_Rasterize(cl,
|
||||||
|
&sig,
|
||||||
|
UI_RectVS, UI_RectPS,
|
||||||
|
1,
|
||||||
|
viewport,
|
||||||
|
scissor,
|
||||||
|
draw_rects_count,
|
||||||
|
GPU_GetCommonQuadIndices(),
|
||||||
|
GPU_RasterizeMode_TriangleList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g->render_fence_target = GPU_EndCommandList(cl);
|
g->render_fence_target = GPU_EndCommandList(cl);
|
||||||
|
|
||||||
/* Reset render state */
|
/* Reset transient buffers */
|
||||||
ResetArena(g->draw_rects_arena);
|
GPU_ResetTransientBuffer(g->draw_rects_tbuff, g->render_fence_target);
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return g->render_target;
|
return g->render_target;
|
||||||
|
|||||||
152
src/ui/ui.h
152
src/ui/ui.h
@ -16,7 +16,7 @@ Enum(UI_SizeKind)
|
|||||||
{
|
{
|
||||||
UI_SizeKind_Children,
|
UI_SizeKind_Children,
|
||||||
UI_SizeKind_Percent,
|
UI_SizeKind_Percent,
|
||||||
UI_SizeKind_Absolute,
|
UI_SizeKind_Pixel,
|
||||||
UI_SizeKind_Text,
|
UI_SizeKind_Text,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,18 +24,12 @@ Struct(UI_Size)
|
|||||||
{
|
{
|
||||||
UI_SizeKind kind;
|
UI_SizeKind kind;
|
||||||
f32 v;
|
f32 v;
|
||||||
|
f32 strictness;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Box types
|
//~ Box types
|
||||||
|
|
||||||
Enum(UI_Flag)
|
|
||||||
{
|
|
||||||
UI_Flag_None = 0,
|
|
||||||
UI_Flag_DrawText = (1 << 0),
|
|
||||||
UI_Flag_DrawImage = (1 << 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(UI_Box)
|
Struct(UI_Box)
|
||||||
{
|
{
|
||||||
//- Hash list
|
//- Hash list
|
||||||
@ -58,9 +52,12 @@ Struct(UI_Box)
|
|||||||
String display_text;
|
String display_text;
|
||||||
GPU_Resource *display_image;
|
GPU_Resource *display_image;
|
||||||
UI_Size pref_size[Axis_CountXY];
|
UI_Size pref_size[Axis_CountXY];
|
||||||
|
Axis layout_dir;
|
||||||
|
u32 tint;
|
||||||
|
|
||||||
//- Solver data
|
//- Layout data
|
||||||
UI_Size solved_size[Axis_CountXY];
|
f32 solved_dims[Axis_CountXY];
|
||||||
|
f32 layout_cursor;
|
||||||
|
|
||||||
//- Post-solve data
|
//- Post-solve data
|
||||||
Vec2 p0;
|
Vec2 p0;
|
||||||
@ -76,8 +73,10 @@ Struct(UI_BoxBin)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Stack types
|
//~ Stack types
|
||||||
|
|
||||||
Struct(UI_Tag) { UI_Tag *next; u64 hash; };
|
Struct(UI_TagNode) { UI_TagNode *next; u64 hash; };
|
||||||
Struct(UI_Parent) { UI_Parent *next; UI_Box *box; };
|
Struct(UI_ParentNode) { UI_ParentNode *next; UI_Box *box; };
|
||||||
|
Struct(UI_SizeNode) { UI_SizeNode *next; UI_Size size; };
|
||||||
|
Struct(UI_AxisNode) { UI_AxisNode *next; Axis axis; };
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ State types
|
//~ State types
|
||||||
@ -100,13 +99,15 @@ Struct(UI_SharedState)
|
|||||||
u64 back_boxes_count;
|
u64 back_boxes_count;
|
||||||
|
|
||||||
//- Stack state
|
//- Stack state
|
||||||
UI_Tag *top_tag;
|
UI_TagNode *top_tag;
|
||||||
UI_Parent *top_parent;
|
UI_ParentNode *top_parent;
|
||||||
|
UI_SizeNode *top_size[Axis_CountXY];
|
||||||
|
UI_AxisNode *top_layout_dir;
|
||||||
|
|
||||||
//- Render state
|
//- Render state
|
||||||
GPU_Resource *render_target;
|
GPU_Resource *render_target;
|
||||||
i64 render_fence_target;
|
i64 render_fence_target;
|
||||||
Arena *draw_rects_arena;
|
GPU_TransientBuffer *draw_rects_tbuff;
|
||||||
} extern UI_shared_state;
|
} extern UI_shared_state;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -128,12 +129,21 @@ void UI_PopTag(void);
|
|||||||
void UI_PushParent(UI_Box *box);
|
void UI_PushParent(UI_Box *box);
|
||||||
void UI_PopParent(void);
|
void UI_PopParent(void);
|
||||||
|
|
||||||
|
//- Size
|
||||||
|
void UI_PushSize(Axis axis, UI_SizeKind kind, f32 v, f32 strictness);
|
||||||
|
void UI_PopSize(Axis axis);
|
||||||
|
|
||||||
|
//- Layout dir
|
||||||
|
void UI_PushLayoutDir(Axis dir);
|
||||||
|
void UI_PopLayoutDir(void);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Box
|
//~ Box
|
||||||
|
|
||||||
UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key);
|
UI_Box *UI_BuildBox(UI_Flag flags, UI_Key key);
|
||||||
|
|
||||||
void UI_SetDisplayText(UI_Box *box, String str);
|
void UI_SetDisplayText(UI_Box *box, String str);
|
||||||
|
void UI_SetDisplayImage(UI_Box *box, GPU_Resource *img);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Image
|
//~ Image
|
||||||
@ -148,114 +158,4 @@ void UI_BeginBuild(void);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ End build
|
//~ End build
|
||||||
|
|
||||||
GPU_Resource *UI_EndBuild(void);
|
GPU_Resource *UI_EndBuild(Rect render_viewport);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Remove this */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Rect
|
|
||||||
|
|
||||||
Struct(UI_RectParams)
|
|
||||||
{
|
|
||||||
Xform xf;
|
|
||||||
GPU_Resource *texture;
|
|
||||||
ClipRect clip;
|
|
||||||
u32 tint;
|
|
||||||
};
|
|
||||||
#define UI_RECTPARAMS(...) ((UI_RectParams) { \
|
|
||||||
.tint = ColorWhite, \
|
|
||||||
.clip = AllClipped, \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
})
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Text types
|
|
||||||
|
|
||||||
/* How is text aligned within its area */
|
|
||||||
Enum(UI_TextAlignment)
|
|
||||||
{
|
|
||||||
UI_TextAlignment_Left, /* Default */
|
|
||||||
UI_TextAlignment_Center,
|
|
||||||
UI_TextAlignment_Right
|
|
||||||
};
|
|
||||||
|
|
||||||
/* How does the specified text position relate to the text area.
|
|
||||||
* E.g. Bottom & Right means the bottom-right of the text area will snap to
|
|
||||||
* the specified position. */
|
|
||||||
Enum(UI_TextOffsetX)
|
|
||||||
{
|
|
||||||
UI_TextOffsetX_Left, /* Default */
|
|
||||||
UI_TextOffsetX_Center,
|
|
||||||
UI_TextOffsetX_Right
|
|
||||||
};
|
|
||||||
|
|
||||||
Enum(UI_TextOffsetY)
|
|
||||||
{
|
|
||||||
UI_TextOffsetY_Top, /* Default */
|
|
||||||
UI_TextOffsetY_Center,
|
|
||||||
UI_TextOffsetY_Bottom
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(UI_TextGlyph)
|
|
||||||
{
|
|
||||||
f32 off_x;
|
|
||||||
f32 off_y;
|
|
||||||
f32 width;
|
|
||||||
f32 height;
|
|
||||||
f32 advance;
|
|
||||||
ClipRect clip;
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(UI_TextLine)
|
|
||||||
{
|
|
||||||
f32 line_width;
|
|
||||||
u32 num_glyphs;
|
|
||||||
UI_TextGlyph *glyphs;
|
|
||||||
UI_TextLine *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
Struct(UI_TextParams)
|
|
||||||
{
|
|
||||||
F_Font *font;
|
|
||||||
Vec2 pos;
|
|
||||||
f32 scale;
|
|
||||||
u32 color;
|
|
||||||
UI_TextAlignment alignment;
|
|
||||||
UI_TextOffsetX offset_x;
|
|
||||||
UI_TextOffsetY offset_y;
|
|
||||||
String str;
|
|
||||||
};
|
|
||||||
#define UI_TEXTPARAMS(...) ((UI_TextParams) { \
|
|
||||||
.scale = 1.0, \
|
|
||||||
.alignment = UI_TextAlignment_Left, \
|
|
||||||
.offset_x = UI_TextOffsetX_Left, \
|
|
||||||
.offset_y = UI_TextOffsetY_Top, \
|
|
||||||
.color = ColorWhite, \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
})s
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ State types
|
|
||||||
|
|
||||||
Struct(UI_SharedState)
|
|
||||||
{
|
|
||||||
i32 _;
|
|
||||||
} extern UI_shared_state;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@ -4,14 +4,16 @@
|
|||||||
@Dep gpu
|
@Dep gpu
|
||||||
|
|
||||||
//- Api
|
//- Api
|
||||||
|
@IncludeC ui_flags.h
|
||||||
@IncludeC ui.h
|
@IncludeC ui.h
|
||||||
@IncludeC ui_widgets.h
|
@IncludeC ui_util.h
|
||||||
@IncludeC ui_draw.h
|
@IncludeC ui_draw.h
|
||||||
|
@IncludeGpu ui_flags.h
|
||||||
@IncludeGpu ui_draw.h
|
@IncludeGpu ui_draw.h
|
||||||
|
|
||||||
//- Impl
|
//- Impl
|
||||||
@IncludeC ui.c
|
@IncludeC ui.c
|
||||||
@IncludeC ui_widgets.c
|
@IncludeC ui_util.c
|
||||||
@IncludeGpu ui_draw.gpu
|
@IncludeGpu ui_draw.gpu
|
||||||
|
|
||||||
//- Shaders
|
//- Shaders
|
||||||
|
|||||||
@ -5,7 +5,11 @@ ConstantBuffer<UI_RectSig> UI_rect_sig : register (b0);
|
|||||||
|
|
||||||
Struct(UI_RectPS_Input)
|
Struct(UI_RectPS_Input)
|
||||||
{
|
{
|
||||||
|
|
||||||
Semantic(Vec4, sv_position);
|
Semantic(Vec4, sv_position);
|
||||||
|
Semantic(Vec4, tint_lin);
|
||||||
|
Semantic(Vec2, uv);
|
||||||
|
Semantic(nointerpolation u32, instance_idx);
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(UI_RectPS_Output)
|
Struct(UI_RectPS_Output)
|
||||||
@ -18,21 +22,25 @@ Struct(UI_RectPS_Output)
|
|||||||
UI_RectPS_Input VSDef(UI_RectVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_vertexid))
|
UI_RectPS_Input VSDef(UI_RectVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_vertexid))
|
||||||
{
|
{
|
||||||
ConstantBuffer<UI_RectSig> sig = UI_rect_sig;
|
ConstantBuffer<UI_RectSig> sig = UI_rect_sig;
|
||||||
static const Vec2 unit_quad_verts[4] = {
|
static const Vec2 uvs[4] = {
|
||||||
Vec2(-0.5f, -0.5f),
|
Vec2(0, 0),
|
||||||
Vec2(0.5f, -0.5f),
|
Vec2(1, 0),
|
||||||
Vec2(0.5f, 0.5f),
|
Vec2(1, 1),
|
||||||
Vec2(-0.5f, 0.5f)
|
Vec2(0, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
StructuredBuffer<UI_RectInstance> instances = UniformResourceFromRid(sig.instances);
|
StructuredBuffer<UI_RectInstance> instances = UniformResourceFromRid(sig.instances);
|
||||||
UI_RectInstance instance = instances[sv_instanceid];
|
UI_RectInstance instance = instances[sv_instanceid];
|
||||||
Vec2 vert = unit_quad_verts[sv_vertexid];
|
Vec2 uv = uvs[sv_vertexid];
|
||||||
// Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
|
Vec2 vert = instance.p0 + (uv * instance.p1);
|
||||||
Vec2 world_pos = 0;
|
Vec2 ndc = NdcFromViewport(sig.viewport_size, vert);
|
||||||
|
|
||||||
UI_RectPS_Input result;
|
UI_RectPS_Input result;
|
||||||
result.sv_position = mul(sig.projection, Vec4(world_pos, 0, 1));
|
result.sv_position = Vec4(ndc.xy, 0, 1);
|
||||||
|
result.tint_lin = LinearFromSrgbU32(instance.tint_srgb);
|
||||||
|
result.instance_idx = sv_instanceid;
|
||||||
|
result.uv = uv;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +49,17 @@ UI_RectPS_Input VSDef(UI_RectVS, Semantic(u32, sv_instanceid), Semantic(u32, sv_
|
|||||||
UI_RectPS_Output PSDef(UI_RectPS, UI_RectPS_Input input)
|
UI_RectPS_Output PSDef(UI_RectPS, UI_RectPS_Input input)
|
||||||
{
|
{
|
||||||
ConstantBuffer<UI_RectSig> sig = UI_rect_sig;
|
ConstantBuffer<UI_RectSig> sig = UI_rect_sig;
|
||||||
f32 color = 0;
|
StructuredBuffer<UI_RectInstance> instances = UniformResourceFromRid(sig.instances);
|
||||||
|
UI_RectInstance instance = instances[input.instance_idx];
|
||||||
|
|
||||||
|
Vec4 color = input.tint_lin;
|
||||||
|
|
||||||
|
if (instance.flags & UI_Flag_DrawImage)
|
||||||
|
{
|
||||||
|
SamplerState sampler = UniformSamplerFromRid(sig.sampler);
|
||||||
|
Texture2D<Vec4> tex = NonUniformResourceFromRid(instance.image_tex);
|
||||||
|
color *= tex.Sample(sampler, input.uv);
|
||||||
|
}
|
||||||
|
|
||||||
UI_RectPS_Output result;
|
UI_RectPS_Output result;
|
||||||
result.sv_target0 = color;
|
result.sv_target0 = color;
|
||||||
|
|||||||
@ -4,21 +4,20 @@
|
|||||||
Struct(UI_RectSig)
|
Struct(UI_RectSig)
|
||||||
{
|
{
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
Mat4x4 projection; /* 16 consts */
|
Vec2I32 viewport_size; /* 02 consts */
|
||||||
/* ----------------------------------------------------- */
|
|
||||||
StructuredBufferRid instances; /* 01 consts */
|
StructuredBufferRid instances; /* 01 consts */
|
||||||
u32 _pad0; /* 01 consts (padding) */
|
SamplerStateRid sampler; /* 01 consts */
|
||||||
u32 _pad1; /* 01 consts (padding) */
|
|
||||||
u32 _pad2; /* 01 consts (padding) */
|
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
};
|
};
|
||||||
AssertRootConst(UI_RectSig, 20);
|
AssertRootConst(UI_RectSig, 4);
|
||||||
|
|
||||||
Struct(UI_RectInstance)
|
Struct(UI_RectInstance)
|
||||||
{
|
{
|
||||||
|
u32 flags;
|
||||||
Vec2 p0;
|
Vec2 p0;
|
||||||
Vec2 p1;
|
Vec2 p1;
|
||||||
u32 tint_srgb;
|
u32 tint_srgb;
|
||||||
|
Texture2DRid image_tex;
|
||||||
};
|
};
|
||||||
#define UI_DefaultRectInstance (UI_RectInstance) { \
|
#define UI_DefaultRectInstance (UI_RectInstance) { \
|
||||||
0 \
|
0 \
|
||||||
|
|||||||
8
src/ui/ui_flags.h
Normal file
8
src/ui/ui_flags.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* NOTE: UI flags are located here since they are shared between application & shader code */
|
||||||
|
|
||||||
|
Enum(UI_Flag)
|
||||||
|
{
|
||||||
|
UI_Flag_None = 0,
|
||||||
|
UI_Flag_DrawText = (1 << 0),
|
||||||
|
UI_Flag_DrawImage = (1 << 1),
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user