don't expose backbuffer texture to user (blit internally during present)
This commit is contained in:
parent
0c0cfdde08
commit
7b0c95d403
11
src/gpu.h
11
src/gpu.h
@ -131,13 +131,12 @@ struct gpu_handle gpu_dispatch_state_alloc(void);
|
|||||||
void gpu_dispatch(struct gpu_handle gpu_dispatch_state, struct gpu_dispatch_params params);
|
void gpu_dispatch(struct gpu_handle gpu_dispatch_state, struct gpu_dispatch_params params);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Backbuffer
|
* Present
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Returns a texture representing the internal backbuffer. Lifetime is managed by gpu layer. */
|
/* 1. Ensures the backbuffer is at size `backbuffer_resolution`
|
||||||
struct gpu_handle gpu_recreate_backbuffer(struct v2i32 size);
|
* 2. Blits `texture` to the backbuffer using `texture_xf` (applied to centered unit square)
|
||||||
|
* 3. Presents the backbuffer */
|
||||||
/* Presents the backbuffer to the screen */
|
void gpu_present(struct v2i32 backbuffer_resolution, struct gpu_handle texture, struct xform texture_xf, i32 vsync);
|
||||||
void gpu_swap_backbuffer(i32 vsync);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
113
src/gpu_dx11.c
113
src/gpu_dx11.c
@ -47,6 +47,24 @@
|
|||||||
#define DX11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM)
|
#define DX11_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM)
|
||||||
#define DX11_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
|
#define DX11_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: Remove this */
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum dx11_shader_kind {
|
enum dx11_shader_kind {
|
||||||
DX11_SHADER_KIND_NONE,
|
DX11_SHADER_KIND_NONE,
|
||||||
DX11_SHADER_KIND_MESH,
|
DX11_SHADER_KIND_MESH,
|
||||||
@ -187,7 +205,6 @@ struct dx11_texture {
|
|||||||
ID3D11Texture2D *texture;
|
ID3D11Texture2D *texture;
|
||||||
ID3D11ShaderResourceView *srv;
|
ID3D11ShaderResourceView *srv;
|
||||||
ID3D11RenderTargetView *rtv;
|
ID3D11RenderTargetView *rtv;
|
||||||
b32 is_backbuffer;
|
|
||||||
struct v2i32 size;
|
struct v2i32 size;
|
||||||
struct dx11_texture *next_free;
|
struct dx11_texture *next_free;
|
||||||
};
|
};
|
||||||
@ -226,6 +243,9 @@ GLOBAL struct {
|
|||||||
struct dx11_texture backbuffer_texture;
|
struct dx11_texture backbuffer_texture;
|
||||||
i64 last_backbuffer_resize_ns;
|
i64 last_backbuffer_resize_ns;
|
||||||
|
|
||||||
|
struct gpu_handle present_blit_plan;
|
||||||
|
struct gpu_handle present_blit_dispatch_state;
|
||||||
|
|
||||||
ID3D11BlendState *blend_state;
|
ID3D11BlendState *blend_state;
|
||||||
ID3D11RasterizerState *rasterizer_state;
|
ID3D11RasterizerState *rasterizer_state;
|
||||||
ID3D11DepthStencilState *depth_stencil_state;
|
ID3D11DepthStencilState *depth_stencil_state;
|
||||||
@ -403,7 +423,6 @@ struct gpu_startup_receipt gpu_startup(struct work_startup_receipt *work_sr, str
|
|||||||
G.dev = device;
|
G.dev = device;
|
||||||
G.devcon = context;
|
G.devcon = context;
|
||||||
G.swapchain = swapchain;
|
G.swapchain = swapchain;
|
||||||
G.backbuffer_texture.is_backbuffer = true;
|
|
||||||
|
|
||||||
/* Create the swapchain waitable object */
|
/* Create the swapchain waitable object */
|
||||||
#if DX11_WAIT_FRAME_LATENCY
|
#if DX11_WAIT_FRAME_LATENCY
|
||||||
@ -528,6 +547,9 @@ struct gpu_startup_receipt gpu_startup(struct work_startup_receipt *work_sr, str
|
|||||||
resource_register_watch_callback(shader_resource_watch_callback);
|
resource_register_watch_callback(shader_resource_watch_callback);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
G.present_blit_plan = gpu_plan_alloc();
|
||||||
|
G.present_blit_dispatch_state = gpu_dispatch_state_alloc();
|
||||||
|
|
||||||
return (struct gpu_startup_receipt) { 0 };
|
return (struct gpu_startup_receipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1087,22 +1109,20 @@ INTERNAL struct dx11_texture *dx11_texture_alloc(enum DXGI_FORMAT format, u32 fl
|
|||||||
|
|
||||||
INTERNAL void dx11_texture_release(struct dx11_texture *t)
|
INTERNAL void dx11_texture_release(struct dx11_texture *t)
|
||||||
{
|
{
|
||||||
if (!t->is_backbuffer) {
|
{
|
||||||
{
|
struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex);
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.textures_mutex);
|
t->next_free = G.first_free_texture;
|
||||||
t->next_free = G.first_free_texture;
|
G.first_free_texture = t;
|
||||||
G.first_free_texture = t;
|
sys_mutex_unlock(&lock);
|
||||||
sys_mutex_unlock(&lock);
|
}
|
||||||
}
|
if (t->rtv) {
|
||||||
if (t->rtv) {
|
ID3D11RenderTargetView_Release(t->rtv);
|
||||||
ID3D11RenderTargetView_Release(t->rtv);
|
}
|
||||||
}
|
if (t->srv) {
|
||||||
if (t->srv) {
|
ID3D11ShaderResourceView_Release(t->srv);
|
||||||
ID3D11ShaderResourceView_Release(t->srv);
|
}
|
||||||
}
|
if (t->texture) {
|
||||||
if (t->texture) {
|
ID3D11Texture2D_Release(t->texture);
|
||||||
ID3D11Texture2D_Release(t->texture);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,6 +1155,7 @@ void gpu_texture_clear(struct gpu_handle target_texture, u32 clear_color)
|
|||||||
__prof;
|
__prof;
|
||||||
struct dx11_texture *t = (struct dx11_texture *)target_texture.v;
|
struct dx11_texture *t = (struct dx11_texture *)target_texture.v;
|
||||||
if (t->rtv) {
|
if (t->rtv) {
|
||||||
|
__profscope_dx11(G.profiling_ctx, Clear, RGB32_F(0.5, 0.1, 0.1));
|
||||||
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
|
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
|
||||||
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
|
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
|
||||||
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
|
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
|
||||||
@ -1952,10 +1973,9 @@ INTERNAL struct DXGI_QUERY_VIDEO_MEMORY_INFO get_memory_info(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct gpu_handle gpu_recreate_backbuffer(struct v2i32 size)
|
INTERNAL void present_resize(struct v2i32 size)
|
||||||
{
|
{
|
||||||
struct gpu_handle res = ZI;
|
__prof;
|
||||||
|
|
||||||
/* Delay backbuffer recreation so that we don't recreate it too quickly.
|
/* Delay backbuffer recreation so that we don't recreate it too quickly.
|
||||||
* It seems that doing this without a delay too often will cause windows
|
* It seems that doing this without a delay too often will cause windows
|
||||||
* to eventually just display a blackscreen rather than the backbuffer
|
* to eventually just display a blackscreen rather than the backbuffer
|
||||||
@ -1986,16 +2006,45 @@ struct gpu_handle gpu_recreate_backbuffer(struct v2i32 size)
|
|||||||
rtv_desc.Format = DX11_SWAPCHAIN_RTV_FORMAT;
|
rtv_desc.Format = DX11_SWAPCHAIN_RTV_FORMAT;
|
||||||
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||||
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)G.backbuffer_texture.texture, &rtv_desc, &G.backbuffer_texture.rtv);
|
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)G.backbuffer_texture.texture, &rtv_desc, &G.backbuffer_texture.rtv);
|
||||||
|
|
||||||
res.v = (u64)&G.backbuffer_texture;
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpu_swap_backbuffer(i32 vsync)
|
INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, struct xform src_xf)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
#if RESOURCE_RELOADING
|
__profscope_dx11(G.profiling_ctx, Blit, RGB32_F(0.3, 0.1, 0.1));
|
||||||
|
struct gpu_handle src_texture_handle = { .v = (u64)src };
|
||||||
|
struct gpu_handle dst_texture_handle = { .v = (u64)dst };
|
||||||
|
|
||||||
|
/* Draw texture to backbuffer texture */
|
||||||
|
/* TODO: Specialized blit shader */
|
||||||
|
{
|
||||||
|
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = src_xf, .texture = src_texture_handle);
|
||||||
|
draw_texture(G.present_blit_plan, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send plans to GPU */
|
||||||
|
gpu_submit_plan(G.present_blit_plan);
|
||||||
|
|
||||||
|
/* Clear textures */
|
||||||
|
gpu_texture_clear(dst_texture_handle, RGBA32_F(0, 0, 0, 1));
|
||||||
|
|
||||||
|
/* Render to backbuffer texture */
|
||||||
|
{
|
||||||
|
struct gpu_dispatch_params params = ZI;
|
||||||
|
params.plan = G.present_blit_plan;
|
||||||
|
params.draw_target = dst_texture_handle;
|
||||||
|
params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->size.x, dst->size.y));
|
||||||
|
params.draw_target_view = XFORM_IDENT;
|
||||||
|
gpu_dispatch(G.present_blit_dispatch_state, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpu_present(struct v2i32 backbuffer_resolution, struct gpu_handle texture, struct xform texture_xf, i32 vsync)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
|
||||||
/* Reload dirty shaders */
|
/* Reload dirty shaders */
|
||||||
|
#if RESOURCE_RELOADING
|
||||||
for (u64 i = DX11_SHADER_KIND_NONE + 1; i < NUM_DX11_SHADER_KINDS; ++i) {
|
for (u64 i = DX11_SHADER_KIND_NONE + 1; i < NUM_DX11_SHADER_KINDS; ++i) {
|
||||||
struct dx11_shader_desc *desc = &G.shader_info[i];
|
struct dx11_shader_desc *desc = &G.shader_info[i];
|
||||||
if (shader_unset_dirty(desc)) {
|
if (shader_unset_dirty(desc)) {
|
||||||
@ -2004,8 +2053,8 @@ void gpu_swap_backbuffer(i32 vsync)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Track vram usage */
|
||||||
#if GSTAT_ENABLED || PROFILING
|
#if GSTAT_ENABLED || PROFILING
|
||||||
/* Check vram usage */
|
|
||||||
{
|
{
|
||||||
struct DXGI_QUERY_VIDEO_MEMORY_INFO info = get_memory_info();
|
struct DXGI_QUERY_VIDEO_MEMORY_INFO info = get_memory_info();
|
||||||
u64 vram = info.CurrentUsage;
|
u64 vram = info.CurrentUsage;
|
||||||
@ -2035,6 +2084,7 @@ void gpu_swap_backbuffer(i32 vsync)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Wait */
|
||||||
i32 flags = 0;
|
i32 flags = 0;
|
||||||
if (vsync) {
|
if (vsync) {
|
||||||
if (G.swapchain_waitable != NULL) {
|
if (G.swapchain_waitable != NULL) {
|
||||||
@ -2047,6 +2097,15 @@ void gpu_swap_backbuffer(i32 vsync)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Resize backbuffer */
|
||||||
|
if (!v2i32_eq(G.backbuffer_texture.size, backbuffer_resolution)) {
|
||||||
|
present_resize(backbuffer_resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blit to backbuffer */
|
||||||
|
present_blit(&G.backbuffer_texture, (struct dx11_texture *)texture.v, texture_xf);
|
||||||
|
|
||||||
|
/* Present */
|
||||||
gpu_capture_image_for_profiler();
|
gpu_capture_image_for_profiler();
|
||||||
{
|
{
|
||||||
__profscope(Present);
|
__profscope(Present);
|
||||||
|
|||||||
@ -1819,7 +1819,7 @@ struct gpu_handle gpu_recreate_backbuffer(struct v2i32 size)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpu_swap_backbuffer(i32 vsync)
|
void gpu_present(i32 vsync)
|
||||||
{
|
{
|
||||||
(UNUSED)vsync;
|
(UNUSED)vsync;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,23 +12,6 @@
|
|||||||
#include "atomic.h"
|
#include "atomic.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void bla(void);
|
|
||||||
void bla(void)
|
|
||||||
{
|
|
||||||
(UNUSED)bla;
|
|
||||||
DEBUGBREAKABLE;
|
|
||||||
}
|
|
||||||
#define NTDDI_WIN11_DT 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
|
|||||||
45
src/user.c
45
src/user.c
@ -72,7 +72,6 @@ GLOBAL struct {
|
|||||||
|
|
||||||
/* Gpu handles */
|
/* Gpu handles */
|
||||||
struct gpu_handle user_texture;
|
struct gpu_handle user_texture;
|
||||||
struct gpu_handle backbuffer_texture;
|
|
||||||
|
|
||||||
struct gpu_handle world_gpu_plan;
|
struct gpu_handle world_gpu_plan;
|
||||||
struct gpu_handle ui_gpu_plan;
|
struct gpu_handle ui_gpu_plan;
|
||||||
@ -2069,32 +2068,15 @@ INTERNAL void user_update(void)
|
|||||||
__profscope(render);
|
__profscope(render);
|
||||||
|
|
||||||
struct rect user_viewport = RECT_FROM_V2(V2(0, 0), G.user_size);
|
struct rect user_viewport = RECT_FROM_V2(V2(0, 0), G.user_size);
|
||||||
struct rect backbuffer_viewport = RECT_FROM_V2(V2(0, 0), G.screen_size);
|
|
||||||
struct v2i32 user_resolution = v2_round_to_int(user_viewport.size);
|
struct v2i32 user_resolution = v2_round_to_int(user_viewport.size);
|
||||||
struct v2i32 backbuffer_resolution = v2_round_to_int(backbuffer_viewport.size);
|
struct v2i32 backbuffer_resolution = v2_round_to_int(G.screen_size);
|
||||||
|
|
||||||
/* Allocate target textures */
|
/* Allocate user texture */
|
||||||
{
|
if (!G.user_texture.v || !v2i32_eq(gpu_texture_get_size(G.user_texture), user_resolution)) {
|
||||||
|
if (G.user_texture.v) {
|
||||||
/* User texture */
|
gpu_release(G.user_texture);
|
||||||
if (!G.user_texture.v || !v2i32_eq(gpu_texture_get_size(G.user_texture), user_resolution)) {
|
|
||||||
if (G.user_texture.v) {
|
|
||||||
gpu_release(G.user_texture);
|
|
||||||
}
|
|
||||||
G.user_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGETABLE, user_resolution, NULL);
|
|
||||||
}
|
}
|
||||||
|
G.user_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGETABLE, user_resolution, NULL);
|
||||||
/* Backbuffer texture */
|
|
||||||
if (!G.backbuffer_texture.v || !v2i32_eq(gpu_texture_get_size(G.backbuffer_texture), backbuffer_resolution)) {
|
|
||||||
G.backbuffer_texture = gpu_recreate_backbuffer(backbuffer_resolution);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw user texture to backbuffer texture */
|
|
||||||
{
|
|
||||||
struct xform xf = XFORM_TRS(.t = v2_mul(V2(backbuffer_resolution.x, backbuffer_resolution.y), 0.5), .s = G.user_size);
|
|
||||||
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = xf, .texture = G.user_texture);
|
|
||||||
draw_texture(G.backbuffer_gpu_plan, params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send plans to GPU */
|
/* Send plans to GPU */
|
||||||
@ -2104,7 +2086,6 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
/* Clear textures */
|
/* Clear textures */
|
||||||
gpu_texture_clear(G.user_texture, 0);
|
gpu_texture_clear(G.user_texture, 0);
|
||||||
gpu_texture_clear(G.backbuffer_texture, RGBA32_F(0, 0, 0, 1));
|
|
||||||
|
|
||||||
/* Render world to user texture */
|
/* Render world to user texture */
|
||||||
{
|
{
|
||||||
@ -2126,18 +2107,8 @@ INTERNAL void user_update(void)
|
|||||||
gpu_dispatch(G.user_dispatch_state, params);
|
gpu_dispatch(G.user_dispatch_state, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render to backbuffer texture */
|
/* Present user texture */
|
||||||
{
|
gpu_present(backbuffer_resolution, G.user_texture, XFORM_TRS(.t = v2_mul(G.screen_size, 0.5), .s = G.user_size), VSYNC_ENABLED);
|
||||||
struct gpu_dispatch_params params = ZI;
|
|
||||||
params.plan = G.backbuffer_gpu_plan;
|
|
||||||
params.draw_target = G.backbuffer_texture;
|
|
||||||
params.draw_target_viewport = backbuffer_viewport;
|
|
||||||
params.draw_target_view = XFORM_IDENT;
|
|
||||||
gpu_dispatch(G.backbuffer_dispatch_state, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Swap backbuffer */
|
|
||||||
gpu_swap_backbuffer(VSYNC_ENABLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user