mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-29 09:58:05 +00:00
Add instance draw counts to vertex buffers
This commit is contained in:
@@ -1244,6 +1244,20 @@ void BufferCache<P>::UpdateIndexBuffer() {
|
||||
template <class P>
|
||||
void BufferCache<P>::UpdateVertexBuffers() {
|
||||
auto& flags = maxwell3d->dirty.flags;
|
||||
const u32 base_instance = maxwell3d->draw_manager.draw_state.base_instance;
|
||||
if (draw_instance_count != last_draw_instance_count ||
|
||||
base_instance != last_draw_base_instance) {
|
||||
last_draw_instance_count = draw_instance_count;
|
||||
last_draw_base_instance = base_instance;
|
||||
const auto& instances = maxwell3d->regs.vertex_stream_instances;
|
||||
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
|
||||
if (!instances.IsInstancingEnabled(index)) {
|
||||
continue;
|
||||
}
|
||||
flags[Dirty::VertexBuffer0 + index] = true;
|
||||
flags[Dirty::VertexBuffers] = true;
|
||||
}
|
||||
}
|
||||
if (!maxwell3d->dirty.flags[Dirty::VertexBuffers]) {
|
||||
return;
|
||||
}
|
||||
@@ -1270,9 +1284,24 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
|
||||
return;
|
||||
}
|
||||
// TODO: Analyze stride and number of vertices
|
||||
u64 address_size = (std::min)(gpu_addr_end - gpu_addr_begin,
|
||||
u64{(std::numeric_limits<u32>::max)()});
|
||||
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || address_size >= 64_MiB) {
|
||||
constexpr u64 implausible_size = 64_MiB;
|
||||
u64 address_size = gpu_addr_end - gpu_addr_begin;
|
||||
if (address_size > u64{(std::numeric_limits<u32>::max)()}) {
|
||||
address_size = implausible_size;
|
||||
}
|
||||
const bool is_instanced = maxwell3d->regs.vertex_stream_instances.IsInstancingEnabled(index);
|
||||
const u64 stride = static_cast<u64>(array.stride);
|
||||
if (is_instanced && stride != 0 && draw_instance_count != 0) {
|
||||
const u64 base_instance = static_cast<u64>(maxwell3d->draw_manager.draw_state.base_instance);
|
||||
u64 elements = base_instance + 1;
|
||||
if (array.frequency != 0) {
|
||||
elements = (base_instance + static_cast<u64>(draw_instance_count) - 1) /
|
||||
static_cast<u64>(array.frequency) +
|
||||
1;
|
||||
}
|
||||
address_size = (std::min)(address_size, (elements + 1) * stride);
|
||||
}
|
||||
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || address_size >= implausible_size) {
|
||||
address_size = gpu_memory->MaxContinuousRange(gpu_addr_begin, address_size);
|
||||
}
|
||||
const u32 size = static_cast<u32>(address_size);
|
||||
|
||||
@@ -307,6 +307,10 @@ public:
|
||||
current_draw_indirect = current_draw_indirect_;
|
||||
}
|
||||
|
||||
void SetDrawInstanceCount(u32 draw_instance_count_) {
|
||||
draw_instance_count = draw_instance_count_;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::pair<Buffer*, u32> GetDrawIndirectCount();
|
||||
|
||||
[[nodiscard]] std::pair<Buffer*, u32> GetDrawIndirectBuffer();
|
||||
@@ -480,6 +484,10 @@ private:
|
||||
|
||||
const Tegra::Engines::Maxwell3D::DrawManager::IndirectParams* current_draw_indirect{};
|
||||
|
||||
u32 draw_instance_count = 0;
|
||||
u32 last_draw_instance_count = 0;
|
||||
u32 last_draw_base_instance = 0;
|
||||
|
||||
u32 last_index_count = 0;
|
||||
|
||||
u32 enabled_vertex_buffers_mask = 0;
|
||||
|
||||
@@ -259,6 +259,7 @@ void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
||||
buffer_cache.SetDrawInstanceCount(instance_count);
|
||||
PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) {
|
||||
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||
const GLuint base_instance = GLuint(draw_state.base_instance);
|
||||
@@ -304,6 +305,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
||||
void RasterizerOpenGL::DrawIndirect() {
|
||||
const auto& params = maxwell3d->draw_manager.indirect_state;
|
||||
buffer_cache.SetDrawIndirect(¶ms);
|
||||
buffer_cache.SetDrawInstanceCount(0);
|
||||
PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) {
|
||||
if (params.is_byte_count) {
|
||||
const GPUVAddr tfb_object_base_addr = params.indirect_start_address - 4U;
|
||||
|
||||
@@ -260,6 +260,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||
}
|
||||
|
||||
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
||||
buffer_cache.SetDrawInstanceCount(instance_count);
|
||||
PrepareDraw(is_indexed, [this, is_indexed, instance_count] {
|
||||
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||
const u32 num_instances{instance_count};
|
||||
@@ -295,6 +296,7 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
||||
void RasterizerVulkan::DrawIndirect() {
|
||||
const auto& params = maxwell3d->draw_manager.indirect_state;
|
||||
buffer_cache.SetDrawIndirect(¶ms);
|
||||
buffer_cache.SetDrawInstanceCount(0);
|
||||
PrepareDraw(params.is_indexed, [this, ¶ms] {
|
||||
const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer();
|
||||
const auto& buffer = indirect_buffer.first;
|
||||
|
||||
Reference in New Issue
Block a user