give passes views instead of lists
A view is a collection of lists. This is useful for a shadow mapping pass that generates more than one shadow map. Each view would create lists of objects visible in one shadow map.
This commit is contained in:
parent
6052f35485
commit
5d988d15b7
@ -14,8 +14,8 @@ void RegisterCVars(void) {
|
||||
static rt_render_graph *_graph;
|
||||
|
||||
static rt_result ForwardPassExecute(rt_command_buffer_handle cmdbuf,
|
||||
const rt_render_list *lists,
|
||||
uint32_t list_count,
|
||||
const rt_render_view *views,
|
||||
uint32_t view_count,
|
||||
void *userdata) {
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
@ -49,7 +49,10 @@ void Init(void) {
|
||||
(rt_color){.r = 1.f, .g = 0.f, .b = 1.f, .a = 1.f});
|
||||
builder.SetBackbuffer(builder.obj, "backbuffer");
|
||||
builder.BindRenderPass(builder.obj, "forward", ForwardPassExecute, NULL);
|
||||
builder.Build(builder.obj, &_graph);
|
||||
if (builder.Build(builder.obj, &_graph) != RT_SUCCESS) {
|
||||
rtReportError("GAME", "Failed to build the render graph.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_renderer.DestroyRenderGraphBuilder(&builder);
|
||||
}
|
||||
@ -65,5 +68,6 @@ void Update(unsigned int frame_id) {
|
||||
}
|
||||
|
||||
void Render(unsigned int frame_id) {
|
||||
g_renderer.ResetRenderGraph(_graph);
|
||||
g_renderer.ExecuteRenderGraph(_graph);
|
||||
}
|
@ -26,6 +26,9 @@ RT_CVAR_S(rt_Renderer,
|
||||
"Select the render backend. Available options: [vk, null], Default: vk",
|
||||
"dx11");
|
||||
|
||||
extern rt_cvar rt_RenderViewArenaSize;
|
||||
extern rt_cvar rt_RenderListPoolSize;
|
||||
|
||||
#ifdef RT_STATIC_LIB
|
||||
extern void RT_RENDERER_API_FN(RegisterCVars)(void);
|
||||
extern rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *);
|
||||
@ -54,6 +57,10 @@ 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 void RT_RENDERER_API_FN(SubmitRenderView)(rt_render_graph *render_graph,
|
||||
uint32_t pass_id,
|
||||
rt_render_view view);
|
||||
extern void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph);
|
||||
|
||||
extern void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle,
|
||||
const rt_cmd_begin_pass_info *);
|
||||
@ -75,6 +82,9 @@ extern void RT_RENDERER_API_FN(CmdDraw)(rt_command_buffer_handle, uint32_t, uint
|
||||
extern rt_result InitRenderLists(void);
|
||||
extern void ShutdownRenderLists(void);
|
||||
extern void ResetRenderLists(void);
|
||||
extern rt_result InitRenderViews(void);
|
||||
extern void ShutdownRenderViews(void);
|
||||
extern void ResetRenderViews(void);
|
||||
|
||||
static bool LoadRenderer(void) {
|
||||
|
||||
@ -109,6 +119,8 @@ static bool LoadRenderer(void) {
|
||||
RETRIEVE_SYMBOL(CreateRenderGrapbuilder, rt_create_render_graph_builder_fn);
|
||||
RETRIEVE_SYMBOL(DestroyRenderGraphBuilder, rt_destroy_render_graph_builder_fn);
|
||||
RETRIEVE_SYMBOL(ExecuteRenderGraph, rt_execute_render_graph_fn);
|
||||
RETRIEVE_SYMBOL(SubmitRenderView, rt_submit_render_view_fn);
|
||||
RETRIEVE_SYMBOL(ResetRenderGraph, rt_reset_render_graph_fn);
|
||||
RETRIEVE_SYMBOL(CmdBeginPass, rt_cmd_begin_pass_fn);
|
||||
RETRIEVE_SYMBOL(CmdEndPass, rt_cmd_end_pass_fn);
|
||||
RETRIEVE_SYMBOL(CmdTransitionRenderTarget, rt_cmd_transition_render_target_fn);
|
||||
@ -140,6 +152,8 @@ static bool LoadRenderer(void) {
|
||||
g_renderer.CreateRenderGraphBuilder = &rtRenCreateRenderGraphBuilder;
|
||||
g_renderer.DestroyRenderGraphBuilder = &rtRenDestroyRenderGraphBuilder;
|
||||
g_renderer.ExecuteRenderGraph = &rtRenExecuteRenderGraph;
|
||||
g_renderer.SubmitRenderView = &rtRenSubmitRenderView;
|
||||
g_renderer.ResetRenderGraph = &rtRenResetRenderGraph;
|
||||
g_renderer.CmdBeginPass = &rtRenCmdBeginPass;
|
||||
g_renderer.CmdEndPass = &rtRenCmdEndPass;
|
||||
g_renderer.CmdTransitionRenderTarget = &rtRenCmdTransitionRenderTarget;
|
||||
@ -162,6 +176,8 @@ RT_DLLEXPORT void rtRegisterRendererCVars(void) {
|
||||
|
||||
RT_DLLEXPORT rt_result rtInitGFX(rt_renderer_init_info *renderer_info) {
|
||||
rtRegisterCVAR(&rt_Renderer);
|
||||
rtRegisterCVAR(&rt_RenderViewArenaSize);
|
||||
rtRegisterCVAR(&rt_RenderListPoolSize);
|
||||
|
||||
if (!_renderer_loaded) {
|
||||
if (!LoadRenderer())
|
||||
@ -177,10 +193,14 @@ RT_DLLEXPORT rt_result rtInitGFX(rt_renderer_init_info *renderer_info) {
|
||||
if ((result = InitRenderLists()) != RT_SUCCESS)
|
||||
return result;
|
||||
|
||||
if ((result = InitRenderViews()) != RT_SUCCESS)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RT_DLLEXPORT void rtShutdownGFX(void) {
|
||||
ShutdownRenderViews();
|
||||
ShutdownRenderLists();
|
||||
g_renderer.Shutdown();
|
||||
}
|
||||
@ -192,4 +212,5 @@ RT_DLLEXPORT void rtBeginGFXFrame(unsigned int frame_id) {
|
||||
RT_DLLEXPORT void rtEndGFXFrame(unsigned int frame_id) {
|
||||
g_renderer.EndFrame(frame_id);
|
||||
ResetRenderLists();
|
||||
ResetRenderViews();
|
||||
}
|
||||
|
@ -6,11 +6,14 @@ gfx_lib = library('rtgfx',
|
||||
'gfx.h',
|
||||
'renderer_api.h',
|
||||
'render_list.h',
|
||||
'render_view.h',
|
||||
|
||||
'builtin_objects.c',
|
||||
'effect.c',
|
||||
'gfx_main.c',
|
||||
'render_list.c',
|
||||
'render_view.c',
|
||||
|
||||
# Contrib Sources
|
||||
dependencies : gfx_deps,
|
||||
include_directories : engine_incdir,
|
||||
|
77
src/gfx/render_view.c
Normal file
77
src/gfx/render_view.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "render_view.h"
|
||||
#include "renderer_api.h"
|
||||
|
||||
#include "runtime/config.h"
|
||||
#include "runtime/mem_arena.h"
|
||||
#include "runtime/threading.h"
|
||||
|
||||
RT_CVAR_I(rt_RenderViewArenaSize,
|
||||
"Size of the memory arena used for allocating render views. Default: 1 MB",
|
||||
RT_MB(1));
|
||||
|
||||
static rt_arena _view_arena;
|
||||
static rt_mutex *_view_lock;
|
||||
|
||||
rt_result InitRenderViews(void) {
|
||||
rt_create_arena_result arena_res = rtCreateArena(NULL, (size_t)rt_RenderViewArenaSize.i);
|
||||
if (!arena_res.ok)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
_view_arena = arena_res.arena;
|
||||
_view_lock = rtCreateMutex();
|
||||
if (!_view_lock) {
|
||||
rtReleaseArena(&_view_arena);
|
||||
return RT_UNKNOWN_ERROR;
|
||||
}
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
void ShutdownRenderViews(void) {
|
||||
rtDestroyMutex(_view_lock);
|
||||
rtReleaseArena(&_view_arena);
|
||||
}
|
||||
|
||||
void ResetRenderViews(void) {
|
||||
rtArenaClear(&_view_arena);
|
||||
}
|
||||
|
||||
RT_DLLEXPORT rt_create_render_view_result rtCreateRenderView(const rt_render_object_type *types,
|
||||
uint32_t type_count) {
|
||||
|
||||
#ifdef RT_DEBUG
|
||||
for (uint32_t i = 0; i < type_count - 1; ++i) {
|
||||
for (uint32_t j = i + 1; j < type_count; ++j) {
|
||||
RT_ASSERT(types[i] != types[j], "Duplicate render list type detected.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t size = type_count * (sizeof(rt_render_list) + sizeof(rt_render_list));
|
||||
rtLockMutex(_view_lock);
|
||||
void *storage = rtArenaPush(&_view_arena, size);
|
||||
rtUnlockMutex(_view_lock);
|
||||
if (!storage) {
|
||||
return (rt_create_render_view_result){
|
||||
.ok = false,
|
||||
};
|
||||
}
|
||||
|
||||
rt_render_view view;
|
||||
view.lists = storage;
|
||||
view.list_types = (rt_render_object_type *)(view.lists + type_count);
|
||||
view.list_count = type_count;
|
||||
return (rt_create_render_view_result){.ok = true, .view = view};
|
||||
}
|
||||
|
||||
RT_DLLEXPORT bool
|
||||
rtPushRenderObjectToView(rt_render_view *view, rt_render_object_type type, const void *object) {
|
||||
for (uint32_t i = 0; i < view->list_count; ++i) {
|
||||
if (view->list_types[i] == type)
|
||||
return rtPushRenderListEntry(&view->lists[i], object);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RT_DLLEXPORT void
|
||||
rtSubmitRenderView(rt_render_view view, rt_render_graph *render_graph, uint32_t pass_id) {
|
||||
g_renderer.SubmitRenderView(render_graph, pass_id, view);
|
||||
}
|
39
src/gfx/render_view.h
Normal file
39
src/gfx/render_view.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef RT_GFX_RENDER_VIEW_H
|
||||
#define RT_GFX_RENDER_VIEW_H
|
||||
|
||||
/* A render view acts as a container of one or more render lists.
|
||||
* Each view is processed by exactly one pass. */
|
||||
|
||||
#include "render_list.h"
|
||||
|
||||
typedef struct rt_render_graph_s rt_render_graph;
|
||||
|
||||
typedef struct {
|
||||
rt_render_list *lists;
|
||||
rt_render_object_type *list_types;
|
||||
uint32_t list_count;
|
||||
} rt_render_view;
|
||||
|
||||
typedef struct {
|
||||
bool ok;
|
||||
rt_render_view view;
|
||||
} rt_create_render_view_result;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
RT_DLLEXPORT rt_create_render_view_result rtCreateRenderView(const rt_render_object_type *types,
|
||||
uint32_t type_count);
|
||||
|
||||
RT_DLLEXPORT bool
|
||||
rtPushRenderObjectToView(rt_render_view *view, rt_render_object_type type, const void *object);
|
||||
|
||||
RT_DLLEXPORT void
|
||||
rtSubmitRenderView(rt_render_view view, rt_render_graph *render_graph, uint32_t pass_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "gfx.h"
|
||||
#include "render_list.h"
|
||||
#include "render_view.h"
|
||||
|
||||
#include "runtime/resources.h"
|
||||
#include "runtime/rt_math.h"
|
||||
@ -242,7 +243,10 @@ typedef struct {
|
||||
} rt_pass_info;
|
||||
|
||||
typedef struct rt_render_graph_s rt_render_graph;
|
||||
typedef rt_result rt_execute_render_pass_fn(rt_command_buffer_handle cmdbuf, const rt_render_list *render_lists, unsigned int render_list_count, void *userdata);
|
||||
typedef rt_result rt_execute_render_pass_fn(rt_command_buffer_handle cmdbuf,
|
||||
const rt_render_view *views,
|
||||
unsigned int view_count,
|
||||
void *userdata);
|
||||
|
||||
typedef struct {
|
||||
void *obj;
|
||||
@ -252,7 +256,12 @@ typedef struct {
|
||||
void (*SetBackbuffer)(void *obj, const char *rt_name);
|
||||
|
||||
void (*AddRenderPass)(void *obj, const rt_pass_info *info);
|
||||
void (*AddColorOutput)(void *obj, const char *pass_name, const char *rt_name, rt_pass_load_mode load, rt_pass_write_mode write, rt_color clear_color);
|
||||
void (*AddColorOutput)(void *obj,
|
||||
const char *pass_name,
|
||||
const char *rt_name,
|
||||
rt_pass_load_mode load,
|
||||
rt_pass_write_mode write,
|
||||
rt_color clear_color);
|
||||
void (*AddSampledInput)(void *obj, const char *pass_name, const char *rt_name);
|
||||
void (*SetDepthStencilAttachment)(void *obj,
|
||||
const char *pass_name,
|
||||
@ -260,12 +269,14 @@ typedef struct {
|
||||
rt_pass_load_mode load,
|
||||
rt_pass_write_mode write,
|
||||
rt_depth_stencil_value clear_value);
|
||||
void (*BindRenderPass)(void *obj, const char *pass_name, rt_execute_render_pass_fn *execute_fn, void *userdata);
|
||||
void (*BindRenderPass)(void *obj,
|
||||
const char *pass_name,
|
||||
rt_execute_render_pass_fn *execute_fn,
|
||||
void *userdata);
|
||||
|
||||
rt_result (*Build)(void *obj, rt_render_graph **p_render_graph);
|
||||
} rt_render_graph_builder;
|
||||
|
||||
|
||||
typedef void rt_register_renderer_cvars_fn(void);
|
||||
typedef rt_result rt_init_renderer_fn(const rt_renderer_init_info *info);
|
||||
typedef void rt_shutdown_renderer_fn(void);
|
||||
@ -286,6 +297,9 @@ 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 void
|
||||
rt_submit_render_view_fn(rt_render_graph *render_graph, uint32_t pass_id, rt_render_view view);
|
||||
typedef void rt_reset_render_graph_fn(rt_render_graph *graph);
|
||||
|
||||
typedef void rt_cmd_begin_pass_fn(rt_command_buffer_handle cmdbuf,
|
||||
const rt_cmd_begin_pass_info *info);
|
||||
@ -301,7 +315,8 @@ typedef void rt_cmd_bind_vertex_buffers_fn(rt_command_buffer_handle cmd,
|
||||
uint32_t count,
|
||||
const rt_buffer_handle *buffers,
|
||||
const uint64_t *offsets);
|
||||
typedef void rt_cmd_draw_fn(rt_command_buffer_handle cmdbuf, uint32_t first_vertex, uint32_t vertex_count);
|
||||
typedef void
|
||||
rt_cmd_draw_fn(rt_command_buffer_handle cmdbuf, uint32_t first_vertex, uint32_t vertex_count);
|
||||
|
||||
typedef struct {
|
||||
rt_register_renderer_cvars_fn *RegisterCVars;
|
||||
@ -321,6 +336,8 @@ typedef struct {
|
||||
rt_create_render_graph_builder_fn *CreateRenderGraphBuilder;
|
||||
rt_destroy_render_graph_builder_fn *DestroyRenderGraphBuilder;
|
||||
rt_execute_render_graph_fn *ExecuteRenderGraph;
|
||||
rt_submit_render_view_fn *SubmitRenderView;
|
||||
rt_reset_render_graph_fn *ResetRenderGraph;
|
||||
|
||||
/* Command Buffer Functions */
|
||||
rt_cmd_begin_pass_fn *CmdBeginPass;
|
||||
|
@ -23,6 +23,8 @@ typedef struct {
|
||||
rt_rgb_require_explicit_synchronization_fn *RequireExplicitSynchronization;
|
||||
} rt_render_graph_builder_platform_callbacks;
|
||||
|
||||
#define RT_MAX_SUBMITTED_VIEWS_PER_PASS 32
|
||||
|
||||
typedef struct {
|
||||
uint32_t flags;
|
||||
|
||||
@ -53,6 +55,11 @@ typedef struct {
|
||||
rt_execute_render_pass_fn *Execute;
|
||||
void *user_data;
|
||||
|
||||
/* Runtime data. */
|
||||
rt_render_view submitted_views[RT_MAX_SUBMITTED_VIEWS_PER_PASS];
|
||||
uint32_t submitted_view_count;
|
||||
|
||||
|
||||
/* These refer to the semaphores array */
|
||||
uint32_t first_wait;
|
||||
uint32_t wait_count;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "gfx/render_view.h"
|
||||
#include "gfx/renderer_api.h"
|
||||
#include "renderer/common/common_render_graph.h"
|
||||
|
||||
@ -26,6 +27,28 @@ extern "C" void RT_RENDERER_API_FN(DestroyRenderGraphBuilder)(rt_render_graph_bu
|
||||
rtDestroyRenderGraphBuilder(builder);
|
||||
}
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(SubmitRenderView)(rt_render_graph *render_graph,
|
||||
uint32_t pass_id,
|
||||
rt_render_view view) {
|
||||
for (uint32_t i = 0; i < render_graph->pass_count; ++i) {
|
||||
if (render_graph->passes[i].id == pass_id) {
|
||||
rt_render_pass *pass = &render_graph->passes[i];
|
||||
if (!RT_VERIFY(pass->submitted_view_count < RT_MAX_SUBMITTED_VIEWS_PER_PASS))
|
||||
return;
|
||||
pass->submitted_views[pass->submitted_view_count++] = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph) {
|
||||
for (uint32_t i = 0; i < graph->pass_count; ++i) {
|
||||
#ifdef RT_DEBUG
|
||||
memset(graph->passes[i].submitted_views, 0, sizeof(graph->passes[i].submitted_views));
|
||||
#endif
|
||||
graph->passes[i].submitted_view_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static rt_result ExecutePass(rt_render_pass *pass, rt_command_buffer_handle cmdbuf_handle) {
|
||||
rt_command_buffer *cmd = rtGetCommandBuffer(cmdbuf_handle);
|
||||
if (!RT_VERIFY(cmd))
|
||||
@ -143,7 +166,8 @@ extern "C" rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *ren
|
||||
} else {
|
||||
// NOTE(Kevin): The most flexible solution would probably be a fullscreen tri draw
|
||||
// that implements a blit.
|
||||
// Another idea would be a compute shader that does a copy&filter but that requires more work
|
||||
// Another idea would be a compute shader that does a copy&filter but that requires more
|
||||
// work
|
||||
RT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,18 @@ rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *render_graph)
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
void RT_RENDERER_API_FN(SubmitRenderView)(rt_render_graph *render_graph,
|
||||
uint32_t pass_id,
|
||||
rt_render_view view) {
|
||||
RT_UNUSED(render_graph);
|
||||
RT_UNUSED(pass_id);
|
||||
RT_UNUSED(view);
|
||||
}
|
||||
|
||||
void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph) {
|
||||
RT_UNUSED(graph);
|
||||
}
|
||||
|
||||
void RT_RENDERER_API_FN(CmdBindPipeline)(rt_command_buffer_handle cmdhandle,
|
||||
rt_pipeline_handle pipeline_handle) {
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ RT_DLLEXPORT int rtAssertHandler(const char *expr, const char *msg, const char *
|
||||
// Asserts if p is "false", evaluates to p
|
||||
// NOTE that this will evaluate p multiple times!
|
||||
#define RT_VERIFY(p) \
|
||||
((!p) ? (rtAssertHandler(#p, "Verify failed", __FILE__, __LINE__), p) : p)
|
||||
((!(p)) ? (rtAssertHandler(#p, "Verify failed", __FILE__, __LINE__), p) : p)
|
||||
|
||||
#else
|
||||
#define RT_ASSERT(x, msg) RT_UNUSED(x)
|
||||
|
Loading…
Reference in New Issue
Block a user