|
|
@ -3,6 +3,8 @@ |
|
|
|
|
|
|
|
|
#include <array>
|
|
|
#include <array>
|
|
|
#include <vector>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "common/scope_exit.h"
|
|
|
|
|
|
#include "video_core/dirty_flags.h"
|
|
|
#include "video_core/engines/maxwell_3d.h"
|
|
|
#include "video_core/engines/maxwell_3d.h"
|
|
|
#include "video_core/macro/macro.h"
|
|
|
#include "video_core/macro/macro.h"
|
|
|
#include "video_core/macro/macro_hle.h"
|
|
|
#include "video_core/macro/macro_hle.h"
|
|
|
@ -58,6 +60,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& |
|
|
maxwell3d.regs.index_array.first = parameters[3]; |
|
|
maxwell3d.regs.index_array.first = parameters[3]; |
|
|
maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
|
|
|
maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base?
|
|
|
maxwell3d.regs.index_array.count = parameters[1]; |
|
|
maxwell3d.regs.index_array.count = parameters[1]; |
|
|
|
|
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
|
|
maxwell3d.regs.vb_element_base = element_base; |
|
|
maxwell3d.regs.vb_element_base = element_base; |
|
|
maxwell3d.regs.vb_base_instance = base_instance; |
|
|
maxwell3d.regs.vb_base_instance = base_instance; |
|
|
maxwell3d.mme_draw.instance_count = instance_count; |
|
|
maxwell3d.mme_draw.instance_count = instance_count; |
|
|
@ -80,10 +83,67 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& |
|
|
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; |
|
|
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{ |
|
|
|
|
|
|
|
|
// Multidraw Indirect
|
|
|
|
|
|
void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { |
|
|
|
|
|
SCOPE_EXIT({ |
|
|
|
|
|
// Clean everything.
|
|
|
|
|
|
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
|
|
|
|
|
|
maxwell3d.regs.index_array.count = 0; |
|
|
|
|
|
maxwell3d.regs.vb_element_base = 0x0; |
|
|
|
|
|
maxwell3d.regs.vb_base_instance = 0x0; |
|
|
|
|
|
maxwell3d.mme_draw.instance_count = 0; |
|
|
|
|
|
maxwell3d.CallMethodFromMME(0x8e3, 0x640); |
|
|
|
|
|
maxwell3d.CallMethodFromMME(0x8e4, 0x0); |
|
|
|
|
|
maxwell3d.CallMethodFromMME(0x8e5, 0x0); |
|
|
|
|
|
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; |
|
|
|
|
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
|
|
|
|
|
}); |
|
|
|
|
|
const u32 start_indirect = parameters[0]; |
|
|
|
|
|
const u32 end_indirect = parameters[1]; |
|
|
|
|
|
if (start_indirect >= end_indirect) { |
|
|
|
|
|
// Nothing to do.
|
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
const auto topology = |
|
|
|
|
|
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[2]); |
|
|
|
|
|
maxwell3d.regs.draw.topology.Assign(topology); |
|
|
|
|
|
const u32 padding = parameters[3]; |
|
|
|
|
|
const std::size_t max_draws = parameters[4]; |
|
|
|
|
|
|
|
|
|
|
|
const u32 indirect_words = 5 + padding; |
|
|
|
|
|
const std::size_t first_draw = start_indirect; |
|
|
|
|
|
const std::size_t effective_draws = end_indirect - start_indirect; |
|
|
|
|
|
const std::size_t last_draw = start_indirect + std::min(effective_draws, max_draws); |
|
|
|
|
|
|
|
|
|
|
|
for (std::size_t index = first_draw; index < last_draw; index++) { |
|
|
|
|
|
const std::size_t base = index * indirect_words + 5; |
|
|
|
|
|
const u32 num_vertices = parameters[base]; |
|
|
|
|
|
const u32 instance_count = parameters[base + 1]; |
|
|
|
|
|
const u32 first_index = parameters[base + 2]; |
|
|
|
|
|
const u32 base_vertex = parameters[base + 3]; |
|
|
|
|
|
const u32 base_instance = parameters[base + 4]; |
|
|
|
|
|
maxwell3d.regs.index_array.first = first_index; |
|
|
|
|
|
maxwell3d.regs.reg_array[0x446] = base_vertex; |
|
|
|
|
|
maxwell3d.regs.index_array.count = num_vertices; |
|
|
|
|
|
maxwell3d.regs.vb_element_base = base_vertex; |
|
|
|
|
|
maxwell3d.regs.vb_base_instance = base_instance; |
|
|
|
|
|
maxwell3d.mme_draw.instance_count = instance_count; |
|
|
|
|
|
maxwell3d.CallMethodFromMME(0x8e3, 0x640); |
|
|
|
|
|
maxwell3d.CallMethodFromMME(0x8e4, base_vertex); |
|
|
|
|
|
maxwell3d.CallMethodFromMME(0x8e5, base_instance); |
|
|
|
|
|
maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
|
|
|
|
|
if (maxwell3d.ShouldExecute()) { |
|
|
|
|
|
maxwell3d.Rasterizer().Draw(true, true); |
|
|
|
|
|
} |
|
|
|
|
|
maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
constexpr std::array<std::pair<u64, HLEFunction>, 4> hle_funcs{{ |
|
|
{0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, |
|
|
{0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, |
|
|
{0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, |
|
|
{0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD}, |
|
|
{0x0217920100488FF7, &HLE_0217920100488FF7}, |
|
|
{0x0217920100488FF7, &HLE_0217920100488FF7}, |
|
|
|
|
|
{0x3F5E74B9C9A50164, &HLE_3F5E74B9C9A50164}, |
|
|
}}; |
|
|
}}; |
|
|
|
|
|
|
|
|
class HLEMacroImpl final : public CachedMacro { |
|
|
class HLEMacroImpl final : public CachedMacro { |
|
|
@ -99,6 +159,7 @@ private: |
|
|
Engines::Maxwell3D& maxwell3d; |
|
|
Engines::Maxwell3D& maxwell3d; |
|
|
HLEFunction func; |
|
|
HLEFunction func; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
|
HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} |
|
|
HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} |
|
|
|