Render a triangle

This commit is contained in:
Kevin Trogant 2024-05-19 12:48:50 +02:00
parent 656b21d1ef
commit 88da8ec889
16 changed files with 267 additions and 75 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -257,3 +257,4 @@ RT_DLLEXPORT void rtReleaseEffect(const rt_effect *effect) {
rtUnlockWrite(&_cache.lock);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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,
};

View File

@ -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;

View File

@ -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);

View File

@ -62,6 +62,7 @@ struct rt_pipeline {
ID3D11ComputeShader *compute_shader;
ID3D11RasterizerState *rasterizer_state;
rt_pipeline *next_free;
uint32_t version;

View File

@ -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>;

View File

@ -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) {

View File

@ -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};

View File

@ -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;
}

View File

@ -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))) {

View File

@ -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;