mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 17:45: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;
|
return constantBufferSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantBufferUpdate(u32 data, u32 offset) {
|
void ConstantBufferUpdate(std::vector<u32> data, u32 offset) {
|
||||||
auto constantBuffer{GetConstantBufferSelector().value()};
|
auto constantBuffer{GetConstantBufferSelector().value()};
|
||||||
auto& constantBufferView{constantBuffer.view};
|
auto& constantBufferView{constantBuffer.view};
|
||||||
{
|
{
|
||||||
@ -708,9 +708,9 @@ namespace skyline::gpu::interconnect {
|
|||||||
constantBufferView.Write(span<u32>(data).cast<u8>(), offset);
|
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};
|
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};
|
bool redundant{registers.raw[method] == argument};
|
||||||
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) {
|
if (!redundant) {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
ENGINE_STRUCT_CASE(mme, shadowRamControl, {
|
ENGINE_STRUCT_CASE(mme, shadowRamControl, {
|
||||||
@ -651,9 +672,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
registers.raw[0xD00] = 1;
|
registers.raw[0xD00] = 1;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 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_) \
|
#define CBUF_UPDATE_CALLBACKS(z, index, data_) \
|
||||||
ENGINE_STRUCT_ARRAY_CASE(constantBufferUpdate, data, index, { \
|
ENGINE_STRUCT_ARRAY_CASE(constantBufferUpdate, data, index, { \
|
||||||
context.ConstantBufferUpdate(data, registers.constantBufferUpdate->offset); \
|
batchConstantBufferUpdate.startOffset = registers.constantBufferUpdate->offset; \
|
||||||
|
batchConstantBufferUpdate.buffer.push_back(data); \
|
||||||
registers.constantBufferUpdate->offset += 4; \
|
registers.constantBufferUpdate->offset += 4; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -22,6 +22,20 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
gpu::interconnect::GraphicsContext context;
|
gpu::interconnect::GraphicsContext context;
|
||||||
Inline2MemoryBackend i2m;
|
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
|
* @brief Calls the appropriate function corresponding to a certain method with the supplied argument
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user