From e93847b1877e8d49bb2e5f0603902e438c789a77 Mon Sep 17 00:00:00 2001 From: Kevin Trogant Date: Wed, 3 Apr 2024 22:56:31 +0200 Subject: [PATCH] Begin and end pass --- src/game/main.c | 20 ++++++ src/renderer/dx11/command_buffers.cpp | 13 +++- src/renderer/dx11/commands.cpp | 87 +++++++++++++++++++++++++++ src/renderer/dx11/device_objects.hpp | 7 +++ src/renderer/dx11/init.cpp | 32 ++-------- src/renderer/dx11/meson.build | 1 + src/renderer/dx11/render_targets.cpp | 8 ++- src/runtime/runtime.h | 9 ++- 8 files changed, 146 insertions(+), 31 deletions(-) create mode 100644 src/renderer/dx11/commands.cpp diff --git a/src/game/main.c b/src/game/main.c index 94d3a9d..2ffdeaa 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -13,12 +13,16 @@ void RegisterCVars(void) { static rt_framegraph *_framegraph; +static rt_render_target_handle _rt; + /* Called after the runtime has finished its initialization and before entering the main-loop*/ void Init(void) { rtLog("GAME", "Init"); rtInitAssetCompiler(); rtWaitForAssetProcessing(); + + _rt = g_renderer.GetSwapchainRenderTarget(); } /* Called after exiting the main-loop and before the runtime starts its shutdown */ @@ -32,4 +36,20 @@ void Update(unsigned int frame_id) { } void Render(unsigned int frame_id) { + rt_alloc_command_buffer_info info = {RT_GRAPHICS_QUEUE}; + rt_command_buffer_handle cmd; + g_renderer.AllocCommandBuffers(1, &info, &cmd); + + rt_cmd_begin_pass_info pass_info = { + .color_buffer_count = 1, + .color_buffers = {_rt}, + .color_buffer_loads = {RT_PASS_LOAD_MODE_CLEAR}, + .color_buffer_clear_values = {{.color = {1.f, 0.f, 0.f, 1.f}}}, + .name = "testme", + }; + g_renderer.CmdBeginPass(cmd, &pass_info); + g_renderer.CmdEndPass(cmd); + + rt_submit_command_buffers_info submit = {.command_buffer_count = 1, .command_buffers = &cmd}; + g_renderer.SubmitCommandBuffers(RT_GRAPHICS_QUEUE, &submit); } \ No newline at end of file diff --git a/src/renderer/dx11/command_buffers.cpp b/src/renderer/dx11/command_buffers.cpp index 319d1cb..b63821a 100644 --- a/src/renderer/dx11/command_buffers.cpp +++ b/src/renderer/dx11/command_buffers.cpp @@ -3,12 +3,12 @@ #include "gfx/renderer_api.h" #include "runtime/config.h" +#include "runtime/handles.h" #include "runtime/threading.h" #include "runtime/threading_helpers.hpp" -#include "runtime/handles.h" -#include "gpu.hpp" #include "device_objects.hpp" +#include "gpu.hpp" RT_CVAR_I(rt_Dx11MaxCommandBuffers, "Maximum number of simultaneously created command buffers. Default: 1024", @@ -80,6 +80,13 @@ RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t count, } return RT_UNKNOWN_ERROR; } + +#ifdef RT_DEBUG + if (FAILED(slot->context->QueryInterface(IID_PPV_ARGS(&slot->annotation)))) { + rtLog("dx11", "Failed to retrieve the annotation interface."); + slot->annotation = nullptr; + } +#endif } else { slot->context->ClearState(); } @@ -117,7 +124,7 @@ RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue, const rt_submit_command_b rtLockMutex(_lock); cmdbuf->next_free = _first_free; - _first_free = cmdbuf; + _first_free = cmdbuf; rtUnlockMutex(_lock); } return RT_SUCCESS; diff --git a/src/renderer/dx11/commands.cpp b/src/renderer/dx11/commands.cpp new file mode 100644 index 0000000..78c99d0 --- /dev/null +++ b/src/renderer/dx11/commands.cpp @@ -0,0 +1,87 @@ +#include +#include + +#include "gfx/renderer_api.h" + +#include "device_objects.hpp" +#include "gpu.hpp" + +extern "C" void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmdhandle, + const rt_cmd_begin_pass_info *info) { + rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); + if (!RT_VERIFY(cmd)) + return; + + if (cmd->annotation) { + WCHAR wname[128]; + if (rtUTF8ToWStr(info->name, wname, sizeof(wname)) == RT_SUCCESS) + cmd->annotation->BeginEvent(wname); + } + + // Setup rtvs + ID3D11RenderTargetView *rtvs[4]; + ID3D11DepthStencilView *dsv = nullptr; + + for (uint32_t i = 0; i < info->color_buffer_count; ++i) { + rt_render_target *rt = rtGetRenderTarget(info->color_buffers[i]); + if (!RT_VERIFY(rt)) + return; + RT_ASSERT(rt->IsColorRenderTarget(), "Needs to provide a valid color render target"); + rtvs[i] = rt->rtv; + + if (info->color_buffer_loads[i] == RT_PASS_LOAD_MODE_CLEAR) { + FLOAT color[4] = { + info->color_buffer_clear_values[i].color.r, + info->color_buffer_clear_values[i].color.g, + info->color_buffer_clear_values[i].color.b, + info->color_buffer_clear_values[i].color.a, + }; + cmd->context->ClearRenderTargetView(rt->rtv, color); + } + } + + rt_render_target *dsvrt = rtGetRenderTarget(info->depth_stencil_buffer); + if (dsvrt) { + RT_ASSERT(dsvrt->IsDepthStencilTarget(), + "Need to provide a valid depth stencil render target"); + dsv = dsvrt->dsv; + + if (info->depth_stencil_buffer_load == RT_PASS_LOAD_MODE_CLEAR) + cmd->context->ClearDepthStencilView( + dsv, + (dsvrt->HasStencilComponent()) ? D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL + : D3D11_CLEAR_DEPTH, + info->depth_stencil_buffer_clear_value.depth_stencil.depth, + static_cast(info->depth_stencil_buffer_clear_value.depth_stencil.stencil)); + } + + cmd->context->OMSetRenderTargets(static_cast(info->color_buffer_count), rtvs, dsv); +} + +extern "C" void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle cmdhandle) { + rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); + if (!RT_VERIFY(cmd)) + return; + if (cmd->annotation) { + cmd->annotation->EndEvent(); + } +} + +extern "C" void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle cmdhandle, + rt_render_target_handle target, + rt_render_target_state state) { + rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); + if (!RT_VERIFY(cmd)) + return; + RT_UNUSED(target); + RT_UNUSED(state); +} + +extern "C" void +RT_RENDERER_API_FN(CmdFlushRenderTargetWrite)(rt_command_buffer_handle cmdhandle, + rt_render_target_handle render_target) { + rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); + if (!RT_VERIFY(cmd)) + return; + RT_UNUSED(render_target); +} diff --git a/src/renderer/dx11/device_objects.hpp b/src/renderer/dx11/device_objects.hpp index fb4f643..dd8bed3 100644 --- a/src/renderer/dx11/device_objects.hpp +++ b/src/renderer/dx11/device_objects.hpp @@ -15,6 +15,12 @@ struct rt_render_target { ID3D11Texture2D *texture; + rt_pixel_format format; + + bool HasStencilComponent() const { + return format == RT_PIXEL_FORMAT_DEPTH24_STENCIL8; + } + bool IsColorRenderTarget() const { RT_ASSERT(!(rtv != nullptr && dsv != nullptr), "A render target should not contain a render target and a depth stencil view"); @@ -34,6 +40,7 @@ struct rt_render_target { struct rt_command_buffer { // Only created once and then re-used. ID3D11DeviceContext1 *context; + ID3DUserDefinedAnnotation *annotation; uint32_t version; rt_command_buffer *next_free; diff --git a/src/renderer/dx11/init.cpp b/src/renderer/dx11/init.cpp index 2676766..25c2512 100644 --- a/src/renderer/dx11/init.cpp +++ b/src/renderer/dx11/init.cpp @@ -112,6 +112,8 @@ extern rt_result InitCommandBufferManagement(); extern void ShutdownCommandBufferManagement(); extern rt_result InitRenderTargetManagement(); extern void ShutdownRenderTargetManagement(); +extern rt_result InitBufferManagement(); +extern void ShutdownBufferManagement(); 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}; @@ -186,6 +188,9 @@ extern "C" rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) if (res != RT_SUCCESS) return res; res = InitRenderTargetManagement(); + if (res != RT_SUCCESS) + return res; + res = InitBufferManagement(); if (res != RT_SUCCESS) return res; @@ -193,6 +198,7 @@ extern "C" rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) } extern "C" void RT_RENDERER_API_FN(Shutdown)(void) { + ShutdownBufferManagement(); ShutdownRenderTargetManagement(); ShutdownCommandBufferManagement(); rtDestroyMutex(g_gpu.context_lock); @@ -262,7 +268,6 @@ void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle handle) { RT_UNUSED(handle); } - rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t count, const rt_gpu_semaphore_info *info, rt_gpu_semaphore_handle *p_semaphores) { @@ -283,7 +288,6 @@ uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle sem) { return 0; } - rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetSwapchainAvailableSemaphore)(void) { return {1, 1}; } @@ -291,28 +295,4 @@ rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetSwapchainAvailableSemaphore)(void) rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void) { return {1, 2}; } - -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); -} } \ No newline at end of file diff --git a/src/renderer/dx11/meson.build b/src/renderer/dx11/meson.build index dc6dc1c..e03fc5f 100644 --- a/src/renderer/dx11/meson.build +++ b/src/renderer/dx11/meson.build @@ -5,6 +5,7 @@ if get_option('build_dx11') 'gpu.hpp', 'buffers.cpp', + 'commands.cpp', 'command_buffers.cpp', 'helpers.cpp', 'init.cpp', diff --git a/src/renderer/dx11/render_targets.cpp b/src/renderer/dx11/render_targets.cpp index d253231..31cfe54 100644 --- a/src/renderer/dx11/render_targets.cpp +++ b/src/renderer/dx11/render_targets.cpp @@ -23,13 +23,17 @@ rt_result InitRenderTargetManagement() { if (!_render_targets) { return RT_OUT_OF_MEMORY; } - + _lock = rtCreateMutex(); if (!_lock) { free(_render_targets); return RT_UNKNOWN_ERROR; } + _render_targets[1].rtv = g_gpu.swap_chain.rtv.Get(); + _render_targets[1].format = RT_PIXEL_FORMAT_B8G8R8A8_SRGB; + _render_targets[1].version = 1; + _first_free = _render_targets + 2; for (int i = 0; i < rt_Dx11MaxRenderTargets.i; ++i) { _render_targets[i].next_free = &_render_targets[i + 1]; @@ -66,6 +70,8 @@ RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_target_info *info) { return RT_INVALID_HANDLE; } + slot->format = info->format; + if (!rtIsDepthFormat(info->format)) { D3D11_TEXTURE2D_DESC tex_desc = {}; tex_desc.Width = info->width; diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 08843b8..956e178 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -123,9 +123,16 @@ RT_DLLEXPORT int rtAssertHandler(const char *expr, const char *msg, const char * } while (0) #define RT_ASSERT_ALWAYS_EVAL(x, msg) RT_ASSERT(x, msg) + +// Asserts if p is "false", evaluates to p +// NOTE that this will evaluate p multiple times! +#define RT_VERIFY(p) \ + ((!p) ? (RT_DEBUGBREAK, rtAssertHandler(#p, "Verify failed", __FILE__, __LINE__), p) : p) + #else -#define RT_ASSERT(x, msg) RT_UNUSED(x) +#define RT_ASSERT(x, msg) RT_UNUSED(x) #define RT_ASSERT_ALWAYS_EVAL(x, msg) (x) +#define RT_VERIFY(p) (p) #endif enum {