mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 17:25:28 +03:00
Implement support for GPU-side constant buffer updating
Previously constant buffer updates would be handled on the CPU and only the end result would be synced to the GPU before execute. This caused issues as if the constant buffer contents was changed between each draw in a renderpass (e.g. text rendering) the draws themselves would only see the final resulting constant buffer. Fix this by updating cbufs on the GPU/CPU seperately, only ever syncing them back at the start or after a guest side CPU write, at the moment only a single word is updated at a time however this can be optimised in the future to batch all consecutive updates into one large one.
This commit is contained in:
parent
036faedabd
commit
d79635772f
@ -145,10 +145,10 @@ namespace skyline::gpu {
|
|||||||
std::memcpy(data.data(), backing.data() + offset, data.size());
|
std::memcpy(data.data(), backing.data() + offset, data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::Write(span<u8> data, vk::DeviceSize offset) {
|
void Buffer::Write(span<u8> data, vk::DeviceSize offset, bool skipCleanHostWrite) {
|
||||||
if (dirtyState == DirtyState::CpuDirty || dirtyState == DirtyState::Clean)
|
if (dirtyState == DirtyState::CpuDirty || dirtyState == DirtyState::Clean)
|
||||||
std::memcpy(mirror.data() + offset, data.data(), data.size());
|
std::memcpy(mirror.data() + offset, data.data(), data.size());
|
||||||
if (dirtyState == DirtyState::GpuDirty || dirtyState == DirtyState::Clean)
|
if ((!skipCleanHostWrite && dirtyState == DirtyState::Clean) || dirtyState == DirtyState::GpuDirty)
|
||||||
std::memcpy(backing.data() + offset, data.data(), data.size());
|
std::memcpy(backing.data() + offset, data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ namespace skyline::gpu {
|
|||||||
bufferDelegate->buffer->Read(data, offset + bufferDelegate->view->offset);
|
bufferDelegate->buffer->Read(data, offset + bufferDelegate->view->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferView::Write(span<u8> data, vk::DeviceSize offset) const {
|
void BufferView::Write(span<u8> data, vk::DeviceSize offset, bool skipCleanHostWrite) const {
|
||||||
bufferDelegate->buffer->Write(data, offset + bufferDelegate->view->offset);
|
bufferDelegate->buffer->Write(data, offset + bufferDelegate->view->offset, skipCleanHostWrite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,8 +171,9 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes data at the specified offset in the buffer
|
* @brief Writes data at the specified offset in the buffer
|
||||||
|
* @param skipCleanHostWrite Skip writing to the host buffer if it's clean, assumes the buffer data will be synchronised externally
|
||||||
*/
|
*/
|
||||||
void Write(span<u8> data, vk::DeviceSize offset);
|
void Write(span<u8> data, vk::DeviceSize offset, bool skipCleanHostWrite = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A cached or newly created view into this buffer with the supplied attributes
|
* @return A cached or newly created view into this buffer with the supplied attributes
|
||||||
@ -250,7 +251,8 @@ namespace skyline::gpu {
|
|||||||
/**
|
/**
|
||||||
* @brief Writes data at the specified offset in the view
|
* @brief Writes data at the specified offset in the view
|
||||||
* @note The view **must** be locked prior to calling this
|
* @note The view **must** be locked prior to calling this
|
||||||
|
* @param skipCleanHostWrite Skip writing to the host buffer if it's clean, assumes the buffer data will be synchronised externally
|
||||||
*/
|
*/
|
||||||
void Write(span<u8> data, vk::DeviceSize offset) const;
|
void Write(span<u8> data, vk::DeviceSize offset, bool skipCleanHostWrite = false) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -629,7 +629,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void Write(T &object, size_t offset) {
|
void Write(T &object, size_t offset) {
|
||||||
std::scoped_lock lock{view};
|
std::scoped_lock lock{view};
|
||||||
view.Write(span<T>(object).template cast<u8>(), offset);
|
view.Write(span<T>(object).template cast<u8>(), offset, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ConstantBuffer constantBufferSelector; //!< The constant buffer selector is used to bind a constant buffer to a stage or update data in it
|
ConstantBuffer constantBufferSelector; //!< The constant buffer selector is used to bind a constant buffer to a stage or update data in it
|
||||||
@ -698,6 +698,11 @@ namespace skyline::gpu::interconnect {
|
|||||||
if (!view) {
|
if (!view) {
|
||||||
auto mappings{channelCtx.asCtx->gmmu.TranslateRange(constantBufferSelector.iova, constantBufferSelector.size)};
|
auto mappings{channelCtx.asCtx->gmmu.TranslateRange(constantBufferSelector.iova, constantBufferSelector.size)};
|
||||||
view = gpu.buffer.FindOrCreate(mappings.front(), executor.cycle);
|
view = gpu.buffer.FindOrCreate(mappings.front(), executor.cycle);
|
||||||
|
{
|
||||||
|
std::scoped_lock lock{*view};
|
||||||
|
view->bufferDelegate->buffer->SynchronizeHost(false);
|
||||||
|
}
|
||||||
|
|
||||||
constantBufferCache.Insert(constantBufferSelector.size, constantBufferSelector.iova, *view);
|
constantBufferCache.Insert(constantBufferSelector.size, constantBufferSelector.iova, *view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +713,11 @@ namespace skyline::gpu::interconnect {
|
|||||||
void ConstantBufferUpdate(u32 data, u32 offset) {
|
void ConstantBufferUpdate(u32 data, u32 offset) {
|
||||||
auto constantBuffer{GetConstantBufferSelector().value()};
|
auto constantBuffer{GetConstantBufferSelector().value()};
|
||||||
constantBuffer.Write(data, offset);
|
constantBuffer.Write(data, offset);
|
||||||
|
|
||||||
|
executor.AddNonGraphicsPass([view = constantBuffer.view, data, offset](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &) {
|
||||||
|
std::scoped_lock lock{view};
|
||||||
|
commandBuffer.updateBuffer<u32>(view.bufferDelegate->buffer->GetBacking(), offset, vk::ArrayProxy(1, &data));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shader Program */
|
/* Shader Program */
|
||||||
|
Loading…
Reference in New Issue
Block a user