Update user code for new megabuffering

This commit is contained in:
Billy Laws 2022-09-17 13:09:06 +01:00
parent cc776ae395
commit 55d77b7eb0
4 changed files with 36 additions and 45 deletions

View File

@ -13,15 +13,6 @@
#include "active_state.h" #include "active_state.h"
namespace skyline::gpu::interconnect::maxwell3d { namespace skyline::gpu::interconnect::maxwell3d {
/* General Buffer Helpers */
static BufferBinding *AllocateMegaBufferBinding(InterconnectContext &ctx, BufferView &view) {
auto megaBufferAllocation{view.AcquireMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator())};
if (megaBufferAllocation)
return ctx.executor.allocator.EmplaceUntracked<BufferBinding>(megaBufferAllocation.buffer, megaBufferAllocation.offset, view.size);
else
return nullptr;
}
/* Vertex Buffer */ /* Vertex Buffer */
void VertexBufferState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { void VertexBufferState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
manager.Bind(handle, vertexStream.format, vertexStream.location); manager.Bind(handle, vertexStream.format, vertexStream.location);
@ -36,24 +27,28 @@ namespace skyline::gpu::interconnect::maxwell3d {
view.Update(ctx, engine->vertexStream.location, size); view.Update(ctx, engine->vertexStream.location, size);
ctx.executor.AttachBuffer(*view); ctx.executor.AttachBuffer(*view);
if (megaBufferBinding = AllocateMegaBufferBinding(ctx, *view); megaBufferBinding) if (megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber);
megaBufferBinding)
builder.SetVertexBuffer(index, megaBufferBinding); builder.SetVertexBuffer(index, megaBufferBinding);
else else
builder.SetVertexBuffer(index, *view); builder.SetVertexBuffer(index, *view);
} else { } else {
auto nullBinding{ctx.executor.allocator.EmplaceUntracked<BufferBinding>()}; // TODO: null descriptor
megaBufferBinding = {};
builder.SetVertexBuffer(index, nullBinding);
} }
} }
bool VertexBufferState::Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder) { bool VertexBufferState::Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder) {
if (megaBufferBinding) { if (megaBufferBinding) {
if (megaBufferBinding = AllocateMegaBufferBinding(ctx, *view); megaBufferBinding) if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber)};
newMegaBufferBinding != megaBufferBinding) {
megaBufferBinding = newMegaBufferBinding;
if (megaBufferBinding)
builder.SetVertexBuffer(index, megaBufferBinding); builder.SetVertexBuffer(index, megaBufferBinding);
else else
builder.SetVertexBuffer(index, *view); builder.SetVertexBuffer(index, *view);
} }
}
return false; return false;
} }
@ -89,7 +84,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
} }
static BufferBinding *GenerateQuadConversionIndexBuffer(InterconnectContext &ctx, vk::IndexType indexType, BufferView &view, u32 elementCount) { static BufferBinding GenerateQuadConversionIndexBuffer(InterconnectContext &ctx, vk::IndexType indexType, BufferView &view, u32 elementCount) {
auto viewSpan{view.GetReadOnlyBackingSpan(false /* We attach above so always false */, []() { auto viewSpan{view.GetReadOnlyBackingSpan(false /* We attach above so always false */, []() {
// TODO: see Read() // TODO: see Read()
Logger::Error("Dirty index buffer reads for attached buffers are unimplemented"); Logger::Error("Dirty index buffer reads for attached buffers are unimplemented");
@ -100,7 +95,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
conversion::quads::GenerateIndexedQuadConversionBuffer(quadConversionAllocation.region.data(), viewSpan.data(), elementCount, indexType); conversion::quads::GenerateIndexedQuadConversionBuffer(quadConversionAllocation.region.data(), viewSpan.data(), elementCount, indexType);
return ctx.executor.allocator.EmplaceUntracked<BufferBinding>(quadConversionAllocation.buffer, quadConversionAllocation.offset, indexBufferSize); return {quadConversionAllocation.buffer, quadConversionAllocation.offset, indexBufferSize};
} }
/* Index Buffer */ /* Index Buffer */
@ -123,7 +118,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
if (quadConversion) if (quadConversion)
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, indexType, *view, elementCount); megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, indexType, *view, elementCount);
else else
megaBufferBinding = AllocateMegaBufferBinding(ctx, *view); megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber);
if (megaBufferBinding) if (megaBufferBinding)
builder.SetIndexBuffer(megaBufferBinding, indexType); builder.SetIndexBuffer(megaBufferBinding, indexType);
@ -143,11 +138,16 @@ namespace skyline::gpu::interconnect::maxwell3d {
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, indexType, *view, elementCount); megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, indexType, *view, elementCount);
builder.SetIndexBuffer(megaBufferBinding, indexType); builder.SetIndexBuffer(megaBufferBinding, indexType);
} else if (megaBufferBinding) { } else if (megaBufferBinding) {
if (megaBufferBinding = AllocateMegaBufferBinding(ctx, *view); megaBufferBinding) if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber)};
newMegaBufferBinding != megaBufferBinding) {
megaBufferBinding = newMegaBufferBinding;
if (megaBufferBinding)
builder.SetIndexBuffer(megaBufferBinding, indexType); builder.SetIndexBuffer(megaBufferBinding, indexType);
else else
builder.SetIndexBuffer(*view, indexType); builder.SetIndexBuffer(*view, indexType);
} }
}
return false; return false;
} }
@ -174,9 +174,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
builder.SetTransformFeedbackBuffer(index, *view); builder.SetTransformFeedbackBuffer(index, *view);
} else { } else {
// Bind an empty buffer ourselves since Vulkan doesn't support passing a VK_NULL_HANDLE xfb buffer // Bind an empty buffer ourselves since Vulkan doesn't support passing a VK_NULL_HANDLE xfb buffer
auto binding{ctx.executor.allocator.EmplaceUntracked<BufferBinding>( builder.SetTransformFeedbackBuffer(index, {ctx.executor.AcquireMegaBufferAllocator().Allocate(ctx.executor.cycle, 0).buffer});
ctx.executor.AcquireMegaBufferAllocator().Allocate(ctx.executor.cycle, 0).buffer)};
builder.SetTransformFeedbackBuffer(index, binding);
} }
} }
} }

View File

@ -21,7 +21,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
dirty::BoundSubresource<EngineRegisters> engine; dirty::BoundSubresource<EngineRegisters> engine;
CachedMappedBufferView view{}; CachedMappedBufferView view{};
BufferBinding *megaBufferBinding{}; BufferBinding megaBufferBinding{};
u32 index{}; u32 index{};
public: public:
@ -45,7 +45,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
private: private:
dirty::BoundSubresource<EngineRegisters> engine; dirty::BoundSubresource<EngineRegisters> engine;
CachedMappedBufferView view{}; CachedMappedBufferView view{};
BufferBinding *megaBufferBinding{}; BufferBinding megaBufferBinding{};
vk::IndexType indexType{}; vk::IndexType indexType{};
u32 usedElementCount{}; u32 usedElementCount{};
bool usedQuadConversion{}; bool usedQuadConversion{};

View File

@ -65,18 +65,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
}; };
/**
* @brief Represents a bound Vulkan buffer that can be used for state updates
*/
struct BufferBinding {
vk::Buffer buffer{};
vk::DeviceSize offset{};
vk::DeviceSize size{};
BufferBinding() = default;
BufferBinding(vk::Buffer buffer, vk::DeviceSize offset = 0, vk::DeviceSize size = 0) : buffer{buffer}, offset{offset}, size{size} {}
};
using DynamicBufferBinding = std::variant<BufferBinding, BufferView>; using DynamicBufferBinding = std::variant<BufferBinding, BufferView>;
using DirtyManager = dirty::Manager<soc::gm20b::engine::EngineMethodsEnd * sizeof(u32), sizeof(u32)>; using DirtyManager = dirty::Manager<soc::gm20b::engine::EngineMethodsEnd * sizeof(u32), sizeof(u32)>;

View File

@ -571,11 +571,16 @@ namespace skyline::gpu::interconnect::maxwell3d {
const auto &stage{shaderStages[i]}; const auto &stage{shaderStages[i]};
writeBufferDescs(vk::DescriptorType::eUniformBuffer, stage.info.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount, writeBufferDescs(vk::DescriptorType::eUniformBuffer, stage.info.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount,
[&](const Shader::ConstantBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) -> DynamicBufferBinding { [&](const Shader::ConstantBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) -> DynamicBufferBinding {
auto view{constantBuffers[i][desc.index + arrayIdx].view}; size_t cbufIdx{desc.index + arrayIdx};
if (auto megaBufferAlloc{view.AcquireMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator())}) { auto view{constantBuffers[i][cbufIdx].view};
return BufferBinding(megaBufferAlloc.buffer, megaBufferAlloc.offset, view.size);
} else {
ctx.executor.AttachBuffer(view); ctx.executor.AttachBuffer(view);
size_t sizeOverride{std::min<size_t>(stage.info.constant_buffer_used_sizes[cbufIdx], view.size)};
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber, sizeOverride)}) {
return megaBufferBinding;
} else {
view.GetBuffer()->BlockSequencedCpuBackingWrites();
return view; return view;
} }
}); });