texture upload test
This commit is contained in:
parent
b96465191e
commit
acc1fd69f1
@ -96,4 +96,4 @@
|
||||
|
||||
#define AUDIO_ENABLED 0
|
||||
#define VSYNC_ENABLED 0
|
||||
#define USER_FPS_LIMIT 30
|
||||
#define USER_FPS_LIMIT 300
|
||||
|
||||
14
src/gp.h
14
src/gp.h
@ -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);
|
||||
|
||||
/* ========================== *
|
||||
* Cmd buffer
|
||||
* Flow
|
||||
* ========================== */
|
||||
|
||||
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_handle flow;
|
||||
struct gp_handle draw_target;
|
||||
@ -124,6 +116,10 @@ struct gp_dispatch_params {
|
||||
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);
|
||||
|
||||
/* ========================== *
|
||||
|
||||
268
src/gp_dx12.c
268
src/gp_dx12.c
@ -89,6 +89,7 @@ struct pipeline_error {
|
||||
};
|
||||
|
||||
struct command_queue {
|
||||
D3D12_COMMAND_LIST_TYPE type;
|
||||
ID3D12CommandQueue *cq;
|
||||
struct arena *arena;
|
||||
struct sys_mutex *mutex;
|
||||
@ -102,8 +103,8 @@ struct command_queue {
|
||||
|
||||
struct command_list {
|
||||
struct command_queue *cq;
|
||||
struct ID3D12GraphicsCommandList *cl;
|
||||
struct ID3D12CommandAllocator *ca;
|
||||
struct ID3D12GraphicsCommandList *cl;
|
||||
|
||||
struct command_descriptor_heap *first_command_descriptor_heap;
|
||||
struct command_buffer *first_command_buffer;
|
||||
@ -1368,71 +1369,6 @@ INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandL
|
||||
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
|
||||
* ========================== */
|
||||
@ -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 = arena;
|
||||
}
|
||||
|
||||
cq->mutex = sys_mutex_alloc();
|
||||
cq->type = type;
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC desc = ZI;
|
||||
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->ca = old_ca;
|
||||
} 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)) {
|
||||
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)) {
|
||||
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 */
|
||||
INTERNAL void command_list_close(struct command_list *cl)
|
||||
INTERNAL u64 command_list_close(struct command_list *cl)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* 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
|
||||
* ========================== */
|
||||
@ -1842,10 +1951,11 @@ void gp_dispatch(struct gp_dispatch_params params)
|
||||
__prof;
|
||||
|
||||
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;
|
||||
struct command_list *cl = command_list_open(cq);
|
||||
/* Material pass */
|
||||
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 */
|
||||
/* TODO: Make these static */
|
||||
@ -1888,7 +1998,7 @@ void gp_dispatch(struct gp_dispatch_params params)
|
||||
/* Create temporary descriptor heap */
|
||||
/* 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 = &G.test_pipeline;
|
||||
@ -1932,8 +2042,7 @@ void gp_dispatch(struct gp_dispatch_params params)
|
||||
/* Reset render target */
|
||||
dx12_resource_barrier(cl->cl, target, old_state);
|
||||
}
|
||||
|
||||
/* Execute command list */
|
||||
}
|
||||
command_list_close(cl);
|
||||
|
||||
/* Reset flow */
|
||||
@ -2083,10 +2192,8 @@ INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src,
|
||||
if (!flow.gen) {
|
||||
flow = gp_flow_alloc();
|
||||
}
|
||||
#if 0
|
||||
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);
|
||||
#endif
|
||||
|
||||
/* Draw texture to backbuffer texture */
|
||||
/* 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)
|
||||
{
|
||||
sys_sleep(0.1);
|
||||
//sys_sleep(0.1);
|
||||
|
||||
#if 0
|
||||
/* FIXME: Remove this */
|
||||
@ -2128,13 +2235,14 @@ void gp_present(struct sys_window *window, struct v2i32 backbuffer_resolution, s
|
||||
CloseHandle(event);
|
||||
#endif
|
||||
|
||||
|
||||
struct dx12_resource *backbuffer_resource = update_swapchain(window, backbuffer_resolution);
|
||||
struct dx12_resource *texture_resource = handle_get_data(texture, DX12_HANDLE_KIND_RESOURCE);
|
||||
|
||||
/* Blit */
|
||||
present_blit(backbuffer_resource, texture_resource, texture_xf);
|
||||
|
||||
//sys_sleep(0.1);
|
||||
|
||||
/* Present */
|
||||
HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user