render targets
This commit is contained in:
parent
2035f73f3e
commit
565c330f71
@ -20,6 +20,9 @@ extern "C" {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) /* anonymous struct */
|
||||
#endif
|
||||
typedef union {
|
||||
float v[4];
|
||||
@ -32,6 +35,8 @@ typedef union {
|
||||
} rt_color;
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/* NOTE(kevin): When you add a value here, you need to handle them in
|
||||
@ -59,6 +64,10 @@ typedef enum {
|
||||
RT_PIXEL_FORMAT_count,
|
||||
} rt_pixel_format;
|
||||
|
||||
RT_INLINE int rtIsDepthFormat(rt_pixel_format format) {
|
||||
return format == RT_PIXEL_FORMAT_DEPTH24_STENCIL8 || format == RT_PIXEL_FORMAT_DEPTH32;
|
||||
}
|
||||
|
||||
/* In renderer_api.h -> Not necessary for almost all gfx usage */
|
||||
typedef struct rt_renderer_init_info_s rt_renderer_init_info;
|
||||
|
||||
|
@ -17,7 +17,7 @@ extern "C" {
|
||||
|
||||
/* Handles for backend objects */
|
||||
|
||||
#define RT_RENDERER_BACKEND_HANDLE_MAX_INDEX ((1u<<24)-1)
|
||||
#define RT_RENDER_BACKEND_HANDLE_MAX_INDEX ((1u<<24)-1)
|
||||
#define RT_RENDER_BACKEND_HANDLE_MAX_VERSION 255
|
||||
|
||||
#define RT_RENDER_BACKEND_HANDLE(name) \
|
||||
|
133
src/renderer/dx11/command_buffers.cpp
Normal file
133
src/renderer/dx11/command_buffers.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_1.h>
|
||||
|
||||
#include "gfx/renderer_api.h"
|
||||
#include "runtime/config.h"
|
||||
#include "runtime/threading.h"
|
||||
#include "runtime/threading_helpers.hpp"
|
||||
#include "runtime/handles.h"
|
||||
|
||||
#include "gpu.hpp"
|
||||
#include "device_objects.hpp"
|
||||
|
||||
RT_CVAR_I(rt_Dx11MaxCommandBuffers,
|
||||
"Maximum number of simultaneously created command buffers. Default: 1024",
|
||||
1024);
|
||||
|
||||
static rt_command_buffer *_buffers;
|
||||
static rt_command_buffer *_first_free;
|
||||
static rt_mutex *_lock;
|
||||
|
||||
rt_result InitCommandBufferManagement() {
|
||||
_buffers = reinterpret_cast<rt_command_buffer *>(
|
||||
calloc((size_t)rt_Dx11MaxCommandBuffers.i, sizeof(rt_command_buffer)));
|
||||
if (!_buffers)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
_first_free = &_buffers[1];
|
||||
|
||||
_lock = rtCreateMutex();
|
||||
if (!_lock) {
|
||||
free(_buffers);
|
||||
return RT_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rt_Dx11MaxCommandBuffers.i - 1; ++i) {
|
||||
_buffers[i].next_free = &_buffers[i + 1];
|
||||
}
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
void ShutdownCommandBufferManagement() {
|
||||
for (int i = 0; i < rt_Dx11MaxCommandBuffers.i; ++i) {
|
||||
if (_buffers[i].context)
|
||||
_buffers[i].context->Release();
|
||||
}
|
||||
free(_buffers);
|
||||
_buffers = nullptr;
|
||||
}
|
||||
|
||||
extern "C" rt_result
|
||||
RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t count,
|
||||
const rt_alloc_command_buffer_info *,
|
||||
rt_command_buffer_handle *p_command_buffers) {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
rtLockMutex(_lock);
|
||||
rt_command_buffer *slot = _first_free;
|
||||
if (slot)
|
||||
_first_free = slot->next_free;
|
||||
rtUnlockMutex(_lock);
|
||||
|
||||
if (!slot) {
|
||||
rtLog("dx11", "Failed to allocate a command buffer slot.");
|
||||
rtLockMutex(_lock);
|
||||
for (uint32_t j = 0; j < i; ++j) {
|
||||
rt_command_buffer *s = &_buffers[p_command_buffers[j].index];
|
||||
s->next_free = _first_free;
|
||||
_first_free = s;
|
||||
}
|
||||
rtUnlockMutex(_lock);
|
||||
return RT_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (!slot->context) {
|
||||
if (FAILED(g_gpu.device->CreateDeferredContext1(0, &slot->context))) {
|
||||
rtLog("dx11", "Failed to create a deferred context.");
|
||||
auto lock_guard = rtAutoLock(_lock);
|
||||
for (uint32_t j = 0; j < i; ++j) {
|
||||
rt_command_buffer *s = &_buffers[p_command_buffers[j].index];
|
||||
s->next_free = _first_free;
|
||||
_first_free = s;
|
||||
}
|
||||
return RT_UNKNOWN_ERROR;
|
||||
}
|
||||
} else {
|
||||
slot->context->ClearState();
|
||||
}
|
||||
|
||||
slot->version = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
|
||||
const uint32_t index = (uint32_t)(slot - _buffers);
|
||||
p_command_buffers[i].version = slot->version;
|
||||
p_command_buffers[i].index = index;
|
||||
}
|
||||
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" rt_result
|
||||
RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue, const rt_submit_command_buffers_info *info) {
|
||||
// TODO: Handle semaphores
|
||||
|
||||
// Submit the command lists to the gpu
|
||||
for (uint32_t i = 0; i < info->command_buffer_count; ++i) {
|
||||
rt_command_buffer *cmdbuf = &_buffers[info->command_buffers[i].index];
|
||||
if (cmdbuf->version != info->command_buffers[i].version) {
|
||||
rtLog("dx11", "Tried to submit an invalid command buffer (version mismatch)");
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
ID3D11CommandList *cmdlist;
|
||||
if (FAILED(cmdbuf->context->FinishCommandList(FALSE, &cmdlist))) {
|
||||
rtLog("dx11", "FinishCommandList failed");
|
||||
return RT_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
rtLockMutex(g_gpu.context_lock);
|
||||
g_gpu.device_context->ExecuteCommandList(cmdlist, FALSE);
|
||||
rtUnlockMutex(g_gpu.context_lock);
|
||||
|
||||
rtLockMutex(_lock);
|
||||
cmdbuf->next_free = _first_free;
|
||||
_first_free = cmdbuf;
|
||||
rtUnlockMutex(_lock);
|
||||
}
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
rt_command_buffer *rtGetCommandBuffer(rt_command_buffer_handle handle) {
|
||||
if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxCommandBuffers.i)
|
||||
return nullptr;
|
||||
auto lg = rtAutoLock(_lock);
|
||||
if (handle.version != _buffers[handle.index].version)
|
||||
return nullptr;
|
||||
return &_buffers[handle.index];
|
||||
}
|
45
src/renderer/dx11/device_objects.hpp
Normal file
45
src/renderer/dx11/device_objects.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef RT_DX11_DEVICE_OBJECTS_HPP
|
||||
#define RT_DX11_DEVICE_OBJECTS_HPP
|
||||
|
||||
// Types containing various api objects
|
||||
#include <stdint.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_1.h>
|
||||
|
||||
#include "runtime/runtime.h"
|
||||
|
||||
struct rt_render_target {
|
||||
// Only one of these should be valid
|
||||
ID3D11RenderTargetView *rtv;
|
||||
ID3D11DepthStencilView *dsv;
|
||||
|
||||
ID3D11Texture2D *texture;
|
||||
|
||||
bool IsColorRenderTarget() const {
|
||||
RT_ASSERT(!(rtv != nullptr && dsv != nullptr),
|
||||
"A render target should not contain a render target and a depth stencil view");
|
||||
return rtv != nullptr;
|
||||
}
|
||||
|
||||
bool IsDepthStencilTarget() const {
|
||||
RT_ASSERT(!(rtv != nullptr && dsv != nullptr),
|
||||
"A render target should not contain a render target and a depth stencil view");
|
||||
return dsv != nullptr;
|
||||
}
|
||||
|
||||
uint32_t version;
|
||||
rt_render_target *next_free;
|
||||
};
|
||||
|
||||
struct rt_command_buffer {
|
||||
// Only created once and then re-used.
|
||||
ID3D11DeviceContext1 *context;
|
||||
|
||||
uint32_t version;
|
||||
rt_command_buffer *next_free;
|
||||
};
|
||||
|
||||
rt_render_target *rtGetRenderTarget(rt_render_target_handle handle);
|
||||
rt_command_buffer *rtGetCommandBuffer(rt_command_buffer_handle handle);
|
||||
|
||||
#endif
|
@ -1,11 +1,14 @@
|
||||
#ifndef RT_DX11_GPU_H
|
||||
#define RT_DX11_GPU_H
|
||||
#ifndef RT_DX11_GPU_HPP
|
||||
#define RT_DX11_GPU_HPP
|
||||
|
||||
#include <wrl.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_3.h>
|
||||
|
||||
#include "runtime/threading.h"
|
||||
#include "gfx/renderer_api.h"
|
||||
|
||||
// Smart pointer for COM-Objects
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
@ -15,6 +18,7 @@ struct rt_swap_chain {
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
};
|
||||
|
||||
|
||||
struct rt_gpu {
|
||||
ComPtr<ID3D11Device1> device;
|
||||
ComPtr<ID3D11DeviceContext1> device_context;
|
||||
@ -22,11 +26,16 @@ struct rt_gpu {
|
||||
|
||||
rt_swap_chain swap_chain;
|
||||
|
||||
rt_mutex *context_lock;
|
||||
|
||||
D3D_FEATURE_LEVEL feature_level;
|
||||
D3D11_FEATURE_DATA_THREADING threading_support;
|
||||
};
|
||||
|
||||
#ifndef DONT_DEFINE_GPU_GLOBAL
|
||||
extern rt_gpu g_gpu;
|
||||
#endif
|
||||
|
||||
DXGI_FORMAT rtConvertPixelFormat(rt_pixel_format format);
|
||||
|
||||
#endif
|
32
src/renderer/dx11/helpers.cpp
Normal file
32
src/renderer/dx11/helpers.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "gpu.hpp"
|
||||
|
||||
DXGI_FORMAT rtConvertPixelFormat(rt_pixel_format format) {
|
||||
switch (format) {
|
||||
case RT_PIXEL_FORMAT_INVALID:
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
case RT_PIXEL_FORMAT_R8G8B8A8_UNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case RT_PIXEL_FORMAT_B8G8R8A8_UNORM:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case RT_PIXEL_FORMAT_R8G8B8A8_SRGB:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
case RT_PIXEL_FORMAT_B8G8R8A8_SRGB:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
case RT_PIXEL_FORMAT_R8G8B8_UNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case RT_PIXEL_FORMAT_B8G8R8_UNORM:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||
case RT_PIXEL_FORMAT_R8G8B8_SRGB:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
case RT_PIXEL_FORMAT_B8G8R8_SRGB:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||
|
||||
case RT_PIXEL_FORMAT_DEPTH24_STENCIL8:
|
||||
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
case RT_PIXEL_FORMAT_DEPTH32:
|
||||
return DXGI_FORMAT_D32_FLOAT;
|
||||
|
||||
default:
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
@ -16,38 +16,44 @@
|
||||
#include "runtime/config.h"
|
||||
|
||||
#define DONT_DEFINE_RENDERER_GLOBAL
|
||||
#include "gpu.h"
|
||||
#include "gpu.hpp"
|
||||
|
||||
RT_CVAR_S(
|
||||
rt_Dx11AdapterName,
|
||||
"Name of the adapter that should be used for device creation. Default: \"\" (Use default)",
|
||||
"");
|
||||
RT_CVAR_I(rt_Dx11VSync, "Enable vsync. Default: 1", 1);
|
||||
RT_CVAR_I(rt_Dx11MaxSubmittedCommandBuffers,
|
||||
"Maximum number of submitted command buffers per frame. Default: 1024",
|
||||
1024);
|
||||
|
||||
extern rt_cvar rt_Dx11MaxCommandBuffers;
|
||||
|
||||
rt_gpu g_gpu;
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(RegisterCVars)(void) {
|
||||
rtRegisterCVAR(&rt_Dx11AdapterName);
|
||||
rtRegisterCVAR(&rt_Dx11VSync);
|
||||
rtRegisterCVAR(&rt_Dx11MaxCommandBuffers);
|
||||
}
|
||||
|
||||
static rt_swap_chain CreateSwapChain(HWND hwnd) {
|
||||
rt_swap_chain swc;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 desc;
|
||||
desc.Width = 0; // use window width
|
||||
desc.Width = 0; // use window width
|
||||
desc.Height = 0; // use window height
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // can't specify _SRGB here when using
|
||||
// DXGI_SWAP_EFFECT_FLIP_* ...;
|
||||
desc.Stereo = FALSE;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = 2;
|
||||
desc.Scaling = DXGI_SCALING_STRETCH;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
desc.Flags = 0;
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // can't specify _SRGB here when using
|
||||
// DXGI_SWAP_EFFECT_FLIP_* ...;
|
||||
desc.Stereo = FALSE;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = 2;
|
||||
desc.Scaling = DXGI_SCALING_STRETCH;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
desc.Flags = 0;
|
||||
|
||||
if (FAILED(g_gpu.dxgi_factory->CreateSwapChainForHwnd(g_gpu.device.Get(),
|
||||
hwnd,
|
||||
@ -84,7 +90,7 @@ static IDXGIAdapter *RetrieveSelectedAdapter(void) {
|
||||
if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
UINT i = 0;
|
||||
IDXGIAdapter *adapter;
|
||||
while (factory->EnumAdapters(i, &adapter) == S_OK) {
|
||||
@ -102,6 +108,11 @@ static IDXGIAdapter *RetrieveSelectedAdapter(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern rt_result InitCommandBufferManagement();
|
||||
extern void ShutdownCommandBufferManagement();
|
||||
extern rt_result InitRenderTargetManagement();
|
||||
extern void ShutdownRenderTargetManagement();
|
||||
|
||||
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};
|
||||
UINT device_flags = 0;
|
||||
@ -163,12 +174,37 @@ extern "C" rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info)
|
||||
return RT_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
g_gpu.device->CheckFeatureSupport(D3D11_FEATURE_THREADING,
|
||||
&g_gpu.threading_support,
|
||||
sizeof(g_gpu.threading_support));
|
||||
|
||||
g_gpu.swap_chain = CreateSwapChain(info->hWnd);
|
||||
|
||||
g_gpu.context_lock = rtCreateMutex();
|
||||
|
||||
rt_result res = InitCommandBufferManagement();
|
||||
if (res != RT_SUCCESS)
|
||||
return res;
|
||||
res = InitRenderTargetManagement();
|
||||
if (res != RT_SUCCESS)
|
||||
return res;
|
||||
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(Shutdown)(void) {
|
||||
ShutdownRenderTargetManagement();
|
||||
ShutdownCommandBufferManagement();
|
||||
rtDestroyMutex(g_gpu.context_lock);
|
||||
g_gpu.swap_chain.rtv.Reset();
|
||||
g_gpu.swap_chain.swap_chain.Reset();
|
||||
g_gpu.dxgi_factory.Reset();
|
||||
g_gpu.device.Reset();
|
||||
}
|
||||
|
||||
extern "C" unsigned int RT_RENDERER_API_FN(GetMaxFramesInFlight)(void) {
|
||||
// TODO: Verify this.
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(BeginFrame)(unsigned int frame_id) {
|
||||
@ -179,13 +215,18 @@ extern "C" void RT_RENDERER_API_FN(BeginFrame)(unsigned int frame_id) {
|
||||
0,
|
||||
0,
|
||||
};
|
||||
rtLockMutex(g_gpu.context_lock);
|
||||
g_gpu.device_context->ClearRenderTargetView(g_gpu.swap_chain.rtv.Get(), clear_color);
|
||||
rtUnlockMutex(g_gpu.context_lock);
|
||||
}
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(EndFrame)(unsigned int frame_id) {
|
||||
RT_UNUSED(frame_id);
|
||||
|
||||
rtLockMutex(g_gpu.context_lock);
|
||||
UINT sync_interval = rt_Dx11VSync.i ? 1 : 0;
|
||||
g_gpu.swap_chain.swap_chain->Present(sync_interval, 0);
|
||||
rtUnlockMutex(g_gpu.context_lock);
|
||||
}
|
||||
|
||||
// Copied from null. Delete once no longer needed
|
||||
@ -194,7 +235,7 @@ extern "C" {
|
||||
|
||||
#define RETURN_HANDLE_STUB2(type, initial) \
|
||||
static unsigned int s_next = (initial); \
|
||||
s_next = (s_next + 1) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX; \
|
||||
s_next = (s_next + 1) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX; \
|
||||
type h = { \
|
||||
1, \
|
||||
s_next, \
|
||||
@ -206,15 +247,12 @@ extern "C" {
|
||||
#define RETURN_HANDLE_ARRAY_STUB2(out, count, initial) \
|
||||
static unsigned int s_next = (initial); \
|
||||
for (uint32_t i = 0; i < (count); ++i) { \
|
||||
(out)[i].index = (s_next++) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX; \
|
||||
(out)[i].index = (s_next++) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX; \
|
||||
(out)[i].version = 1; \
|
||||
}
|
||||
|
||||
#define RETURN_HANDLE_ARRAY_STUB(out, count) RETURN_HANDLE_ARRAY_STUB2(out, count, 1)
|
||||
|
||||
unsigned int RT_RENDERER_API_FN(GetMaxFramesInFlight)(void) {
|
||||
return 2;
|
||||
}
|
||||
rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *info) {
|
||||
RT_UNUSED(info);
|
||||
RETURN_HANDLE_STUB(rt_pipeline_handle);
|
||||
@ -224,33 +262,6 @@ void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle handle) {
|
||||
RT_UNUSED(handle);
|
||||
}
|
||||
|
||||
rt_render_target_handle RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_target_info *info) {
|
||||
RT_UNUSED(info);
|
||||
RETURN_HANDLE_STUB2(rt_render_target_handle, 2);
|
||||
}
|
||||
|
||||
rt_render_target_handle RT_RENDERER_API_FN(GetSwapchainRenderTarget)(void) {
|
||||
return {1, 1};
|
||||
}
|
||||
|
||||
void RT_RENDERER_API_FN(DestroyRenderTarget)(rt_render_target_handle handle) {
|
||||
RT_UNUSED(handle);
|
||||
}
|
||||
|
||||
rt_result RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t count,
|
||||
const rt_alloc_command_buffer_info *info,
|
||||
rt_command_buffer_handle *p_command_buffers) {
|
||||
RT_UNUSED(info);
|
||||
RETURN_HANDLE_ARRAY_STUB(p_command_buffers, count)
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue queue,
|
||||
const rt_submit_command_buffers_info *info) {
|
||||
RT_UNUSED(queue);
|
||||
RT_UNUSED(info);
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t count,
|
||||
const rt_gpu_semaphore_info *info,
|
||||
@ -316,15 +327,4 @@ void RT_RENDERER_API_FN(CmdFlushRenderTargetWrite)(rt_command_buffer_handle cmdb
|
||||
RT_UNUSED(cmdbuf_handle);
|
||||
RT_UNUSED(render_target);
|
||||
}
|
||||
|
||||
rt_render_graph_builder RT_RENDERER_API_FN(CreateRenderGraphBuilder)(void) {
|
||||
rt_render_graph_builder b = {
|
||||
.obj = NULL,
|
||||
};
|
||||
return b;
|
||||
}
|
||||
|
||||
void RT_RENDERER_API_FN(DestroyRenderGraphBuilder)(rt_render_graph_builder *builder) {
|
||||
RT_UNUSED(builder);
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
if get_option('build_dx11')
|
||||
dx11_renderer_lib = library('rtdx11',
|
||||
# Project Sources
|
||||
'gpu.h',
|
||||
'device_objects.hpp',
|
||||
'gpu.hpp',
|
||||
|
||||
'command_buffers.cpp',
|
||||
'helpers.cpp',
|
||||
'init.cpp',
|
||||
'render_targets.cpp',
|
||||
|
||||
dependencies : [m_dep, windowing_dep],
|
||||
include_directories : [engine_incdir, contrib_incdir],
|
||||
|
166
src/renderer/dx11/render_targets.cpp
Normal file
166
src/renderer/dx11/render_targets.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_1.h>
|
||||
|
||||
#include "gfx/renderer_api.h"
|
||||
#include "runtime/config.h"
|
||||
#include "runtime/handles.h"
|
||||
#include "runtime/threading_helpers.hpp"
|
||||
|
||||
#include "device_objects.hpp"
|
||||
#include "gpu.hpp"
|
||||
|
||||
RT_CVAR_I(rt_Dx11MaxRenderTargets,
|
||||
"Maximum number of simultaneously existing render targets. Default: 128",
|
||||
128);
|
||||
|
||||
static rt_render_target *_render_targets;
|
||||
static rt_render_target *_first_free;
|
||||
static rt_mutex *_lock;
|
||||
|
||||
rt_result InitRenderTargetManagement() {
|
||||
_render_targets = reinterpret_cast<rt_render_target *>(
|
||||
calloc((size_t)rt_Dx11MaxRenderTargets.i, sizeof(rt_render_target)));
|
||||
if (!_render_targets) {
|
||||
return RT_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
_lock = rtCreateMutex();
|
||||
if (!_lock) {
|
||||
free(_render_targets);
|
||||
return RT_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
_first_free = _render_targets + 2;
|
||||
for (int i = 0; i < rt_Dx11MaxRenderTargets.i; ++i) {
|
||||
_render_targets[i].next_free = &_render_targets[i + 1];
|
||||
}
|
||||
return RT_SUCCESS;
|
||||
}
|
||||
|
||||
void ShutdownRenderTargetManagement() {
|
||||
for (int i = 0; i < rt_Dx11MaxRenderTargets.i; ++i) {
|
||||
if (_render_targets[i].rtv)
|
||||
_render_targets[i].rtv->Release();
|
||||
if (_render_targets[i].dsv)
|
||||
_render_targets[i].dsv->Release();
|
||||
if (_render_targets[i].texture)
|
||||
_render_targets[i].texture->Release();
|
||||
}
|
||||
free(_render_targets);
|
||||
rtDestroyMutex(_lock);
|
||||
}
|
||||
|
||||
extern "C" rt_render_target_handle
|
||||
RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_target_info *info) {
|
||||
rt_render_target *slot = nullptr;
|
||||
{
|
||||
auto lock_guard = rtAutoLock(_lock);
|
||||
slot = _first_free;
|
||||
_first_free = slot->next_free;
|
||||
}
|
||||
|
||||
if (!slot) {
|
||||
rtLog("dx11",
|
||||
"Could not create a new render target, because all available slots are currently in "
|
||||
"use.");
|
||||
return RT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (!rtIsDepthFormat(info->format)) {
|
||||
D3D11_TEXTURE2D_DESC tex_desc = {};
|
||||
tex_desc.Width = info->width;
|
||||
tex_desc.Height = info->height;
|
||||
tex_desc.MipLevels = 1;
|
||||
tex_desc.ArraySize = 1;
|
||||
tex_desc.Format = rtConvertPixelFormat(info->format);
|
||||
tex_desc.SampleDesc.Count = 1;
|
||||
tex_desc.SampleDesc.Quality = 0;
|
||||
tex_desc.Usage = D3D11_USAGE_DEFAULT; // read and write
|
||||
tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
tex_desc.CPUAccessFlags = 0; // none
|
||||
tex_desc.MiscFlags = 0;
|
||||
if (FAILED(g_gpu.device->CreateTexture2D(&tex_desc, nullptr, &slot->texture))) {
|
||||
rtLog("dx11", "Failed to create backing texture for render target %s", info->name);
|
||||
auto lg = rtAutoLock(_lock);
|
||||
slot->next_free = _first_free;
|
||||
_first_free = slot;
|
||||
return RT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
|
||||
rtv_desc.Format = rtConvertPixelFormat(info->format);
|
||||
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
rtv_desc.Texture2D.MipSlice = 0;
|
||||
if (FAILED(g_gpu.device->CreateRenderTargetView(slot->texture, &rtv_desc, &slot->rtv))) {
|
||||
slot->texture->Release();
|
||||
rtLog("dx11",
|
||||
"Failed to create the render target view for render target %s",
|
||||
info->name);
|
||||
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 - _render_targets);
|
||||
return {.version = slot->version, .index = index};
|
||||
} else {
|
||||
D3D11_TEXTURE2D_DESC tex_desc = {};
|
||||
tex_desc.Width = info->width;
|
||||
tex_desc.Height = info->height;
|
||||
tex_desc.MipLevels = 1;
|
||||
tex_desc.ArraySize = 1;
|
||||
tex_desc.Format = rtConvertPixelFormat(info->format);
|
||||
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.CPUAccessFlags = 0; // none
|
||||
tex_desc.MiscFlags = 0;
|
||||
if (FAILED(g_gpu.device->CreateTexture2D(&tex_desc, nullptr, &slot->texture))) {
|
||||
rtLog("dx11", "Failed to create backing texture for render target %s", info->name);
|
||||
auto lg = rtAutoLock(_lock);
|
||||
slot->next_free = _first_free;
|
||||
_first_free = slot;
|
||||
return RT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
|
||||
dsv_desc.Format = rtConvertPixelFormat(info->format);
|
||||
dsv_desc.Flags = 0;
|
||||
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
dsv_desc.Texture2D.MipSlice = 0;
|
||||
if (FAILED(g_gpu.device->CreateDepthStencilView(slot->texture, &dsv_desc, &slot->dsv))) {
|
||||
slot->texture->Release();
|
||||
rtLog("dx11",
|
||||
"Failed to create the depth stencil view for render target %s",
|
||||
info->name);
|
||||
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 - _render_targets);
|
||||
return {.version = slot->version, .index = index};
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" rt_render_target_handle RT_RENDERER_API_FN(GetSwapchainRenderTarget)(void) {
|
||||
return {1, 1};
|
||||
}
|
||||
|
||||
extern "C" void RT_RENDERER_API_FN(DestroyRenderTarget)(rt_render_target_handle handle) {
|
||||
RT_UNUSED(handle);
|
||||
}
|
||||
|
||||
rt_render_target *rtGetRenderTarget(rt_render_target_handle handle) {
|
||||
if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxRenderTargets.i)
|
||||
return nullptr;
|
||||
auto lg = rtAutoLock(_lock);
|
||||
if (_render_targets[handle.index].version != handle.version)
|
||||
return nullptr;
|
||||
return &_render_targets[handle.index];
|
||||
}
|
@ -6,14 +6,14 @@
|
||||
|
||||
#define RETURN_HANDLE_STUB2(type, initial) \
|
||||
static unsigned int s_next = (initial); \
|
||||
return (type) { .index = (s_next++) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX, .version = 1 }
|
||||
return (type) { .index = (s_next++) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX, .version = 1 }
|
||||
|
||||
#define RETURN_HANDLE_STUB(type) RETURN_HANDLE_STUB2(type, 1)
|
||||
|
||||
#define RETURN_HANDLE_ARRAY_STUB2(out, count, initial) \
|
||||
static unsigned int s_next = (initial); \
|
||||
for (uint32_t i = 0; i < (count); ++i) { \
|
||||
(out)[i].index = (s_next++) % RT_RENDERER_BACKEND_HANDLE_MAX_INDEX; \
|
||||
(out)[i].index = (s_next++) % RT_RENDER_BACKEND_HANDLE_MAX_INDEX; \
|
||||
(out)[i].version = 1; \
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ runtime_lib = library('rt',
|
||||
'resources.h',
|
||||
'runtime.h',
|
||||
'threading.h',
|
||||
'threading_helpers.hpp',
|
||||
|
||||
'aio.c',
|
||||
'assert.c',
|
||||
|
@ -5,6 +5,9 @@
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) /* anonymous struct */
|
||||
#endif
|
||||
|
||||
struct vec2 {
|
||||
@ -44,6 +47,8 @@ typedef struct {
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -121,8 +121,11 @@ 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)
|
||||
#else
|
||||
#define RT_ASSERT(x, msg) RT_UNUSED(x)
|
||||
#define RT_ASSERT_ALWAYS_EVAL(x, msg) (x)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
|
61
src/runtime/threading_helpers.hpp
Normal file
61
src/runtime/threading_helpers.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef RT_THREADING_HELPERS_HPP
|
||||
#define RT_THREADING_HELPERS_HPP
|
||||
|
||||
// C++ wrappers around threading functions/types
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error This file must only be used from C++ code
|
||||
#endif
|
||||
|
||||
#include "threading.h"
|
||||
|
||||
template <typename _LockType, void (*_AcquireFunc)(_LockType *), void (*_ReleaseFunc)(_LockType *)>
|
||||
class rt_generic_auto_lock {
|
||||
public:
|
||||
explicit rt_generic_auto_lock(_LockType *lock) : m_lock(lock) {
|
||||
_AcquireFunc(lock);
|
||||
}
|
||||
|
||||
~rt_generic_auto_lock() {
|
||||
_ReleaseFunc(m_lock);
|
||||
}
|
||||
|
||||
rt_generic_auto_lock(const rt_generic_auto_lock &) = delete;
|
||||
const rt_generic_auto_lock &operator=(const rt_generic_auto_lock &) = delete;
|
||||
|
||||
private:
|
||||
_LockType *m_lock;
|
||||
};
|
||||
|
||||
namespace __rt_auto_lock_mutex_wrappers {
|
||||
|
||||
RT_INLINE void Lock(rt_mutex *mtx) {
|
||||
RT_ASSERT_ALWAYS_EVAL(rtLockMutex(mtx), "Lock mutex failed!");
|
||||
}
|
||||
|
||||
RT_INLINE void Unlock(rt_mutex *mtx) {
|
||||
RT_ASSERT_ALWAYS_EVAL(rtUnlockMutex(mtx), "Unlock mutex failed!");
|
||||
}
|
||||
|
||||
} // namespace __rt_auto_lock_mutex_wrappers
|
||||
|
||||
using rt_mutex_auto_lock = rt_generic_auto_lock<rt_mutex,
|
||||
__rt_auto_lock_mutex_wrappers::Lock,
|
||||
__rt_auto_lock_mutex_wrappers::Unlock>;
|
||||
|
||||
using rt_read_auto_lock = rt_generic_auto_lock<rt_rwlock, rtLockRead, rtUnlockRead>;
|
||||
using rt_write_auto_lock = rt_generic_auto_lock<rt_rwlock, rtLockWrite, rtUnlockWrite>;
|
||||
|
||||
RT_INLINE rt_mutex_auto_lock rtAutoLock(rt_mutex *mutex) {
|
||||
return rt_mutex_auto_lock(mutex);
|
||||
}
|
||||
|
||||
RT_INLINE rt_read_auto_lock rtAutoLock(rt_rwlock *rw) {
|
||||
return rt_read_auto_lock(rw);
|
||||
}
|
||||
|
||||
RT_INLINE rt_write_auto_lock rtAutoWriteLock(rt_rwlock *rw) {
|
||||
return rt_write_auto_lock(rw);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user