diff --git a/src/renderer/dx11/buffers.cpp b/src/renderer/dx11/buffers.cpp new file mode 100644 index 0000000..3f565ad --- /dev/null +++ b/src/renderer/dx11/buffers.cpp @@ -0,0 +1,146 @@ +#include +#include + +#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_Dx11MaxBuffers, + "Maximum number of simultaneously existing buffers. Default: 4096", + 4096); + +static rt_buffer *_buffers; +static rt_buffer *_first_free; +static rt_mutex *_lock; + +rt_result InitBufferManagement() { + _buffers = + reinterpret_cast(calloc((size_t)rt_Dx11MaxBuffers.i, sizeof(rt_buffer))); + if (!_buffers) { + return RT_OUT_OF_MEMORY; + } + + _lock = rtCreateMutex(); + if (!_lock) { + free(_buffers); + return RT_UNKNOWN_ERROR; + } + + _first_free = _buffers + 2; + for (int i = 0; i < rt_Dx11MaxBuffers.i; ++i) { + _buffers[i].next_free = &_buffers[i + 1]; + } + return RT_SUCCESS; +} + +void ShutdownBufferManagement() { + for (int i = 0; i < rt_Dx11MaxBuffers.i; ++i) { + if (_buffers[i].buffer) + _buffers[i].buffer->Release(); + } + free(_buffers); + rtDestroyMutex(_lock); +} + +rt_buffer *rtGetBuffer(rt_buffer_handle handle) { + if (!RT_IS_HANDLE_VALID(handle) || (int)handle.index >= rt_Dx11MaxBuffers.i) + return nullptr; + auto lg = rtAutoLock(_lock); + if (handle.version != _buffers[handle.index].version) + return nullptr; + return &_buffers[handle.index]; +} + +extern "C" rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t count, + const rt_buffer_info *info, + rt_buffer_handle *p_buffers) { + for (uint32_t i = 0; i < count; ++i) { + rtLockMutex(_lock); + rt_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_buffer *s = &_buffers[p_buffers[j].index]; + s->next_free = _first_free; + _first_free = s; + _first_free = s; + } + rtUnlockMutex(_lock); + return RT_OUT_OF_MEMORY; + } + + D3D11_USAGE usage = D3D11_USAGE_DEFAULT; + if (info[i].usage == RT_BUFFER_USAGE_STATIC) { + usage = D3D11_USAGE_IMMUTABLE; + } else if (info[i].usage == RT_BUFFER_USAGE_DYNAMIC) { + usage = D3D11_USAGE_DEFAULT; + } else if (info[i].usage == RT_BUFFER_USAGE_TRANSIENT) { + usage = D3D11_USAGE_DYNAMIC; + } + + UINT bind_flags = D3D11_BIND_UNORDERED_ACCESS; + if (info[i].type == RT_BUFFER_TYPE_VERTEX) + bind_flags = D3D11_BIND_VERTEX_BUFFER; + else if (info[i].type == RT_BUFFER_TYPE_INDEX) + bind_flags = D3D11_BIND_INDEX_BUFFER; + else if (info[i].type == RT_BUFFER_TYPE_UNIFORM) + bind_flags = D3D11_BIND_CONSTANT_BUFFER; + else if (info[i].type == RT_BUFFER_TYPE_STORAGE) + bind_flags = D3D11_BIND_UNORDERED_ACCESS; + + + D3D11_BUFFER_DESC desc = {}; + desc.ByteWidth = static_cast(((info[i].size + 15) / 16) * 16); + desc.Usage = usage; + desc.BindFlags = bind_flags; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.StructureByteStride = 1; + + D3D11_SUBRESOURCE_DATA data; + data.pSysMem = info->data; + data.SysMemPitch = 0; + data.SysMemSlicePitch = 0; + + if (FAILED( + g_gpu.device->CreateBuffer(&desc, info[i].data ? &data : nullptr, &slot->buffer))) { + rtLog("dx11", "Failed to create a deferred context."); + auto lock_guard = rtAutoLock(_lock); + for (uint32_t j = 0; j < i; ++j) { + rt_buffer *s = &_buffers[p_buffers[j].index]; + s->next_free = _first_free; + _first_free = s; + } + return RT_UNKNOWN_ERROR; + } + + slot->version = (slot->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION; + const uint32_t index = (uint32_t)(slot - _buffers); + p_buffers[i].version = slot->version; + p_buffers[i].index = index; + } + + return RT_SUCCESS; +} + +extern "C" void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers) { + for (uint32_t i = 0; i < count; ++i) { + if (!RT_IS_HANDLE_VALID(buffers[i]) || (int)buffers[i].index >= rt_Dx11MaxBuffers.i) + continue; + auto lg = rtAutoLock(_lock); + if (buffers[i].version != _buffers[buffers[i].index].version) + continue; + _buffers[buffers[i].index].buffer->Release(); + _buffers[buffers[i].index].next_free = _first_free; + _first_free = &_buffers[buffers[i].index]; + } +} diff --git a/src/renderer/dx11/device_objects.hpp b/src/renderer/dx11/device_objects.hpp index d5ffec3..fb4f643 100644 --- a/src/renderer/dx11/device_objects.hpp +++ b/src/renderer/dx11/device_objects.hpp @@ -39,7 +39,17 @@ struct rt_command_buffer { rt_command_buffer *next_free; }; +struct rt_buffer { + ID3D11Buffer *buffer; + rt_buffer_type type; + rt_buffer_usage usage; + + uint32_t version; + rt_buffer *next_free; +}; + rt_render_target *rtGetRenderTarget(rt_render_target_handle handle); rt_command_buffer *rtGetCommandBuffer(rt_command_buffer_handle handle); +rt_buffer *rtGetBuffer(rt_buffer_handle handle); #endif \ No newline at end of file diff --git a/src/renderer/dx11/init.cpp b/src/renderer/dx11/init.cpp index ca9a87b..2676766 100644 --- a/src/renderer/dx11/init.cpp +++ b/src/renderer/dx11/init.cpp @@ -283,6 +283,7 @@ uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle sem) { return 0; } + rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetSwapchainAvailableSemaphore)(void) { return {1, 1}; } @@ -291,19 +292,6 @@ rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void) { return {1, 2}; } -rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t count, - const rt_buffer_info *info, - rt_buffer_handle *p_buffers) { - RT_UNUSED(info); - RETURN_HANDLE_ARRAY_STUB(p_buffers, count); - return RT_SUCCESS; -} - -void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t count, rt_buffer_handle *buffers) { - RT_UNUSED(count); - RT_UNUSED(buffers); -} - void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle cmd, const rt_cmd_begin_pass_info *info) { RT_UNUSED(cmd); diff --git a/src/renderer/dx11/meson.build b/src/renderer/dx11/meson.build index 4522cfa..dc6dc1c 100644 --- a/src/renderer/dx11/meson.build +++ b/src/renderer/dx11/meson.build @@ -4,6 +4,7 @@ if get_option('build_dx11') 'device_objects.hpp', 'gpu.hpp', + 'buffers.cpp', 'command_buffers.cpp', 'helpers.cpp', 'init.cpp',