mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 10:15:28 +03:00
Implement batch constant buffer updates
Avoids spamming the driver with hundreds of cbuf updates per frame by batching all consecutive updates into one.
This commit is contained in:
parent
02f99273ac
commit
32fe01e145
@ -698,7 +698,7 @@ namespace skyline::gpu::interconnect {
|
||||
return constantBufferSelector;
|
||||
}
|
||||
|
||||
void ConstantBufferUpdate(u32 data, u32 offset) {
|
||||
void ConstantBufferUpdate(std::vector<u32> data, u32 offset) {
|
||||
auto constantBuffer{GetConstantBufferSelector().value()};
|
||||
auto& constantBufferView{constantBuffer.view};
|
||||
{
|
||||
@ -708,9 +708,9 @@ namespace skyline::gpu::interconnect {
|
||||
constantBufferView.Write(span<u32>(data).cast<u8>(), offset);
|
||||
}
|
||||
|
||||
executor.AddOutsideRpCommand([constantBufferView, data, offset](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &) {
|
||||
executor.AddOutsideRpCommand([constantBufferView, data = std::move(data), offset](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &) {
|
||||
std::scoped_lock lock{constantBufferView};
|
||||
commandBuffer.updateBuffer<u32>(constantBufferView->buffer->GetBacking(), constantBufferView->view->offset + offset, vk::ArrayProxy(1, &data));
|
||||
commandBuffer.updateBuffer<u32>(constantBufferView->buffer->GetBacking(), constantBufferView->view->offset + offset, vk::ArrayProxy(static_cast<u32>(data.size()), data.data()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,27 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
bool redundant{registers.raw[method] == argument};
|
||||
registers.raw[method] = argument;
|
||||
|
||||
if (batchConstantBufferUpdate.Active()) {
|
||||
switch (method) {
|
||||
// Add to the batch constant buffer update buffer
|
||||
// Return early here so that any code below can rely on the fact that any cbuf updates will always be the first of a batch
|
||||
#define CBUF_UPDATE_CALLBACKS(z, index, data_) \
|
||||
ENGINE_STRUCT_ARRAY_CASE(constantBufferUpdate, data, index, { \
|
||||
batchConstantBufferUpdate.buffer.push_back(data); \
|
||||
registers.constantBufferUpdate->offset += 4; \
|
||||
return; \
|
||||
})
|
||||
|
||||
BOOST_PP_REPEAT(16, CBUF_UPDATE_CALLBACKS, 0)
|
||||
#undef CBUF_UPDATE_CALLBACKS
|
||||
default:
|
||||
// When a method other than constant buffer update is called submit our submit the previously built-up update as a batch
|
||||
context.ConstantBufferUpdate(std::move(batchConstantBufferUpdate.buffer), batchConstantBufferUpdate.startOffset);
|
||||
batchConstantBufferUpdate.Reset();
|
||||
break; // Continue on here to handle the actual method
|
||||
}
|
||||
}
|
||||
|
||||
if (!redundant) {
|
||||
switch (method) {
|
||||
ENGINE_STRUCT_CASE(mme, shadowRamControl, {
|
||||
@ -651,10 +672,12 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
registers.raw[0xD00] = 1;
|
||||
})
|
||||
|
||||
#define CBUF_UPDATE_CALLBACKS(z, index, data_) \
|
||||
ENGINE_STRUCT_ARRAY_CASE(constantBufferUpdate, data, index, { \
|
||||
context.ConstantBufferUpdate(data, registers.constantBufferUpdate->offset); \
|
||||
registers.constantBufferUpdate->offset += 4; \
|
||||
// Begin a batch constant buffer update, this case will never be reached if a batch update is currently active
|
||||
#define CBUF_UPDATE_CALLBACKS(z, index, data_) \
|
||||
ENGINE_STRUCT_ARRAY_CASE(constantBufferUpdate, data, index, { \
|
||||
batchConstantBufferUpdate.startOffset = registers.constantBufferUpdate->offset; \
|
||||
batchConstantBufferUpdate.buffer.push_back(data); \
|
||||
registers.constantBufferUpdate->offset += 4; \
|
||||
})
|
||||
|
||||
BOOST_PP_REPEAT(16, CBUF_UPDATE_CALLBACKS, 0)
|
||||
|
@ -22,6 +22,20 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
gpu::interconnect::GraphicsContext context;
|
||||
Inline2MemoryBackend i2m;
|
||||
|
||||
struct BatchConstantBufferUpdateState {
|
||||
std::vector<u32> buffer;
|
||||
u32 startOffset{std::numeric_limits<u32>::max()};
|
||||
|
||||
bool Active() {
|
||||
return startOffset != std::numeric_limits<u32>::max();
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
buffer.clear();
|
||||
startOffset = std::numeric_limits<u32>::max();
|
||||
}
|
||||
} batchConstantBufferUpdate; //!< Holds state for updating constant buffer data in a batch rather than word by word
|
||||
|
||||
/**
|
||||
* @brief Calls the appropriate function corresponding to a certain method with the supplied argument
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user