12 changed files with 341 additions and 267 deletions
-
2src/video_core/CMakeLists.txt
-
32src/video_core/buffer_cache/buffer_cache.h
-
191src/video_core/engines/draw_manager.cpp
-
69src/video_core/engines/draw_manager.h
-
171src/video_core/engines/maxwell_3d.cpp
-
25src/video_core/engines/maxwell_3d.h
-
69src/video_core/macro/macro_hle.cpp
-
16src/video_core/renderer_opengl/gl_rasterizer.cpp
-
6src/video_core/renderer_opengl/gl_shader_cache.cpp
-
6src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
-
3src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
-
18src/video_core/renderer_vulkan/vk_rasterizer.cpp
@ -0,0 +1,191 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
|
||||
|
#include "video_core/dirty_flags.h"
|
||||
|
#include "video_core/engines/draw_manager.h"
|
||||
|
#include "video_core/rasterizer_interface.h"
|
||||
|
|
||||
|
namespace Tegra::Engines { |
||||
|
DrawManager::DrawManager(Maxwell3D* maxwell3d_) : maxwell3d(maxwell3d_) {} |
||||
|
|
||||
|
void DrawManager::ProcessMethodCall(u32 method, u32 argument) { |
||||
|
const auto& regs{maxwell3d->regs}; |
||||
|
switch (method) { |
||||
|
case MAXWELL3D_REG_INDEX(clear_surface): |
||||
|
return Clear(1); |
||||
|
case MAXWELL3D_REG_INDEX(draw.begin): |
||||
|
return DrawBegin(); |
||||
|
case MAXWELL3D_REG_INDEX(draw.end): |
||||
|
return DrawEnd(); |
||||
|
case MAXWELL3D_REG_INDEX(vertex_buffer.first): |
||||
|
case MAXWELL3D_REG_INDEX(vertex_buffer.count): |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer.first): |
||||
|
break; |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer.count): |
||||
|
draw_state.draw_indexed = true; |
||||
|
break; |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer32_subsequent): |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer16_subsequent): |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer8_subsequent): |
||||
|
draw_state.instance_count++; |
||||
|
[[fallthrough]]; |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer32_first): |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer16_first): |
||||
|
case MAXWELL3D_REG_INDEX(index_buffer8_first): |
||||
|
return DrawIndexSmall(argument); |
||||
|
case MAXWELL3D_REG_INDEX(draw_inline_index): |
||||
|
SetInlineIndexBuffer(argument); |
||||
|
break; |
||||
|
case MAXWELL3D_REG_INDEX(inline_index_2x16.even): |
||||
|
SetInlineIndexBuffer(regs.inline_index_2x16.even); |
||||
|
SetInlineIndexBuffer(regs.inline_index_2x16.odd); |
||||
|
break; |
||||
|
case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): |
||||
|
SetInlineIndexBuffer(regs.inline_index_4x8.index0); |
||||
|
SetInlineIndexBuffer(regs.inline_index_4x8.index1); |
||||
|
SetInlineIndexBuffer(regs.inline_index_4x8.index2); |
||||
|
SetInlineIndexBuffer(regs.inline_index_4x8.index3); |
||||
|
break; |
||||
|
case MAXWELL3D_REG_INDEX(topology_override): |
||||
|
use_topology_override = true; |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DrawManager::Clear(u32 layer_count) { |
||||
|
maxwell3d->rasterizer->Clear(layer_count); |
||||
|
} |
||||
|
|
||||
|
void DrawManager::DrawDeferred() { |
||||
|
if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) |
||||
|
return; |
||||
|
DrawEnd(draw_state.instance_count + 1, true); |
||||
|
draw_state.instance_count = 0; |
||||
|
} |
||||
|
|
||||
|
void DrawManager::DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, |
||||
|
u32 base_instance, u32 num_instances) { |
||||
|
draw_state.topology = topology; |
||||
|
draw_state.vertex_buffer.first = vertex_first; |
||||
|
draw_state.vertex_buffer.count = vertex_count; |
||||
|
draw_state.base_instance = base_instance; |
||||
|
ProcessDraw(false, num_instances); |
||||
|
} |
||||
|
|
||||
|
void DrawManager::DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, |
||||
|
u32 base_index, u32 base_instance, u32 num_instances) { |
||||
|
const auto& regs{maxwell3d->regs}; |
||||
|
draw_state.topology = topology; |
||||
|
draw_state.index_buffer = regs.index_buffer; |
||||
|
draw_state.index_buffer.first = index_first; |
||||
|
draw_state.index_buffer.count = index_count; |
||||
|
draw_state.base_index = base_index; |
||||
|
draw_state.base_instance = base_instance; |
||||
|
ProcessDraw(true, num_instances); |
||||
|
} |
||||
|
|
||||
|
void DrawManager::SetInlineIndexBuffer(u32 index) { |
||||
|
draw_state.inline_index_draw_indexes.push_back(static_cast<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(static_cast<u8>((index & 0x00ff0000) >> 16)); |
||||
|
draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); |
||||
|
draw_state.draw_mode = DrawMode::InlineIndex; |
||||
|
} |
||||
|
|
||||
|
void DrawManager::DrawBegin() { |
||||
|
const auto& regs{maxwell3d->regs}; |
||||
|
auto reset_instance_count = regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First; |
||||
|
auto increment_instance_count = |
||||
|
regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent; |
||||
|
if (reset_instance_count) { |
||||
|
DrawDeferred(); |
||||
|
draw_state.instance_count = 0; |
||||
|
draw_state.draw_mode = DrawMode::General; |
||||
|
} else if (increment_instance_count) { |
||||
|
draw_state.instance_count++; |
||||
|
draw_state.draw_mode = DrawMode::Instance; |
||||
|
} |
||||
|
|
||||
|
draw_state.topology = regs.draw.topology; |
||||
|
} |
||||
|
|
||||
|
void DrawManager::DrawEnd(u32 instance_count, bool force_draw) { |
||||
|
const auto& regs{maxwell3d->regs}; |
||||
|
switch (draw_state.draw_mode) { |
||||
|
case DrawMode::Instance: |
||||
|
if (!force_draw) |
||||
|
break; |
||||
|
[[fallthrough]]; |
||||
|
case DrawMode::General: |
||||
|
draw_state.base_instance = regs.global_base_instance_index; |
||||
|
draw_state.base_index = regs.global_base_vertex_index; |
||||
|
if (draw_state.draw_indexed) { |
||||
|
draw_state.index_buffer = regs.index_buffer; |
||||
|
ProcessDraw(true, instance_count); |
||||
|
} else { |
||||
|
draw_state.vertex_buffer = regs.vertex_buffer; |
||||
|
ProcessDraw(false, instance_count); |
||||
|
} |
||||
|
draw_state.draw_indexed = false; |
||||
|
break; |
||||
|
case DrawMode::InlineIndex: |
||||
|
draw_state.base_instance = regs.global_base_instance_index; |
||||
|
draw_state.base_index = regs.global_base_vertex_index; |
||||
|
draw_state.index_buffer = regs.index_buffer; |
||||
|
draw_state.index_buffer.count = |
||||
|
static_cast<u32>(draw_state.inline_index_draw_indexes.size() / 4); |
||||
|
draw_state.index_buffer.format = Maxwell3D::Regs::IndexFormat::UnsignedInt; |
||||
|
ProcessDraw(true, instance_count); |
||||
|
draw_state.inline_index_draw_indexes.clear(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DrawManager::DrawIndexSmall(u32 argument) { |
||||
|
const auto& regs{maxwell3d->regs}; |
||||
|
IndexBufferSmall index_small_params{argument}; |
||||
|
draw_state.base_instance = regs.global_base_instance_index; |
||||
|
draw_state.base_index = regs.global_base_vertex_index; |
||||
|
draw_state.index_buffer = regs.index_buffer; |
||||
|
draw_state.index_buffer.first = index_small_params.first; |
||||
|
draw_state.index_buffer.count = index_small_params.count; |
||||
|
draw_state.topology = index_small_params.topology; |
||||
|
maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
||||
|
ProcessDraw(true, 1); |
||||
|
} |
||||
|
|
||||
|
void DrawManager::ProcessTopologyOverride() { |
||||
|
if (!use_topology_override) |
||||
|
return; |
||||
|
|
||||
|
const auto& regs{maxwell3d->regs}; |
||||
|
switch (regs.topology_override) { |
||||
|
case PrimitiveTopologyOverride::None: |
||||
|
break; |
||||
|
case PrimitiveTopologyOverride::Points: |
||||
|
draw_state.topology = PrimitiveTopology::Points; |
||||
|
break; |
||||
|
case PrimitiveTopologyOverride::Lines: |
||||
|
draw_state.topology = PrimitiveTopology::Lines; |
||||
|
break; |
||||
|
case PrimitiveTopologyOverride::LineStrip: |
||||
|
draw_state.topology = PrimitiveTopology::LineStrip; |
||||
|
break; |
||||
|
default: |
||||
|
draw_state.topology = static_cast<PrimitiveTopology>(regs.topology_override); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DrawManager::ProcessDraw(bool draw_indexed, u32 instance_count) { |
||||
|
LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology.Value(), |
||||
|
draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count); |
||||
|
|
||||
|
ProcessTopologyOverride(); |
||||
|
|
||||
|
if (maxwell3d->ShouldExecute()) |
||||
|
maxwell3d->rasterizer->Draw(draw_indexed, instance_count); |
||||
|
} |
||||
|
} // namespace Tegra::Engines
|
||||
@ -0,0 +1,69 @@ |
|||||
|
// 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 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; |
||||
|
}; |
||||
|
|
||||
|
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 DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, |
||||
|
u32 base_instance, u32 num_instances); |
||||
|
|
||||
|
const State& GetDrawState() const { |
||||
|
return draw_state; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
void SetInlineIndexBuffer(u32 index); |
||||
|
|
||||
|
void DrawBegin(); |
||||
|
|
||||
|
void DrawEnd(u32 instance_count = 1, bool force_draw = false); |
||||
|
|
||||
|
void DrawIndexSmall(u32 argument); |
||||
|
|
||||
|
void ProcessTopologyOverride(); |
||||
|
|
||||
|
void ProcessDraw(bool draw_indexed, u32 instance_count); |
||||
|
|
||||
|
Maxwell3D* maxwell3d{}; |
||||
|
State draw_state{}; |
||||
|
bool use_topology_override{}; |
||||
|
}; |
||||
|
} // namespace Tegra::Engines |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue