Render a triangle
This commit is contained in:
parent
656b21d1ef
commit
88da8ec889
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
127
src/game/main.c
127
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 <stdlib.h>
|
||||
|
||||
/* 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);
|
||||
}
|
@ -257,3 +257,4 @@ RT_DLLEXPORT void rtReleaseEffect(const rt_effect *effect) {
|
||||
rtUnlockWrite(&_cache.lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -57,6 +57,18 @@ extern "C" void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmdhan
|
||||
}
|
||||
|
||||
cmd->context->OMSetRenderTargets(static_cast<UINT>(info->color_buffer_count), rtvs, dsv);
|
||||
|
||||
D3D11_VIEWPORT viewport;
|
||||
viewport.TopLeftX = static_cast<float>(info->render_area.offset.x);
|
||||
viewport.TopLeftY = static_cast<float>(info->render_area.offset.y);
|
||||
viewport.Width = static_cast<float>(info->render_area.size.x);
|
||||
viewport.Height = static_cast<float>(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<UINT>(_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);
|
||||
|
@ -62,6 +62,7 @@ struct rt_pipeline {
|
||||
|
||||
ID3D11ComputeShader *compute_shader;
|
||||
|
||||
ID3D11RasterizerState *rasterizer_state;
|
||||
|
||||
rt_pipeline *next_free;
|
||||
uint32_t version;
|
||||
|
@ -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<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
@ -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) {
|
||||
|
@ -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<uint32_t>(slot - _pipelines);
|
||||
return {slot->version, index};
|
||||
|
@ -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<rt_pass_runtime_data *>(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<rt_pass_runtime_data *>(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<UINT>(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<float>(desc.BufferDesc.Width);
|
||||
if (viewport.Height == 0)
|
||||
viewport.Height = static_cast<float>(desc.BufferDesc.Height);
|
||||
}
|
||||
|
||||
cmd->context->RSSetViewports(1, &viewport);
|
||||
|
||||
auto runtime_data = reinterpret_cast<rt_pass_runtime_data *>(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;
|
||||
}
|
||||
|
@ -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))) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user