mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 06:16:55 +01:00
renderer: minor optimizations
This commit is contained in:
@@ -924,22 +924,21 @@ RenderExecutor::PrepareGraphicsBindings(CommandBuffer& buffer, const ShaderStage
|
|||||||
return bindings;
|
return bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RetainBindings(CommandBuffer& buffer,
|
static void RetainBindings(CommandBuffer& buffer, DescriptorCache::NativeDescriptors& resources) {
|
||||||
const DescriptorCache::NativeDescriptors& resources) {
|
|
||||||
if (resources.flattened_srt.owner != nullptr) {
|
if (resources.flattened_srt.owner != nullptr) {
|
||||||
buffer.RetainResourceUntilFence(resources.flattened_srt.owner);
|
buffer.RetainResourceUntilFence(std::move(resources.flattened_srt.owner));
|
||||||
}
|
}
|
||||||
if (resources.user_data.owner != nullptr) {
|
if (resources.user_data.owner != nullptr) {
|
||||||
buffer.RetainResourceUntilFence(resources.user_data.owner);
|
buffer.RetainResourceUntilFence(std::move(resources.user_data.owner));
|
||||||
}
|
}
|
||||||
for (const auto& view: resources.buffers) {
|
for (auto& view: resources.buffers) {
|
||||||
if (view.owner != nullptr) {
|
if (view.owner != nullptr) {
|
||||||
buffer.RetainResourceUntilFence(view.owner);
|
buffer.RetainResourceUntilFence(std::move(view.owner));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& view: resources.addresses) {
|
for (auto& view: resources.addresses) {
|
||||||
if (view.owner != nullptr) {
|
if (view.owner != nullptr) {
|
||||||
buffer.RetainResourceUntilFence(view.owner);
|
buffer.RetainResourceUntilFence(std::move(view.owner));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -684,11 +684,24 @@ struct VertexBufferRange {
|
|||||||
[[nodiscard]] uint64_t RequestedSize() const { return requested_end - base_address; }
|
[[nodiscard]] uint64_t RequestedSize() const { return requested_end - base_address; }
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<BufferBinding> AcquireVertexBuffers(RenderCommandBuffer& buffer,
|
struct PreparedVertexBuffers {
|
||||||
const ShaderVertexInputInfo& vs_input_info) {
|
static constexpr uint32_t MaxBuffers = ShaderVertexInputInfo::RES_MAX;
|
||||||
|
|
||||||
|
std::array<vk::Buffer, MaxBuffers> buffers {};
|
||||||
|
std::array<vk::DeviceSize, MaxBuffers> offsets {};
|
||||||
|
std::array<std::shared_ptr<void>, MaxBuffers> owners {};
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t owner_count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static PreparedVertexBuffers AcquireVertexBuffers(RenderCommandBuffer& buffer,
|
||||||
|
const ShaderVertexInputInfo& vs_input_info) {
|
||||||
|
EXIT_IF(vs_input_info.buffers_num < 0 ||
|
||||||
|
vs_input_info.buffers_num > ShaderVertexInputInfo::RES_MAX);
|
||||||
|
|
||||||
// Collect the non-empty guest vertex ranges.
|
// Collect the non-empty guest vertex ranges.
|
||||||
std::vector<VertexBufferRange> ranges;
|
std::array<VertexBufferRange, ShaderVertexInputInfo::RES_MAX> ranges {};
|
||||||
ranges.reserve(vs_input_info.buffers_num);
|
uint32_t range_count = 0;
|
||||||
for (int i = 0; i < vs_input_info.buffers_num; i++) {
|
for (int i = 0; i < vs_input_info.buffers_num; i++) {
|
||||||
const auto& vertex = vs_input_info.buffers[i];
|
const auto& vertex = vs_input_info.buffers[i];
|
||||||
const auto size = VertexBufferDescriptorSize(vertex);
|
const auto size = VertexBufferDescriptorSize(vertex);
|
||||||
@@ -699,27 +712,31 @@ static std::vector<BufferBinding> AcquireVertexBuffers(RenderCommandBuffer&
|
|||||||
EXIT("invalid vertex buffer range: addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
EXIT("invalid vertex buffer range: addr=0x%016" PRIx64 " size=0x%016" PRIx64 "\n",
|
||||||
vertex.addr, size);
|
vertex.addr, size);
|
||||||
}
|
}
|
||||||
ranges.push_back({vertex.addr, vertex.addr + size});
|
ranges[range_count++] = {vertex.addr, vertex.addr + size};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ranges::sort(ranges, [](const VertexBufferRange& left, const VertexBufferRange& right) {
|
std::sort(ranges.begin(), ranges.begin() + range_count,
|
||||||
return left.base_address < right.base_address;
|
[](const VertexBufferRange& left, const VertexBufferRange& right) {
|
||||||
});
|
return left.base_address < right.base_address;
|
||||||
|
});
|
||||||
|
|
||||||
// Merge overlapping or touching ranges before acquiring host buffers.
|
// Merge overlapping or touching ranges before acquiring host buffers.
|
||||||
std::vector<VertexBufferRange> merged_ranges;
|
std::array<VertexBufferRange, ShaderVertexInputInfo::RES_MAX> merged_ranges {};
|
||||||
merged_ranges.reserve(ranges.size());
|
uint32_t merged_count = 0;
|
||||||
for (const auto& range: ranges) {
|
for (uint32_t i = 0; i < range_count; i++) {
|
||||||
if (!merged_ranges.empty() && merged_ranges.back().requested_end >= range.base_address) {
|
const auto& range = ranges[i];
|
||||||
merged_ranges.back().requested_end =
|
if (merged_count != 0 &&
|
||||||
std::max(merged_ranges.back().requested_end, range.requested_end);
|
merged_ranges[merged_count - 1].requested_end >= range.base_address) {
|
||||||
|
merged_ranges[merged_count - 1].requested_end =
|
||||||
|
std::max(merged_ranges[merged_count - 1].requested_end, range.requested_end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
merged_ranges.push_back(range);
|
merged_ranges[merged_count++] = {range.base_address, range.requested_end};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& cache = buffer.GetContext().GetBufferCache();
|
auto& cache = buffer.GetContext().GetBufferCache();
|
||||||
for (auto& range: merged_ranges) {
|
for (uint32_t i = 0; i < merged_count; i++) {
|
||||||
|
auto& range = merged_ranges[i];
|
||||||
// PPSA20298
|
// PPSA20298
|
||||||
const auto size =
|
const auto size =
|
||||||
Libs::LibKernel::Memory::ClampRangeSize(range.base_address, range.RequestedSize());
|
Libs::LibKernel::Memory::ClampRangeSize(range.base_address, range.RequestedSize());
|
||||||
@@ -728,30 +745,47 @@ static std::vector<BufferBinding> AcquireVertexBuffers(RenderCommandBuffer&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild slot bindings, offsetting non-empty slots into their acquired merged range.
|
// Rebuild slot bindings, offsetting non-empty slots into their acquired merged range.
|
||||||
std::vector<BufferBinding> bindings;
|
PreparedVertexBuffers prepared;
|
||||||
bindings.reserve(vs_input_info.buffers_num);
|
prepared.count = static_cast<uint32_t>(vs_input_info.buffers_num);
|
||||||
|
std::shared_ptr<Buffer> null_owner;
|
||||||
|
vk::Buffer null_buffer = nullptr;
|
||||||
for (int i = 0; i < vs_input_info.buffers_num; i++) {
|
for (int i = 0; i < vs_input_info.buffers_num; i++) {
|
||||||
const auto& vertex = vs_input_info.buffers[i];
|
const auto& vertex = vs_input_info.buffers[i];
|
||||||
const auto size = VertexBufferDescriptorSize(vertex);
|
const auto size = VertexBufferDescriptorSize(vertex);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
auto owner = cache.ObtainNullBuffer();
|
if (null_owner == nullptr) {
|
||||||
bindings.push_back({owner, owner->Handle(), 0});
|
null_owner = cache.ObtainNullBuffer();
|
||||||
|
null_buffer = null_owner->Handle();
|
||||||
|
}
|
||||||
|
prepared.buffers[i] = null_buffer;
|
||||||
|
prepared.offsets[i] = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto range = std::ranges::find_if(merged_ranges, [&](const VertexBufferRange& value) {
|
const auto range = std::find_if(merged_ranges.begin(), merged_ranges.begin() + merged_count,
|
||||||
return vertex.addr >= value.base_address && vertex.addr < value.acquired_end;
|
[&](const VertexBufferRange& value) {
|
||||||
});
|
return vertex.addr >= value.base_address &&
|
||||||
if (range == merged_ranges.end()) {
|
vertex.addr < value.acquired_end;
|
||||||
|
});
|
||||||
|
if (range == merged_ranges.begin() + merged_count) {
|
||||||
EXIT("vertex buffer address is outside the acquired range: addr=0x%016" PRIx64 "\n",
|
EXIT("vertex buffer address is outside the acquired range: addr=0x%016" PRIx64 "\n",
|
||||||
vertex.addr);
|
vertex.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto binding = range->binding;
|
prepared.buffers[i] = range->binding.buffer;
|
||||||
binding.offset += vertex.addr - range->base_address;
|
prepared.offsets[i] = range->binding.offset + vertex.addr - range->base_address;
|
||||||
bindings.push_back(std::move(binding));
|
|
||||||
}
|
}
|
||||||
return bindings;
|
|
||||||
|
if (null_owner != nullptr) {
|
||||||
|
prepared.owners[prepared.owner_count++] = std::move(null_owner);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < merged_count; i++) {
|
||||||
|
if (merged_ranges[i].binding.owner != nullptr) {
|
||||||
|
EXIT_IF(prepared.owner_count >= PreparedVertexBuffers::MaxBuffers);
|
||||||
|
prepared.owners[prepared.owner_count++] = std::move(merged_ranges[i].binding.owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prepared;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetDrawDebugPhase(RenderCommandBuffer& buffer, uint64_t submit_id,
|
static void SetDrawDebugPhase(RenderCommandBuffer& buffer, uint64_t submit_id,
|
||||||
@@ -883,10 +917,9 @@ static void RefreshShaders(RenderCommandBuffer& buffer, const DrawCallInfo& draw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<BufferBinding> PrepareVertexBuffers(uint64_t submit_id,
|
static PreparedVertexBuffers PrepareVertexBuffers(uint64_t submit_id, RenderCommandBuffer& buffer,
|
||||||
RenderCommandBuffer& buffer,
|
const DrawCallInfo& draw,
|
||||||
const DrawCallInfo& draw,
|
const ShaderVertexInputInfo& vs_input_info) {
|
||||||
const ShaderVertexInputInfo& vs_input_info) {
|
|
||||||
EXIT_IF(draw.name == nullptr);
|
EXIT_IF(draw.name == nullptr);
|
||||||
(void)submit_id;
|
(void)submit_id;
|
||||||
|
|
||||||
@@ -920,24 +953,28 @@ static PreparedIndexBuffer PrepareIndexBuffer(RenderCommandBuffer& buffe
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void CommitVertexBuffers(RenderCommandBuffer& buffer, vk::CommandBuffer vk_buffer,
|
static void CommitVertexBuffers(RenderCommandBuffer& buffer, vk::CommandBuffer vk_buffer,
|
||||||
std::vector<BufferBinding>& bindings) {
|
PreparedVertexBuffers& prepared) {
|
||||||
for (uint32_t slot = 0; slot < bindings.size(); slot++) {
|
for (uint32_t i = 0; i < prepared.owner_count; i++) {
|
||||||
auto& binding = bindings[slot];
|
if (prepared.owners[i] != nullptr) {
|
||||||
if (binding.owner != nullptr) {
|
buffer.RetainResourceUntilFence(std::move(prepared.owners[i]));
|
||||||
buffer.RetainResourceUntilFence(binding.owner);
|
|
||||||
}
|
}
|
||||||
EXIT_IF(binding.buffer == nullptr);
|
}
|
||||||
vk_buffer.bindVertexBuffers(slot, 1, &binding.buffer, &binding.offset);
|
for (uint32_t i = 0; i < prepared.count; i++) {
|
||||||
|
EXIT_IF(prepared.buffers[i] == nullptr);
|
||||||
|
}
|
||||||
|
if (prepared.count != 0) {
|
||||||
|
vk_buffer.bindVertexBuffers(0, prepared.count, prepared.buffers.data(),
|
||||||
|
prepared.offsets.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CommitIndexBuffer(RenderCommandBuffer& buffer, vk::CommandBuffer vk_buffer,
|
static void CommitIndexBuffer(RenderCommandBuffer& buffer, vk::CommandBuffer vk_buffer,
|
||||||
const PreparedIndexBuffer& prepared) {
|
PreparedIndexBuffer& prepared) {
|
||||||
if (prepared.size == 0) {
|
if (prepared.size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (prepared.owner != nullptr) {
|
if (prepared.owner != nullptr) {
|
||||||
buffer.RetainResourceUntilFence(prepared.owner);
|
buffer.RetainResourceUntilFence(std::move(prepared.owner));
|
||||||
}
|
}
|
||||||
EXIT_IF(prepared.buffer == nullptr);
|
EXIT_IF(prepared.buffer == nullptr);
|
||||||
vk_buffer.bindIndexBuffer(prepared.buffer, prepared.offset, prepared.type);
|
vk_buffer.bindIndexBuffer(prepared.buffer, prepared.offset, prepared.type);
|
||||||
|
|||||||
Reference in New Issue
Block a user