dx12 present testing
This commit is contained in:
parent
92258b6f3e
commit
b96465191e
@ -7,7 +7,7 @@
|
|||||||
#define NURI(i) NonUniformResourceIndex(i)
|
#define NURI(i) NonUniformResourceIndex(i)
|
||||||
|
|
||||||
#if !SH_CPU
|
#if !SH_CPU
|
||||||
# define INLINE
|
# define INLINE /* For intellisense */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Linear color from normalized sRGB */
|
/* Linear color from normalized sRGB */
|
||||||
|
|||||||
106
res/sh/grid.hlsl
106
res/sh/grid.hlsl
@ -1,106 +0,0 @@
|
|||||||
#include "shaders/common.hlsl"
|
|
||||||
|
|
||||||
struct vs_instance {
|
|
||||||
float2x3 xf;
|
|
||||||
float line_thickness;
|
|
||||||
float line_spacing;
|
|
||||||
float2 offset;
|
|
||||||
uint bg0_srgb;
|
|
||||||
uint bg1_srgb;
|
|
||||||
uint line_srgb;
|
|
||||||
uint x_srgb;
|
|
||||||
uint y_srgb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ps_input {
|
|
||||||
DESV(float4, screen_pos, SV_POSITION);
|
|
||||||
DECL(float, line_thickness);
|
|
||||||
DECL(float, line_spacing);
|
|
||||||
DECL(float2, offset);
|
|
||||||
DECL(float4, bg0_lin);
|
|
||||||
DECL(float4, bg1_lin);
|
|
||||||
DECL(float4, line_lin);
|
|
||||||
DECL(float4, x_lin);
|
|
||||||
DECL(float4, y_lin);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Globals
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
StructuredBuffer<vs_instance> g_instance_buffer : register(t0);
|
|
||||||
|
|
||||||
cbuffer constants : register(b0)
|
|
||||||
{
|
|
||||||
float4x4 g_projection;
|
|
||||||
uint g_instance_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Vertex shader
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
static const float2 G_quad_verts[4] = {
|
|
||||||
float2(-0.5f, -0.5f),
|
|
||||||
float2( 0.5f, -0.5f),
|
|
||||||
float2( 0.5f, 0.5f),
|
|
||||||
float2(-0.5f, 0.5f)
|
|
||||||
};
|
|
||||||
|
|
||||||
ps_input vs_main(uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID)
|
|
||||||
{
|
|
||||||
vs_instance instance = g_instance_buffer[g_instance_offset + instance_id];
|
|
||||||
float2 vert = G_quad_verts[vertex_id];
|
|
||||||
float2 world_pos = mul(instance.xf, float3(vert, 1)).xy;
|
|
||||||
|
|
||||||
ps_input output;
|
|
||||||
output.screen_pos = mul(g_projection, float4(world_pos, 0, 1));
|
|
||||||
output.line_thickness = instance.line_thickness;
|
|
||||||
output.line_spacing = instance.line_spacing;
|
|
||||||
output.offset = instance.offset;
|
|
||||||
output.bg0_lin = linear_from_srgb32(instance.bg0_srgb);
|
|
||||||
output.bg1_lin = linear_from_srgb32(instance.bg1_srgb);
|
|
||||||
output.line_lin = linear_from_srgb32(instance.line_srgb);
|
|
||||||
output.x_lin = linear_from_srgb32(instance.x_srgb);
|
|
||||||
output.y_lin = linear_from_srgb32(instance.y_srgb);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Pixel shader
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
float4 ps_main(ps_input input) : SV_TARGET
|
|
||||||
{
|
|
||||||
float2 grid_pos = input.screen_pos.xy + input.offset;
|
|
||||||
float half_thickness = input.line_thickness / 2;
|
|
||||||
float spacing = input.line_spacing;
|
|
||||||
|
|
||||||
float4 color = input.bg0_lin;
|
|
||||||
|
|
||||||
float2 v = abs(round(grid_pos / spacing) * spacing - grid_pos);
|
|
||||||
float dist = min(v.x, v.y);
|
|
||||||
|
|
||||||
if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) {
|
|
||||||
color = input.x_lin;
|
|
||||||
} else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) {
|
|
||||||
color = input.y_lin;
|
|
||||||
} else if (dist < half_thickness) {
|
|
||||||
color = input.line_lin;
|
|
||||||
} else {
|
|
||||||
bool checker = false;
|
|
||||||
uint cell_x = (uint)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0);
|
|
||||||
uint cell_y = (uint)(abs(grid_pos.y) / spacing) + (grid_pos.y < 0);
|
|
||||||
if (cell_x % 2 == 0) {
|
|
||||||
checker = cell_y % 2 == 0;
|
|
||||||
} else {
|
|
||||||
checker = cell_y % 2 == 1;
|
|
||||||
}
|
|
||||||
if (checker) {
|
|
||||||
color = input.bg1_lin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#include "sh/common.hlsl"
|
#include "sh/common.hlsl"
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Root Signature
|
* Root signature
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define ROOTSIG \
|
#define ROOTSIG \
|
||||||
@ -24,13 +24,6 @@ SamplerState g_sampler : register(s0);
|
|||||||
* Vertex shader
|
* Vertex shader
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
static const float2 g_quad_verts[4] = {
|
|
||||||
float2(-0.5f, -0.5f),
|
|
||||||
float2( 0.5f, -0.5f),
|
|
||||||
float2( 0.5f, 0.5f),
|
|
||||||
float2(-0.5f, 0.5f)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vs_input {
|
struct vs_input {
|
||||||
DECL(uint, SV_InstanceID);
|
DECL(uint, SV_InstanceID);
|
||||||
DECL(uint, SV_VertexID);
|
DECL(uint, SV_VertexID);
|
||||||
@ -45,8 +38,15 @@ struct vs_output {
|
|||||||
|
|
||||||
SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
|
SH_ENTRY(ROOTSIG) struct vs_output vs(struct vs_input input)
|
||||||
{
|
{
|
||||||
|
static const float2 unit_quad_verts[4] = {
|
||||||
|
float2(-0.5f, -0.5f),
|
||||||
|
float2(0.5f, -0.5f),
|
||||||
|
float2(0.5f, 0.5f),
|
||||||
|
float2(-0.5f, 0.5f)
|
||||||
|
};
|
||||||
|
|
||||||
struct sh_material_instance instance = g_instances[g_constants.instance_offset + input.SV_InstanceID];
|
struct sh_material_instance instance = g_instances[g_constants.instance_offset + input.SV_InstanceID];
|
||||||
float2 vert = g_quad_verts[input.SV_VertexID];
|
float2 vert = unit_quad_verts[input.SV_VertexID];
|
||||||
float2 world_pos = mul(instance.xf, float3(vert, 1)).xy;
|
float2 world_pos = mul(instance.xf, float3(vert, 1)).xy;
|
||||||
|
|
||||||
struct vs_output output;
|
struct vs_output output;
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
#include "shaders/common.hlsl"
|
|
||||||
|
|
||||||
struct vs_input {
|
|
||||||
DECL(float4, pos);
|
|
||||||
DECL(float4, color_srgb);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ps_input {
|
|
||||||
DESV(float4, screen_pos, SV_POSITION);
|
|
||||||
DECL(float4, color_lin);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Globals
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
cbuffer constants : register(b0)
|
|
||||||
{
|
|
||||||
float4x4 g_projection;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Vertex shader
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
ps_input vs_main(vs_input input)
|
|
||||||
{
|
|
||||||
ps_input output;
|
|
||||||
output.screen_pos = mul(g_projection, float4(input.pos.xy, 0.f, 1.f));
|
|
||||||
output.color_lin = linear_from_srgb(input.color_srgb);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Pixel shader
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
float4 ps_main(ps_input input) : SV_TARGET
|
|
||||||
{
|
|
||||||
return input.color_lin;
|
|
||||||
}
|
|
||||||
@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
#define SH_STRUCT(s) PACK(struct s)
|
#define SH_STRUCT(s) PACK(struct s)
|
||||||
#define SH_DECL(t, n) struct CAT(sh_, t) n
|
#define SH_DECL(t, n) struct CAT(sh_, t) n
|
||||||
|
#define SH_ENTRY(rootsig) static
|
||||||
#define SH_ENTRY static /* For intellisense */
|
|
||||||
|
|
||||||
struct sh_uint { u32 v; };
|
struct sh_uint { u32 v; };
|
||||||
INLINE struct sh_uint sh_uint_from_u32(u32 v)
|
INLINE struct sh_uint sh_uint_from_u32(u32 v)
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
#include "shaders/common.hlsl"
|
|
||||||
|
|
||||||
struct vs_instance {
|
|
||||||
float2x3 xf;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ps_input {
|
|
||||||
DESV(float4, screen_pos, SV_POSITION);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Globals
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
StructuredBuffer<vs_instance> g_instance_buffer : register(t0);
|
|
||||||
|
|
||||||
cbuffer constants : register(b0)
|
|
||||||
{
|
|
||||||
float4x4 g_projection;
|
|
||||||
uint g_instance_offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Vertex shader
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
static const float2 G_quad_verts[4] = {
|
|
||||||
float2(-0.5f, -0.5f),
|
|
||||||
float2( 0.5f, -0.5f),
|
|
||||||
float2( 0.5f, 0.5f),
|
|
||||||
float2(-0.5f, 0.5f)
|
|
||||||
};
|
|
||||||
|
|
||||||
ps_input vs_main(uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID)
|
|
||||||
{
|
|
||||||
vs_instance instance = g_instance_buffer[g_instance_offset + instance_id];
|
|
||||||
float2 vert = G_quad_verts[vertex_id];
|
|
||||||
float2 world_pos = mul(instance.xf, float3(vert, 1)).xy;
|
|
||||||
ps_input output;
|
|
||||||
output.screen_pos = mul(g_projection, float4(world_pos, 0, 1));
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Pixel shader
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
float4 ps_main(ps_input input) : SV_TARGET
|
|
||||||
{
|
|
||||||
return float4(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
@ -323,7 +323,7 @@ void app_entry_point(struct string args_str)
|
|||||||
struct host_startup_receipt host_sr = host_startup(&sock_sr);
|
struct host_startup_receipt host_sr = host_startup(&sock_sr);
|
||||||
struct resource_startup_receipt resource_sr = resource_startup();
|
struct resource_startup_receipt resource_sr = resource_startup();
|
||||||
struct work_startup_receipt work_sr = work_startup(worker_count);
|
struct work_startup_receipt work_sr = work_startup(worker_count);
|
||||||
struct gp_startup_receipt gp_sr = gp_startup(&work_sr, window);
|
struct gp_startup_receipt gp_sr = gp_startup(&work_sr);
|
||||||
struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup(&work_sr);
|
struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup(&work_sr);
|
||||||
struct ttf_startup_receipt ttf_sr = ttf_startup();
|
struct ttf_startup_receipt ttf_sr = ttf_startup();
|
||||||
struct font_startup_receipt font_sr = font_startup(&work_sr, &gp_sr, &asset_cache_sr, &ttf_sr, &resource_sr);
|
struct font_startup_receipt font_sr = font_startup(&work_sr, &gp_sr, &asset_cache_sr, &ttf_sr, &resource_sr);
|
||||||
|
|||||||
@ -96,4 +96,4 @@
|
|||||||
|
|
||||||
#define AUDIO_ENABLED 0
|
#define AUDIO_ENABLED 0
|
||||||
#define VSYNC_ENABLED 0
|
#define VSYNC_ENABLED 0
|
||||||
#define USER_FPS_LIMIT 300
|
#define USER_FPS_LIMIT 30
|
||||||
|
|||||||
4
src/gp.h
4
src/gp.h
@ -9,7 +9,7 @@ struct work_startup_receipt;
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_startup_receipt { i32 _; };
|
struct gp_startup_receipt { i32 _; };
|
||||||
struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struct sys_window *window);
|
struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Handle
|
* Handle
|
||||||
@ -133,6 +133,6 @@ void gp_dispatch(struct gp_dispatch_params params);
|
|||||||
/* 1. Ensures the backbuffer is at size `backbuffer_resolution`
|
/* 1. Ensures the backbuffer is at size `backbuffer_resolution`
|
||||||
* 2. Blits `texture` to the backbuffer using `texture_xf` (applied to centered unit square)
|
* 2. Blits `texture` to the backbuffer using `texture_xf` (applied to centered unit square)
|
||||||
* 3. Presents the backbuffer */
|
* 3. Presents the backbuffer */
|
||||||
void gp_present(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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -318,6 +318,7 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc
|
|||||||
|
|
||||||
/* Create D3D11 device & context */
|
/* Create D3D11 device & context */
|
||||||
{
|
{
|
||||||
|
__profscope(Create device);
|
||||||
#if DX11_DEBUG
|
#if DX11_DEBUG
|
||||||
u32 flags = D3D11_CREATE_DEVICE_DEBUG;
|
u32 flags = D3D11_CREATE_DEVICE_DEBUG;
|
||||||
#else
|
#else
|
||||||
@ -362,6 +363,7 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc
|
|||||||
|
|
||||||
/* Create swap chain */
|
/* Create swap chain */
|
||||||
{
|
{
|
||||||
|
__profscope(Create swapchain);
|
||||||
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
||||||
|
|
||||||
/* Get DXGI device from D3D11 device */
|
/* Get DXGI device from D3D11 device */
|
||||||
@ -1966,11 +1968,10 @@ INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, s
|
|||||||
draw_texture(G.present_blit_flow, params);
|
draw_texture(G.present_blit_flow, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear textures */
|
/* Clear texture */
|
||||||
gp_texture_clear(dst_texture_handle, RGBA32_F(0, 0, 0, 1));
|
gp_texture_clear(dst_texture_handle, RGBA32_F(0, 0, 0, 1));
|
||||||
|
|
||||||
/* Render to backbuffer texture */
|
/* Render to backbuffer texture */
|
||||||
{
|
|
||||||
struct gp_dispatch_params params = ZI;
|
struct gp_dispatch_params params = ZI;
|
||||||
params.flow = G.present_blit_flow;
|
params.flow = G.present_blit_flow;
|
||||||
params.draw_target = dst_texture_handle;
|
params.draw_target = dst_texture_handle;
|
||||||
@ -1978,7 +1979,6 @@ INTERNAL void present_blit(struct dx11_texture *dst, struct dx11_texture *src, s
|
|||||||
params.draw_target_view = XFORM_IDENT;
|
params.draw_target_view = XFORM_IDENT;
|
||||||
gp_dispatch(params);
|
gp_dispatch(params);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
|
void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
|
||||||
{
|
{
|
||||||
|
|||||||
288
src/gp_dx12.c
288
src/gp_dx12.c
@ -14,6 +14,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
#include "gstat.h"
|
||||||
|
|
||||||
/* Include common shader types */
|
/* Include common shader types */
|
||||||
#define SH_CPU 1
|
#define SH_CPU 1
|
||||||
@ -254,6 +255,9 @@ GLOBAL struct {
|
|||||||
/* Factory */
|
/* Factory */
|
||||||
IDXGIFactory6 *factory;
|
IDXGIFactory6 *factory;
|
||||||
|
|
||||||
|
/* Adapter */
|
||||||
|
IDXGIAdapter1 *adapter;
|
||||||
|
|
||||||
/* Device */
|
/* Device */
|
||||||
ID3D12Device *device;
|
ID3D12Device *device;
|
||||||
|
|
||||||
@ -273,6 +277,8 @@ GLOBAL struct {
|
|||||||
struct command_queue *cq_copy_background;
|
struct command_queue *cq_copy_background;
|
||||||
|
|
||||||
/* Swapchain */
|
/* Swapchain */
|
||||||
|
HWND swapchain_hwnd;
|
||||||
|
struct v2i32 swapchain_resolution;
|
||||||
u32 swapchain_frame_index;
|
u32 swapchain_frame_index;
|
||||||
IDXGISwapChain3 *swapchain;
|
IDXGISwapChain3 *swapchain;
|
||||||
struct dx12_resource *swapchain_resources[DX12_SWAPCHAIN_BUFFER_COUNT];
|
struct dx12_resource *swapchain_resources[DX12_SWAPCHAIN_BUFFER_COUNT];
|
||||||
@ -285,15 +291,13 @@ GLOBAL struct {
|
|||||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gp_shutdown);
|
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(gp_shutdown);
|
||||||
INTERNAL void dx12_init_device(void);
|
INTERNAL void dx12_init_device(void);
|
||||||
INTERNAL void dx12_init_objects(void);
|
INTERNAL void dx12_init_objects(void);
|
||||||
INTERNAL void dx12_init_swapchain(struct sys_window *window);
|
|
||||||
INTERNAL void dx12_init_pipelines(void);
|
INTERNAL void dx12_init_pipelines(void);
|
||||||
INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type);
|
INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRIPTOR_HEAP_TYPE type);
|
||||||
INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority);
|
INTERNAL struct command_queue *command_queue_alloc(enum D3D12_COMMAND_LIST_TYPE type, enum D3D12_COMMAND_QUEUE_PRIORITY priority);
|
||||||
INTERNAL void command_queue_release(struct command_queue *cq);
|
INTERNAL void command_queue_release(struct command_queue *cq);
|
||||||
INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff);
|
|
||||||
INTERNAL void dx12_resource_release(struct dx12_resource *resource);
|
INTERNAL void dx12_resource_release(struct dx12_resource *resource);
|
||||||
|
|
||||||
struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struct sys_window *window)
|
struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
(UNUSED)work_sr;
|
(UNUSED)work_sr;
|
||||||
@ -317,13 +321,8 @@ struct gp_startup_receipt gp_startup(struct work_startup_receipt *work_sr, struc
|
|||||||
/* Initialize dx12 */
|
/* Initialize dx12 */
|
||||||
dx12_init_device();
|
dx12_init_device();
|
||||||
dx12_init_objects();
|
dx12_init_objects();
|
||||||
dx12_init_swapchain(window);
|
|
||||||
dx12_init_pipelines();
|
dx12_init_pipelines();
|
||||||
|
|
||||||
/* Init dummy buffers */
|
|
||||||
/* TODO */
|
|
||||||
|
|
||||||
|
|
||||||
/* Register callbacks */
|
/* Register callbacks */
|
||||||
app_register_exit_callback(gp_shutdown);
|
app_register_exit_callback(gp_shutdown);
|
||||||
|
|
||||||
@ -503,12 +502,12 @@ INTERNAL void dx12_init_device(void)
|
|||||||
|
|
||||||
/* Create device */
|
/* Create device */
|
||||||
{
|
{
|
||||||
|
IDXGIAdapter1 *adapter = NULL;
|
||||||
ID3D12Device *device = NULL;
|
ID3D12Device *device = NULL;
|
||||||
struct string error = LIT("Could not initialize GPU device.");
|
struct string error = LIT("Could not initialize GPU device.");
|
||||||
struct string first_gpu_name = ZI;
|
struct string first_gpu_name = ZI;
|
||||||
u32 adapter_index = 0;
|
u32 adapter_index = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
IDXGIAdapter1 *adapter = NULL;
|
|
||||||
hr = IDXGIFactory6_EnumAdapterByGpuPreference(G.factory, adapter_index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, &IID_IDXGIAdapter1, (void **)&adapter);
|
hr = IDXGIFactory6_EnumAdapterByGpuPreference(G.factory, adapter_index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, &IID_IDXGIAdapter1, (void **)&adapter);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
DXGI_ADAPTER_DESC1 desc;
|
DXGI_ADAPTER_DESC1 desc;
|
||||||
@ -518,8 +517,6 @@ INTERNAL void dx12_init_device(void)
|
|||||||
}
|
}
|
||||||
hr = D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device, (void **)&device);
|
hr = D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device, (void **)&device);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
IDXGIAdapter1_Release(adapter);
|
|
||||||
adapter = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ID3D12Device_Release(device);
|
ID3D12Device_Release(device);
|
||||||
@ -538,6 +535,7 @@ INTERNAL void dx12_init_device(void)
|
|||||||
}
|
}
|
||||||
dx12_init_error(error);
|
dx12_init_error(error);
|
||||||
}
|
}
|
||||||
|
G.adapter = adapter;
|
||||||
G.device = device;
|
G.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,63 +595,6 @@ INTERNAL void dx12_init_objects(void)
|
|||||||
G.cq_copy_background = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COPY, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
|
G.cq_copy_background = command_queue_alloc(D3D12_COMMAND_LIST_TYPE_COPY, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Dx12 swapchain initialization
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
INTERNAL void dx12_init_swapchain(struct sys_window *window)
|
|
||||||
{
|
|
||||||
HRESULT hr = 0;
|
|
||||||
|
|
||||||
/* Create swapchain */
|
|
||||||
{
|
|
||||||
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
|
||||||
DXGI_SWAP_CHAIN_DESC1 desc = {
|
|
||||||
.Format = DX12_SWAPCHAIN_FORMAT,
|
|
||||||
.SampleDesc = { 1, 0 },
|
|
||||||
.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
|
||||||
.BufferCount = DX12_SWAPCHAIN_BUFFER_COUNT,
|
|
||||||
.Scaling = DXGI_SCALING_NONE,
|
|
||||||
.Flags = DX12_SWAPCHAIN_FLAGS,
|
|
||||||
.AlphaMode = DXGI_ALPHA_MODE_IGNORE,
|
|
||||||
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Create swapchain1 */
|
|
||||||
IDXGISwapChain1 *swapchain1 = NULL;
|
|
||||||
hr = IDXGIFactory2_CreateSwapChainForHwnd(G.factory, (IUnknown *)G.cq_direct->cq, hwnd, &desc, NULL, NULL, &swapchain1);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dx12_init_error(LIT("Failed to create IDXGISwapChain1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Upgrade to swapchain3 */
|
|
||||||
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&G.swapchain);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dx12_init_error(LIT("Failed to create IDXGISwapChain3"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable Alt+Enter changing monitor resolution to match window size */
|
|
||||||
IDXGIFactory_MakeWindowAssociation(G.factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
|
|
||||||
|
|
||||||
/* Get initial frame index */
|
|
||||||
G.swapchain_frame_index = IDXGISwapChain3_GetCurrentBackBufferIndex(G.swapchain);
|
|
||||||
|
|
||||||
IDXGISwapChain1_Release(swapchain1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create swacphain RTVs */
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < DX12_SWAPCHAIN_BUFFER_COUNT; ++i) {
|
|
||||||
ID3D12Resource *resource = NULL;
|
|
||||||
hr = IDXGISwapChain3_GetBuffer(G.swapchain, i, &IID_ID3D12Resource, (void **)&resource);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dx12_init_error(LIT("Failed to get swapchain buffer"));
|
|
||||||
}
|
|
||||||
G.swapchain_resources[i] = dx12_resource_alloc_from_swapchain_buffer(resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Dx12 pipeline initialization
|
* Dx12 pipeline initialization
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -1069,6 +1010,7 @@ INTERNAL WORK_TASK_FUNC_DEF(pipeline_load_task, load_arg_raw)
|
|||||||
pso_desc.NumRenderTargets = 1;
|
pso_desc.NumRenderTargets = 1;
|
||||||
pso_desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
pso_desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
pso_desc.SampleDesc.Count = 1;
|
pso_desc.SampleDesc.Count = 1;
|
||||||
|
pso_desc.SampleDesc.Quality = 0;
|
||||||
hr = ID3D12Device_CreateGraphicsPipelineState(G.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso);
|
hr = ID3D12Device_CreateGraphicsPipelineState(G.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_str = LIT("Failed to create pipeline state object");
|
error_str = LIT("Failed to create pipeline state object");
|
||||||
@ -1187,6 +1129,7 @@ INTERNAL struct descriptor *descriptor_alloc(struct cpu_descriptor_heap *dh)
|
|||||||
MEMZERO_STRUCT(d);
|
MEMZERO_STRUCT(d);
|
||||||
d->heap = dh;
|
d->heap = dh;
|
||||||
d->handle = handle;
|
d->handle = handle;
|
||||||
|
d->index = index;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1366,7 +1309,7 @@ INTERNAL struct dx12_resource *dx12_resource_alloc(D3D12_HEAP_PROPERTIES heap_pr
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff)
|
INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12Resource *buff, struct v2i32 texture_size)
|
||||||
{
|
{
|
||||||
struct dx12_resource *r = NULL;
|
struct dx12_resource *r = NULL;
|
||||||
{
|
{
|
||||||
@ -1384,8 +1327,10 @@ INTERNAL struct dx12_resource *dx12_resource_alloc_from_swapchain_buffer(ID3D12R
|
|||||||
/* FIXME: Initialize dx12 resource struct here */
|
/* FIXME: Initialize dx12 resource struct here */
|
||||||
|
|
||||||
r->resource = buff;
|
r->resource = buff;
|
||||||
|
|
||||||
r->rtv_descriptor = descriptor_alloc(G.rtv_heap);
|
r->rtv_descriptor = descriptor_alloc(G.rtv_heap);
|
||||||
|
r->texture_size = texture_size;
|
||||||
|
r->state = D3D12_RESOURCE_STATE_PRESENT; /* FIXME */
|
||||||
|
|
||||||
ID3D12Device_CreateRenderTargetView(G.device, r->resource, NULL, r->rtv_descriptor->handle);
|
ID3D12Device_CreateRenderTargetView(G.device, r->resource, NULL, r->rtv_descriptor->handle);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@ -1396,6 +1341,11 @@ INTERNAL void dx12_resource_release(struct dx12_resource *t)
|
|||||||
(UNUSED)t;
|
(UNUSED)t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL void dx12_resource_release_now(struct dx12_resource *t)
|
||||||
|
{
|
||||||
|
(UNUSED)t;
|
||||||
|
}
|
||||||
|
|
||||||
INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandList *cl, struct dx12_resource *resource, enum D3D12_RESOURCE_STATES state)
|
INTERNAL enum D3D12_RESOURCE_STATES dx12_resource_barrier(ID3D12GraphicsCommandList *cl, struct dx12_resource *resource, enum D3D12_RESOURCE_STATES state)
|
||||||
{
|
{
|
||||||
enum D3D12_RESOURCE_STATES old_state = resource->state;
|
enum D3D12_RESOURCE_STATES old_state = resource->state;
|
||||||
@ -1451,6 +1401,7 @@ struct gp_handle gp_texture_alloc(enum gp_texture_format format, u32 flags, stru
|
|||||||
desc.DepthOrArraySize = 1;
|
desc.DepthOrArraySize = 1;
|
||||||
desc.MipLevels = 1;
|
desc.MipLevels = 1;
|
||||||
desc.SampleDesc.Count = 1;
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
if (flags & GP_TEXTURE_FLAG_TARGETABLE) {
|
if (flags & GP_TEXTURE_FLAG_TARGETABLE) {
|
||||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
view_flags |= DX12_RESOURCE_VIEW_FLAG_RTV;
|
view_flags |= DX12_RESOURCE_VIEW_FLAG_RTV;
|
||||||
@ -1848,7 +1799,7 @@ INTERNAL struct command_buffer *command_list_push_buffer(struct command_list *cl
|
|||||||
desc.DepthOrArraySize = 1;
|
desc.DepthOrArraySize = 1;
|
||||||
desc.MipLevels = 1;
|
desc.MipLevels = 1;
|
||||||
desc.SampleDesc.Count = 1;
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
D3D12_RESOURCE_STATES initial_state = D3D12_RESOURCE_STATE_GENERIC_READ;
|
D3D12_RESOURCE_STATES initial_state = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||||
|
|
||||||
cb->resource = dx12_resource_alloc(heap_props, heap_flags, desc, initial_state, view_flags);
|
cb->resource = dx12_resource_alloc(heap_props, heap_flags, desc, initial_state, view_flags);
|
||||||
@ -1991,12 +1942,205 @@ void gp_dispatch(struct gp_dispatch_params params)
|
|||||||
arena_reset(flow->material_instances_arena);
|
arena_reset(flow->material_instances_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Swapchain
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Present
|
* Present
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void gp_present(struct v2i32 backbuffer_resolution, struct gp_handle texture, struct xform texture_xf, i32 vsync)
|
#if 0
|
||||||
|
#if GSTAT_ENABLED || PROFILING
|
||||||
|
INTERNAL void query_memory_info(void)
|
||||||
{
|
{
|
||||||
|
HRESULT hr = 0;
|
||||||
|
IDXGIAdapter3 *dxgiAdapter3 = NULL;
|
||||||
|
struct DXGI_QUERY_VIDEO_MEMORY_INFO info = ZI;
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = IDXGIAdapter_QueryInterface(G.adapter, &IID_IDXGIAdapter3, (void **)&dxgiAdapter3);
|
||||||
|
ASSERT(SUCCEEDED(hr));
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
IDXGIAdapter3_QueryVideoMemoryInfo(dxgiAdapter3, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info);
|
||||||
|
{
|
||||||
|
u64 vram = info.CurrentUsage;
|
||||||
|
u64 budget = info.Budget;
|
||||||
|
(UNUSED)vram;
|
||||||
|
(UNUSED)budget;
|
||||||
|
#if GSTAT_ENABLED
|
||||||
|
{
|
||||||
|
gstat_set(GSTAT_VRAM_USAGE, vram);
|
||||||
|
gstat_set(GSTAT_VRAM_BUDGET, budget);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if PROFILING
|
||||||
|
{
|
||||||
|
LOCAL_PERSIST char *vram_plot_name = NULL;
|
||||||
|
LOCAL_PERSIST u64 prev_vram = 0;
|
||||||
|
if (!vram_plot_name) {
|
||||||
|
vram_plot_name = "Video memory usage";
|
||||||
|
__prof_plot_init(vram_plot_name, __prof_plot_type_memory, 1, 1, 0);
|
||||||
|
}
|
||||||
|
if (vram != prev_vram) {
|
||||||
|
__prof_plot_i(vram_plot_name, vram);
|
||||||
|
}
|
||||||
|
prev_vram = vram;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dxgiAdapter3) {
|
||||||
|
IDXGIAdapter_Release(dxgiAdapter3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
INTERNAL void query_memory_info(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
INTERNAL struct dx12_resource *update_swapchain(struct sys_window *window, struct v2i32 resolution)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
||||||
|
b32 should_rebuild = !v2i32_eq(G.swapchain_resolution, resolution);
|
||||||
|
if (should_rebuild) {
|
||||||
|
HRESULT hr = 0;
|
||||||
|
|
||||||
|
if (G.swapchain) {
|
||||||
|
ASSERT(hwnd == G.swapchain_hwnd);
|
||||||
|
/* Resize existing swapchain */
|
||||||
|
/* FIXME: Fence */
|
||||||
|
|
||||||
|
/* Release resources */
|
||||||
|
for (u32 i = 0; i < ARRAY_COUNT(G.swapchain_resources); ++i) {
|
||||||
|
struct dx12_resource *resource = G.swapchain_resources[i];
|
||||||
|
dx12_resource_release_now(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resize buffers */
|
||||||
|
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, resolution.x, resolution.y, DXGI_FORMAT_UNKNOWN, DX12_SWAPCHAIN_FLAGS);
|
||||||
|
} else {
|
||||||
|
/* Create swapchain1 */
|
||||||
|
IDXGISwapChain1 *swapchain1 = NULL;
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC1 desc = ZI;
|
||||||
|
desc.Format = DX12_SWAPCHAIN_FORMAT;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
desc.BufferCount = DX12_SWAPCHAIN_BUFFER_COUNT;
|
||||||
|
desc.Scaling = DXGI_SCALING_NONE;
|
||||||
|
desc.Flags = DX12_SWAPCHAIN_FLAGS;
|
||||||
|
desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||||
|
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
hr = IDXGIFactory2_CreateSwapChainForHwnd(G.factory, (IUnknown *)G.cq_direct->cq, hwnd, &desc, NULL, NULL, &swapchain1);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
dx12_init_error(LIT("Failed to create IDXGISwapChain1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Upgrade to swapchain3 */
|
||||||
|
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&G.swapchain);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
dx12_init_error(LIT("Failed to create IDXGISwapChain3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable Alt+Enter changing monitor resolution to match window size */
|
||||||
|
IDXGIFactory_MakeWindowAssociation(G.factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
|
||||||
|
IDXGISwapChain1_Release(swapchain1);
|
||||||
|
G.swapchain_hwnd = hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate swapchain resources */
|
||||||
|
for (u32 i = 0; i < ARRAY_COUNT(G.swapchain_resources); ++i) {
|
||||||
|
ID3D12Resource *resource = NULL;
|
||||||
|
hr = IDXGISwapChain3_GetBuffer(G.swapchain, i, &IID_ID3D12Resource, (void **)&resource);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
/* TODO: Don't panic */
|
||||||
|
dx12_init_error(LIT("Failed to get swapchain buffer"));
|
||||||
|
}
|
||||||
|
G.swapchain_resources[i] = dx12_resource_alloc_from_swapchain_buffer(resource, resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
G.swapchain_resolution = resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
G.swapchain_frame_index = IDXGISwapChain3_GetCurrentBackBufferIndex(G.swapchain);
|
||||||
|
return G.swapchain_resources[G.swapchain_frame_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Remove this */
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
INTERNAL void present_blit(struct dx12_resource *dst, struct dx12_resource *src, struct xform src_xf)
|
||||||
|
{
|
||||||
|
/* FIXME: Remove this */
|
||||||
|
static struct gp_handle flow = ZI;
|
||||||
|
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 */
|
||||||
|
{
|
||||||
|
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = src_xf, .texture = src_texture_handle);
|
||||||
|
draw_texture(flow, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Clear backbuffer */
|
||||||
|
|
||||||
|
/* Render to backbuffer texture */
|
||||||
|
struct gp_dispatch_params params = ZI;
|
||||||
|
params.flow = flow;
|
||||||
|
params.draw_target = dst_texture_handle;
|
||||||
|
params.draw_target_viewport = RECT_FROM_V2(V2(0, 0), V2(dst->texture_size.x, dst->texture_size.y));
|
||||||
|
params.draw_target_view = XFORM_IDENT;
|
||||||
|
gp_dispatch(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* FIXME: Remove this */
|
||||||
|
static b32 bla = false;
|
||||||
|
static ID3D12Fence *fence = ZI;
|
||||||
|
static u64 fence_value = 0;
|
||||||
|
if (!bla) {
|
||||||
|
bla = true;
|
||||||
|
ID3D12Device_CreateFence(G.device, 0, 0, &IID_ID3D12Fence, (void **)&fence);
|
||||||
|
}
|
||||||
|
++fence_value;
|
||||||
|
ID3D12CommandQueue_Signal(G.cq_direct->cq, fence, fence_value);
|
||||||
|
|
||||||
|
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
ID3D12Fence_SetEventOnCompletion(fence, fence_value, event);
|
||||||
|
WaitForSingleObject(event, INFINITE);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Present */
|
||||||
|
HRESULT hr = IDXGISwapChain3_Present(G.swapchain, 0, 0);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
(UNUSED)backbuffer_resolution;
|
(UNUSED)backbuffer_resolution;
|
||||||
(UNUSED)texture;
|
(UNUSED)texture;
|
||||||
(UNUSED)texture_xf;
|
(UNUSED)texture_xf;
|
||||||
|
|||||||
@ -2093,7 +2093,7 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Present user texture */
|
/* Present user texture */
|
||||||
gp_present(backbuffer_resolution, G.user_texture, XFORM_TRS(.t = v2_mul(G.screen_size, 0.5), .s = G.user_size), VSYNC_ENABLED);
|
gp_present(G.window, backbuffer_resolution, G.user_texture, XFORM_TRS(.t = v2_mul(G.screen_size, 0.5), .s = G.user_size), VSYNC_ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user