Move buffer copies to render thread if they happen in the main thread.

This commit is contained in:
Skyth 2024-10-27 17:17:12 +03:00
parent b867961000
commit 882f371de4

View file

@ -355,6 +355,8 @@ enum class RenderCommandType
SetRenderState, SetRenderState,
DestructResource, DestructResource,
UnlockTextureRect, UnlockTextureRect,
UnlockBuffer16,
UnlockBuffer32,
Present, Present,
StretchRect, StretchRect,
SetRenderTarget, SetRenderTarget,
@ -398,6 +400,11 @@ struct RenderCommand
GuestTexture* texture; GuestTexture* texture;
} unlockTextureRect; } unlockTextureRect;
struct
{
GuestBuffer* buffer;
} unlockBuffer;
struct struct
{ {
GuestDevice* device; GuestDevice* device;
@ -1169,32 +1176,58 @@ static void ExecuteCopyCommandList(const T& function)
g_copyQueue->waitForCommandFence(g_copyCommandFence.get()); g_copyQueue->waitForCommandFence(g_copyCommandFence.get());
} }
template<typename T>
static void UnlockBufferImpl(GuestBuffer* buffer)
{
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(buffer->dataSize));
auto dest = reinterpret_cast<T*>(uploadBuffer->map());
auto src = reinterpret_cast<const T*>(buffer->mappedMemory);
for (size_t i = 0; i < buffer->dataSize; i += sizeof(T))
{
*dest = std::byteswap(*src);
++dest;
++src;
}
uploadBuffer->unmap();
ExecuteCopyCommandList([&]
{
g_copyCommandList->copyBufferRegion(buffer->buffer->at(0), uploadBuffer->at(0), buffer->dataSize);
});
}
template<typename T> template<typename T>
static void UnlockBuffer(GuestBuffer* buffer) static void UnlockBuffer(GuestBuffer* buffer)
{ {
if (!buffer->lockedReadOnly) if (!buffer->lockedReadOnly)
{ {
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(buffer->dataSize)); if (GetCurrentThreadId() == g_mainThreadId)
auto dest = reinterpret_cast<T*>(uploadBuffer->map());
auto src = reinterpret_cast<const T*>(buffer->mappedMemory);
for (size_t i = 0; i < buffer->dataSize; i += sizeof(T))
{ {
*dest = std::byteswap(*src); RenderCommand cmd;
++dest; cmd.type = (sizeof(T) == 2) ? RenderCommandType::UnlockBuffer16 : RenderCommandType::UnlockBuffer32;
++src; cmd.unlockBuffer.buffer = buffer;
g_renderQueue.enqueue(cmd);
}
else
{
UnlockBufferImpl<T>(buffer);
} }
uploadBuffer->unmap();
ExecuteCopyCommandList([&]
{
g_copyCommandList->copyBufferRegion(buffer->buffer->at(0), uploadBuffer->at(0), buffer->dataSize);
});
} }
} }
static void ProcUnlockBuffer16(const RenderCommand& cmd)
{
UnlockBufferImpl<uint16_t>(cmd.unlockBuffer.buffer);
}
static void ProcUnlockBuffer32(const RenderCommand& cmd)
{
UnlockBufferImpl<uint32_t>(cmd.unlockBuffer.buffer);
}
static void UnlockVertexBuffer(GuestBuffer* buffer) static void UnlockVertexBuffer(GuestBuffer* buffer)
{ {
UnlockBuffer<uint32_t>(buffer); UnlockBuffer<uint32_t>(buffer);
@ -2777,6 +2810,8 @@ static std::thread g_renderThread([]
case RenderCommandType::SetRenderState: ProcSetRenderState(cmd); break; case RenderCommandType::SetRenderState: ProcSetRenderState(cmd); break;
case RenderCommandType::DestructResource: ProcDestructResource(cmd); break; case RenderCommandType::DestructResource: ProcDestructResource(cmd); break;
case RenderCommandType::UnlockTextureRect: ProcUnlockTextureRect(cmd); break; case RenderCommandType::UnlockTextureRect: ProcUnlockTextureRect(cmd); break;
case RenderCommandType::UnlockBuffer16: ProcUnlockBuffer16(cmd); break;
case RenderCommandType::UnlockBuffer32: ProcUnlockBuffer32(cmd); break;
case RenderCommandType::Present: ProcPresent(cmd); break; case RenderCommandType::Present: ProcPresent(cmd); break;
case RenderCommandType::StretchRect: ProcStretchRect(cmd); break; case RenderCommandType::StretchRect: ProcStretchRect(cmd); break;
case RenderCommandType::SetRenderTarget: ProcSetRenderTarget(cmd); break; case RenderCommandType::SetRenderTarget: ProcSetRenderTarget(cmd); break;