mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 05:28:56 +02:00
[video_core/engines/maxwell3d] memory inline DrawState to reduce indirection on hot paths
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
f0d77e86e3
commit
3eb537ed82
15 changed files with 231 additions and 350 deletions
|
|
@ -44,7 +44,6 @@ add_library(video_core STATIC
|
||||||
engines/sw_blitter/converter.h
|
engines/sw_blitter/converter.h
|
||||||
engines/const_buffer_info.h
|
engines/const_buffer_info.h
|
||||||
engines/draw_manager.cpp
|
engines/draw_manager.cpp
|
||||||
engines/draw_manager.h
|
|
||||||
engines/engine_interface.h
|
engines/engine_interface.h
|
||||||
engines/engine_upload.cpp
|
engines/engine_upload.cpp
|
||||||
engines/engine_upload.h
|
engines/engine_upload.h
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ void BufferCache<P>::BindHostGeometryBuffers(bool is_indexed) {
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
BindHostIndexBuffer();
|
BindHostIndexBuffer();
|
||||||
} else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
|
} else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
if (draw_state.topology == Maxwell::PrimitiveTopology::Quads ||
|
if (draw_state.topology == Maxwell::PrimitiveTopology::Quads ||
|
||||||
draw_state.topology == Maxwell::PrimitiveTopology::QuadStrip) {
|
draw_state.topology == Maxwell::PrimitiveTopology::QuadStrip) {
|
||||||
runtime.BindQuadIndexBuffer(draw_state.topology, draw_state.vertex_buffer.first,
|
runtime.BindQuadIndexBuffer(draw_state.topology, draw_state.vertex_buffer.first,
|
||||||
|
|
@ -740,30 +740,25 @@ void BufferCache<P>::BindHostIndexBuffer() {
|
||||||
TouchBuffer(buffer, channel_state->index_buffer.buffer_id);
|
TouchBuffer(buffer, channel_state->index_buffer.buffer_id);
|
||||||
const u32 offset = buffer.Offset(channel_state->index_buffer.device_addr);
|
const u32 offset = buffer.Offset(channel_state->index_buffer.device_addr);
|
||||||
const u32 size = channel_state->index_buffer.size;
|
const u32 size = channel_state->index_buffer.size;
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
if (!draw_state.inline_index_draw_indexes.empty()) [[unlikely]] {
|
if (draw_state.inline_index_draw_indexes.empty()) {
|
||||||
|
SynchronizeBuffer(buffer, channel_state->index_buffer.device_addr, size);
|
||||||
|
} else {
|
||||||
if constexpr (USE_MEMORY_MAPS_FOR_UPLOADS) {
|
if constexpr (USE_MEMORY_MAPS_FOR_UPLOADS) {
|
||||||
auto upload_staging = runtime.UploadStagingBuffer(size);
|
auto upload_staging = runtime.UploadStagingBuffer(size);
|
||||||
std::array<BufferCopy, 1> copies{
|
std::array<BufferCopy, 1> copies{{BufferCopy{.src_offset = upload_staging.offset, .dst_offset = 0, .size = size}}};
|
||||||
{BufferCopy{.src_offset = upload_staging.offset, .dst_offset = 0, .size = size}}};
|
std::memcpy(upload_staging.mapped_span.data(), draw_state.inline_index_draw_indexes.data(), size);
|
||||||
std::memcpy(upload_staging.mapped_span.data(),
|
|
||||||
draw_state.inline_index_draw_indexes.data(), size);
|
|
||||||
runtime.CopyBuffer(buffer, upload_staging.buffer, copies, true);
|
runtime.CopyBuffer(buffer, upload_staging.buffer, copies, true);
|
||||||
} else {
|
} else {
|
||||||
buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes);
|
buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SynchronizeBuffer(buffer, channel_state->index_buffer.device_addr, size);
|
|
||||||
}
|
}
|
||||||
if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
|
if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
|
||||||
const u32 new_offset =
|
const u32 new_offset = offset + draw_state.index_buffer.first * draw_state.index_buffer.FormatSizeInBytes();
|
||||||
offset + draw_state.index_buffer.first * draw_state.index_buffer.FormatSizeInBytes();
|
|
||||||
runtime.BindIndexBuffer(buffer, new_offset, size);
|
runtime.BindIndexBuffer(buffer, new_offset, size);
|
||||||
} else {
|
} else {
|
||||||
buffer.MarkUsage(offset, size);
|
buffer.MarkUsage(offset, size);
|
||||||
runtime.BindIndexBuffer(draw_state.topology, draw_state.index_buffer.format,
|
runtime.BindIndexBuffer(draw_state.topology, draw_state.index_buffer.format, draw_state.index_buffer.first, draw_state.index_buffer.count, buffer, offset, size);
|
||||||
draw_state.index_buffer.first, draw_state.index_buffer.count,
|
|
||||||
buffer, offset, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -945,10 +940,9 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
||||||
return alignment > 1 && (offset % alignment) != 0;
|
return alignment > 1 && (offset % alignment) != 0;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
const bool use_fast_buffer = needs_alignment_stream ||
|
const bool use_fast_buffer = needs_alignment_stream
|
||||||
(has_host_buffer &&
|
|| (has_host_buffer && size <= channel_state->uniform_buffer_skip_cache_size
|
||||||
size <= channel_state->uniform_buffer_skip_cache_size &&
|
&& !memory_tracker.IsRegionGpuModified(device_addr, size));
|
||||||
!memory_tracker.IsRegionGpuModified(device_addr, size));
|
|
||||||
if (use_fast_buffer) {
|
if (use_fast_buffer) {
|
||||||
if constexpr (IS_OPENGL) {
|
if constexpr (IS_OPENGL) {
|
||||||
if (runtime.HasFastBufferSubData()) {
|
if (runtime.HasFastBufferSubData()) {
|
||||||
|
|
@ -1226,7 +1220,7 @@ template <class P>
|
||||||
void BufferCache<P>::UpdateIndexBuffer() {
|
void BufferCache<P>::UpdateIndexBuffer() {
|
||||||
// We have to check for the dirty flags and index count
|
// We have to check for the dirty flags and index count
|
||||||
// The index count is currently changed without updating the dirty flags
|
// The index count is currently changed without updating the dirty flags
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
const auto& index_buffer_ref = draw_state.index_buffer;
|
const auto& index_buffer_ref = draw_state.index_buffer;
|
||||||
auto& flags = maxwell3d->dirty.flags;
|
auto& flags = maxwell3d->dirty.flags;
|
||||||
if (!flags[Dirty::IndexBuffer]) {
|
if (!flags[Dirty::IndexBuffer]) {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
#include "video_core/control/channel_state_cache.h"
|
#include "video_core/control/channel_state_cache.h"
|
||||||
#include "video_core/delayed_destruction_ring.h"
|
#include "video_core/delayed_destruction_ring.h"
|
||||||
#include "video_core/dirty_flags.h"
|
#include "video_core/dirty_flags.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
@ -305,7 +305,7 @@ public:
|
||||||
[[nodiscard]] bool IsRegionCpuModified(DAddr addr, size_t size);
|
[[nodiscard]] bool IsRegionCpuModified(DAddr addr, size_t size);
|
||||||
|
|
||||||
void SetDrawIndirect(
|
void SetDrawIndirect(
|
||||||
const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect_) {
|
const Tegra::Engines::Maxwell3D::DrawManager::IndirectParams* current_draw_indirect_) {
|
||||||
current_draw_indirect = current_draw_indirect_;
|
current_draw_indirect = current_draw_indirect_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -480,7 +480,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
DelayedDestructionRing<Buffer, TICKS_TO_DESTROY> delayed_destruction_ring;
|
DelayedDestructionRing<Buffer, TICKS_TO_DESTROY> delayed_destruction_ring;
|
||||||
|
|
||||||
const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{};
|
const Tegra::Engines::Maxwell3D::DrawManager::IndirectParams* current_draw_indirect{};
|
||||||
|
|
||||||
u32 last_index_count = 0;
|
u32 last_index_count = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "video_core/dirty_flags.h"
|
#include "video_core/dirty_flags.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
|
||||||
namespace Tegra::Engines {
|
namespace Tegra::Engines {
|
||||||
DrawManager::DrawManager(Maxwell3D* maxwell3d_) : maxwell3d(maxwell3d_) {}
|
|
||||||
|
|
||||||
void DrawManager::ProcessMethodCall(u32 method, u32 argument) {
|
void Maxwell3D::DrawManager::ProcessMethodCall(Maxwell3D& maxwell3d, u32 method, u32 argument) {
|
||||||
const auto& regs{maxwell3d->regs};
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case MAXWELL3D_REG_INDEX(clear_surface):
|
case MAXWELL3D_REG_INDEX(clear_surface):
|
||||||
return Clear(1);
|
return Clear(maxwell3d, 1);
|
||||||
case MAXWELL3D_REG_INDEX(draw.begin):
|
case MAXWELL3D_REG_INDEX(draw.begin):
|
||||||
return DrawBegin();
|
return DrawBegin(maxwell3d);
|
||||||
case MAXWELL3D_REG_INDEX(draw.end):
|
case MAXWELL3D_REG_INDEX(draw.end):
|
||||||
return DrawEnd();
|
return DrawEnd(maxwell3d);
|
||||||
case MAXWELL3D_REG_INDEX(vertex_buffer.first):
|
case MAXWELL3D_REG_INDEX(vertex_buffer.first):
|
||||||
case MAXWELL3D_REG_INDEX(vertex_buffer.count):
|
case MAXWELL3D_REG_INDEX(vertex_buffer.count):
|
||||||
case MAXWELL3D_REG_INDEX(index_buffer.first):
|
case MAXWELL3D_REG_INDEX(index_buffer.first):
|
||||||
|
|
@ -33,33 +34,29 @@ void DrawManager::ProcessMethodCall(u32 method, u32 argument) {
|
||||||
case MAXWELL3D_REG_INDEX(index_buffer32_first):
|
case MAXWELL3D_REG_INDEX(index_buffer32_first):
|
||||||
case MAXWELL3D_REG_INDEX(index_buffer16_first):
|
case MAXWELL3D_REG_INDEX(index_buffer16_first):
|
||||||
case MAXWELL3D_REG_INDEX(index_buffer8_first):
|
case MAXWELL3D_REG_INDEX(index_buffer8_first):
|
||||||
return DrawIndexSmall(argument);
|
return DrawIndexSmall(maxwell3d, argument);
|
||||||
case MAXWELL3D_REG_INDEX(draw_inline_index):
|
case MAXWELL3D_REG_INDEX(draw_inline_index):
|
||||||
SetInlineIndexBuffer(argument);
|
SetInlineIndexBuffer(maxwell3d, argument);
|
||||||
break;
|
break;
|
||||||
case MAXWELL3D_REG_INDEX(inline_index_2x16.even):
|
case MAXWELL3D_REG_INDEX(inline_index_2x16.even):
|
||||||
SetInlineIndexBuffer(regs.inline_index_2x16.even);
|
SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_2x16.even);
|
||||||
SetInlineIndexBuffer(regs.inline_index_2x16.odd);
|
SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_2x16.odd);
|
||||||
break;
|
break;
|
||||||
case MAXWELL3D_REG_INDEX(inline_index_4x8.index0):
|
case MAXWELL3D_REG_INDEX(inline_index_4x8.index0):
|
||||||
SetInlineIndexBuffer(regs.inline_index_4x8.index0);
|
SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index0);
|
||||||
SetInlineIndexBuffer(regs.inline_index_4x8.index1);
|
SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index1);
|
||||||
SetInlineIndexBuffer(regs.inline_index_4x8.index2);
|
SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index2);
|
||||||
SetInlineIndexBuffer(regs.inline_index_4x8.index3);
|
SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index3);
|
||||||
break;
|
break;
|
||||||
case MAXWELL3D_REG_INDEX(vertex_array_instance_first):
|
case MAXWELL3D_REG_INDEX(vertex_array_instance_first):
|
||||||
DrawArrayInstanced(regs.vertex_array_instance_first.topology.Value(),
|
DrawArrayInstanced(maxwell3d, maxwell3d.regs.vertex_array_instance_first.topology.Value(), maxwell3d.regs.vertex_array_instance_first.start.Value(), maxwell3d.regs.vertex_array_instance_first.count.Value(), false);
|
||||||
regs.vertex_array_instance_first.start.Value(),
|
|
||||||
regs.vertex_array_instance_first.count.Value(), false);
|
|
||||||
break;
|
break;
|
||||||
case MAXWELL3D_REG_INDEX(vertex_array_instance_subsequent): {
|
case MAXWELL3D_REG_INDEX(vertex_array_instance_subsequent): {
|
||||||
DrawArrayInstanced(regs.vertex_array_instance_subsequent.topology.Value(),
|
DrawArrayInstanced(maxwell3d, maxwell3d.regs.vertex_array_instance_subsequent.topology.Value(), maxwell3d.regs.vertex_array_instance_subsequent.start.Value(), maxwell3d.regs.vertex_array_instance_subsequent.count.Value(), true);
|
||||||
regs.vertex_array_instance_subsequent.start.Value(),
|
|
||||||
regs.vertex_array_instance_subsequent.count.Value(), true);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MAXWELL3D_REG_INDEX(draw_texture.src_y0): {
|
case MAXWELL3D_REG_INDEX(draw_texture.src_y0): {
|
||||||
DrawTexture();
|
DrawTexture(maxwell3d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -67,101 +64,87 @@ void DrawManager::ProcessMethodCall(u32 method, u32 argument) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::Clear(u32 layer_count) {
|
void Maxwell3D::DrawManager::Clear(Maxwell3D& maxwell3d, u32 layer_count) {
|
||||||
if (maxwell3d->ShouldExecute()) {
|
if (maxwell3d.ShouldExecute()) {
|
||||||
maxwell3d->rasterizer->Clear(layer_count);
|
maxwell3d.rasterizer->Clear(layer_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawDeferred() {
|
void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d) {
|
||||||
if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) {
|
if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DrawEnd(draw_state.instance_count + 1, true);
|
DrawEnd(maxwell3d, draw_state.instance_count + 1, true);
|
||||||
draw_state.instance_count = 0;
|
draw_state.instance_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count,
|
void Maxwell3D::DrawManager::DrawArray(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, u32 base_instance, u32 num_instances) {
|
||||||
u32 base_instance, u32 num_instances) {
|
|
||||||
draw_state.topology = topology;
|
draw_state.topology = topology;
|
||||||
draw_state.vertex_buffer.first = vertex_first;
|
draw_state.vertex_buffer.first = vertex_first;
|
||||||
draw_state.vertex_buffer.count = vertex_count;
|
draw_state.vertex_buffer.count = vertex_count;
|
||||||
draw_state.base_instance = base_instance;
|
draw_state.base_instance = base_instance;
|
||||||
ProcessDraw(false, num_instances);
|
ProcessDraw(maxwell3d, false, num_instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawArrayInstanced(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count,
|
void Maxwell3D::DrawManager::DrawArrayInstanced(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, bool subsequent) {
|
||||||
bool subsequent) {
|
|
||||||
draw_state.topology = topology;
|
draw_state.topology = topology;
|
||||||
draw_state.vertex_buffer.first = vertex_first;
|
draw_state.vertex_buffer.first = vertex_first;
|
||||||
draw_state.vertex_buffer.count = vertex_count;
|
draw_state.vertex_buffer.count = vertex_count;
|
||||||
|
|
||||||
if (!subsequent) {
|
if (!subsequent) {
|
||||||
draw_state.instance_count = 1;
|
draw_state.instance_count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_state.base_instance = draw_state.instance_count - 1;
|
draw_state.base_instance = draw_state.instance_count - 1;
|
||||||
draw_state.draw_mode = DrawMode::Instance;
|
draw_state.draw_mode = DrawMode::Instance;
|
||||||
draw_state.instance_count++;
|
draw_state.instance_count++;
|
||||||
ProcessDraw(false, 1);
|
ProcessDraw(maxwell3d, false, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count,
|
void Maxwell3D::DrawManager::DrawIndex(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, u32 base_instance, u32 num_instances) {
|
||||||
u32 base_index, u32 base_instance, u32 num_instances) {
|
|
||||||
const auto& regs{maxwell3d->regs};
|
|
||||||
draw_state.topology = topology;
|
draw_state.topology = topology;
|
||||||
draw_state.index_buffer = regs.index_buffer;
|
draw_state.index_buffer = maxwell3d.regs.index_buffer;
|
||||||
draw_state.index_buffer.first = index_first;
|
draw_state.index_buffer.first = index_first;
|
||||||
draw_state.index_buffer.count = index_count;
|
draw_state.index_buffer.count = index_count;
|
||||||
draw_state.base_index = base_index;
|
draw_state.base_index = base_index;
|
||||||
draw_state.base_instance = base_instance;
|
draw_state.base_instance = base_instance;
|
||||||
ProcessDraw(true, num_instances);
|
ProcessDraw(maxwell3d, true, num_instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawArrayIndirect(PrimitiveTopology topology) {
|
void Maxwell3D::DrawManager::DrawArrayIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology) {
|
||||||
draw_state.topology = topology;
|
draw_state.topology = topology;
|
||||||
|
ProcessDrawIndirect(maxwell3d);
|
||||||
ProcessDrawIndirect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawIndexedIndirect(PrimitiveTopology topology, u32 index_first,
|
void Maxwell3D::DrawManager::DrawIndexedIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count) {
|
||||||
u32 index_count) {
|
|
||||||
const auto& regs{maxwell3d->regs};
|
|
||||||
draw_state.topology = topology;
|
draw_state.topology = topology;
|
||||||
draw_state.index_buffer = regs.index_buffer;
|
draw_state.index_buffer = maxwell3d.regs.index_buffer;
|
||||||
draw_state.index_buffer.first = index_first;
|
draw_state.index_buffer.first = index_first;
|
||||||
draw_state.index_buffer.count = index_count;
|
draw_state.index_buffer.count = index_count;
|
||||||
|
ProcessDrawIndirect(maxwell3d);
|
||||||
ProcessDrawIndirect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::SetInlineIndexBuffer(u32 index) {
|
void Maxwell3D::DrawManager::SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 index) {
|
||||||
draw_state.inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff));
|
draw_state.inline_index_draw_indexes.push_back(u8(index & 0x000000ff));
|
||||||
draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8));
|
draw_state.inline_index_draw_indexes.push_back(u8((index & 0x0000ff00) >> 8));
|
||||||
draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16));
|
draw_state.inline_index_draw_indexes.push_back(u8((index & 0x00ff0000) >> 16));
|
||||||
draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24));
|
draw_state.inline_index_draw_indexes.push_back(u8((index & 0xff000000) >> 24));
|
||||||
draw_state.draw_mode = DrawMode::InlineIndex;
|
draw_state.draw_mode = DrawMode::InlineIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawBegin() {
|
void Maxwell3D::DrawManager::DrawBegin(Maxwell3D& maxwell3d) {
|
||||||
const auto& regs{maxwell3d->regs};
|
auto reset_instance_count = maxwell3d.regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First;
|
||||||
auto reset_instance_count = regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First;
|
auto increment_instance_count = maxwell3d.regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent;
|
||||||
auto increment_instance_count =
|
|
||||||
regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent;
|
|
||||||
if (reset_instance_count) {
|
if (reset_instance_count) {
|
||||||
DrawDeferred();
|
DrawDeferred(maxwell3d);
|
||||||
draw_state.instance_count = 0;
|
draw_state.instance_count = 0;
|
||||||
draw_state.draw_mode = DrawMode::General;
|
draw_state.draw_mode = DrawMode::General;
|
||||||
} else if (increment_instance_count) {
|
} else if (increment_instance_count) {
|
||||||
draw_state.instance_count++;
|
draw_state.instance_count++;
|
||||||
draw_state.draw_mode = DrawMode::Instance;
|
draw_state.draw_mode = DrawMode::Instance;
|
||||||
}
|
}
|
||||||
|
draw_state.topology = maxwell3d.regs.draw.topology;
|
||||||
draw_state.topology = regs.draw.topology;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawEnd(u32 instance_count, bool force_draw) {
|
void Maxwell3D::DrawManager::DrawEnd(Maxwell3D& maxwell3d, u32 instance_count, bool force_draw) {
|
||||||
const auto& regs{maxwell3d->regs};
|
|
||||||
switch (draw_state.draw_mode) {
|
switch (draw_state.draw_mode) {
|
||||||
case DrawMode::Instance:
|
case DrawMode::Instance:
|
||||||
if (!force_draw) {
|
if (!force_draw) {
|
||||||
|
|
@ -169,119 +152,100 @@ void DrawManager::DrawEnd(u32 instance_count, bool force_draw) {
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case DrawMode::General:
|
case DrawMode::General:
|
||||||
draw_state.base_instance = regs.global_base_instance_index;
|
draw_state.base_instance = maxwell3d.regs.global_base_instance_index;
|
||||||
draw_state.base_index = regs.global_base_vertex_index;
|
draw_state.base_index = maxwell3d.regs.global_base_vertex_index;
|
||||||
if (draw_state.draw_indexed) {
|
if (draw_state.draw_indexed) {
|
||||||
draw_state.index_buffer = regs.index_buffer;
|
draw_state.index_buffer = maxwell3d.regs.index_buffer;
|
||||||
ProcessDraw(true, instance_count);
|
ProcessDraw(maxwell3d, true, instance_count);
|
||||||
} else {
|
} else {
|
||||||
draw_state.vertex_buffer = regs.vertex_buffer;
|
draw_state.vertex_buffer = maxwell3d.regs.vertex_buffer;
|
||||||
ProcessDraw(false, instance_count);
|
ProcessDraw(maxwell3d, false, instance_count);
|
||||||
}
|
}
|
||||||
draw_state.draw_indexed = false;
|
draw_state.draw_indexed = false;
|
||||||
break;
|
break;
|
||||||
case DrawMode::InlineIndex:
|
case DrawMode::InlineIndex:
|
||||||
draw_state.base_instance = regs.global_base_instance_index;
|
draw_state.base_instance = maxwell3d.regs.global_base_instance_index;
|
||||||
draw_state.base_index = regs.global_base_vertex_index;
|
draw_state.base_index = maxwell3d.regs.global_base_vertex_index;
|
||||||
draw_state.index_buffer = regs.index_buffer;
|
draw_state.index_buffer = maxwell3d.regs.index_buffer;
|
||||||
draw_state.index_buffer.count =
|
draw_state.index_buffer.count = u32(draw_state.inline_index_draw_indexes.size() / 4);
|
||||||
static_cast<u32>(draw_state.inline_index_draw_indexes.size() / 4);
|
|
||||||
draw_state.index_buffer.format = Maxwell3D::Regs::IndexFormat::UnsignedInt;
|
draw_state.index_buffer.format = Maxwell3D::Regs::IndexFormat::UnsignedInt;
|
||||||
maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
ProcessDraw(true, instance_count);
|
ProcessDraw(maxwell3d, true, instance_count);
|
||||||
draw_state.inline_index_draw_indexes.clear();
|
draw_state.inline_index_draw_indexes.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawIndexSmall(u32 argument) {
|
void Maxwell3D::DrawManager::DrawIndexSmall(Maxwell3D& maxwell3d, u32 argument) {
|
||||||
const auto& regs{maxwell3d->regs};
|
Maxwell3D::Regs::IndexBufferSmall index_small_params{argument};
|
||||||
IndexBufferSmall index_small_params{argument};
|
draw_state.base_instance = maxwell3d.regs.global_base_instance_index;
|
||||||
draw_state.base_instance = regs.global_base_instance_index;
|
draw_state.base_index = maxwell3d.regs.global_base_vertex_index;
|
||||||
draw_state.base_index = regs.global_base_vertex_index;
|
draw_state.index_buffer = maxwell3d.regs.index_buffer;
|
||||||
draw_state.index_buffer = regs.index_buffer;
|
|
||||||
draw_state.index_buffer.first = index_small_params.first;
|
draw_state.index_buffer.first = index_small_params.first;
|
||||||
draw_state.index_buffer.count = index_small_params.count;
|
draw_state.index_buffer.count = index_small_params.count;
|
||||||
draw_state.topology = index_small_params.topology;
|
draw_state.topology = index_small_params.topology;
|
||||||
maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
ProcessDraw(true, 1);
|
ProcessDraw(maxwell3d, true, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::DrawTexture() {
|
void Maxwell3D::DrawManager::DrawTexture(Maxwell3D& maxwell3d) {
|
||||||
const auto& regs{maxwell3d->regs};
|
draw_texture_state.dst_x0 = f32(maxwell3d.regs.draw_texture.dst_x0) / 4096.f;
|
||||||
draw_texture_state.dst_x0 = static_cast<float>(regs.draw_texture.dst_x0) / 4096.f;
|
draw_texture_state.dst_y0 = f32(maxwell3d.regs.draw_texture.dst_y0) / 4096.f;
|
||||||
draw_texture_state.dst_y0 = static_cast<float>(regs.draw_texture.dst_y0) / 4096.f;
|
const auto dst_width = f32(maxwell3d.regs.draw_texture.dst_width) / 4096.f;
|
||||||
const auto dst_width = static_cast<float>(regs.draw_texture.dst_width) / 4096.f;
|
const auto dst_height = f32(maxwell3d.regs.draw_texture.dst_height) / 4096.f;
|
||||||
const auto dst_height = static_cast<float>(regs.draw_texture.dst_height) / 4096.f;
|
const bool lower_left{maxwell3d.regs.window_origin.mode != Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft};
|
||||||
const bool lower_left{regs.window_origin.mode !=
|
|
||||||
Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft};
|
|
||||||
if (lower_left) {
|
if (lower_left) {
|
||||||
draw_texture_state.dst_y0 =
|
draw_texture_state.dst_y0 = f32(maxwell3d.regs.surface_clip.height) - draw_texture_state.dst_y0;
|
||||||
static_cast<f32>(regs.surface_clip.height) - draw_texture_state.dst_y0;
|
|
||||||
}
|
}
|
||||||
draw_texture_state.dst_x1 = draw_texture_state.dst_x0 + dst_width;
|
draw_texture_state.dst_x1 = draw_texture_state.dst_x0 + dst_width;
|
||||||
draw_texture_state.dst_y1 = draw_texture_state.dst_y0 + dst_height;
|
draw_texture_state.dst_y1 = draw_texture_state.dst_y0 + dst_height;
|
||||||
draw_texture_state.src_x0 = static_cast<float>(regs.draw_texture.src_x0) / 4096.f;
|
draw_texture_state.src_x0 = f32(maxwell3d.regs.draw_texture.src_x0) / 4096.f;
|
||||||
draw_texture_state.src_y0 = static_cast<float>(regs.draw_texture.src_y0) / 4096.f;
|
draw_texture_state.src_y0 = f32(maxwell3d.regs.draw_texture.src_y0) / 4096.f;
|
||||||
draw_texture_state.src_x1 =
|
draw_texture_state.src_x1 = (f32(maxwell3d.regs.draw_texture.dx_du) / 4294967296.f) * dst_width + draw_texture_state.src_x0;
|
||||||
(static_cast<float>(regs.draw_texture.dx_du) / 4294967296.f) * dst_width +
|
draw_texture_state.src_y1 = (f32(maxwell3d.regs.draw_texture.dy_dv) / 4294967296.f) * dst_height + draw_texture_state.src_y0;
|
||||||
draw_texture_state.src_x0;
|
draw_texture_state.src_sampler = maxwell3d.regs.draw_texture.src_sampler;
|
||||||
draw_texture_state.src_y1 =
|
draw_texture_state.src_texture = maxwell3d.regs.draw_texture.src_texture;
|
||||||
(static_cast<float>(regs.draw_texture.dy_dv) / 4294967296.f) * dst_height +
|
maxwell3d.rasterizer->DrawTexture();
|
||||||
draw_texture_state.src_y0;
|
|
||||||
draw_texture_state.src_sampler = regs.draw_texture.src_sampler;
|
|
||||||
draw_texture_state.src_texture = regs.draw_texture.src_texture;
|
|
||||||
maxwell3d->rasterizer->DrawTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::UpdateTopology() {
|
void Maxwell3D::DrawManager::UpdateTopology(Maxwell3D& maxwell3d) {
|
||||||
const auto& regs{maxwell3d->regs};
|
switch (maxwell3d.regs.primitive_topology_control) {
|
||||||
switch (regs.primitive_topology_control) {
|
case Maxwell3D::Regs::PrimitiveTopologyControl::UseInBeginMethods:
|
||||||
case PrimitiveTopologyControl::UseInBeginMethods:
|
|
||||||
break;
|
break;
|
||||||
case PrimitiveTopologyControl::UseSeparateState:
|
case Maxwell3D::Regs::PrimitiveTopologyControl::UseSeparateState:
|
||||||
switch (regs.topology_override) {
|
switch (maxwell3d.regs.topology_override) {
|
||||||
case PrimitiveTopologyOverride::None:
|
case Maxwell3D::Regs::PrimitiveTopologyOverride::None:
|
||||||
break;
|
break;
|
||||||
case PrimitiveTopologyOverride::Points:
|
case Maxwell3D::Regs::PrimitiveTopologyOverride::Points:
|
||||||
draw_state.topology = PrimitiveTopology::Points;
|
draw_state.topology = Maxwell3D::Regs::PrimitiveTopology::Points;
|
||||||
break;
|
break;
|
||||||
case PrimitiveTopologyOverride::Lines:
|
case Maxwell3D::Regs::PrimitiveTopologyOverride::Lines:
|
||||||
draw_state.topology = PrimitiveTopology::Lines;
|
draw_state.topology = Maxwell3D::Regs::PrimitiveTopology::Lines;
|
||||||
break;
|
break;
|
||||||
case PrimitiveTopologyOverride::LineStrip:
|
case Maxwell3D::Regs::PrimitiveTopologyOverride::LineStrip:
|
||||||
draw_state.topology = PrimitiveTopology::LineStrip;
|
draw_state.topology = Maxwell3D::Regs::PrimitiveTopology::LineStrip;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
draw_state.topology = static_cast<PrimitiveTopology>(regs.topology_override);
|
draw_state.topology = Maxwell3D::Regs::PrimitiveTopology(maxwell3d.regs.topology_override);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::ProcessDraw(bool draw_indexed, u32 instance_count) {
|
void Maxwell3D::DrawManager::ProcessDraw(Maxwell3D& maxwell3d, bool draw_indexed, u32 instance_count) {
|
||||||
LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology,
|
LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology, draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count);
|
||||||
draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count);
|
UpdateTopology(maxwell3d);
|
||||||
|
if (maxwell3d.ShouldExecute()) {
|
||||||
UpdateTopology();
|
maxwell3d.rasterizer->Draw(draw_indexed, instance_count);
|
||||||
|
|
||||||
if (maxwell3d->ShouldExecute()) {
|
|
||||||
maxwell3d->rasterizer->Draw(draw_indexed, instance_count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawManager::ProcessDrawIndirect() {
|
void Maxwell3D::DrawManager::ProcessDrawIndirect(Maxwell3D& maxwell3d) {
|
||||||
LOG_TRACE(
|
LOG_TRACE(HW_GPU, "called, topology={}, is_indexed={}, includes_count={}, buffer_size={}, max_draw_count={}", draw_state.topology, indirect_state.is_indexed, indirect_state.include_count, indirect_state.buffer_size, indirect_state.max_draw_counts);
|
||||||
HW_GPU,
|
UpdateTopology(maxwell3d);
|
||||||
"called, topology={}, is_indexed={}, includes_count={}, buffer_size={}, max_draw_count={}",
|
if (maxwell3d.ShouldExecute()) {
|
||||||
draw_state.topology, indirect_state.is_indexed, indirect_state.include_count,
|
maxwell3d.rasterizer->DrawIndirect();
|
||||||
indirect_state.buffer_size, indirect_state.max_draw_counts);
|
|
||||||
|
|
||||||
UpdateTopology();
|
|
||||||
|
|
||||||
if (maxwell3d->ShouldExecute()) {
|
|
||||||
maxwell3d->rasterizer->DrawIndirect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace Tegra::Engines
|
} // namespace Tegra::Engines
|
||||||
|
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
|
||||||
|
|
||||||
namespace VideoCore {
|
|
||||||
class RasterizerInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Tegra::Engines {
|
|
||||||
using PrimitiveTopologyControl = Maxwell3D::Regs::PrimitiveTopologyControl;
|
|
||||||
using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology;
|
|
||||||
using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride;
|
|
||||||
using IndexBuffer = Maxwell3D::Regs::IndexBuffer;
|
|
||||||
using VertexBuffer = Maxwell3D::Regs::VertexBuffer;
|
|
||||||
using IndexBufferSmall = Maxwell3D::Regs::IndexBufferSmall;
|
|
||||||
|
|
||||||
class DrawManager {
|
|
||||||
public:
|
|
||||||
enum class DrawMode : u32 { General = 0, Instance, InlineIndex };
|
|
||||||
struct State {
|
|
||||||
PrimitiveTopology topology{};
|
|
||||||
DrawMode draw_mode{};
|
|
||||||
bool draw_indexed{};
|
|
||||||
u32 base_index{};
|
|
||||||
VertexBuffer vertex_buffer;
|
|
||||||
IndexBuffer index_buffer;
|
|
||||||
u32 base_instance{};
|
|
||||||
u32 instance_count{};
|
|
||||||
std::vector<u8> inline_index_draw_indexes;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DrawTextureState {
|
|
||||||
f32 dst_x0;
|
|
||||||
f32 dst_y0;
|
|
||||||
f32 dst_x1;
|
|
||||||
f32 dst_y1;
|
|
||||||
f32 src_x0;
|
|
||||||
f32 src_y0;
|
|
||||||
f32 src_x1;
|
|
||||||
f32 src_y1;
|
|
||||||
u32 src_sampler;
|
|
||||||
u32 src_texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IndirectParams {
|
|
||||||
bool is_byte_count;
|
|
||||||
bool is_indexed;
|
|
||||||
bool include_count;
|
|
||||||
GPUVAddr count_start_address;
|
|
||||||
GPUVAddr indirect_start_address;
|
|
||||||
size_t buffer_size;
|
|
||||||
size_t max_draw_counts;
|
|
||||||
size_t stride;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit DrawManager(Maxwell3D* maxwell_3d);
|
|
||||||
|
|
||||||
void ProcessMethodCall(u32 method, u32 argument);
|
|
||||||
|
|
||||||
void Clear(u32 layer_count);
|
|
||||||
|
|
||||||
void DrawDeferred();
|
|
||||||
|
|
||||||
void DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count,
|
|
||||||
u32 base_instance, u32 num_instances);
|
|
||||||
void DrawArrayInstanced(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count,
|
|
||||||
bool subsequent);
|
|
||||||
|
|
||||||
void DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index,
|
|
||||||
u32 base_instance, u32 num_instances);
|
|
||||||
|
|
||||||
void DrawArrayIndirect(PrimitiveTopology topology);
|
|
||||||
|
|
||||||
void DrawIndexedIndirect(PrimitiveTopology topology, u32 index_first, u32 index_count);
|
|
||||||
|
|
||||||
const State& GetDrawState() const {
|
|
||||||
return draw_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DrawTextureState& GetDrawTextureState() const {
|
|
||||||
return draw_texture_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
IndirectParams& GetIndirectParams() {
|
|
||||||
return indirect_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
const IndirectParams& GetIndirectParams() const {
|
|
||||||
return indirect_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetInlineIndexBuffer(u32 index);
|
|
||||||
|
|
||||||
void DrawBegin();
|
|
||||||
|
|
||||||
void DrawEnd(u32 instance_count = 1, bool force_draw = false);
|
|
||||||
|
|
||||||
void DrawIndexSmall(u32 argument);
|
|
||||||
|
|
||||||
void DrawTexture();
|
|
||||||
|
|
||||||
void UpdateTopology();
|
|
||||||
|
|
||||||
void ProcessDraw(bool draw_indexed, u32 instance_count);
|
|
||||||
|
|
||||||
void ProcessDrawIndirect();
|
|
||||||
|
|
||||||
Maxwell3D* maxwell3d{};
|
|
||||||
State draw_state{};
|
|
||||||
DrawTextureState draw_texture_state{};
|
|
||||||
IndirectParams indirect_state{};
|
|
||||||
};
|
|
||||||
} // namespace Tegra::Engines
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "video_core/dirty_flags.h"
|
#include "video_core/dirty_flags.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
@ -26,7 +26,8 @@ namespace Tegra::Engines {
|
||||||
constexpr u32 MacroRegistersStart = 0xE00;
|
constexpr u32 MacroRegistersStart = 0xE00;
|
||||||
|
|
||||||
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
||||||
: draw_manager{std::make_unique<DrawManager>(this)}, system{system_}
|
: draw_manager()
|
||||||
|
, system{system_}
|
||||||
, memory_manager{memory_manager_}
|
, memory_manager{memory_manager_}
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
, macro_engine(bool(Settings::values.disable_macro_jit))
|
, macro_engine(bool(Settings::values.disable_macro_jit))
|
||||||
|
|
@ -373,8 +374,7 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
|
||||||
case MAXWELL3D_REG_INDEX(sync_info):
|
case MAXWELL3D_REG_INDEX(sync_info):
|
||||||
return ProcessSyncPoint();
|
return ProcessSyncPoint();
|
||||||
case MAXWELL3D_REG_INDEX(launch_dma):
|
case MAXWELL3D_REG_INDEX(launch_dma):
|
||||||
return upload_state.ProcessExec(regs.launch_dma.memory_layout.Value() ==
|
return upload_state.ProcessExec(regs.launch_dma.memory_layout.Value() == Regs::LaunchDMA::Layout::Pitch);
|
||||||
Regs::LaunchDMA::Layout::Pitch);
|
|
||||||
case MAXWELL3D_REG_INDEX(inline_data):
|
case MAXWELL3D_REG_INDEX(inline_data):
|
||||||
upload_state.ProcessData(argument, is_last_call);
|
upload_state.ProcessData(argument, is_last_call);
|
||||||
return;
|
return;
|
||||||
|
|
@ -386,7 +386,7 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
|
||||||
case MAXWELL3D_REG_INDEX(tiled_cache_barrier):
|
case MAXWELL3D_REG_INDEX(tiled_cache_barrier):
|
||||||
return rasterizer->TiledCacheBarrier();
|
return rasterizer->TiledCacheBarrier();
|
||||||
default:
|
default:
|
||||||
draw_manager->ProcessMethodCall(method, argument);
|
draw_manager.ProcessMethodCall(*this, method, argument);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,8 +401,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters)
|
||||||
|
|
||||||
// Execute the current macro.
|
// Execute the current macro.
|
||||||
macro_engine.Execute(*this, macro_positions[entry], parameters);
|
macro_engine.Execute(*this, macro_positions[entry], parameters);
|
||||||
|
draw_manager.DrawDeferred(*this);
|
||||||
draw_manager->DrawDeferred();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/macro.h"
|
#include "video_core/macro.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
|
@ -40,8 +41,6 @@ class RasterizerInterface;
|
||||||
|
|
||||||
namespace Tegra::Engines {
|
namespace Tegra::Engines {
|
||||||
|
|
||||||
class DrawManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Engine is known as GF100_3D. Documentation can be found in:
|
* This Engine is known as GF100_3D. Documentation can be found in:
|
||||||
* https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h
|
* https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h
|
||||||
|
|
@ -3023,8 +3022,7 @@ public:
|
||||||
u32 bindless_texture_const_buffer_slot; ///< 0x2608
|
u32 bindless_texture_const_buffer_slot; ///< 0x2608
|
||||||
u32 trap_handler; ///< 0x260C
|
u32 trap_handler; ///< 0x260C
|
||||||
INSERT_PADDING_BYTES_NOINIT(0x1F0);
|
INSERT_PADDING_BYTES_NOINIT(0x1F0);
|
||||||
std::array<std::array<StreamOutLayout, 32>, NumTransformFeedbackBuffers>
|
std::array<std::array<StreamOutLayout, 32>, NumTransformFeedbackBuffers> stream_out_layout; ///< 0x2800
|
||||||
stream_out_layout; ///< 0x2800
|
|
||||||
INSERT_PADDING_BYTES_NOINIT(0x93C);
|
INSERT_PADDING_BYTES_NOINIT(0x93C);
|
||||||
ShaderPerformance shader_performance; ///< 0x333C
|
ShaderPerformance shader_performance; ///< 0x333C
|
||||||
INSERT_PADDING_BYTES_NOINIT(0x18);
|
INSERT_PADDING_BYTES_NOINIT(0x18);
|
||||||
|
|
@ -3035,6 +3033,62 @@ public:
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
struct DrawManager {
|
||||||
|
enum class DrawMode : u32 { General = 0, Instance, InlineIndex };
|
||||||
|
struct State {
|
||||||
|
Maxwell3D::Regs::PrimitiveTopology topology{};
|
||||||
|
DrawMode draw_mode{};
|
||||||
|
bool draw_indexed{};
|
||||||
|
u32 base_index{};
|
||||||
|
Maxwell3D::Regs::VertexBuffer vertex_buffer;
|
||||||
|
Maxwell3D::Regs::IndexBuffer index_buffer;
|
||||||
|
u32 base_instance{};
|
||||||
|
u32 instance_count{};
|
||||||
|
std::vector<u8> inline_index_draw_indexes;
|
||||||
|
};
|
||||||
|
struct DrawTextureState {
|
||||||
|
f32 dst_x0;
|
||||||
|
f32 dst_y0;
|
||||||
|
f32 dst_x1;
|
||||||
|
f32 dst_y1;
|
||||||
|
f32 src_x0;
|
||||||
|
f32 src_y0;
|
||||||
|
f32 src_x1;
|
||||||
|
f32 src_y1;
|
||||||
|
u32 src_sampler;
|
||||||
|
u32 src_texture;
|
||||||
|
};
|
||||||
|
struct IndirectParams {
|
||||||
|
bool is_byte_count;
|
||||||
|
bool is_indexed;
|
||||||
|
bool include_count;
|
||||||
|
GPUVAddr count_start_address;
|
||||||
|
GPUVAddr indirect_start_address;
|
||||||
|
size_t buffer_size;
|
||||||
|
size_t max_draw_counts;
|
||||||
|
size_t stride;
|
||||||
|
};
|
||||||
|
void ProcessMethodCall(Maxwell3D& maxwell3d, u32 method, u32 argument);
|
||||||
|
void Clear(Maxwell3D& maxwell3d, u32 layer_count);
|
||||||
|
void DrawDeferred(Maxwell3D& maxwell3d);
|
||||||
|
void DrawArray(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, u32 base_instance, u32 num_instances);
|
||||||
|
void DrawArrayInstanced(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, bool subsequent);
|
||||||
|
void DrawIndex(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, u32 base_instance, u32 num_instances);
|
||||||
|
void DrawArrayIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology);
|
||||||
|
void DrawIndexedIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count);
|
||||||
|
void SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 index);
|
||||||
|
void DrawBegin(Maxwell3D& maxwell3d);
|
||||||
|
void DrawEnd(Maxwell3D& maxwell3d, u32 instance_count = 1, bool force_draw = false);
|
||||||
|
void DrawIndexSmall(Maxwell3D& maxwell3d, u32 argument);
|
||||||
|
void DrawTexture(Maxwell3D& maxwell3d);
|
||||||
|
void UpdateTopology(Maxwell3D& maxwell3d);
|
||||||
|
void ProcessDraw(Maxwell3D& maxwell3d, bool draw_indexed, u32 instance_count);
|
||||||
|
void ProcessDrawIndirect(Maxwell3D& maxwell3d);
|
||||||
|
State draw_state{};
|
||||||
|
DrawTextureState draw_texture_state{};
|
||||||
|
IndirectParams indirect_state{};
|
||||||
|
};
|
||||||
|
|
||||||
Regs regs{};
|
Regs regs{};
|
||||||
|
|
||||||
/// Store temporary hw register values, used by some calls to restore state after a operation
|
/// Store temporary hw register values, used by some calls to restore state after a operation
|
||||||
|
|
@ -3102,8 +3156,7 @@ public:
|
||||||
Tables tables{};
|
Tables tables{};
|
||||||
} dirty;
|
} dirty;
|
||||||
|
|
||||||
std::unique_ptr<DrawManager> draw_manager;
|
DrawManager draw_manager;
|
||||||
friend class DrawManager;
|
|
||||||
|
|
||||||
GPUVAddr GetMacroAddress(size_t index) const {
|
GPUVAddr GetMacroAddress(size_t index) const {
|
||||||
return macro_addresses[index];
|
return macro_addresses[index];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -63,9 +63,7 @@ ThreadManager::ThreadManager(Core::System& system_, bool is_async_)
|
||||||
|
|
||||||
ThreadManager::~ThreadManager() = default;
|
ThreadManager::~ThreadManager() = default;
|
||||||
|
|
||||||
void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
|
void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, Tegra::Control::Scheduler& scheduler) {
|
||||||
Core::Frontend::GraphicsContext& context,
|
|
||||||
Tegra::Control::Scheduler& scheduler) {
|
|
||||||
rasterizer = renderer.ReadRasterizer();
|
rasterizer = renderer.ReadRasterizer();
|
||||||
thread = std::jthread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
|
thread = std::jthread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
|
||||||
std::ref(scheduler), std::ref(state));
|
std::ref(scheduler), std::ref(state));
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/container_hash.h"
|
#include "common/container_hash.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/dirty_flags.h"
|
#include "video_core/dirty_flags.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/macro.h"
|
#include "video_core/macro.h"
|
||||||
|
|
@ -83,7 +83,7 @@ void HLE_DrawArraysIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span<co
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& params = maxwell3d.draw_manager->GetIndirectParams();
|
auto& params = maxwell3d.draw_manager.indirect_state;
|
||||||
params.is_byte_count = false;
|
params.is_byte_count = false;
|
||||||
params.is_indexed = false;
|
params.is_indexed = false;
|
||||||
params.include_count = false;
|
params.include_count = false;
|
||||||
|
|
@ -98,7 +98,7 @@ void HLE_DrawArraysIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span<co
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
maxwell3d.draw_manager->DrawArrayIndirect(topology);
|
maxwell3d.draw_manager.DrawArrayIndirect(maxwell3d, topology);
|
||||||
|
|
||||||
if (extended) {
|
if (extended) {
|
||||||
maxwell3d.engine_state = Maxwell3D::EngineHint::None;
|
maxwell3d.engine_state = Maxwell3D::EngineHint::None;
|
||||||
|
|
@ -127,7 +127,7 @@ void HLE_DrawArraysIndirect::Fallback(Engines::Maxwell3D& maxwell3d, std::span<c
|
||||||
maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro;
|
maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro;
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
||||||
}
|
}
|
||||||
maxwell3d.draw_manager->DrawArray(topology, vertex_first, vertex_count, base_instance, instance_count);
|
maxwell3d.draw_manager.DrawArray(maxwell3d, topology, vertex_first, vertex_count, base_instance, instance_count);
|
||||||
if (extended) {
|
if (extended) {
|
||||||
maxwell3d.regs.global_base_instance_index = 0;
|
maxwell3d.regs.global_base_instance_index = 0;
|
||||||
maxwell3d.engine_state = Maxwell3D::EngineHint::None;
|
maxwell3d.engine_state = Maxwell3D::EngineHint::None;
|
||||||
|
|
@ -154,7 +154,7 @@ void HLE_DrawIndexedIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span<c
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex);
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
||||||
}
|
}
|
||||||
auto& params = maxwell3d.draw_manager->GetIndirectParams();
|
auto& params = maxwell3d.draw_manager.indirect_state;
|
||||||
params.is_byte_count = false;
|
params.is_byte_count = false;
|
||||||
params.is_indexed = true;
|
params.is_indexed = true;
|
||||||
params.include_count = false;
|
params.include_count = false;
|
||||||
|
|
@ -164,7 +164,7 @@ void HLE_DrawIndexedIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span<c
|
||||||
params.max_draw_counts = 1;
|
params.max_draw_counts = 1;
|
||||||
params.stride = 0;
|
params.stride = 0;
|
||||||
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, estimate);
|
maxwell3d.draw_manager.DrawIndexedIndirect(maxwell3d, topology, 0, estimate);
|
||||||
maxwell3d.regs.vertex_id_base = 0x0;
|
maxwell3d.regs.vertex_id_base = 0x0;
|
||||||
maxwell3d.regs.global_base_vertex_index = 0x0;
|
maxwell3d.regs.global_base_vertex_index = 0x0;
|
||||||
maxwell3d.regs.global_base_instance_index = 0x0;
|
maxwell3d.regs.global_base_instance_index = 0x0;
|
||||||
|
|
@ -187,7 +187,7 @@ void HLE_DrawIndexedIndirect::Fallback(Engines::Maxwell3D& maxwell3d, std::span<
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex);
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
||||||
}
|
}
|
||||||
maxwell3d.draw_manager->DrawIndex(Tegra::Maxwell3D::Regs::PrimitiveTopology(parameters[0]), parameters[3], parameters[1], element_base, base_instance, instance_count);
|
maxwell3d.draw_manager.DrawIndex(maxwell3d, Tegra::Maxwell3D::Regs::PrimitiveTopology(parameters[0]), parameters[3], parameters[1], element_base, base_instance, instance_count);
|
||||||
maxwell3d.regs.vertex_id_base = 0x0;
|
maxwell3d.regs.vertex_id_base = 0x0;
|
||||||
maxwell3d.regs.global_base_vertex_index = 0x0;
|
maxwell3d.regs.global_base_vertex_index = 0x0;
|
||||||
maxwell3d.regs.global_base_instance_index = 0x0;
|
maxwell3d.regs.global_base_instance_index = 0x0;
|
||||||
|
|
@ -206,7 +206,7 @@ void HLE_MultiLayerClear::Execute(Engines::Maxwell3D& maxwell3d, std::span<const
|
||||||
ASSERT(clear_params.layer == 0);
|
ASSERT(clear_params.layer == 0);
|
||||||
|
|
||||||
maxwell3d.regs.clear_surface.raw = clear_params.raw;
|
maxwell3d.regs.clear_surface.raw = clear_params.raw;
|
||||||
maxwell3d.draw_manager->Clear(num_layers);
|
maxwell3d.draw_manager.Clear(maxwell3d, num_layers);
|
||||||
}
|
}
|
||||||
void HLE_MultiDrawIndexedIndirectCount::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
|
void HLE_MultiDrawIndexedIndirectCount::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
|
||||||
const auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[2]);
|
const auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[2]);
|
||||||
|
|
@ -230,7 +230,7 @@ void HLE_MultiDrawIndexedIndirectCount::Execute(Engines::Maxwell3D& maxwell3d, s
|
||||||
const std::size_t draw_count = end_indirect - start_indirect;
|
const std::size_t draw_count = end_indirect - start_indirect;
|
||||||
const u32 estimate = static_cast<u32>(maxwell3d.EstimateIndexBufferSize());
|
const u32 estimate = static_cast<u32>(maxwell3d.EstimateIndexBufferSize());
|
||||||
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
auto& params = maxwell3d.draw_manager->GetIndirectParams();
|
auto& params = maxwell3d.draw_manager.indirect_state;
|
||||||
params.is_byte_count = false;
|
params.is_byte_count = false;
|
||||||
params.is_indexed = true;
|
params.is_indexed = true;
|
||||||
params.include_count = true;
|
params.include_count = true;
|
||||||
|
|
@ -244,7 +244,7 @@ void HLE_MultiDrawIndexedIndirectCount::Execute(Engines::Maxwell3D& maxwell3d, s
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex);
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance);
|
||||||
maxwell3d.SetHLEReplacementAttributeType(0, 0x648, Maxwell3D::HLEReplacementAttributeType::DrawID);
|
maxwell3d.SetHLEReplacementAttributeType(0, 0x648, Maxwell3D::HLEReplacementAttributeType::DrawID);
|
||||||
maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, estimate);
|
maxwell3d.draw_manager.DrawIndexedIndirect(maxwell3d, topology, 0, estimate);
|
||||||
maxwell3d.engine_state = Maxwell3D::EngineHint::None;
|
maxwell3d.engine_state = Maxwell3D::EngineHint::None;
|
||||||
maxwell3d.replace_table.clear();
|
maxwell3d.replace_table.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +280,7 @@ void HLE_MultiDrawIndexedIndirectCount::Fallback(Engines::Maxwell3D& maxwell3d,
|
||||||
maxwell3d.CallMethod(0x8e3, 0x648, true);
|
maxwell3d.CallMethod(0x8e3, 0x648, true);
|
||||||
maxwell3d.CallMethod(0x8e4, static_cast<u32>(index), true);
|
maxwell3d.CallMethod(0x8e4, static_cast<u32>(index), true);
|
||||||
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
|
||||||
maxwell3d.draw_manager->DrawIndex(topology, parameters[base + 2], parameters[base], base_vertex, base_instance, parameters[base + 1]);
|
maxwell3d.draw_manager.DrawIndex(maxwell3d, topology, parameters[base + 2], parameters[base], base_vertex, base_instance, parameters[base + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
|
void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
|
||||||
|
|
@ -290,7 +290,7 @@ void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span
|
||||||
Fallback(maxwell3d, parameters);
|
Fallback(maxwell3d, parameters);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& params = maxwell3d.draw_manager->GetIndirectParams();
|
auto& params = maxwell3d.draw_manager.indirect_state;
|
||||||
params.is_byte_count = true;
|
params.is_byte_count = true;
|
||||||
params.is_indexed = false;
|
params.is_indexed = false;
|
||||||
params.include_count = false;
|
params.include_count = false;
|
||||||
|
|
@ -302,18 +302,14 @@ void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span
|
||||||
maxwell3d.regs.draw.begin = parameters[0];
|
maxwell3d.regs.draw.begin = parameters[0];
|
||||||
maxwell3d.regs.draw_auto_stride = parameters[1];
|
maxwell3d.regs.draw_auto_stride = parameters[1];
|
||||||
maxwell3d.regs.draw_auto_byte_count = parameters[2];
|
maxwell3d.regs.draw_auto_byte_count = parameters[2];
|
||||||
maxwell3d.draw_manager->DrawArrayIndirect(topology);
|
maxwell3d.draw_manager.DrawArrayIndirect(maxwell3d, topology);
|
||||||
}
|
}
|
||||||
void HLE_DrawIndirectByteCount::Fallback(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters) {
|
void HLE_DrawIndirectByteCount::Fallback(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters) {
|
||||||
maxwell3d.RefreshParameters();
|
maxwell3d.RefreshParameters();
|
||||||
|
|
||||||
maxwell3d.regs.draw.begin = parameters[0];
|
maxwell3d.regs.draw.begin = parameters[0];
|
||||||
maxwell3d.regs.draw_auto_stride = parameters[1];
|
maxwell3d.regs.draw_auto_stride = parameters[1];
|
||||||
maxwell3d.regs.draw_auto_byte_count = parameters[2];
|
maxwell3d.regs.draw_auto_byte_count = parameters[2];
|
||||||
|
maxwell3d.draw_manager.DrawArray(maxwell3d, maxwell3d.regs.draw.topology, 0, maxwell3d.regs.draw_auto_byte_count / maxwell3d.regs.draw_auto_stride, 0, 1);
|
||||||
maxwell3d.draw_manager->DrawArray(
|
|
||||||
maxwell3d.regs.draw.topology, 0,
|
|
||||||
maxwell3d.regs.draw_auto_byte_count / maxwell3d.regs.draw_auto_stride, 0, 1);
|
|
||||||
}
|
}
|
||||||
void HLE_C713C83D8F63CCF3::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
|
void HLE_C713C83D8F63CCF3::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
|
||||||
maxwell3d.RefreshParameters();
|
maxwell3d.RefreshParameters();
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||||
|
|
||||||
SyncState();
|
SyncState();
|
||||||
|
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
|
|
||||||
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology);
|
const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(draw_state.topology);
|
||||||
BeginTransformFeedback(pipeline, primitive_mode);
|
BeginTransformFeedback(pipeline, primitive_mode);
|
||||||
|
|
@ -260,12 +260,12 @@ void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||||
|
|
||||||
void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
||||||
PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) {
|
PrepareDraw(is_indexed, [this, is_indexed, instance_count](GLenum primitive_mode) {
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
const GLuint base_instance = static_cast<GLuint>(draw_state.base_instance);
|
const GLuint base_instance = GLuint(draw_state.base_instance);
|
||||||
const GLsizei num_instances = static_cast<GLsizei>(instance_count);
|
const GLsizei num_instances = GLsizei(instance_count);
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
const GLint base_vertex = static_cast<GLint>(draw_state.base_index);
|
const GLint base_vertex = GLint(draw_state.base_index);
|
||||||
const GLsizei num_vertices = static_cast<GLsizei>(draw_state.index_buffer.count);
|
const GLsizei num_vertices = GLsizei(draw_state.index_buffer.count);
|
||||||
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
|
const GLvoid* const offset = buffer_cache_runtime.IndexOffset();
|
||||||
const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format);
|
const GLenum format = MaxwellToGL::IndexFormat(draw_state.index_buffer.format);
|
||||||
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
|
if (num_instances == 1 && base_instance == 0 && base_vertex == 0) {
|
||||||
|
|
@ -302,7 +302,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::DrawIndirect() {
|
void RasterizerOpenGL::DrawIndirect() {
|
||||||
const auto& params = maxwell3d->draw_manager->GetIndirectParams();
|
const auto& params = maxwell3d->draw_manager.indirect_state;
|
||||||
buffer_cache.SetDrawIndirect(¶ms);
|
buffer_cache.SetDrawIndirect(¶ms);
|
||||||
PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) {
|
PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) {
|
||||||
if (params.is_byte_count) {
|
if (params.is_byte_count) {
|
||||||
|
|
@ -358,12 +358,12 @@ void RasterizerOpenGL::DrawTexture() {
|
||||||
|
|
||||||
SyncState();
|
SyncState();
|
||||||
|
|
||||||
const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();
|
const auto& draw_texture_state = maxwell3d->draw_manager.draw_texture_state;
|
||||||
const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
|
const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
|
||||||
const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
|
const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
|
||||||
|
|
||||||
const auto Scale = [&](auto dim) -> s32 {
|
const auto Scale = [&](auto dim) -> s32 {
|
||||||
return Settings::values.resolution_info.ScaleUp(static_cast<s32>(dim));
|
return Settings::values.resolution_info.ScaleUp(s32(dim));
|
||||||
};
|
};
|
||||||
|
|
||||||
Region2D dst_region = {
|
Region2D dst_region = {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
#include "shader_recompiler/frontend/maxwell/control_flow.h"
|
#include "shader_recompiler/frontend/maxwell/control_flow.h"
|
||||||
#include "shader_recompiler/frontend/maxwell/translate_program.h"
|
#include "shader_recompiler/frontend/maxwell/translate_program.h"
|
||||||
#include "shader_recompiler/profile.h"
|
#include "shader_recompiler/profile.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
@ -362,7 +362,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
|
||||||
const auto& regs{maxwell3d->regs};
|
const auto& regs{maxwell3d->regs};
|
||||||
graphics_key.raw = 0;
|
graphics_key.raw = 0;
|
||||||
graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
|
graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0);
|
||||||
graphics_key.gs_input_topology.Assign(maxwell3d->draw_manager->GetDrawState().topology);
|
graphics_key.gs_input_topology.Assign(maxwell3d->draw_manager.draw_state.topology);
|
||||||
graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value());
|
graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value());
|
||||||
graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value());
|
graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value());
|
||||||
graphics_key.tessellation_clockwise.Assign(
|
graphics_key.tessellation_clockwise.Assign(
|
||||||
|
|
@ -402,7 +402,7 @@ GraphicsPipeline* ShaderCache::BuiltPipeline(GraphicsPipeline* pipeline) const n
|
||||||
// If games are using a small index count, we can assume these are full screen quads.
|
// If games are using a small index count, we can assume these are full screen quads.
|
||||||
// Usually these shaders are only used once for building textures so we can assume they
|
// Usually these shaders are only used once for building textures so we can assume they
|
||||||
// can't be built async
|
// can't be built async
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) {
|
if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) {
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
#include "common/cityhash.h"
|
#include "common/cityhash.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
|
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
|
||||||
#include "video_core/renderer_vulkan/vk_state_tracker.h"
|
#include "video_core/renderer_vulkan/vk_state_tracker.h"
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ void RefreshXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell&
|
||||||
|
|
||||||
void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFeatures& features) {
|
void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFeatures& features) {
|
||||||
const Maxwell& regs = maxwell3d.regs;
|
const Maxwell& regs = maxwell3d.regs;
|
||||||
const auto topology_ = maxwell3d.draw_manager->GetDrawState().topology;
|
const auto topology_ = maxwell3d.draw_manager.draw_state.topology;
|
||||||
|
|
||||||
raw1 = 0;
|
raw1 = 0;
|
||||||
extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0);
|
extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0);
|
||||||
|
|
|
||||||
|
|
@ -675,7 +675,7 @@ GraphicsPipeline* PipelineCache::BuiltPipeline(GraphicsPipeline* pipeline) const
|
||||||
// If games are using a small index count, we can assume these are full screen quads.
|
// If games are using a small index count, we can assume these are full screen quads.
|
||||||
// Usually these shaders are only used once for building textures so we can assume they
|
// Usually these shaders are only used once for building textures so we can assume they
|
||||||
// can't be built async
|
// can't be built async
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) {
|
if (draw_state.index_buffer.count <= 6 || draw_state.vertex_buffer.count <= 6) {
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/host1x/gpu_device_memory_manager.h"
|
#include "video_core/host1x/gpu_device_memory_manager.h"
|
||||||
#include "video_core/query_cache/query_cache.h"
|
#include "video_core/query_cache/query_cache.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
|
@ -902,7 +902,7 @@ private:
|
||||||
streams_mask = 0; // reset previously recorded streams
|
streams_mask = 0; // reset previously recorded streams
|
||||||
runtime.View3DRegs([this](Maxwell3D& maxwell3d) {
|
runtime.View3DRegs([this](Maxwell3D& maxwell3d) {
|
||||||
buffers_count = 0;
|
buffers_count = 0;
|
||||||
out_topology = maxwell3d.draw_manager->GetDrawState().topology;
|
out_topology = maxwell3d.draw_manager.draw_state.topology;
|
||||||
for (size_t i = 0; i < Maxwell3D::Regs::NumTransformFeedbackBuffers; i++) {
|
for (size_t i = 0; i < Maxwell3D::Regs::NumTransformFeedbackBuffers; i++) {
|
||||||
const auto& tf = maxwell3d.regs.transform_feedback;
|
const auto& tf = maxwell3d.regs.transform_feedback;
|
||||||
if (tf.buffers[i].enable == 0) {
|
if (tf.buffers[i].enable == 0) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#include "video_core/buffer_cache/buffer_cache.h"
|
#include "video_core/buffer_cache/buffer_cache.h"
|
||||||
#include "video_core/gpu_logging/gpu_logging.h"
|
#include "video_core/gpu_logging/gpu_logging.h"
|
||||||
#include "video_core/control/channel_state.h"
|
#include "video_core/control/channel_state.h"
|
||||||
#include "video_core/engines/draw_manager.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/host1x/gpu_device_memory_manager.h"
|
#include "video_core/host1x/gpu_device_memory_manager.h"
|
||||||
|
|
@ -46,7 +46,6 @@
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
using MaxwellDrawState = Tegra::Engines::DrawManager::State;
|
|
||||||
using VideoCommon::ImageViewId;
|
using VideoCommon::ImageViewId;
|
||||||
using VideoCommon::ImageViewType;
|
using VideoCommon::ImageViewType;
|
||||||
|
|
||||||
|
|
@ -151,7 +150,7 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3
|
||||||
return scissor;
|
return scissor;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, bool is_indexed) {
|
DrawParams MakeDrawParams(const Tegra::Engines::Maxwell3D::DrawManager::State& draw_state, u32 num_instances, bool is_indexed) {
|
||||||
DrawParams params{
|
DrawParams params{
|
||||||
.base_instance = draw_state.base_instance,
|
.base_instance = draw_state.base_instance,
|
||||||
.num_instances = num_instances,
|
.num_instances = num_instances,
|
||||||
|
|
@ -231,15 +230,13 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||||
UpdateDynamicStates();
|
UpdateDynamicStates();
|
||||||
|
|
||||||
HandleTransformFeedback();
|
HandleTransformFeedback();
|
||||||
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
|
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable);
|
||||||
maxwell3d->regs.zpass_pixel_count_enable);
|
|
||||||
|
|
||||||
draw_func();
|
draw_func();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
||||||
PrepareDraw(is_indexed, [this, is_indexed, instance_count] {
|
PrepareDraw(is_indexed, [this, is_indexed, instance_count] {
|
||||||
const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
const u32 num_instances{instance_count};
|
const u32 num_instances{instance_count};
|
||||||
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
|
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
|
||||||
|
|
||||||
|
|
@ -298,7 +295,7 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::DrawIndirect() {
|
void RasterizerVulkan::DrawIndirect() {
|
||||||
const auto& params = maxwell3d->draw_manager->GetIndirectParams();
|
const auto& params = maxwell3d->draw_manager.indirect_state;
|
||||||
buffer_cache.SetDrawIndirect(¶ms);
|
buffer_cache.SetDrawIndirect(¶ms);
|
||||||
PrepareDraw(params.is_indexed, [this, ¶ms] {
|
PrepareDraw(params.is_indexed, [this, ¶ms] {
|
||||||
const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer();
|
const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer();
|
||||||
|
|
@ -368,9 +365,8 @@ void RasterizerVulkan::DrawTexture() {
|
||||||
|
|
||||||
UpdateDynamicStates();
|
UpdateDynamicStates();
|
||||||
|
|
||||||
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
|
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable);
|
||||||
maxwell3d->regs.zpass_pixel_count_enable);
|
const auto& draw_texture_state = maxwell3d->draw_manager.draw_texture_state;
|
||||||
const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();
|
|
||||||
const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
|
const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler);
|
||||||
const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
|
const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture);
|
||||||
const auto* framebuffer = texture_cache.GetFramebuffer();
|
const auto* framebuffer = texture_cache.GetFramebuffer();
|
||||||
|
|
@ -1530,10 +1526,9 @@ void RasterizerVulkan::UpdateDepthBiasEnable(Tegra::Engines::Maxwell3D::Regs& re
|
||||||
regs.polygon_offset_line_enable,
|
regs.polygon_offset_line_enable,
|
||||||
regs.polygon_offset_fill_enable,
|
regs.polygon_offset_fill_enable,
|
||||||
};
|
};
|
||||||
const u32 topology_index = static_cast<u32>(maxwell3d->draw_manager->GetDrawState().topology);
|
const u32 topology_index = u32(maxwell3d->draw_manager.draw_state.topology);
|
||||||
const u32 enable = enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]];
|
const u32 enable = enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]];
|
||||||
scheduler.Record(
|
scheduler.Record([enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBiasEnableEXT(enable != 0); });
|
||||||
[enable](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBiasEnableEXT(enable != 0); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
|
void RasterizerVulkan::UpdateLogicOpEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue