texture upload test

This commit is contained in:
jacob 2025-06-23 14:26:41 -05:00
parent b96465191e
commit acc1fd69f1
3 changed files with 268 additions and 164 deletions

View File

@ -96,4 +96,4 @@
#define AUDIO_ENABLED 0 #define AUDIO_ENABLED 0
#define VSYNC_ENABLED 0 #define VSYNC_ENABLED 0
#define USER_FPS_LIMIT 30 #define USER_FPS_LIMIT 300

View File

@ -58,7 +58,7 @@ void gp_texture_clear(struct gp_handle target_texture, u32 clear_color);
struct v2i32 gp_texture_get_size(struct gp_handle texture); struct v2i32 gp_texture_get_size(struct gp_handle texture);
/* ========================== * /* ========================== *
* Cmd buffer * Flow
* ========================== */ * ========================== */
struct gp_indices { struct gp_indices {
@ -109,14 +109,6 @@ struct gp_cmd_params {
}; };
}; };
struct gp_handle gp_flow_alloc(void);
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_params params);
/* ========================== *
* Dispatch
* ========================== */
struct gp_dispatch_params { struct gp_dispatch_params {
struct gp_handle flow; struct gp_handle flow;
struct gp_handle draw_target; struct gp_handle draw_target;
@ -124,6 +116,10 @@ struct gp_dispatch_params {
struct xform draw_target_view; struct xform draw_target_view;
}; };
struct gp_handle gp_flow_alloc(void);
void gp_push_cmd(struct gp_handle gp_flow, struct gp_cmd_params params);
void gp_dispatch(struct gp_dispatch_params params); void gp_dispatch(struct gp_dispatch_params params);
/* ========================== * /* ========================== *

View File

@ -89,6 +89,7 @@ struct pipeline_error {
}; };
struct command_queue { struct command_queue {
D3D12_COMMAND_LIST_TYPE type;
ID3D12CommandQueue *cq; ID3D12CommandQueue *cq;
struct arena *arena; struct arena *arena;
struct sys_mutex *mutex; struct sys_mutex *mutex;
@ -102,8 +103,8 @@ struct command_queue {
struct command_list { struct command_list {
struct command_queue *cq; struct command_queue *cq;
struct ID3D12GraphicsCommandList *cl;
struct ID3D12CommandAllocator *ca; struct ID3D12CommandAllocator *ca;
struct ID3D12GraphicsCommandList *cl;
struct command_descriptor_heap *first_command_descriptor_heap; struct command_descriptor_heap *first_command_descriptor_heap;
struct command_buffer *first_command_buffer; struct command_buffer *first_command_buffer;
@ -1368,71 +1369,6 @@ INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandL
return old_state; return old_state;
} }
struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
{
LOCAL_PERSIST const DXGI_FORMAT formats[] = {
[GP_TEXTURE_FORMAT_R8G8B8A8_UNORM] = DXGI_FORMAT_R8G8B8A8_UNORM,
[GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
};
DXGI_FORMAT dxgi_format = 0;
if (format < (i32)ARRAY_COUNT(formats)) {
dxgi_format = formats[format];
}
if (format == 0) {
sys_panic(LIT("Tried to create texture with unknown format"));
}
enum dx12_resource_view_flags view_flags = DX12_RESOURCE_VIEW_FLAG_SRV;
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
heap_props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heap_props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_HEAP_FLAGS heap_flags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
D3D12_RESOURCE_DESC desc = ZI;
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
desc.Format = dxgi_format;
desc.Alignment = 0;
desc.Width = size.x;
desc.Height = size.y;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
if (flags & GP_TEXTURE_FLAG_TARGETABLE) {
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
view_flags |= DX12_RESOURCE_VIEW_FLAG_RTV;
}
D3D12_RESOURCE_STATES initial_state = D3D12_RESOURCE_STATE_COPY_DEST;
struct dx12_resource *r = dx12_resource_alloc(heap_props, heap_flags, desc, initial_state, view_flags);
r->texture_size = size;
(UNUSED)initial_data;
return handle_alloc(DX12_HANDLE_KIND_RESOURCE, r);
}
void gp_texture_clear(struct gp_handle target_resource, u32 clear_color)
{
(UNUSED)target_resource;
(UNUSED)clear_color;
}
struct v2i32 gp_texture_get_size(struct gp_handle resource)
{
struct v2i32 res = ZI;
struct dx12_resource *dx12_resource = handle_get_data(resource, DX12_HANDLE_KIND_RESOURCE);
if (dx12_resource) {
res = dx12_resource->texture_size;
}
return res;
}
/* ========================== * /* ========================== *
* Command queue * Command queue
* ========================== */ * ========================== */
@ -1445,8 +1381,8 @@ INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE
cq = arena_push(arena, struct command_queue); cq = arena_push(arena, struct command_queue);
cq->arena = arena; cq->arena = arena;
} }
cq->mutex = sys_mutex_alloc(); cq->mutex = sys_mutex_alloc();
cq->type = type;
D3D12_COMMAND_QUEUE_DESC desc = ZI; D3D12_COMMAND_QUEUE_DESC desc = ZI;
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
@ -1522,12 +1458,12 @@ INTERNAL struct command_list *command_list_open(struct command_queue *cq)
cl->cl = old_cl; cl->cl = old_cl;
cl->ca = old_ca; cl->ca = old_ca;
} else { } else {
hr = ID3D12Device_CreateCommandAllocator(G.device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&cl->ca); hr = ID3D12Device_CreateCommandAllocator(G.device, cq->type, &IID_ID3D12CommandAllocator, (void **)&cl->ca);
if (FAILED(hr)) { if (FAILED(hr)) {
sys_panic(LIT("Failed to create command allocator")); sys_panic(LIT("Failed to create command allocator"));
} }
hr = ID3D12Device_CreateCommandList(G.device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, cl->ca, NULL, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl); hr = ID3D12Device_CreateCommandList(G.device, 0, cq->type, cl->ca, NULL, &IID_ID3D12GraphicsCommandList, (void **)&cl->cl);
if (FAILED(hr)) { if (FAILED(hr)) {
sys_panic(LIT("Failed to create command list")); sys_panic(LIT("Failed to create command list"));
} }
@ -1553,7 +1489,7 @@ INTERNAL struct command_list *command_list_open(struct command_queue *cq)
} }
/* TODO: Allow multiple command list submissions */ /* TODO: Allow multiple command list submissions */
INTERNAL void command_list_close(struct command_list *cl) INTERNAL u64 command_list_close(struct command_list *cl)
{ {
struct command_queue *cq = cl->cq; struct command_queue *cq = cl->cq;
@ -1614,6 +1550,8 @@ INTERNAL void command_list_close(struct command_list *cl)
cq->last_submitted_command_list = cl; cq->last_submitted_command_list = cl;
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
return target_fence_value;
} }
/* ========================== * /* ========================== *
@ -1825,6 +1763,177 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl
return cb; return cb;
} }
/* ========================== *
* Texture
* ========================== */
struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
{
struct dxgi_format_info { DXGI_FORMAT format; u32 size; };
LOCAL_PERSIST const struct dxgi_format_info formats[] = {
[GP_TEXTURE_FORMAT_R8G8B8A8_UNORM] = { DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
[GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB] = { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 4 }
};
DXGI_FORMAT dxgi_format = ZI;
u32 pixel_size = 0;
if (format < (i32)ARRAY_COUNT(formats)) {
dxgi_format = formats[format].format;
pixel_size = formats[format].size;
ASSERT(dxgi_format != 0);
ASSERT(pixel_size != 0);
}
if (format == 0) {
sys_panic(LIT("Tried to create texture with unknown format"));
}
enum dx12_resource_view_flags view_flags = DX12_RESOURCE_VIEW_FLAG_SRV;
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
heap_props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heap_props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_HEAP_FLAGS heap_flags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
D3D12_RESOURCE_DESC desc = ZI;
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
desc.Format = dxgi_format;
desc.Alignment = 0;
desc.Width = size.x;
desc.Height = size.y;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
if (flags & GP_TEXTURE_FLAG_TARGETABLE) {
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
view_flags |= DX12_RESOURCE_VIEW_FLAG_RTV;
}
D3D12_RESOURCE_STATES initial_state = D3D12_RESOURCE_STATE_COPY_DEST;
struct dx12_resource *r = dx12_resource_alloc(heap_props, heap_flags, desc, initial_state, view_flags);
r->texture_size = size;
/* Upload texture */
if (initial_data) {
u64 upload_size = 0;
u64 upload_row_size = 0;
u32 upload_num_rows = 0;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = ZI;
ID3D12Device_GetCopyableFootprints(G.device, &desc, 0, 1, 0, &footprint, &upload_num_rows, &upload_row_size, &upload_size);
/* Create temp upload heap */
struct dx12_resource *upload = NULL;
{
enum dx12_resource_view_flags upload_view_flags = DX12_RESOURCE_VIEW_FLAG_NONE;
D3D12_HEAP_PROPERTIES upload_heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
upload_heap_props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
upload_heap_props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_HEAP_FLAGS upload_heap_flags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
D3D12_RESOURCE_DESC upload_desc = ZI;
upload_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
upload_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
upload_desc.Format = DXGI_FORMAT_UNKNOWN;
upload_desc.Alignment = 0;
upload_desc.Width = upload_size;
upload_desc.Height = 1;
upload_desc.DepthOrArraySize = 1;
upload_desc.MipLevels = 1;
upload_desc.SampleDesc.Count = 1;
upload_desc.SampleDesc.Quality = 0;
D3D12_RESOURCE_STATES upload_initial_state = D3D12_RESOURCE_STATE_GENERIC_READ;
/* FIXME: Release */
upload = dx12_resource_alloc(upload_heap_props, upload_heap_flags, upload_desc, upload_initial_state, upload_view_flags);
/* Copy to upload heap */
#if 0
/* FIXME: Copy based on footprint */
{
D3D12_RANGE read_range = ZI;
void *dst = NULL;
HRESULT hr = ID3D12Resource_Map(upload->resource, 0, &read_range, &dst);
if (FAILED(hr) || !dst) {
/* TODO: Don't panic */
sys_panic(LIT("Failed to map texture upload resource"));
}
MEMCPY(dst, initial_data, size.x * size.y * pixel_size);
ID3D12Resource_Unmap(upload->resource, 0, NULL);
}
#else
/* FIXME: Copy based on footprint */
{
D3D12_RANGE read_range = ZI;
void *mapped = NULL;
HRESULT hr = ID3D12Resource_Map(upload->resource, 0, &read_range, &mapped);
if (FAILED(hr) || !mapped) {
/* TODO: Don't panic */
sys_panic(LIT("Failed to map texture upload resource"));
}
u8 *dst = (u8 *)mapped + footprint.Offset;
u8 *src = initial_data;
for (u32 y = 0; y < upload_num_rows; ++y) {
memcpy(dst + y * footprint.Footprint.RowPitch, src + y * size.x * pixel_size, size.x * pixel_size);
}
ID3D12Resource_Unmap(upload->resource, 0, NULL);
}
#endif
}
/* Copy from upload heap to texture */
struct command_queue *cq = G.cq_copy_background;
struct command_list *cl = command_list_open(cq);
{
D3D12_TEXTURE_COPY_LOCATION dst_loc = {
.pResource = r->resource,
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
.SubresourceIndex = 0,
};
D3D12_TEXTURE_COPY_LOCATION src_loc = {
.pResource = upload->resource,
.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
.PlacedFootprint = footprint,
};
ID3D12GraphicsCommandList_CopyTextureRegion(cl->cl, &dst_loc, 0, 0, 0, &src_loc, NULL);
/* FIXME: Better barrier? */
//dx12_resource_barrier(cl->cl, r, D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE);
}
u64 fence_target = command_list_close(cl);
/* Wait */
/* TODO: Return async waitable to caller */
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
ID3D12Fence_SetEventOnCompletion(cq->fence, fence_target, event);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
return handle_alloc(DX12_HANDLE_KIND_RESOURCE, r);
}
void gp_texture_clear(struct gp_handle target_resource, u32 clear_color)
{
(UNUSED)target_resource;
(UNUSED)clear_color;
}
struct v2i32 gp_texture_get_size(struct gp_handle resource)
{
struct v2i32 res = ZI;
struct dx12_resource *dx12_resource = handle_get_data(resource, DX12_HANDLE_KIND_RESOURCE);
if (dx12_resource) {
res = dx12_resource->texture_size;
}
return res;
}
/* ========================== * /* ========================== *
* Dispatch * Dispatch
* ========================== */ * ========================== */
@ -1842,10 +1951,11 @@ void gp_dispatch(struct gp_dispatch_params params)
__prof; __prof;
struct flow *flow = handle_get_data(params.flow, DX12_HANDLE_KIND_FLOW); struct flow *flow = handle_get_data(params.flow, DX12_HANDLE_KIND_FLOW);
struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE);
struct command_queue *cq = G.cq_direct; /* Material pass */
struct command_list *cl = command_list_open(cq); struct command_list *cl = command_list_open(G.cq_direct);
{
struct dx12_resource *target = handle_get_data(params.draw_target, DX12_HANDLE_KIND_RESOURCE);
/* Upload dummmy vert & index buffer */ /* Upload dummmy vert & index buffer */
/* TODO: Make these static */ /* TODO: Make these static */
@ -1888,7 +1998,7 @@ void gp_dispatch(struct gp_dispatch_params params)
/* Create temporary descriptor heap */ /* Create temporary descriptor heap */
/* NOTE: This should always occur after buffers are submitted */ /* NOTE: This should always occur after buffers are submitted */
/* Material pass */ /* Push commands */
{ {
//struct pipeline *pipeline = dx12_get_pipeline(pipeline_scope, LIT("material")); //struct pipeline *pipeline = dx12_get_pipeline(pipeline_scope, LIT("material"));
struct pipeline *pipeline = &G.test_pipeline; struct pipeline *pipeline = &G.test_pipeline;
@ -1932,8 +2042,7 @@ void gp_dispatch(struct gp_dispatch_params params)
/* Reset render target */ /* Reset render target */
dx12_resource_barrier(cl->cl, target, old_state); dx12_resource_barrier(cl->cl, target, old_state);
} }
}
/* Execute command list */
command_list_close(cl); command_list_close(cl);
/* Reset flow */ /* Reset flow */
@ -2083,10 +2192,8 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
if (!flow.gen) { if (!flow.gen) {
flow = gp_flow_alloc(); flow = gp_flow_alloc();
} }
#if 0
struct gp_handle dst_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, dst); struct gp_handle dst_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, dst);
struct gp_handle src_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, src); struct gp_handle src_texture_handle = handle_alloc(DX12_HANDLE_KIND_RESOURCE, src);
#endif
/* Draw texture to backbuffer texture */ /* Draw texture to backbuffer texture */
/* TODO: Specialized blit shader */ /* TODO: Specialized blit shader */
@ -2108,7 +2215,7 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync) void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
{ {
sys_sleep(0.1); //sys_sleep(0.1);
#if 0 #if 0
/* FIXME: Remove this */ /* FIXME: Remove this */
@ -2128,13 +2235,14 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
CloseHandle(event); CloseHandle(event);
#endif #endif
struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution); struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution);
struct dx12_resource *texture_resource = handle_get_data(texture, DX12_HANDLE_KIND_RESOURCE); struct dx12_resource *texture_resource = handle_get_data(texture, DX12_HANDLE_KIND_RESOURCE);
/* Blit */ /* Blit */
present_blit(backbuffer_resource, texture_resource, texture_xf); present_blit(backbuffer_resource, texture_resource, texture_xf);
//sys_sleep(0.1);
/* Present */ /* Present */
HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0); HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0);
if (!SUCCEEDED(hr)) { if (!SUCCEEDED(hr)) {