Skip to content

Commit 16f2b57

Browse files
Apply upstream renderer optimizations from 869329e
- Refactor AcquireVertexBuffers to return PreparedVertexBuffers struct - Use std::array instead of std::vector for vertex buffer ranges - Improve vertex buffer range merging logic - Update PrepareVertexBuffers, CommitVertexBuffers, RebindVertexBuffers to use new types
1 parent 9937a8f commit 16f2b57

1 file changed

Lines changed: 76 additions & 38 deletions

File tree

src/graphics/host_gpu/renderer/renderDraw.cpp

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -736,11 +736,24 @@ struct VertexBufferRange {
736736
[[nodiscard]] uint64_t RequestedSize() const { return requested_end - base_address; }
737737
};
738738

739-
static std::vector<BufferBinding> AcquireVertexBuffers(RenderCommandBuffer& buffer,
740-
const ShaderVertexInputInfo& vs_input_info) {
739+
struct PreparedVertexBuffers {
740+
static constexpr uint32_t MaxBuffers = ShaderVertexInputInfo::RES_MAX;
741+
742+
std::array<vk::Buffer, MaxBuffers> buffers {};
743+
std::array<vk::DeviceSize, MaxBuffers> offsets {};
744+
std::array<std::shared_ptr<void>, MaxBuffers> owners {};
745+
uint32_t count = 0;
746+
uint32_t owner_count = 0;
747+
};
748+
749+
static PreparedVertexBuffers AcquireVertexBuffers(RenderCommandBuffer& buffer,
750+
const ShaderVertexInputInfo& vs_input_info) {
751+
EXIT_IF(vs_input_info.buffers_num < 0 ||
752+
vs_input_info.buffers_num > ShaderVertexInputInfo::RES_MAX);
753+
741754
// Collect the non-empty guest vertex ranges.
742-
std::vector<VertexBufferRange> ranges;
743-
ranges.reserve(vs_input_info.buffers_num);
755+
std::array<VertexBufferRange, ShaderVertexInputInfo::RES_MAX> ranges {};
756+
uint32_t range_count = 0;
744757
for (int i = 0; i < vs_input_info.buffers_num; i++) {
745758
const auto& vertex = vs_input_info.buffers[i];
746759
const auto size = VertexBufferDescriptorSize(vertex);
@@ -751,27 +764,31 @@ static std::vector<BufferBinding> AcquireVertexBuffers(RenderCommandBuffer&
751764
EXIT("invalid vertex buffer range: addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
752765
vertex.addr, size);
753766
}
754-
ranges.push_back({vertex.addr, vertex.addr + size});
767+
ranges[range_count++] = {vertex.addr, vertex.addr + size};
755768
}
756769

757-
std::ranges::sort(ranges, [](const VertexBufferRange& left, const VertexBufferRange& right) {
758-
return left.base_address < right.base_address;
759-
});
770+
std::sort(ranges.begin(), ranges.begin() + range_count,
771+
[](const VertexBufferRange& left, const VertexBufferRange& right) {
772+
return left.base_address < right.base_address;
773+
});
760774

761775
// Merge overlapping or touching ranges before acquiring host buffers.
762-
std::vector<VertexBufferRange> merged_ranges;
763-
merged_ranges.reserve(ranges.size());
764-
for (const auto& range: ranges) {
765-
if (!merged_ranges.empty() && merged_ranges.back().requested_end >= range.base_address) {
766-
merged_ranges.back().requested_end =
767-
std::max(merged_ranges.back().requested_end, range.requested_end);
776+
std::array<VertexBufferRange, ShaderVertexInputInfo::RES_MAX> merged_ranges {};
777+
uint32_t merged_count = 0;
778+
for (uint32_t i = 0; i < range_count; i++) {
779+
const auto& range = ranges[i];
780+
if (merged_count != 0 &&
781+
merged_ranges[merged_count - 1].requested_end >= range.base_address) {
782+
merged_ranges[merged_count - 1].requested_end =
783+
std::max(merged_ranges[merged_count - 1].requested_end, range.requested_end);
768784
continue;
769785
}
770-
merged_ranges.push_back(range);
786+
merged_ranges[merged_count++] = {range.base_address, range.requested_end};
771787
}
772788

773789
auto& cache = buffer.GetContext().GetBufferCache();
774-
for (auto& range: merged_ranges) {
790+
for (uint32_t i = 0; i < merged_count; i++) {
791+
auto& range = merged_ranges[i];
775792
// PPSA20298
776793
const auto size =
777794
Libs::LibKernel::Memory::ClampRangeSize(range.base_address, range.RequestedSize());
@@ -780,30 +797,47 @@ static std::vector<BufferBinding> AcquireVertexBuffers(RenderCommandBuffer&
780797
}
781798

782799
// Rebuild slot bindings, offsetting non-empty slots into their acquired merged range.
783-
std::vector<BufferBinding> bindings;
784-
bindings.reserve(vs_input_info.buffers_num);
800+
PreparedVertexBuffers prepared;
801+
prepared.count = static_cast<uint32_t>(vs_input_info.buffers_num);
802+
std::shared_ptr<Buffer> null_owner;
803+
vk::Buffer null_buffer = nullptr;
785804
for (int i = 0; i < vs_input_info.buffers_num; i++) {
786805
const auto& vertex = vs_input_info.buffers[i];
787806
const auto size = VertexBufferDescriptorSize(vertex);
788807
if (size == 0) {
789-
auto owner = cache.ObtainNullBuffer();
790-
bindings.push_back({owner, owner->Handle(), 0});
808+
if (null_owner == nullptr) {
809+
null_owner = cache.ObtainNullBuffer();
810+
null_buffer = null_owner->Handle();
811+
}
812+
prepared.buffers[i] = null_buffer;
813+
prepared.offsets[i] = 0;
791814
continue;
792815
}
793816

794-
const auto range = std::ranges::find_if(merged_ranges, [&](const VertexBufferRange& value) {
795-
return vertex.addr >= value.base_address && vertex.addr < value.acquired_end;
796-
});
797-
if (range == merged_ranges.end()) {
817+
const auto range = std::find_if(merged_ranges.begin(), merged_ranges.begin() + merged_count,
818+
[&](const VertexBufferRange& value) {
819+
return vertex.addr >= value.base_address &&
820+
vertex.addr < value.acquired_end;
821+
});
822+
if (range == merged_ranges.begin() + merged_count) {
798823
EXIT("vertex buffer address is outside the acquired range: addr=0x%016" PRIx64 "\n",
799824
vertex.addr);
800825
}
801826

802-
auto binding = range->binding;
803-
binding.offset += vertex.addr - range->base_address;
804-
bindings.push_back(std::move(binding));
827+
prepared.buffers[i] = range->binding.buffer;
828+
prepared.offsets[i] = range->binding.offset + vertex.addr - range->base_address;
829+
}
830+
831+
if (null_owner != nullptr) {
832+
prepared.owners[prepared.owner_count++] = std::move(null_owner);
833+
}
834+
for (uint32_t i = 0; i < merged_count; i++) {
835+
if (merged_ranges[i].binding.owner != nullptr) {
836+
EXIT_IF(prepared.owner_count >= PreparedVertexBuffers::MaxBuffers);
837+
prepared.owners[prepared.owner_count++] = std::move(merged_ranges[i].binding.owner);
838+
}
805839
}
806-
return bindings;
840+
return prepared;
807841
}
808842

809843
static void SetDrawDebugPhase(RenderCommandBuffer& buffer, uint64_t submit_id,
@@ -937,7 +971,7 @@ static bool RefreshShaders(RenderCommandBuffer& buffer, const DrawCallInfo& draw
937971
return true;
938972
}
939973

940-
static std::vector<BufferBinding> PrepareVertexBuffers(uint64_t submit_id,
974+
static PreparedVertexBuffers PrepareVertexBuffers(uint64_t submit_id,
941975
RenderCommandBuffer& buffer,
942976
const DrawCallInfo& draw,
943977
const ShaderVertexInputInfo& vs_input_info) {
@@ -950,8 +984,8 @@ static std::vector<BufferBinding> PrepareVertexBuffers(uint64_t
950984

951985
static void RebindVertexBuffers(RenderCommandBuffer& buffer,
952986
const ShaderVertexInputInfo& vs_input_info,
953-
std::vector<BufferBinding>& bindings) {
954-
bindings = AcquireVertexBuffers(buffer, vs_input_info);
987+
PreparedVertexBuffers& prepared) {
988+
prepared = AcquireVertexBuffers(buffer, vs_input_info);
955989
}
956990

957991
static PreparedIndexBuffer PrepareIndexBuffer(RenderCommandBuffer& buffer,
@@ -993,14 +1027,18 @@ static void RebindIndexBuffer(RenderCommandBuffer& buffer, PreparedIndexBuffer&
9931027
}
9941028

9951029
static void CommitVertexBuffers(RenderCommandBuffer& buffer, vk::CommandBuffer vk_buffer,
996-
std::vector<BufferBinding>& bindings) {
997-
for (uint32_t slot = 0; slot < bindings.size(); slot++) {
998-
auto& binding = bindings[slot];
999-
if (binding.owner != nullptr) {
1000-
buffer.RetainResourceUntilFence(binding.owner);
1030+
PreparedVertexBuffers& prepared) {
1031+
for (uint32_t i = 0; i < prepared.owner_count; i++) {
1032+
if (prepared.owners[i] != nullptr) {
1033+
buffer.RetainResourceUntilFence(std::move(prepared.owners[i]));
10011034
}
1002-
EXIT_IF(binding.buffer == nullptr);
1003-
vk_buffer.bindVertexBuffers(slot, 1, &binding.buffer, &binding.offset);
1035+
}
1036+
for (uint32_t i = 0; i < prepared.count; i++) {
1037+
EXIT_IF(prepared.buffers[i] == nullptr);
1038+
}
1039+
if (prepared.count != 0) {
1040+
vk_buffer.bindVertexBuffers(0, prepared.count, prepared.buffers.data(),
1041+
prepared.offsets.data());
10041042
}
10051043
}
10061044

0 commit comments

Comments
 (0)