From 88da8ec8896913dfe2af338e1576c93685118828 Mon Sep 17 00:00:00 2001 From: Kevin Trogant Date: Sun, 19 May 2024 12:48:50 +0200 Subject: [PATCH] Render a triangle --- assets/shader/static_object.effect | 18 +-- src/app_framework/main_loop.c | 2 +- src/game/main.c | 127 ++++++++++++++++++---- src/gfx/effect.c | 1 + src/gfx/gfx_main.c | 7 +- src/gfx/renderer_api.h | 8 +- src/renderer/common/common_render_graph.c | 21 ++++ src/renderer/common/common_render_graph.h | 5 + src/renderer/dx11/commands.cpp | 41 ++++--- src/renderer/dx11/device_objects.hpp | 1 + src/renderer/dx11/gpu.hpp | 2 + src/renderer/dx11/init.cpp | 3 +- src/renderer/dx11/pipelines.cpp | 23 +++- src/renderer/dx11/render_graph.cpp | 55 +++++++--- src/renderer/dx11/render_targets.cpp | 2 +- src/runtime/rt_math.h | 26 +++-- 16 files changed, 267 insertions(+), 75 deletions(-) diff --git a/assets/shader/static_object.effect b/assets/shader/static_object.effect index fc4ec34..2089f9a 100644 --- a/assets/shader/static_object.effect +++ b/assets/shader/static_object.effect @@ -1,6 +1,6 @@ optimization speed; passes { - pass0 { + forward { vertex { vk BEGIN #include "common.hlsl" @@ -26,6 +26,10 @@ VSOutput VsMain(VSInput input, uint vertexIndex : SV_VertexID) { struct VSInput { + float3 Position : POSITION0; + float3 Normal : NORMAL0; + float3 Tangent : TANGENT0; + float2 TexCoord : TEXCOORD0; }; struct VSOutput @@ -34,7 +38,8 @@ struct VSOutput }; VSOutput VsMain(VSInput input, uint vertexIndex : SV_VertexID) { - VSOutput output = (VSOutput)0; + VSOutput output; + output.Pos = float4(input.Position, 0.1); return output; } END @@ -58,15 +63,12 @@ PSOutput PsMain(void) { dx11 BEGIN struct PSOutput { -float4 Color : SV_TARGET0; + float4 Color : SV_TARGET0; }; PSOutput PsMain(void) { - PSOutput output = (PSOutput)0; - output.Color[0] = 0; - output.Color[1] = 0; - output.Color[2] = 0; - output.Color[3] = 0; + PSOutput output; + output.Color = float4(1, 1, 1, 1); return output; } END diff --git a/src/app_framework/main_loop.c b/src/app_framework/main_loop.c index d40d7f1..1a3374c 100644 --- a/src/app_framework/main_loop.c +++ b/src/app_framework/main_loop.c @@ -5,7 +5,7 @@ #include "gfx/gfx.h" -RT_CVAR_I(rt_MaxFrameLatency, "Maximum latency between update and rendering. Default: 2", 2); +RT_CVAR_I(rt_MaxFrameLatency, "Maximum latency between update and rendering. Default: 2", 1); RT_DLLEXPORT rt_main_loop g_main_loop; diff --git a/src/game/main.c b/src/game/main.c index aac6973..44dfa59 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -1,17 +1,34 @@ #include "runtime/mem_arena.h" #include "runtime/resources.h" +#include "runtime/rt_math.h" #include "runtime/threading.h" #include "gfx/builtin_objects.h" +#include "gfx/effect.h" #include "gfx/gfx.h" #include "gfx/renderer_api.h" -#include "gfx/effect.h" #include "asset_compiler/asset_compiler.h" -void RegisterCVars(void) { - rtRegisterAssetCompilerCVars(); -} +#include + +/* Matches the default vertex layout */ + +typedef struct { + rt_v3 pos; + rt_v3 normal; + rt_v3 tangent; + rt_v2 texcoord; +} rt_vertex; + +typedef struct { + const rt_effect *effect; + rt_buffer_handle vbo; + uint32_t vertex_count; +} rt_demo_renderable; + +static rt_demo_renderable *_renderables; +static unsigned int _renderable_count; static rt_render_graph *_graph; @@ -38,13 +55,17 @@ static rt_result ForwardPassExecute(uint32_t pass_id, bound_pipeline = mesh.pipeline; g_renderer.CmdBindPipeline(cmdbuf, bound_pipeline); } - g_renderer.CmdBindVertexBuffers(cmdbuf, 0, 1, &mesh.vbo, NULL); + uint32_t stride = sizeof(rt_vertex); + g_renderer.CmdBindVertexBuffers(cmdbuf, 0, 1, &mesh.vbo, &stride, NULL); g_renderer.CmdDraw(cmdbuf, 0, mesh.vertex_count); } return RT_SUCCESS; } +void RegisterCVars(void) { + rtRegisterAssetCompilerCVars(); +} /* Called after the runtime has finished its initialization and before entering the main-loop*/ void Init(void) { rtLog("GAME", "Init"); @@ -64,6 +85,13 @@ void Init(void) { .layers = 1, }; builder.AddRenderTarget(builder.obj, &backbuffer); + rt_attachment_info depth = {.name = "depth", + .format = RT_PIXEL_FORMAT_DEPTH24_STENCIL8, + .width = RT_RENDER_TARGET_SIZE_SWAPCHAIN, + .height = RT_RENDER_TARGET_SIZE_SWAPCHAIN, + .samples = 1, + .layers = 1}; + builder.AddRenderTarget(builder.obj, &depth); rt_pass_info forward = {.name = "forward", .flags = RT_PASS_FLAG_EXECUTE_ALWAYS | RT_PASS_FLAG_GRAPHICS}; @@ -74,6 +102,20 @@ void Init(void) { RT_PASS_LOAD_MODE_CLEAR, RT_PASS_WRITE_MODE_STORE, (rt_color){.r = 1.f, .g = 0.f, .b = 1.f, .a = 1.f}); + builder.SetDepthStencilAttachment(builder.obj, + "forward", + "depth", + RT_PASS_LOAD_MODE_CLEAR, + RT_PASS_WRITE_MODE_DISCARD, + (rt_depth_stencil_value){.depth = 1.f, .stencil = 0}); + builder.SetRenderArea( + builder.obj, + "forward", + (rt_rect2){ + .size = {RT_RENDER_TARGET_SIZE_SWAPCHAIN, RT_RENDER_TARGET_SIZE_SWAPCHAIN} + }, + 0.f, + 1.f); builder.SetBackbuffer(builder.obj, "backbuffer"); builder.BindRenderPass(builder.obj, "forward", ForwardPassExecute, NULL); if (builder.Build(builder.obj, &_graph) != RT_SUCCESS) { @@ -83,36 +125,81 @@ void Init(void) { g_renderer.DestroyRenderGraphBuilder(&builder); - const rt_effect *effect; - if (rtLoadEffect(rtGetResourceID("assets/shader/static_object.effect"), &effect) != - RT_SUCCESS) { - rtReportError("GAME", "Oh noo..."); - } + /* Create a simple "scene" */ + _renderable_count = 1; + _renderables = calloc(_renderable_count, sizeof(rt_demo_renderable)); + RT_VERIFY(_renderables); + for (unsigned int i = 0; i < _renderable_count; ++i) { - const rt_effect *effect2; - if (rtLoadEffect(rtGetResourceID("assets/shader/static_object.effect"), &effect2) != - RT_SUCCESS) { - rtReportError("GAME", "Oh noo..."); - } + rt_vertex tri[3] = { + {.pos = {0.f, 0.5f, 0.f}}, + {.pos = {-.5f, -.5f, 0.f}}, + {.pos = {.5f, -.5f, 0.f}}, + }; - rtReleaseEffect(effect); - rtReleaseEffect(effect2); + rt_buffer_handle vbo; + rt_buffer_info vbo_info = { + .data = tri, + .size = sizeof(tri), + .type = RT_BUFFER_TYPE_VERTEX, + .usage = RT_BUFFER_USAGE_STATIC, + }; + if (g_renderer.CreateBuffers(1, &vbo_info, &vbo) != RT_SUCCESS) { + rtReportError("GAME", "Oh noo..."); + return; + } + _renderables[i].vbo = vbo; + _renderables[i].vertex_count = 3; + + const rt_effect *effect; + if (rtLoadEffect(rtGetResourceID("assets/shader/static_object.effect"), &effect) != + RT_SUCCESS) { + rtReportError("GAME", "Oh noo..."); + return; + } + _renderables[i].effect = effect; + } } /* Called after exiting the main-loop and before the runtime starts its shutdown */ void Shutdown(void) { rtLog("GAME", "Shutdown"); + + for (unsigned int i = 0; i < _renderable_count; ++i) { + rtReleaseEffect(_renderables[i].effect); + g_renderer.DestroyBuffers(1, &_renderables[i].vbo); + } + rtShutdownAssetCompiler(); } +static void DrawRenderables(unsigned int frame_id) { + rt_create_render_view_result main_view_res = + rtCreateRenderView(&g_builtin_render_object_types.render_mesh, 1, frame_id); + if (!main_view_res.ok) + return; + rt_render_view main_view = main_view_res.view; + const rt_effect_pass *pass = &_renderables[0].effect->passes[0]; + + for (unsigned int i = 0; i < _renderable_count; ++i) { + pass = &_renderables[i].effect->passes[0]; + rt_render_mesh mesh; + mesh.vbo = _renderables[i].vbo; + mesh.vertex_count = _renderables[i].vertex_count; + mesh.pipeline = pass->pipeline; + rtPushRenderObjectToView(&main_view, g_builtin_render_object_types.render_mesh, &mesh); + } + rtSubmitRenderView(main_view, _graph, pass->pass_id, frame_id); +} + // Question; How do we move data from update to render. // This is where we could fill the render views, but that would // mean double/triple buffering the views void Update(unsigned int frame_id) { - RT_UNUSED(frame_id); + DrawRenderables(frame_id); } void Render(unsigned int frame_id) { - g_renderer.ResetRenderGraph(_graph); - g_renderer.ExecuteRenderGraph(_graph); + g_renderer.ExecuteRenderGraph(_graph, frame_id); + g_renderer.ResetRenderGraph(_graph, frame_id); } \ No newline at end of file diff --git a/src/gfx/effect.c b/src/gfx/effect.c index f657c41..f9f2dd6 100644 --- a/src/gfx/effect.c +++ b/src/gfx/effect.c @@ -257,3 +257,4 @@ RT_DLLEXPORT void rtReleaseEffect(const rt_effect *effect) { rtUnlockWrite(&_cache.lock); } } + diff --git a/src/gfx/gfx_main.c b/src/gfx/gfx_main.c index 4ecb388..5a26a46 100644 --- a/src/gfx/gfx_main.c +++ b/src/gfx/gfx_main.c @@ -56,12 +56,12 @@ extern void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t, rt_buffer_handle *); extern rt_render_graph_builder RT_RENDERER_API_FN(CreateRenderGraphBuilder)(void); extern void RT_RENDERER_API_FN(DestroyRenderGraphBuilder)(rt_render_graph_builder *); -extern rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *); +extern rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *, unsigned int); extern void RT_RENDERER_API_FN(SubmitRenderView)(rt_render_graph *render_graph, uint32_t pass_id, rt_render_view view, unsigned int frame_id); -extern void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph); +extern void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph, unsigned int frame_id); extern void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle, const rt_cmd_begin_pass_info *); @@ -76,7 +76,8 @@ extern void RT_RENDERER_API_FN(CmdBindVertexBuffers)(rt_command_buffer_handle, uint32_t, uint32_t, const rt_buffer_handle *, - const uint64_t *); + const uint32_t *, + const uint32_t *); extern void RT_RENDERER_API_FN(CmdDraw)(rt_command_buffer_handle, uint32_t, uint32_t); #endif diff --git a/src/gfx/renderer_api.h b/src/gfx/renderer_api.h index c7bdab7..8e424f5 100644 --- a/src/gfx/renderer_api.h +++ b/src/gfx/renderer_api.h @@ -272,6 +272,7 @@ typedef struct { rt_pass_load_mode load, rt_pass_write_mode write, rt_depth_stencil_value clear_value); + void (*SetRenderArea)(void *obj, const char *pass_name, rt_rect2 area, float min_depth, float max_depth); void (*BindRenderPass)(void *obj, const char *pass_name, rt_execute_render_pass_fn *execute_fn, @@ -299,10 +300,10 @@ typedef void rt_destroy_buffers_fn(uint32_t count, rt_buffer_handle *buffers); typedef rt_render_graph_builder rt_create_render_graph_builder_fn(void); typedef void rt_destroy_render_graph_builder_fn(rt_render_graph_builder *builder); -typedef rt_result rt_execute_render_graph_fn(rt_render_graph *rgraph); +typedef rt_result rt_execute_render_graph_fn(rt_render_graph *rgraph, unsigned int frame_id); typedef void rt_submit_render_view_fn(rt_render_graph *render_graph, uint32_t pass_id, rt_render_view view, unsigned int frame_id); -typedef void rt_reset_render_graph_fn(rt_render_graph *graph); +typedef void rt_reset_render_graph_fn(rt_render_graph *graph, unsigned int frame_id); typedef void rt_cmd_begin_pass_fn(rt_command_buffer_handle cmdbuf, const rt_cmd_begin_pass_info *info); @@ -317,7 +318,8 @@ typedef void rt_cmd_bind_vertex_buffers_fn(rt_command_buffer_handle cmd, uint32_t first_binding, uint32_t count, const rt_buffer_handle *buffers, - const uint64_t *offsets); + const uint32_t *strides, + const uint32_t *offsets); typedef void rt_cmd_draw_fn(rt_command_buffer_handle cmdbuf, uint32_t first_vertex, uint32_t vertex_count); diff --git a/src/renderer/common/common_render_graph.c b/src/renderer/common/common_render_graph.c index 0899a81..7d917f4 100644 --- a/src/renderer/common/common_render_graph.c +++ b/src/renderer/common/common_render_graph.c @@ -33,6 +33,10 @@ typedef struct rt_pass_build_info { void *userdata; rt_execute_render_pass_fn *Execute; + rt_rect2 render_area; + float min_depth; + float max_depth; + uint32_t color_attachments[MAX_COLOR_ATTACHMENTS_PER_PASS]; rt_color color_attachment_clear_values[MAX_COLOR_ATTACHMENTS_PER_PASS]; rt_pass_load_mode color_attachment_loads[MAX_COLOR_ATTACHMENTS_PER_PASS]; @@ -256,6 +260,19 @@ static void SetDepthStencilAttachment(void *_obj, pass_name); } +static void SetRenderArea(void *_obj, const char *pass_name, rt_rect2 area, float min_depth, float max_depth) { + rt_render_graph_builder_obj *obj = _obj; + for (uint32_t i = 0; i < obj->pass_count; ++i) { + if (strcmp(obj->passes[i].name, pass_name) == 0) { + obj->passes[i].render_area = area; + obj->passes[i].min_depth = min_depth; + obj->passes[i].max_depth = max_depth; + return; + } + } + rtLog("ren", "Tried to bind unknown render pass %s.", pass_name); +} + static void BindRenderPass(void *_obj, const char *pass_name, rt_execute_render_pass_fn *execute_fn, @@ -732,6 +749,9 @@ static rt_render_graph *CreateRenderGraph(rt_render_graph_builder_obj *obj, graph->passes[i].first_wait = 0; graph->passes[i].wait_count = 0; graph->passes[i].execution_level = execution_levels[passidx]; + graph->passes[i].render_area = obj->passes[passidx].render_area; + graph->passes[i].min_depth = obj->passes[passidx].min_depth; + graph->passes[i].max_depth = obj->passes[passidx].max_depth; graph->passes[i].depth_stencil = (obj->passes[i].depth_stencil_attachment != UINT_MAX) @@ -843,6 +863,7 @@ rtCreateRenderGraphBuilder(const rt_render_graph_builder_platform_callbacks *pla .AddColorOutput = AddColorOutput, .AddSampledInput = AddSampledInput, .SetDepthStencilAttachment = SetDepthStencilAttachment, + .SetRenderArea = SetRenderArea, .BindRenderPass = BindRenderPass, .Build = Build, }; diff --git a/src/renderer/common/common_render_graph.h b/src/renderer/common/common_render_graph.h index 4c4614f..2e5227e 100644 --- a/src/renderer/common/common_render_graph.h +++ b/src/renderer/common/common_render_graph.h @@ -34,6 +34,11 @@ typedef struct { /* Used for debug output */ const char *name; + /* Viewport info */ + rt_rect2 render_area; + float min_depth; + float max_depth; + /* Render targets */ rt_render_target_handle *color_outputs; rt_color *color_clear_values; diff --git a/src/renderer/dx11/commands.cpp b/src/renderer/dx11/commands.cpp index 8f68772..f7fba86 100644 --- a/src/renderer/dx11/commands.cpp +++ b/src/renderer/dx11/commands.cpp @@ -57,6 +57,18 @@ extern "C" void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmdhan } cmd->context->OMSetRenderTargets(static_cast(info->color_buffer_count), rtvs, dsv); + + D3D11_VIEWPORT viewport; + viewport.TopLeftX = static_cast(info->render_area.offset.x); + viewport.TopLeftY = static_cast(info->render_area.offset.y); + viewport.Width = static_cast(info->render_area.size.x); + viewport.Height = static_cast(info->render_area.size.y); + viewport.MinDepth = 0.f; + viewport.MaxDepth = 1.f; + cmd->context->RSSetViewports(1, &viewport); + + // We currently only support triangles, so here is a good place to set this + cmd->context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } extern "C" void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle cmdhandle) { @@ -101,16 +113,20 @@ extern "C" void RT_RENDERER_API_FN(CmdBindPipeline)(rt_command_buffer_handle cmd return; } - cmd->context->IASetInputLayout(pipeline->input_layout); - cmd->context->VSSetShader(pipeline->vertex_shader, nullptr, 0); - cmd->context->PSSetShader(pipeline->pixel_shader, nullptr, 0); + auto context = cmd->context; + context->IASetInputLayout(pipeline->input_layout); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->VSSetShader(pipeline->vertex_shader, nullptr, 0); + context->PSSetShader(pipeline->pixel_shader, nullptr, 0); + context->RSSetState(pipeline->rasterizer_state); } extern "C" void RT_RENDERER_API_FN(CmdBindVertexBuffers)(rt_command_buffer_handle cmdhandle, uint32_t first_binding, uint32_t count, const rt_buffer_handle *buffers, - const uint64_t *_offsets) { + const uint32_t *_strides, + const uint32_t *_offsets) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdhandle); if (!RT_VERIFY(cmd)) return; @@ -119,18 +135,15 @@ extern "C" void RT_RENDERER_API_FN(CmdBindVertexBuffers)(rt_command_buffer_handl return; ID3D11Buffer **vbos = RT_ARENA_PUSH_ARRAY(temp.arena, ID3D11Buffer *, count); - UINT *offsets = nullptr; + static_assert(sizeof(UINT) == sizeof(uint32_t)); + const UINT *offsets = _offsets; + const UINT *strides = _strides; - if (!vbos) + if (!vbos || !strides) goto out; - if (_offsets) { - offsets = RT_ARENA_PUSH_ARRAY(temp.arena, UINT, count); - if (!offsets) - goto out; - for (uint32_t i = 0; i < count; ++i) { - offsets[i] = static_cast(_offsets[i]); - } + if (!offsets) { + offsets = RT_ARENA_PUSH_ARRAY_ZERO(temp.arena, UINT, count); } for (uint32_t i = 0; i < count; ++i) { @@ -139,7 +152,7 @@ extern "C" void RT_RENDERER_API_FN(CmdBindVertexBuffers)(rt_command_buffer_handl vbos[i] = buffer->buffer; } - cmd->context->IASetVertexBuffers(first_binding, count, vbos, nullptr, offsets); + cmd->context->IASetVertexBuffers(first_binding, count, vbos, strides, offsets); out: rtReturnTemporaryArena(temp); diff --git a/src/renderer/dx11/device_objects.hpp b/src/renderer/dx11/device_objects.hpp index 5d1d527..38324db 100644 --- a/src/renderer/dx11/device_objects.hpp +++ b/src/renderer/dx11/device_objects.hpp @@ -62,6 +62,7 @@ struct rt_pipeline { ID3D11ComputeShader *compute_shader; + ID3D11RasterizerState *rasterizer_state; rt_pipeline *next_free; uint32_t version; diff --git a/src/renderer/dx11/gpu.hpp b/src/renderer/dx11/gpu.hpp index 43595bc..26f96c8 100644 --- a/src/renderer/dx11/gpu.hpp +++ b/src/renderer/dx11/gpu.hpp @@ -9,6 +9,8 @@ #include "runtime/threading.h" #include "gfx/renderer_api.h" +#define RT_DX11_MAX_FRAMES_IN_FLIGHT 2 + // Smart pointer for COM-Objects template using ComPtr = Microsoft::WRL::ComPtr; diff --git a/src/renderer/dx11/init.cpp b/src/renderer/dx11/init.cpp index 22de56c..93576d2 100644 --- a/src/renderer/dx11/init.cpp +++ b/src/renderer/dx11/init.cpp @@ -209,8 +209,7 @@ extern "C" void RT_RENDERER_API_FN(Shutdown)(void) { } extern "C" unsigned int RT_RENDERER_API_FN(GetMaxFramesInFlight)(void) { - // TODO: Verify this. - return 1; + return RT_DX11_MAX_FRAMES_IN_FLIGHT; } extern "C" void RT_RENDERER_API_FN(BeginFrame)(unsigned int frame_id) { diff --git a/src/renderer/dx11/pipelines.cpp b/src/renderer/dx11/pipelines.cpp index 2b84e0a..8b4cc5e 100644 --- a/src/renderer/dx11/pipelines.cpp +++ b/src/renderer/dx11/pipelines.cpp @@ -120,7 +120,6 @@ extern "C" rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipel {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; /* clang-format on */ - if (FAILED(g_gpu.device->CreateInputLayout(default_layout, RT_ARRAY_COUNT(default_layout), bytecode, @@ -180,6 +179,28 @@ extern "C" rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipel } } + // TODO: Effects should specifiy the rasterizer state + // DX11 only supports up to 4096 rasterizer state objects. + // We could cache these and only create the distinct objects. + D3D11_RASTERIZER_DESC rasterizer_desc; + rasterizer_desc.FillMode = D3D11_FILL_SOLID; + rasterizer_desc.CullMode = D3D11_CULL_NONE; + rasterizer_desc.FrontCounterClockwise = TRUE; + rasterizer_desc.DepthBias = 0; + rasterizer_desc.DepthBiasClamp = 0.f; + rasterizer_desc.SlopeScaledDepthBias = 0.f; + rasterizer_desc.DepthClipEnable = TRUE; + rasterizer_desc.ScissorEnable = FALSE; + rasterizer_desc.MultisampleEnable = TRUE; + rasterizer_desc.AntialiasedLineEnable = TRUE; + if (FAILED(g_gpu.device->CreateRasterizerState(&rasterizer_desc, &slot->rasterizer_state))) { + rtReportError("dx11", "Rasterizer state creation failed"); + auto lg = rtAutoLock(_lock); + slot->next_free = _first_free; + _first_free = slot; + return RT_INVALID_HANDLE; + } + slot->version = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION; uint32_t index = static_cast(slot - _pipelines); return {slot->version, index}; diff --git a/src/renderer/dx11/render_graph.cpp b/src/renderer/dx11/render_graph.cpp index 54a2ce4..b2b0075 100644 --- a/src/renderer/dx11/render_graph.cpp +++ b/src/renderer/dx11/render_graph.cpp @@ -8,9 +8,9 @@ static constexpr unsigned int MAX_SUBMITTED_VIEWS_PER_PASS = 4; struct rt_pass_runtime_data { - rt_render_view views[MAX_SUBMITTED_VIEWS_PER_PASS]; - uint32_t view_count; - unsigned int views_frame_id; + rt_render_view views[RT_DX11_MAX_FRAMES_IN_FLIGHT][MAX_SUBMITTED_VIEWS_PER_PASS]; + uint32_t view_count[RT_DX11_MAX_FRAMES_IN_FLIGHT]; + unsigned int views_frame_id[RT_DX11_MAX_FRAMES_IN_FLIGHT]; }; static rt_render_target_handle CreateRenderTarget(const rt_physical_render_target_info *rtinfo) { @@ -49,28 +49,33 @@ extern "C" void RT_RENDERER_API_FN(SubmitRenderView)(rt_render_graph *render_gra rt_render_pass *pass = &render_graph->passes[i]; rt_pass_runtime_data *runtime_data = reinterpret_cast(pass->runtime_data); - RT_ASSERT(runtime_data->views_frame_id == frame_id || runtime_data->views_frame_id == 0, + unsigned int frame_slot = frame_id % RT_DX11_MAX_FRAMES_IN_FLIGHT; + RT_ASSERT(runtime_data->views_frame_id[frame_slot] == frame_id || + runtime_data->views_frame_id[frame_slot] == 0, "Tried to submit a view for a not-current frame."); - if (!RT_VERIFY(runtime_data->view_count < MAX_SUBMITTED_VIEWS_PER_PASS)) + if (!RT_VERIFY(runtime_data->view_count[frame_slot] < MAX_SUBMITTED_VIEWS_PER_PASS)) return; - runtime_data->views[runtime_data->view_count++] = view; - runtime_data->views_frame_id = frame_id; + runtime_data->views[frame_slot][runtime_data->view_count[frame_slot]++] = view; + runtime_data->views_frame_id[frame_slot] = frame_id; } } } -extern "C" void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph) { +extern "C" void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph, + unsigned int frame_id) { + unsigned int frame_slot = frame_id % RT_DX11_MAX_FRAMES_IN_FLIGHT; for (uint32_t i = 0; i < graph->pass_count; ++i) { rt_pass_runtime_data *runtime_data = reinterpret_cast(graph->passes[i].runtime_data); #ifdef RT_DEBUG - memset(runtime_data->views, 0, sizeof(runtime_data->views)); + memset(runtime_data->views[frame_slot], 0, sizeof(runtime_data->views[frame_slot])); #endif - runtime_data->view_count = 0; + runtime_data->view_count[frame_slot] = 0; + runtime_data->views_frame_id[frame_slot] = 0; } } -static rt_result ExecutePass(rt_render_pass *pass, rt_command_buffer_handle cmdbuf_handle) { +static rt_result ExecutePass(rt_render_pass *pass, rt_command_buffer_handle cmdbuf_handle, unsigned int frame_id) { rt_command_buffer *cmd = rtGetCommandBuffer(cmdbuf_handle); if (!RT_VERIFY(cmd)) return RT_INVALID_VALUE; @@ -120,13 +125,33 @@ static rt_result ExecutePass(rt_render_pass *pass, rt_command_buffer_handle cmdb cmd->context->OMSetRenderTargets(static_cast(pass->color_output_count), rtvs, dsv); + D3D11_VIEWPORT viewport; + viewport.TopLeftX = pass->render_area.offset.x; + viewport.TopLeftY = pass->render_area.offset.y; + viewport.Width = pass->render_area.size.x; + viewport.Height = pass->render_area.size.y; + viewport.MinDepth = pass->min_depth; + viewport.MaxDepth = pass->max_depth; + + if (viewport.Width == 0 || viewport.Height == 0) { + DXGI_SWAP_CHAIN_DESC desc; + g_gpu.swap_chain.swap_chain->GetDesc(&desc); + if (viewport.Width == 0) + viewport.Width = static_cast(desc.BufferDesc.Width); + if (viewport.Height == 0) + viewport.Height = static_cast(desc.BufferDesc.Height); + } + + cmd->context->RSSetViewports(1, &viewport); + auto runtime_data = reinterpret_cast(pass->runtime_data); RT_VERIFY(runtime_data); + unsigned int frame_slot = frame_id % RT_DX11_MAX_FRAMES_IN_FLIGHT; rt_result res = RT_VERIFY(pass->Execute)(pass->id, cmdbuf_handle, - runtime_data->views, - runtime_data->view_count, + runtime_data->views[frame_slot], + runtime_data->view_count[frame_slot], pass->user_data); if (cmd->annotation) { @@ -148,7 +173,7 @@ static bool IsCopyResourcePossible(const rt_render_target *backbuffer) { scd.SampleDesc.Count == td.SampleDesc.Count && scd.BufferDesc.Format == td.Format; } -extern "C" rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *render_graph) { +extern "C" rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *render_graph, unsigned int frame_id) { rt_temp_arena temp = rtGetTemporaryArena(NULL, 0); if (!temp.arena) return RT_OUT_OF_MEMORY; @@ -165,7 +190,7 @@ extern "C" rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *ren for (uint32_t i = 0; i < render_graph->pass_count; ++i) { rt_render_pass *pass = &render_graph->passes[i]; - res = ExecutePass(pass, cmdbufs[i]); + res = ExecutePass(pass, cmdbufs[i], frame_id); if (res != RT_SUCCESS) break; } diff --git a/src/renderer/dx11/render_targets.cpp b/src/renderer/dx11/render_targets.cpp index 5ca9678..59cba72 100644 --- a/src/renderer/dx11/render_targets.cpp +++ b/src/renderer/dx11/render_targets.cpp @@ -135,7 +135,7 @@ rt_render_target_handle rtCreateRenderTarget(const rt_render_target_create_info tex_desc.SampleDesc.Count = 1; tex_desc.SampleDesc.Quality = 0; tex_desc.Usage = D3D11_USAGE_DEFAULT; // read and write - tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; tex_desc.CPUAccessFlags = 0; // none tex_desc.MiscFlags = 0; if (FAILED(g_gpu.device->CreateTexture2D(&tex_desc, nullptr, &slot->texture))) { diff --git a/src/runtime/rt_math.h b/src/runtime/rt_math.h index 821eb5f..aebcee4 100644 --- a/src/runtime/rt_math.h +++ b/src/runtime/rt_math.h @@ -10,13 +10,6 @@ #pragma warning(disable : 4201) /* anonymous struct */ #endif -struct vec2 { - struct xy { - float x; - float y; - }; -}; - /* 2d vector */ typedef union { struct { @@ -34,6 +27,25 @@ typedef union { int e[2]; } rt_v2i; +/* 3d vector */ +typedef union { + struct { + float x; + float y; + float z; + }; + float e[3]; +} rt_v3; + +typedef union { + struct { + int x; + int y; + int z; + }; + int e[3]; +} rt_v3i; + /* 2d rectangle defined by its upper left corner and its size. */ typedef struct { rt_v2 offset;