summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/arm/arm_interface.h11
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.h4
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h32
-rw-r--r--src/core/hle/service/gsp_gpu.cpp8
-rw-r--r--src/core/hle/service/y2r_u.cpp2
-rw-r--r--src/core/hw/gpu.cpp12
-rw-r--r--src/video_core/CMakeLists.txt5
-rw-r--r--src/video_core/clipper.cpp2
-rw-r--r--src/video_core/clipper.h2
-rw-r--r--src/video_core/command_processor.cpp27
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp6
-rw-r--r--src/video_core/primitive_assembly.cpp9
-rw-r--r--src/video_core/rasterizer_interface.h (renamed from src/video_core/hwrasterizer_base.h)19
-rw-r--r--src/video_core/renderer_base.cpp28
-rw-r--r--src/video_core/renderer_base.h8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp23
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h25
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h8
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp15
-rw-r--r--src/video_core/swrasterizer.cpp16
-rw-r--r--src/video_core/swrasterizer.h26
24 files changed, 165 insertions, 134 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 5cffe513c..533067d4f 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -14,10 +14,6 @@ namespace Core {
/// Generic ARM11 CPU interface
class ARM_Interface : NonCopyable {
public:
- ARM_Interface() {
- num_instructions = 0;
- }
-
virtual ~ARM_Interface() {
}
@@ -146,11 +142,11 @@ public:
virtual void PrepareReschedule() = 0;
/// Getter for num_instructions
- u64 GetNumInstructions() {
+ u64 GetNumInstructions() const {
return num_instructions;
}
- s64 down_count; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop
+ s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop
protected:
@@ -162,6 +158,5 @@ protected:
private:
- u64 num_instructions; ///< Number of instructions executed
-
+ u64 num_instructions = 0; ///< Number of instructions executed
};
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 96c88c83a..2cff2a26a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -51,7 +51,7 @@ enum {
typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
-static bool CondPassed(ARMul_State* cpu, unsigned int cond) {
+static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
const bool n_flag = cpu->NFlag != 0;
const bool z_flag = cpu->ZFlag != 0;
const bool c_flag = cpu->CFlag != 0;
diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h
index 13bef17fc..8eb694fee 100644
--- a/src/core/arm/dyncom/arm_dyncom_run.h
+++ b/src/core/arm/dyncom/arm_dyncom_run.h
@@ -30,7 +30,7 @@
* @return If the PC is being read, then the word-aligned PC value is returned.
* If the PC is not being read, then the value stored in the register is returned.
*/
-static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) {
+inline u32 CHECK_READ_REG15_WA(const ARMul_State* cpu, int Rn) {
return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
}
@@ -43,6 +43,6 @@ static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) {
* @return If the PC is being read, then the incremented PC value is returned.
* If the PC is not being read, then the values stored in the register is returned.
*/
-static inline u32 CHECK_READ_REG15(ARMul_State* cpu, int Rn) {
+inline u32 CHECK_READ_REG15(const ARMul_State* cpu, int Rn) {
return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn];
}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
index 447974363..c1be3c735 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -38,7 +38,7 @@ enum class ThumbDecodeStatus {
// Translates a Thumb mode instruction into its ARM equivalent.
ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size);
-static inline u32 GetThumbInstruction(u32 instr, u32 address) {
+inline u32 GetThumbInstruction(u32 instr, u32 address) {
// Normally you would need to handle instruction endianness,
// however, it is fixed to little-endian on the MPCore, so
// there's no need to check for this beforehand.
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 91a8d4d57..210972917 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -85,7 +85,7 @@ enum : u32 {
#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
-static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
+inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
{
if (shift) {
if (shift < 32)
@@ -96,7 +96,7 @@ static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
return val;
}
-static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
+inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
{
if (shift) {
if (shift < 64)
@@ -107,7 +107,7 @@ static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
return val;
}
-static inline u32 vfp_hi64to32jamming(u64 val)
+inline u32 vfp_hi64to32jamming(u64 val)
{
u32 v;
u32 highval = val >> 32;
@@ -121,7 +121,7 @@ static inline u32 vfp_hi64to32jamming(u64 val)
return v;
}
-static inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
+inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
{
*resl = nl + ml;
*resh = nh + mh;
@@ -129,7 +129,7 @@ static inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
*resh += 1;
}
-static inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
+inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
{
*resl = nl - ml;
*resh = nh - mh;
@@ -137,7 +137,7 @@ static inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml)
*resh -= 1;
}
-static inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
+inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
{
u32 nh, nl, mh, ml;
u64 rh, rma, rmb, rl;
@@ -164,20 +164,20 @@ static inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
*resh = rh;
}
-static inline void shift64left(u64* resh, u64* resl, u64 n)
+inline void shift64left(u64* resh, u64* resl, u64 n)
{
*resh = n >> 63;
*resl = n << 1;
}
-static inline u64 vfp_hi64multiply64(u64 n, u64 m)
+inline u64 vfp_hi64multiply64(u64 n, u64 m)
{
u64 rh, rl;
mul64to128(&rh, &rl, n, m);
return rh | (rl != 0);
}
-static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
+inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
{
u64 mh, ml, remh, reml, termh, terml, z;
@@ -249,7 +249,7 @@ enum : u32 {
VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL)
};
-static inline int vfp_single_type(vfp_single* s)
+inline int vfp_single_type(const vfp_single* s)
{
int type = VFP_NUMBER;
if (s->exponent == 255) {
@@ -271,7 +271,7 @@ static inline int vfp_single_type(vfp_single* s)
// Unpack a single-precision float. Note that this returns the magnitude
// of the single-precision float mantissa with the 1. if necessary,
// aligned to bit 30.
-static inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
+inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
{
s->sign = vfp_single_packed_sign(val) >> 16,
s->exponent = vfp_single_packed_exponent(val);
@@ -293,7 +293,7 @@ static inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr)
// Re-pack a single-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
-static inline s32 vfp_single_pack(vfp_single* s)
+inline s32 vfp_single_pack(const vfp_single* s)
{
u32 val = (s->sign << 16) +
(s->exponent << VFP_SINGLE_MANTISSA_BITS) +
@@ -335,7 +335,7 @@ struct vfp_double {
#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
-static inline int vfp_double_type(vfp_double* s)
+inline int vfp_double_type(const vfp_double* s)
{
int type = VFP_NUMBER;
if (s->exponent == 2047) {
@@ -357,7 +357,7 @@ static inline int vfp_double_type(vfp_double* s)
// Unpack a double-precision float. Note that this returns the magnitude
// of the double-precision float mantissa with the 1. if necessary,
// aligned to bit 62.
-static inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
+inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
{
s->sign = vfp_double_packed_sign(val) >> 48;
s->exponent = vfp_double_packed_exponent(val);
@@ -379,7 +379,7 @@ static inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr)
// Re-pack a double-precision float. This assumes that the float is
// already normalised such that the MSB is bit 30, _not_ bit 31.
-static inline s64 vfp_double_pack(vfp_double* s)
+inline s64 vfp_double_pack(const vfp_double* s)
{
u64 val = ((u64)s->sign << 48) +
((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
@@ -415,7 +415,7 @@ struct op {
u32 flags;
};
-static inline u32 fls(u32 x)
+inline u32 fls(u32 x)
{
int r = 32;
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 481da0c9f..98b11c798 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -275,7 +275,7 @@ static void FlushDataCache(Service::Interface* self) {
u32 size = cmd_buff[2];
u32 process = cmd_buff[4];
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(Memory::VirtualToPhysicalAddress(address), size);
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(Memory::VirtualToPhysicalAddress(address), size);
// TODO(purpasmart96): Verify return header on HW
@@ -365,7 +365,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
// GX request DMA - typically used for copying memory from GSP heap to VRAM
case CommandId::REQUEST_DMA:
- VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
+ VideoCore::g_renderer->rasterizer->FlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
command.dma_request.size);
memcpy(Memory::GetPointer(command.dma_request.dest_address),
@@ -373,7 +373,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
command.dma_request.size);
SignalInterrupt(InterruptId::DMA);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
command.dma_request.size);
break;
@@ -467,7 +467,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
if (region.size == 0)
break;
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(
Memory::VirtualToPhysicalAddress(region.address), region.size);
}
break;
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index 6b1b71fe4..0429927f2 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -267,7 +267,7 @@ static void StartConversion(Service::Interface* self) {
// dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
u32 total_output_size = conversion.input_lines *
(conversion.dst.transfer_unit + conversion.dst.gap);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(
Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
LOG_DEBUG(Service_Y2R, "called");
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index bc7bde903..4bd3a632d 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -26,7 +26,7 @@
#include "core/tracer/recorder.h"
#include "video_core/command_processor.h"
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
#include "video_core/utils.h"
#include "video_core/video_core.h"
@@ -141,7 +141,7 @@ inline void Write(u32 addr, const T data) {
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
}
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress());
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress());
}
// Reset "trigger" flag and set the "finish" flag
@@ -172,7 +172,7 @@ inline void Write(u32 addr, const T data) {
u32 output_gap = config.texture_copy.output_gap * 16;
size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap);
- VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), contiguous_input_size);
+ VideoCore::g_renderer->rasterizer->FlushRegion(config.GetPhysicalInputAddress(), contiguous_input_size);
u32 remaining_size = config.texture_copy.size;
u32 remaining_input = input_width;
@@ -205,7 +205,7 @@ inline void Write(u32 addr, const T data) {
config.flags);
size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), contiguous_output_size);
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(config.GetPhysicalOutputAddress(), contiguous_output_size);
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
break;
@@ -232,7 +232,7 @@ inline void Write(u32 addr, const T data) {
u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format);
u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format);
- VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), input_size);
+ VideoCore::g_renderer->rasterizer->FlushRegion(config.GetPhysicalInputAddress(), input_size);
for (u32 y = 0; y < output_height; ++y) {
for (u32 x = 0; x < output_width; ++x) {
@@ -339,7 +339,7 @@ inline void Write(u32 addr, const T data) {
g_regs.display_transfer_config.trigger = 0;
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
- VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size);
+ VideoCore::g_renderer->rasterizer->InvalidateRegion(config.GetPhysicalOutputAddress(), output_size);
}
break;
}
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 2a924f4ad..c3d7294d5 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -11,8 +11,10 @@ set(SRCS
pica.cpp
primitive_assembly.cpp
rasterizer.cpp
+ renderer_base.cpp
shader/shader.cpp
shader/shader_interpreter.cpp
+ swrasterizer.cpp
utils.cpp
video_core.cpp
)
@@ -30,13 +32,14 @@ set(HEADERS
clipper.h
command_processor.h
gpu_debugger.h
- hwrasterizer_base.h
pica.h
primitive_assembly.h
rasterizer.h
+ rasterizer_interface.h
renderer_base.h
shader/shader.h
shader/shader_interpreter.h
+ swrasterizer.h
utils.h
video_core.h
)
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index ed99c4f13..5d609da06 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -78,7 +78,7 @@ static void InitScreenCoordinates(OutputVertex& vtx)
vtx.screenpos[2] = viewport.offset_z + vtx.pos.z * inv_w * viewport.zscale;
}
-void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
+void ProcessTriangle(const OutputVertex &v0, const OutputVertex &v1, const OutputVertex &v2) {
using boost::container::static_vector;
// Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at
diff --git a/src/video_core/clipper.h b/src/video_core/clipper.h
index 6ed01e877..f85d8d4c9 100644
--- a/src/video_core/clipper.h
+++ b/src/video_core/clipper.h
@@ -14,7 +14,7 @@ namespace Clipper {
using Shader::OutputVertex;
-void ProcessTriangle(OutputVertex& v0, OutputVertex& v1, OutputVertex& v2);
+void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2);
} // namespace
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index bd1b09a4b..35b976c60 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -336,19 +336,14 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
}
}
- if (Settings::values.use_hw_renderer) {
- // Send to hardware renderer
- static auto AddHWTriangle = [](const Pica::Shader::OutputVertex& v0,
- const Pica::Shader::OutputVertex& v1,
- const Pica::Shader::OutputVertex& v2) {
- VideoCore::g_renderer->hw_rasterizer->AddTriangle(v0, v1, v2);
- };
-
- primitive_assembler.SubmitVertex(output, AddHWTriangle);
- } else {
- // Send to triangle clipper
- primitive_assembler.SubmitVertex(output, Clipper::ProcessTriangle);
- }
+ // Send to renderer
+ using Pica::Shader::OutputVertex;
+ auto AddTriangle = [](
+ const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) {
+ VideoCore::g_renderer->rasterizer->AddTriangle(v0, v1, v2);
+ };
+
+ primitive_assembler.SubmitVertex(output, AddTriangle);
}
for (auto& range : memory_accesses.ranges) {
@@ -356,9 +351,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
range.second, range.first);
}
- if (Settings::values.use_hw_renderer) {
- VideoCore::g_renderer->hw_rasterizer->DrawTriangles();
- }
+ VideoCore::g_renderer->rasterizer->DrawTriangles();
#if PICA_DUMP_GEOMETRY
geometry_dumper.Dump();
@@ -475,7 +468,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
break;
}
- VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id);
+ VideoCore::g_renderer->rasterizer->NotifyPicaRegisterChanged(id);
if (g_debug_context)
g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id));
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index f1cfa9361..4f66dbd65 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -46,10 +46,8 @@ void DebugContext::OnEvent(Event event, void* data) {
{
std::unique_lock<std::mutex> lock(breakpoint_mutex);
- if (Settings::values.use_hw_renderer) {
- // Commit the hardware renderer's framebuffer so it will show on debug widgets
- VideoCore::g_renderer->hw_rasterizer->CommitFramebuffer();
- }
+ // Commit the hardware renderer's framebuffer so it will show on debug widgets
+ VideoCore::g_renderer->rasterizer->FlushFramebuffer();
// TODO: Should stop the CPU thread here once we multithread emulation.
diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp
index 44a8dbfe9..d5a0a96a4 100644
--- a/src/video_core/primitive_assembly.cpp
+++ b/src/video_core/primitive_assembly.cpp
@@ -39,13 +39,12 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(VertexType& vtx, TriangleHandl
buffer[buffer_index] = vtx;
- if (topology == Regs::TriangleTopology::Strip) {
- strip_ready |= (buffer_index == 1);
+ strip_ready |= (buffer_index == 1);
+
+ if (topology == Regs::TriangleTopology::Strip)
buffer_index = !buffer_index;
- } else if (topology == Regs::TriangleTopology::Fan) {
+ else if (topology == Regs::TriangleTopology::Fan)
buffer_index = 1;
- strip_ready = true;
- }
break;
default:
diff --git a/src/video_core/hwrasterizer_base.h b/src/video_core/rasterizer_interface.h
index 54b8892fb..008c5827b 100644
--- a/src/video_core/hwrasterizer_base.h
+++ b/src/video_core/rasterizer_interface.h
@@ -12,10 +12,11 @@ struct OutputVertex;
}
}
-class HWRasterizer {
+namespace VideoCore {
+
+class RasterizerInterface {
public:
- virtual ~HWRasterizer() {
- }
+ virtual ~RasterizerInterface() {}
/// Initialize API-specific GPU objects
virtual void InitObjects() = 0;
@@ -32,14 +33,16 @@ public:
virtual void DrawTriangles() = 0;
/// Commit the rasterizer's framebuffer contents immediately to the current 3DS memory framebuffer
- virtual void CommitFramebuffer() = 0;
+ virtual void FlushFramebuffer() = 0;
/// Notify rasterizer that the specified PICA register has been changed
virtual void NotifyPicaRegisterChanged(u32 id) = 0;
- /// Notify rasterizer that the specified 3DS memory region will be read from after this notification
- virtual void NotifyPreRead(PAddr addr, u32 size) = 0;
+ /// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory.
+ virtual void FlushRegion(PAddr addr, u32 size) = 0;
- /// Notify rasterizer that a 3DS memory region has been changed
- virtual void NotifyFlush(PAddr addr, u32 size) = 0;
+ /// Notify rasterizer that any caches of the specified region should be discraded and reloaded from 3DS memory.
+ virtual void InvalidateRegion(PAddr addr, u32 size) = 0;
};
+
+}
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
new file mode 100644
index 000000000..93e980216
--- /dev/null
+++ b/src/video_core/renderer_base.cpp
@@ -0,0 +1,28 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/make_unique.h"
+
+#include "core/settings.h"
+
+#include "video_core/renderer_base.h"
+#include "video_core/video_core.h"
+#include "video_core/swrasterizer.h"
+#include "video_core/renderer_opengl/gl_rasterizer.h"
+
+void RendererBase::RefreshRasterizerSetting() {
+ bool hw_renderer_enabled = VideoCore::g_hw_renderer_enabled;
+ if (rasterizer == nullptr || opengl_rasterizer_active != hw_renderer_enabled) {
+ opengl_rasterizer_active = hw_renderer_enabled;
+
+ if (hw_renderer_enabled) {
+ rasterizer = Common::make_unique<RasterizerOpenGL>();
+ } else {
+ rasterizer = Common::make_unique<VideoCore::SWRasterizer>();
+ }
+ rasterizer->InitObjects();
+ }
+}
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 6587bcf27..506bff815 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -8,7 +8,7 @@
#include "common/common_types.h"
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/rasterizer_interface.h"
class EmuWindow;
@@ -54,10 +54,14 @@ public:
return m_current_frame;
}
- std::unique_ptr<HWRasterizer> hw_rasterizer;
+ void RefreshRasterizerSetting();
+
+ std::unique_ptr<VideoCore::RasterizerInterface> rasterizer;
protected:
f32 m_current_fps; ///< Current framerate, should be set by the renderer
int m_current_frame; ///< Current frame, should be set by the renderer
+private:
+ bool opengl_rasterizer_active = false;
};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 23d9517da..092351dce 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -135,7 +135,7 @@ void RasterizerOpenGL::Reset() {
SetShader();
- res_cache.FullFlush();
+ res_cache.InvalidateAll();
}
void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0,
@@ -176,11 +176,11 @@ void RasterizerOpenGL::DrawTriangles() {
u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
* regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
- res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size, true);
- res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size, true);
+ res_cache.InvalidateInRange(cur_fb_color_addr, cur_fb_color_size, true);
+ res_cache.InvalidateInRange(cur_fb_depth_addr, cur_fb_depth_size, true);
}
-void RasterizerOpenGL::CommitFramebuffer() {
+void RasterizerOpenGL::FlushFramebuffer() {
CommitColorBuffer();
CommitDepthBuffer();
}
@@ -188,9 +188,6 @@ void RasterizerOpenGL::CommitFramebuffer() {
void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
const auto& regs = Pica::g_state.regs;
- if (!Settings::values.use_hw_renderer)
- return;
-
switch(id) {
// Culling
case PICA_REG_INDEX(cull_mode):
@@ -284,12 +281,9 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
}
}
-void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) {
+void RasterizerOpenGL::FlushRegion(PAddr addr, u32 size) {
const auto& regs = Pica::g_state.regs;
- if (!Settings::values.use_hw_renderer)
- return;
-
PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
* regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
@@ -306,12 +300,9 @@ void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) {
CommitDepthBuffer();
}
-void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
+void RasterizerOpenGL::InvalidateRegion(PAddr addr, u32 size) {
const auto& regs = Pica::g_state.regs;
- if (!Settings::values.use_hw_renderer)
- return;
-
PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
* regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
@@ -328,7 +319,7 @@ void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
ReloadDepthBuffer();
// Notify cache of flush in case the region touches a cached resource
- res_cache.NotifyFlush(addr, size);
+ res_cache.InvalidateInRange(addr, size);
}
void RasterizerOpenGL::SamplerInfo::Create() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 5ba898189..92b1f812e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -14,7 +14,7 @@
#include "common/hash.h"
#include "video_core/pica.h"
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/shader/shader_interpreter.h"
@@ -102,37 +102,22 @@ struct hash<PicaShaderConfig> {
} // namespace std
-class RasterizerOpenGL : public HWRasterizer {
+class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
RasterizerOpenGL();
~RasterizerOpenGL() override;
- /// Initialize API-specific GPU objects
void InitObjects() override;
-
- /// Reset the rasterizer, such as flushing all caches and updating all state
void Reset() override;
-
- /// Queues the primitive formed by the given vertices for rendering
void AddTriangle(const Pica::Shader::OutputVertex& v0,
const Pica::Shader::OutputVertex& v1,
const Pica::Shader::OutputVertex& v2) override;
-
- /// Draw the current batch of triangles
void DrawTriangles() override;
-
- /// Commit the rasterizer's framebuffer contents immediately to the current 3DS memory framebuffer
- void CommitFramebuffer() override;
-
- /// Notify rasterizer that the specified PICA register has been changed
+ void FlushFramebuffer() override;
void NotifyPicaRegisterChanged(u32 id) override;
-
- /// Notify rasterizer that the specified 3DS memory region will be read from after this notification
- void NotifyPreRead(PAddr addr, u32 size) override;
-
- /// Notify rasterizer that a 3DS memory region has been changed
- void NotifyFlush(PAddr addr, u32 size) override;
+ void FlushRegion(PAddr addr, u32 size) override;
+ void InvalidateRegion(PAddr addr, u32 size) override;
/// OpenGL shader generated for a given Pica register state
struct PicaShader {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 10d4ab0b6..a9ad46fe0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -15,7 +15,7 @@
#include "video_core/renderer_opengl/pica_to_gl.h"
RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
- FullFlush();
+ InvalidateAll();
}
MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
@@ -58,8 +58,7 @@ void RasterizerCacheOpenGL::LoadAndBindTexture(OpenGLState &state, unsigned text
}
}
-void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size, bool ignore_hash) {
- // Flush any texture that falls in the flushed region
+void RasterizerCacheOpenGL::InvalidateInRange(PAddr addr, u32 size, bool ignore_hash) {
// TODO: Optimize by also inserting upper bound (addr + size) of each texture into the same map and also narrow using lower_bound
auto cache_upper_bound = texture_cache.upper_bound(addr + size);
@@ -77,6 +76,6 @@ void RasterizerCacheOpenGL::NotifyFlush(PAddr addr, u32 size, bool ignore_hash)
}
}
-void RasterizerCacheOpenGL::FullFlush() {
+void RasterizerCacheOpenGL::InvalidateAll() {
texture_cache.clear();
}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 98a48ffbe..b69651427 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -23,11 +23,11 @@ public:
LoadAndBindTexture(state, texture_unit, Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format));
}
- /// Flush any cached resource that touches the flushed region
- void NotifyFlush(PAddr addr, u32 size, bool ignore_hash = false);
+ /// Invalidate any cached resource intersecting the specified region.
+ void InvalidateInRange(PAddr addr, u32 size, bool ignore_hash = false);
- /// Flush all cached OpenGL resources tracked by this cache manager
- void FullFlush();
+ /// Invalidate all cached OpenGL resources tracked by this cache manager
+ void InvalidateAll();
private:
struct CachedTexture {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 1420229cc..c14bdb8ab 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -93,7 +93,6 @@ static std::array<GLfloat, 3*2> MakeOrthographicMatrix(const float width, const
/// RendererOpenGL constructor
RendererOpenGL::RendererOpenGL() {
- hw_rasterizer.reset(new RasterizerOpenGL());
resolution_width = std::max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth);
resolution_height = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight;
}
@@ -157,15 +156,7 @@ void RendererOpenGL::SwapBuffers() {
profiler.BeginFrame();
- bool hw_renderer_enabled = VideoCore::g_hw_renderer_enabled;
- if (Settings::values.use_hw_renderer != hw_renderer_enabled) {
- // TODO: Save new setting value to config file for next startup
- Settings::values.use_hw_renderer = hw_renderer_enabled;
-
- if (Settings::values.use_hw_renderer) {
- hw_rasterizer->Reset();
- }
- }
+ RefreshRasterizerSetting();
if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
Pica::g_debug_context->recorder->FrameFinished();
@@ -286,8 +277,6 @@ void RendererOpenGL::InitOpenGLObjects() {
state.texture_units[0].texture_2d = 0;
state.Apply();
-
- hw_rasterizer->InitObjects();
}
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
@@ -419,6 +408,8 @@ void RendererOpenGL::Init() {
LOG_INFO(Render_OpenGL, "GL_VENDOR: %s", glGetString(GL_VENDOR));
LOG_INFO(Render_OpenGL, "GL_RENDERER: %s", glGetString(GL_RENDERER));
InitOpenGLObjects();
+
+ RefreshRasterizerSetting();
}
/// Shutdown the renderer
diff --git a/src/video_core/swrasterizer.cpp b/src/video_core/swrasterizer.cpp
new file mode 100644
index 000000000..03df15b01
--- /dev/null
+++ b/src/video_core/swrasterizer.cpp
@@ -0,0 +1,16 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "video_core/clipper.h"
+#include "video_core/swrasterizer.h"
+
+namespace VideoCore {
+
+void SWRasterizer::AddTriangle(const Pica::Shader::OutputVertex& v0,
+ const Pica::Shader::OutputVertex& v1,
+ const Pica::Shader::OutputVertex& v2) {
+ Pica::Clipper::ProcessTriangle(v0, v1, v2);
+}
+
+}
diff --git a/src/video_core/swrasterizer.h b/src/video_core/swrasterizer.h
new file mode 100644
index 000000000..e9a4e39c6
--- /dev/null
+++ b/src/video_core/swrasterizer.h
@@ -0,0 +1,26 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+#include "video_core/rasterizer_interface.h"
+
+namespace VideoCore {
+
+class SWRasterizer : public RasterizerInterface {
+ void InitObjects() override {}
+ void Reset() override {}
+ void AddTriangle(const Pica::Shader::OutputVertex& v0,
+ const Pica::Shader::OutputVertex& v1,
+ const Pica::Shader::OutputVertex& v2);
+ void DrawTriangles() override {}
+ void FlushFramebuffer() override {}
+ void NotifyPicaRegisterChanged(u32 id) override {}
+ void FlushRegion(PAddr addr, u32 size) override {}
+ void InvalidateRegion(PAddr addr, u32 size) override {}
+};
+
+}