dx12 testing
This commit is contained in:
parent
da2de90de1
commit
d0ec962123
@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define DX12_TEST 0
|
#define DX12_TEST 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
src/gpu.h
10
src/gpu.h
@ -15,7 +15,15 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gpu_handle {
|
struct gpu_handle {
|
||||||
u64 v;
|
union {
|
||||||
|
/* dx11 style */
|
||||||
|
u64 v;
|
||||||
|
/* dx12 style */
|
||||||
|
struct {
|
||||||
|
u64 gen;
|
||||||
|
u64 idx;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
void gpu_release(struct gpu_handle handle);
|
void gpu_release(struct gpu_handle handle);
|
||||||
|
|||||||
@ -338,12 +338,12 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window)
|
|||||||
|
|
||||||
/* DXGI Debug break */
|
/* DXGI Debug break */
|
||||||
{
|
{
|
||||||
IDXGIInfoQueue *dxgiInfo;
|
IDXGIInfoQueue *dxgi_info;
|
||||||
hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgiInfo);
|
hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgi_info);
|
||||||
ASSERT(SUCCEEDED(hr));
|
ASSERT(SUCCEEDED(hr));
|
||||||
IDXGIInfoQueue_SetBreakOnSeverity(dxgiInfo, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||||
IDXGIInfoQueue_SetBreakOnSeverity(dxgiInfo, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
IDXGIInfoQueue_Release(dxgiInfo);
|
IDXGIInfoQueue_Release(dxgi_info);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -388,6 +388,7 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window)
|
|||||||
/* Disable Alt+Enter changing monitor resolution to match window size */
|
/* Disable Alt+Enter changing monitor resolution to match window size */
|
||||||
IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
|
IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
|
||||||
|
IDXGISwapChain1_Release(swapchain1);
|
||||||
IDXGIFactory2_Release(factory);
|
IDXGIFactory2_Release(factory);
|
||||||
IDXGIAdapter_Release(dxgiAdapter);
|
IDXGIAdapter_Release(dxgiAdapter);
|
||||||
IDXGIDevice_Release(dxgiDevice);
|
IDXGIDevice_Release(dxgiDevice);
|
||||||
@ -2066,7 +2067,7 @@ void gpu_swap_backbuffer(i32 vsync)
|
|||||||
gpu_capture_image_for_profiler();
|
gpu_capture_image_for_profiler();
|
||||||
{
|
{
|
||||||
__profscope(Present);
|
__profscope(Present);
|
||||||
IDXGISwapChain1_Present(G.swapchain, vsync, flags);
|
IDXGISwapChain2_Present(G.swapchain, vsync, flags);
|
||||||
__prof_dx11_collect(G.profiling_ctx);
|
__prof_dx11_collect(G.profiling_ctx);
|
||||||
__profframe(0);
|
__profframe(0);
|
||||||
}
|
}
|
||||||
|
|||||||
307
src/gpu_dx12.c
307
src/gpu_dx12.c
@ -2,13 +2,73 @@
|
|||||||
|
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
#include "arena.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "scratch.h"
|
||||||
|
|
||||||
|
#pragma warning(push, 0)
|
||||||
|
# define UNICODE
|
||||||
|
# define COBJMACROS
|
||||||
|
# include <Windows.h>
|
||||||
|
# include <d3d12.h>
|
||||||
|
# include <dxgidebug.h>
|
||||||
|
# include <dxgi1_6.h>
|
||||||
|
# include <combaseapi.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
#pragma comment(lib, "d3d12")
|
||||||
|
#pragma comment(lib, "dxgi")
|
||||||
|
#pragma comment(lib, "dxguid")
|
||||||
|
|
||||||
|
#define DX12_WAIT_FRAME_LATENCY 1
|
||||||
|
#define DX12_ALLOW_TEARING 1
|
||||||
|
|
||||||
|
#define DX12_SWAPCHAIN_BUFFER_COUNT (3)
|
||||||
|
#define DX12_SWAPCHAIN_FLAGS ((DX12_ALLOW_TEARING * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) | (DX12_WAIT_FRAME_LATENCY * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
|
||||||
|
#define DX12_SWAPCHAIN_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM)
|
||||||
|
//#define DX12_SWAPCHAIN_RTV_FORMAT (DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
|
||||||
|
|
||||||
|
#if RTC
|
||||||
|
# define DX12_DEBUG 1
|
||||||
|
# define DX12_SHADER_DEBUG 1
|
||||||
|
#else
|
||||||
|
# define DX12_DEBUG 0
|
||||||
|
# define DX12_SHADER_DEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum dx12_handle_kind {
|
||||||
|
DX12_HANDLE_KIND_NONE,
|
||||||
|
DX12_HANDLE_KIND_TEXTURE,
|
||||||
|
|
||||||
|
NUM_DX12_HANDLE_KINDS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dx12_handle_entry {
|
||||||
|
enum dx12_handle_kind kind;
|
||||||
|
u64 gen;
|
||||||
|
u64 idx;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
struct dx12_handle_entry *next_free;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dx12_texture {
|
||||||
|
i32 _;
|
||||||
|
};
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Global state
|
* Global state
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
i32 _;
|
/* Handles pool */
|
||||||
|
struct sys_mutex handle_entries_mutex;
|
||||||
|
struct arena handle_entries_arena;
|
||||||
|
struct dx12_handle_entry *first_free_handle_entry;
|
||||||
|
u64 num_handle_entries_reserved;
|
||||||
|
|
||||||
|
/* Swapchain */
|
||||||
} G = ZI, DEBUG_ALIAS(G, G_gpu_dx12);
|
} G = ZI, DEBUG_ALIAS(G, G_gpu_dx12);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -17,7 +77,163 @@ GLOBAL struct {
|
|||||||
|
|
||||||
struct gpu_startup_receipt gpu_startup(struct sys_window *window)
|
struct gpu_startup_receipt gpu_startup(struct sys_window *window)
|
||||||
{
|
{
|
||||||
(UNUSED)window;
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
/* Initialize handles pool */
|
||||||
|
G.handle_entries_mutex = sys_mutex_alloc();
|
||||||
|
G.handle_entries_arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
|
/* Create debug controller */
|
||||||
|
u32 dxgi_factory_flags = 0;
|
||||||
|
#if DX12_DEBUG
|
||||||
|
ID3D12Debug *debug_controller = NULL;
|
||||||
|
{
|
||||||
|
hr = D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug_controller);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to create D3D12 debug controller"));
|
||||||
|
}
|
||||||
|
ID3D12Debug_EnableDebugLayer(debug_controller);
|
||||||
|
ID3D12Debug_Release(debug_controller);
|
||||||
|
dxgi_factory_flags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create factory */
|
||||||
|
IDXGIFactory6 *factory = NULL;
|
||||||
|
hr = CreateDXGIFactory2(dxgi_factory_flags, &IID_IDXGIFactory6, (void **)&factory);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to initialize DXGI factory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create device */
|
||||||
|
ID3D12Device *device = NULL;
|
||||||
|
{
|
||||||
|
struct string error = LIT("Could not initialize GPU device.");
|
||||||
|
struct string first_gpu_name = ZI;
|
||||||
|
u32 adapter_index = 0;
|
||||||
|
while (true) {
|
||||||
|
IDXGIAdapter1 *adapter = NULL;
|
||||||
|
hr = IDXGIFactory6_EnumAdapterByGpuPreference(factory, adapter_index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, &IID_IDXGIAdapter1, (void **)&adapter);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
DXGI_ADAPTER_DESC1 desc;
|
||||||
|
IDXGIAdapter1_GetDesc1(adapter, &desc);
|
||||||
|
if (!(desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) {
|
||||||
|
if (first_gpu_name.len == 0) {
|
||||||
|
first_gpu_name = string_from_wstr_no_limit(scratch.arena, desc.Description);
|
||||||
|
}
|
||||||
|
/* Using feature level 12_0 instead of 12_2 because mesh feature check happens separately
|
||||||
|
* (because 1600 series cards support mesh shaders but not the rest of 12_2) */
|
||||||
|
hr = D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device, (void **)&device);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
D3D12_FEATURE_DATA_D3D12_OPTIONS7 features = ZI;
|
||||||
|
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS7, &features, sizeof(features));
|
||||||
|
if (SUCCEEDED(hr) && features.MeshShaderTier >= D3D12_MESH_SHADER_TIER_1) {
|
||||||
|
IDXGIAdapter1_Release(adapter);
|
||||||
|
adapter = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ID3D12Device_Release(device);
|
||||||
|
IDXGIAdapter1_Release(adapter);
|
||||||
|
adapter = NULL;
|
||||||
|
device = NULL;
|
||||||
|
++adapter_index;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* TODO: Fall back to compute shaders if mesh shaders aren't supported */
|
||||||
|
if (!device) {
|
||||||
|
if (first_gpu_name.len > 0) {
|
||||||
|
struct string fmt = LIT("Device '%F' does not support DirectX 12_2. Ensure that your drivers are up to date.\n\n"
|
||||||
|
"Note that older GPUs such as those up to and including the GTX 1000 series, the RX 5000 series, and the Intel Xe-LP series do not support DirectX 12_2 features.");
|
||||||
|
error = string_format(scratch.arena, fmt, FMT_STR(first_gpu_name));
|
||||||
|
}
|
||||||
|
sys_panic(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DX12_DEBUG
|
||||||
|
/* D3D12 Debug break */
|
||||||
|
{
|
||||||
|
ID3D12InfoQueue *info = NULL;
|
||||||
|
hr = ID3D12Device_QueryInterface(device, &IID_ID3D12InfoQueue, (void **)&info);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to query ID3D12Device interface"));
|
||||||
|
}
|
||||||
|
ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||||
|
ID3D12InfoQueue_SetBreakOnSeverity(info, D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
|
ID3D12InfoQueue_Release(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DXGI Debug break */
|
||||||
|
{
|
||||||
|
IDXGIInfoQueue *dxgi_info = NULL;
|
||||||
|
hr = DXGIGetDebugInterface1(0, &IID_IDXGIInfoQueue, (void **)&dxgi_info);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to get DXGI debug interface"));
|
||||||
|
}
|
||||||
|
IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||||
|
IDXGIInfoQueue_SetBreakOnSeverity(dxgi_info, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
|
IDXGIInfoQueue_Release(dxgi_info);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create command queue */
|
||||||
|
ID3D12CommandQueue *cq = NULL;
|
||||||
|
{
|
||||||
|
D3D12_COMMAND_QUEUE_DESC desc = ZI;
|
||||||
|
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
|
desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&cq);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to create command queue"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create swapchain */
|
||||||
|
IDXGISwapChain3 *swapchain = NULL;
|
||||||
|
u32 swapchain_frame_index = 0;
|
||||||
|
{
|
||||||
|
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 = 3,
|
||||||
|
.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(factory, (IUnknown *)cq, hwnd, &desc, NULL, NULL, &swapchain1);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to create IDXGISwapChain1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Upgrade to swapchain3 */
|
||||||
|
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain);
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
sys_panic(LIT("Failed to create IDXGISwapChain3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable Alt+Enter changing monitor resolution to match window size */
|
||||||
|
IDXGIFactory_MakeWindowAssociation(factory, hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
|
||||||
|
swapchain_frame_index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
|
||||||
|
(UNUSED)swapchain_frame_index;
|
||||||
|
|
||||||
|
IDXGISwapChain1_Release(swapchain1);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDXGIFactory6_Release(factory);
|
||||||
|
scratch_end(scratch);
|
||||||
struct gpu_startup_receipt res = ZI;
|
struct gpu_startup_receipt res = ZI;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -26,23 +242,104 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window)
|
|||||||
* Handle
|
* Handle
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
INTERNAL void dx12_texture_release(struct dx12_texture *t);
|
||||||
|
|
||||||
|
INTERNAL struct gpu_handle handle_alloc(enum dx12_handle_kind kind, void *data)
|
||||||
|
{
|
||||||
|
u64 old_gen = 0;
|
||||||
|
u64 idx = 0;
|
||||||
|
struct dx12_handle_entry *entry = NULL;
|
||||||
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.handle_entries_mutex);
|
||||||
|
if (G.first_free_handle_entry) {
|
||||||
|
entry = G.first_free_handle_entry;
|
||||||
|
G.first_free_handle_entry = entry->next_free;
|
||||||
|
old_gen = entry->gen;
|
||||||
|
idx = entry->idx;
|
||||||
|
} else {
|
||||||
|
entry = arena_push_no_zero(&G.handle_entries_arena, struct dx12_handle_entry);
|
||||||
|
idx = G.num_handle_entries_reserved++;
|
||||||
|
}
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
MEMZERO_STRUCT(entry);
|
||||||
|
entry->kind = kind;
|
||||||
|
entry->gen = old_gen + 1;
|
||||||
|
entry->idx = idx;
|
||||||
|
entry->data = data;
|
||||||
|
|
||||||
|
struct gpu_handle res = ZI;
|
||||||
|
res.gen = entry->gen;
|
||||||
|
res.idx = entry->idx;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL struct dx12_handle_entry *handle_get_entry(struct gpu_handle handle, struct sys_lock *lock)
|
||||||
|
{
|
||||||
|
sys_assert_locked_e_or_s(lock, &G.handle_entries_mutex);
|
||||||
|
struct dx12_handle_entry *res = NULL;
|
||||||
|
if (handle.idx > 0 && handle.idx < G.num_handle_entries_reserved) {
|
||||||
|
struct dx12_handle_entry *tmp = &((struct dx12_handle_entry *)G.handle_entries_arena.base)[handle.idx];
|
||||||
|
if (tmp->gen == handle.gen) {
|
||||||
|
res = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: The GPU api should ensure that resources freed by the caller will not cause issues on the GPU (via fencing),
|
||||||
|
* however the caller is responsible for managing resource lifetimes on the CPU side (e.g. using sprites w/ sprite scopes
|
||||||
|
* to ensure freed textures aren't being used in pending command lists. */
|
||||||
void gpu_release(struct gpu_handle handle)
|
void gpu_release(struct gpu_handle handle)
|
||||||
{
|
{
|
||||||
(UNUSED)handle;
|
enum dx12_handle_kind kind = NULL;
|
||||||
|
void *data = NULL;
|
||||||
|
|
||||||
|
/* Release handle entry */
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.handle_entries_mutex);
|
||||||
|
{
|
||||||
|
struct dx12_handle_entry *entry = handle_get_entry(handle, &lock);
|
||||||
|
if (entry) {
|
||||||
|
kind = entry->kind;
|
||||||
|
data = entry->data;
|
||||||
|
}
|
||||||
|
++entry->gen;
|
||||||
|
entry->next_free = G.first_free_handle_entry;
|
||||||
|
G.first_free_handle_entry = entry;
|
||||||
|
}
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
|
|
||||||
|
/* Release data */
|
||||||
|
if (data) {
|
||||||
|
switch (kind) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case DX12_HANDLE_KIND_TEXTURE:
|
||||||
|
{
|
||||||
|
dx12_texture_release(data);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Texture
|
* Texture
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
INTERNAL void dx12_texture_release(struct dx12_texture *t)
|
||||||
|
{
|
||||||
|
(UNUSED)t;
|
||||||
|
}
|
||||||
|
|
||||||
struct gpu_handle gpu_texture_alloc(enum gpu_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
|
struct gpu_handle gpu_texture_alloc(enum gpu_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
|
||||||
{
|
{
|
||||||
(UNUSED)format;
|
(UNUSED)format;
|
||||||
(UNUSED)flags;
|
(UNUSED)flags;
|
||||||
(UNUSED)size;
|
(UNUSED)size;
|
||||||
(UNUSED)initial_data;
|
(UNUSED)initial_data;
|
||||||
struct gpu_handle res = ZI;
|
struct dx12_texture *t = NULL;
|
||||||
return res;
|
|
||||||
|
return handle_alloc(DX12_HANDLE_KIND_TEXTURE, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpu_texture_clear(struct gpu_handle target_texture, u32 clear_color)
|
void gpu_texture_clear(struct gpu_handle target_texture, u32 clear_color)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user