init dx11 and basic present

This commit is contained in:
Kevin Trogant 2024-04-02 19:46:08 +02:00
parent 3bc192b281
commit 2035f73f3e
8 changed files with 389 additions and 72 deletions

View File

@ -2,7 +2,7 @@ project('rtengine', ['c', 'cpp'],
default_options: ['buildtype=debug', default_options: ['buildtype=debug',
'b_sanitize=address', 'b_sanitize=address',
'c_std=c17', 'c_std=c17',
'cpp_std=c++14', 'cpp_std=c++20',
'warning_level=3', 'warning_level=3',
'werror=true', 'werror=true',
'b_vscrt=static_from_buildtype', 'b_vscrt=static_from_buildtype',
@ -85,6 +85,8 @@ if get_option('default_library') == 'static'
engine_link_libs = [runtime_lib, gfx_lib, app_lib, vk_renderer_lib] engine_link_libs = [runtime_lib, gfx_lib, app_lib, vk_renderer_lib]
elif get_option('static_renderer') == 'null' elif get_option('static_renderer') == 'null'
engine_link_libs = [runtime_lib, gfx_lib, app_lib, null_renderer_lib] engine_link_libs = [runtime_lib, gfx_lib, app_lib, null_renderer_lib]
elif get_option('static_renderer') == 'dx11'
engine_link_libs = [runtime_lib, gfx_lib, app_lib, dx11_renderer_lib]
else else
error('Invalid static_renderer option ', get_option('static_renderer')) error('Invalid static_renderer option ', get_option('static_renderer'))
endif endif

View File

@ -3,4 +3,4 @@ option('use_xlib', type : 'boolean', value : false, description : 'Use Xlib for
option('error_report_debugbreak', type : 'boolean', value : true, description : 'Debugbreak in ReportError') option('error_report_debugbreak', type : 'boolean', value : true, description : 'Debugbreak in ReportError')
option('enable_dxc_shader_compiler', type : 'boolean', value : true, description : 'Enables building the dxc-based shader compiler.') option('enable_dxc_shader_compiler', type : 'boolean', value : true, description : 'Enables building the dxc-based shader compiler.')
option('game_as_subdir', type : 'boolean', value : false, description : 'If true, adds the directory "src/game" to the build.') option('game_as_subdir', type : 'boolean', value : false, description : 'If true, adds the directory "src/game" to the build.')
option('build_dx11', type : 'boolean', value : true, description : 'Enables/disables the build of the dx11 renderer.')

View File

@ -13,87 +13,18 @@ void RegisterCVars(void) {
static rt_framegraph *_framegraph; static rt_framegraph *_framegraph;
static void PassPrepare(rt_render_pass_id pass,
const rt_render_target_write *writes,
uint32_t write_count,
const rt_render_target_read *reads,
uint32_t read_count) {
// rtLog("GAME", "Prepare pass %x", pass);
}
static void PassExecute(rt_render_pass_id pass,
const rt_render_target_write *writes,
uint32_t write_count,
const rt_render_target_read *reads,
uint32_t read_count) {
// rtLog("GAME", "Execute pass %x", pass);
}
static void PassFinalize(rt_render_pass_id pass,
const rt_render_target_write *writes,
uint32_t write_count,
const rt_render_target_read *reads,
uint32_t read_count) {
// rtLog("GAME", "Finalize pass %x", pass);
}
/* Called after the runtime has finished its initialization and before entering the main-loop*/ /* Called after the runtime has finished its initialization and before entering the main-loop*/
void Init(void) { void Init(void) {
rtLog("GAME", "Init"); rtLog("GAME", "Init");
rtInitAssetCompiler(); rtInitAssetCompiler();
rtWaitForAssetProcessing(); rtWaitForAssetProcessing();
rt_temp_arena temp = rtGetTemporaryArena(NULL, 0);
#if 0
rt_resource_id resid = rtGetResourceID("assets/forward.framegraph");
size_t size = rtGetResourceSize(resid);
rt_resource *res = rtArenaPush(temp.arena, size);
rtGetResource(resid, res);
_framegraph = rtCreateFramegraph(res->data);
rt_render_pass_bind_fns bind = {.Execute = PassExecute,
.Prepare = PassPrepare,
.Finalize = PassFinalize};
rtBindRenderPass(_framegraph, rtCalculateRenderPassID("forward", sizeof("forward") - 1), &bind);
#else
rt_resource_id resid = rtGetResourceID("assets/test.framegraph");
size_t size = rtGetResourceSize(resid);
rt_resource *res = rtArenaPush(temp.arena, size);
rtGetResource(resid, res);
_framegraph = rtCreateFramegraph(res->data);
rt_render_pass_bind_fns bind = {.Execute = PassExecute,
.Prepare = PassPrepare,
.Finalize = PassFinalize};
rtBindRenderPass(_framegraph, rtCalculateRenderPassID("pass0", sizeof("pass0") - 1), &bind);
rtBindRenderPass(_framegraph, rtCalculateRenderPassID("pass1", sizeof("pass1") - 1), &bind);
rt_v2 vertices[] = {
{ 0, 0.5},
{ 0.5, -0.5},
{-0.5, -0.5}
};
rt_buffer_info info = {
.type = RT_BUFFER_TYPE_VERTEX,
.usage = RT_BUFFER_USAGE_STATIC,
.size = sizeof(vertices),
.data = vertices,
};
rt_buffer_handle buf;
g_renderer.CreateBuffers(1, &info, &buf);
#endif
} }
/* Called after exiting the main-loop and before the runtime starts its shutdown */ /* Called after exiting the main-loop and before the runtime starts its shutdown */
void Shutdown(void) { void Shutdown(void) {
rtLog("GAME", "Shutdown"); rtLog("GAME", "Shutdown");
rtShutdownAssetCompiler(); rtShutdownAssetCompiler();
rtDestroyFramegraph(_framegraph);
} }
void Update(unsigned int frame_id) { void Update(unsigned int frame_id) {
@ -101,5 +32,4 @@ void Update(unsigned int frame_id) {
} }
void Render(unsigned int frame_id) { void Render(unsigned int frame_id) {
rtExecuteFramegraph(_framegraph, frame_id);
} }

View File

@ -6,3 +6,4 @@ subdir('app_framework')
# Renderer libs # Renderer libs
subdir('renderer/vk') subdir('renderer/vk')
subdir('renderer/null') subdir('renderer/null')
subdir('renderer/dx11')

32
src/renderer/dx11/gpu.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef RT_DX11_GPU_H
#define RT_DX11_GPU_H
#include <wrl.h>
#include <d3d11.h>
#include <d3d11_1.h>
#include <dxgi1_3.h>
// Smart pointer for COM-Objects
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
struct rt_swap_chain {
ComPtr<IDXGISwapChain1> swap_chain;
ComPtr<ID3D11RenderTargetView> rtv;
};
struct rt_gpu {
ComPtr<ID3D11Device1> device;
ComPtr<ID3D11DeviceContext1> device_context;
ComPtr<IDXGIFactory2> dxgi_factory;
rt_swap_chain swap_chain;
D3D_FEATURE_LEVEL feature_level;
};
#ifndef DONT_DEFINE_GPU_GLOBAL
extern rt_gpu g_gpu;
#endif
#endif

330
src/renderer/dx11/init.cpp Normal file
View File

@ -0,0 +1,330 @@
#ifndef _WIN32
#pragma warning Building DX11 on non - windows is probably a mistake
#endif
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "dxguid.lib")
#include <d3d11.h>
#include <dxgi1_3.h>
#include <wrl.h>
#include "gfx/renderer_api.h"
#include "runtime/config.h"
#define DONT_DEFINE_RENDERER_GLOBAL
#include "gpu.h"
RT_CVAR_S(
rt_Dx11AdapterName,
"Name of the adapter that should be used for device creation. Default: \"\" (Use default)",
"");
RT_CVAR_I(rt_Dx11VSync, "Enable vsync. Default: 1", 1);
rt_gpu g_gpu;
extern "C" void RT_RENDERER_API_FN(RegisterCVars)(void) {
rtRegisterCVAR(&rt_Dx11AdapterName);
rtRegisterCVAR(&rt_Dx11VSync);
}
static rt_swap_chain CreateSwapChain(HWND hwnd) {
rt_swap_chain swc;
DXGI_SWAP_CHAIN_DESC1 desc;
desc.Width = 0; // use window width
desc.Height = 0; // use window height
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // can't specify _SRGB here when using
// DXGI_SWAP_EFFECT_FLIP_* ...;
desc.Stereo = FALSE;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 2;
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
desc.Flags = 0;
if (FAILED(g_gpu.dxgi_factory->CreateSwapChainForHwnd(g_gpu.device.Get(),
hwnd,
&desc,
nullptr,
nullptr,
&swc.swap_chain))) {
rtReportError("dx11", "Failed to create the swap chain.");
return swc;
}
ID3D11Texture2D *frame_buffer;
if (FAILED(swc.swap_chain->GetBuffer(0, IID_PPV_ARGS(&frame_buffer)))) {
rtReportError("dx11", "Failed to retrieve the backbuffer.");
swc.swap_chain.Reset();
return swc;
}
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
rtv_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
if (FAILED(g_gpu.device->CreateRenderTargetView(frame_buffer, &rtv_desc, &swc.rtv))) {
rtReportError("dx11", "Failed to create the render target view for the backbuffer.");
swc.swap_chain.Reset();
return swc;
}
return swc;
}
static IDXGIAdapter *RetrieveSelectedAdapter(void) {
ComPtr<IDXGIFactory2> factory;
if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)))) {
return NULL;
}
UINT i = 0;
IDXGIAdapter *adapter;
while (factory->EnumAdapters(i, &adapter) == S_OK) {
++i;
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
char utf8_desc[256];
rtWStrToUTF8(desc.Description, utf8_desc, 256);
if (strncmp(utf8_desc, rt_Dx11AdapterName.s, 256) == 0)
return adapter;
}
return NULL;
}
extern "C" rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
constexpr D3D_FEATURE_LEVEL feature_levels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
UINT device_flags = 0;
#ifdef RT_DEBUG
device_flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
IDXGIAdapter *selected_adapter = RetrieveSelectedAdapter();
ID3D11Device *base_device;
ID3D11DeviceContext *base_context;
if (FAILED(D3D11CreateDevice(selected_adapter,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
device_flags,
feature_levels,
RT_ARRAY_COUNT(feature_levels),
D3D11_SDK_VERSION,
&base_device,
&g_gpu.feature_level,
&base_context))) {
rtLog("dx11", "Feature level 11.1 creation failed, retrying with feature level 11.0");
if (FAILED(D3D11CreateDevice(selected_adapter,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
device_flags,
&feature_levels[1],
RT_ARRAY_COUNT(feature_levels) - 1,
D3D11_SDK_VERSION,
&base_device,
&g_gpu.feature_level,
&base_context))) {
rtReportError("dx11", "Failed to create the d3d11 device.");
return RT_UNKNOWN_ERROR;
}
}
if (FAILED(base_device->QueryInterface(IID_PPV_ARGS(&g_gpu.device)))) {
rtReportError("dx11", "Failed to query the D3D11Device1 interface.");
return RT_UNKNOWN_ERROR;
}
if (FAILED(base_context->QueryInterface(IID_PPV_ARGS(&g_gpu.device_context)))) {
rtReportError("dx11", "Failed to query the D3D11DeviceContext1 interface.");
return RT_UNKNOWN_ERROR;
}
IDXGIDevice1 *dxgi_device;
if (FAILED(g_gpu.device->QueryInterface(&dxgi_device))) {
rtReportError("dx11", "Failed to query the DXGIDevice1 interface.");
return RT_UNKNOWN_ERROR;
}
IDXGIAdapter *adapter;
if (FAILED(dxgi_device->GetAdapter(&adapter))) {
rtReportError("dx11", "Failed to retrieve the dxgi adapter.");
return RT_UNKNOWN_ERROR;
}
if (FAILED(adapter->GetParent(IID_PPV_ARGS(&g_gpu.dxgi_factory)))) {
rtReportError("dx11", "Failed to retrieve the dxgi factory.");
return RT_UNKNOWN_ERROR;
}
g_gpu.swap_chain = CreateSwapChain(info->hWnd);
return RT_SUCCESS;
}
extern "C" void RT_RENDERER_API_FN(Shutdown)(void) {
}
extern "C" void RT_RENDERER_API_FN(BeginFrame)(unsigned int frame_id) {
RT_UNUSED(frame_id);
FLOAT clear_color[4] = {
0,
0,
0,
0,
};
g_gpu.device_context->ClearRenderTargetView(g_gpu.swap_chain.rtv.Get(), clear_color);
}
extern "C" void RT_RENDERER_API_FN(EndFrame)(unsigned int frame_id) {
RT_UNUSED(frame_id);
UINT sync_interval = rt_Dx11VSync.i ? 1 : 0;
g_gpu.swap_chain.swap_chain->Present(sync_interval, 0);
}
// Copied from null. Delete once no longer needed
extern "C" {
#define RETURN_HANDLE_STUB2(type, initial) \
static unsigned int s_next = (initial); \
s_next = (s_next + 1) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX; \
type h = { \
1, \
s_next, \
}; \
return h;
#define RETURN_HANDLE_STUB(type) RETURN_HANDLE_STUB2(type, 1)
#define RETURN_HANDLE_ARRAY_STUB2(out, count, initial) \
static unsigned int s_next = (initial); \
for (uint32_t i = 0; i < (count); ++i) { \
(out)[i].index = (s_next++) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX; \
(out)[i].version = 1; \
}
#define RETURN_HANDLE_ARRAY_STUB(out, count) RETURN_HANDLE_ARRAY_STUB2(out, count, 1)
unsigned int RT_RENDERER_API_FN(GetMaxFramesInFlight)(void) {
return 2;
}
rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *info) {
RT_UNUSED(info);
RETURN_HANDLE_STUB(rt_pipeline_handle);
}
void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle handle) {
RT_UNUSED(handle);
}
rt_render_target_handle RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_target_info *info) {
RT_UNUSED(info);
RETURN_HANDLE_STUB2(rt_render_target_handle, 2);
}
rt_render_target_handle RT_RENDERER_API_FN(GetSwapchainRenderTarget)(void) {
return {1, 1};
}
void RT_RENDERER_API_FN(DestroyRenderTarget)(rt_render_target_handle handle) {
RT_UNUSED(handle);
}
rt_result RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t count,
const rt_alloc_command_buffer_info *info,
rt_command_buffer_handle *p_command_buffers) {
RT_UNUSED(info);
RETURN_HANDLE_ARRAY_STUB(p_command_buffers, count)
return RT_SUCCESS;
}
rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue queue,
const rt_submit_command_buffers_info *info) {
RT_UNUSED(queue);
RT_UNUSED(info);
return RT_SUCCESS;
}
rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t count,
const rt_gpu_semaphore_info *info,
rt_gpu_semaphore_handle *p_semaphores) {
RT_UNUSED(info);
RETURN_HANDLE_ARRAY_STUB2(p_semaphores, count, 3)
return RT_SUCCESS;
}
void RT_RENDERER_API_FN(DestroySemaphores)(uint32_t count, rt_gpu_semaphore_handle *semaphores) {
RT_UNUSED(count);
RT_UNUSED(semaphores);
}
/* NOTE(Kevin): It might become necessary to actually track the value, to correctly simulate gpu
* behaviour */
uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle sem) {
RT_UNUSED(sem);
return 0;
}
rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetSwapchainAvailableSemaphore)(void) {
return {1, 1};
}
rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void) {
return {1, 2};
}
rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t count,
const rt_buffer_info *info,
rt_buffer_handle *p_buffers) {
RT_UNUSED(info);
RETURN_HANDLE_ARRAY_STUB(p_buffers, count);
return RT_SUCCESS;
}
void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers) {
RT_UNUSED(count);
RT_UNUSED(buffers);
}
void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmd,
const rt_cmd_begin_pass_info *info) {
RT_UNUSED(cmd);
RT_UNUSED(info);
}
void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle cmd) {
RT_UNUSED(cmd);
}
void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmd,
rt_render_target_handle target,
rt_render_target_state state) {
RT_UNUSED(cmd);
RT_UNUSED(target);
RT_UNUSED(state);
}
void RT_RENDERER_API_FN(CmdFlushRenderTargetWrite)(rt_command_buffer_handle cmdbuf_handle,
rt_render_target_handle render_target) {
RT_UNUSED(cmdbuf_handle);
RT_UNUSED(render_target);
}
rt_render_graph_builder RT_RENDERER_API_FN(CreateRenderGraphBuilder)(void) {
rt_render_graph_builder b = {
.obj = NULL,
};
return b;
}
void RT_RENDERER_API_FN(DestroyRenderGraphBuilder)(rt_render_graph_builder *builder) {
RT_UNUSED(builder);
}
}

View File

@ -0,0 +1,17 @@
if get_option('build_dx11')
dx11_renderer_lib = library('rtdx11',
# Project Sources
'gpu.h',
'init.cpp',
dependencies : [m_dep, windowing_dep],
include_directories : [engine_incdir, contrib_incdir],
link_with : [runtime_lib],
cpp_pch : 'pch/dx11_pch.h',
override_options : ['b_sanitize=none'],
install : true)
engine_libs += dx11_renderer_lib
engine_lib_paths += dx11_renderer_lib.full_path()
endif

View File

@ -0,0 +1,5 @@
// DX11 headers
#include <wrl.h>
#include <d3d11.h>
#include <d3d11_1.h>
#include <dxgi1_3.h>