131 lines
4.3 KiB
C++
131 lines
4.3 KiB
C++
// IAEngine: 2D Game Engine by IA
|
|
// Copyright (C) 2025 IAS (ias@iasoft.dev)
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
#include <IAEngine/Rendering/GPUBuffer.hpp>
|
|
|
|
#include <SDL3/SDL_gpu.h>
|
|
|
|
namespace ia::iae
|
|
{
|
|
EXTERN SDL_GPUDevice *g_gpuDevice;
|
|
|
|
UINT32 g_stagingBufferSize = 4096;
|
|
SDL_GPUTransferBuffer *g_stagingBuffer{};
|
|
|
|
RefPtr<GPUBuffer> GPUBuffer::Create(IN Usage usage, IN PCVOID data, IN UINT32 dataSize)
|
|
{
|
|
const auto res = MakeRefPtr<GPUBuffer>();
|
|
|
|
SDL_GPUBufferUsageFlags _usage{};
|
|
switch (usage)
|
|
{
|
|
case Usage::VERTEX:
|
|
_usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
|
break;
|
|
|
|
case Usage::INDEX:
|
|
_usage = SDL_GPU_BUFFERUSAGE_INDEX;
|
|
break;
|
|
|
|
case Usage::STORAGE:
|
|
_usage = SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ;
|
|
break;
|
|
|
|
default:
|
|
THROW_INVALID_DATA("Invalid usage value for GPUBuffer");
|
|
break;
|
|
}
|
|
res->m_usage = usage;
|
|
|
|
SDL_GPUBufferCreateInfo createInfo{.usage = _usage, .size = dataSize};
|
|
SDL_GPUBuffer *handle{};
|
|
if (!(handle = SDL_CreateGPUBuffer(g_gpuDevice, &createInfo)))
|
|
{
|
|
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Buffer: ", SDL_GetError());
|
|
return nullptr;
|
|
}
|
|
|
|
if (data && dataSize)
|
|
{
|
|
if (!EnsureStagingBufferSize((UINT32) dataSize))
|
|
return nullptr;
|
|
|
|
res->m_size = dataSize;
|
|
|
|
const auto mappedPtr = SDL_MapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer, false);
|
|
memcpy(mappedPtr, data, dataSize);
|
|
SDL_UnmapGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
|
|
|
|
const auto cmdBuffer = SDL_AcquireGPUCommandBuffer(g_gpuDevice);
|
|
const auto copyPass = SDL_BeginGPUCopyPass(cmdBuffer);
|
|
|
|
SDL_GPUTransferBufferLocation src{.transfer_buffer = g_stagingBuffer, .offset = 0};
|
|
SDL_GPUBufferRegion dst{.buffer = handle, .offset = 0, .size = dataSize};
|
|
SDL_UploadToGPUBuffer(copyPass, &src, &dst, false);
|
|
|
|
SDL_EndGPUCopyPass(copyPass);
|
|
SDL_SubmitGPUCommandBuffer(cmdBuffer);
|
|
SDL_WaitForGPUIdle(g_gpuDevice);
|
|
}
|
|
|
|
res->m_handle = (Handle) handle;
|
|
|
|
return res;
|
|
}
|
|
|
|
GPUBuffer::~GPUBuffer()
|
|
{
|
|
if (m_handle)
|
|
SDL_ReleaseGPUBuffer(g_gpuDevice, (SDL_GPUBuffer *) m_handle);
|
|
}
|
|
|
|
BOOL GPUBuffer::InitializeStagingBuffer()
|
|
{
|
|
SDL_GPUTransferBufferCreateInfo createInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
|
.size = g_stagingBufferSize};
|
|
if (!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
|
|
{
|
|
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
VOID GPUBuffer::TerminateStagingBuffer()
|
|
{
|
|
if (!g_stagingBuffer)
|
|
return;
|
|
|
|
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
|
|
}
|
|
|
|
BOOL GPUBuffer::EnsureStagingBufferSize(IN UINT32 size)
|
|
{
|
|
if (!g_stagingBuffer)
|
|
return false;
|
|
if (size <= g_stagingBufferSize)
|
|
return true;
|
|
SDL_ReleaseGPUTransferBuffer(g_gpuDevice, g_stagingBuffer);
|
|
SDL_GPUTransferBufferCreateInfo createInfo{.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
|
.size = (g_stagingBufferSize = size)};
|
|
if (!(g_stagingBuffer = SDL_CreateGPUTransferBuffer(g_gpuDevice, &createInfo)))
|
|
{
|
|
IAE_LOG_ERROR("Couldn't create a SDL3 GPU Staging Buffer: ", SDL_GetError());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
} // namespace ia::iae
|