Просмотр исходного кода

Merge pull request #1272 from yuriks/merge-rasterizer

VideoCore: Unify interface to OpenGL and SW rasterizers
Yuri Kunde Schlesner 10 лет назад
Родитель
Сommit
31764c48fb

+ 4 - 4
src/core/hle/service/gsp_gpu.cpp

@@ -275,7 +275,7 @@ static void FlushDataCache(Service::Interface* self) {
     u32 size    = cmd_buff[2];
     u32 size    = cmd_buff[2];
     u32 process = cmd_buff[4];
     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
     // 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
     // GX request DMA - typically used for copying memory from GSP heap to VRAM
     case CommandId::REQUEST_DMA:
     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);
                                                             command.dma_request.size);
 
 
         memcpy(Memory::GetPointer(command.dma_request.dest_address),
         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);
                command.dma_request.size);
         SignalInterrupt(InterruptId::DMA);
         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);
                                                           command.dma_request.size);
         break;
         break;
 
 
@@ -467,7 +467,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
             if (region.size == 0)
             if (region.size == 0)
                 break;
                 break;
 
 
-            VideoCore::g_renderer->hw_rasterizer->NotifyFlush(
+            VideoCore::g_renderer->rasterizer->InvalidateRegion(
                 Memory::VirtualToPhysicalAddress(region.address), region.size);
                 Memory::VirtualToPhysicalAddress(region.address), region.size);
         }
         }
         break;
         break;

+ 1 - 1
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 :(
     // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
     u32 total_output_size = conversion.input_lines *
     u32 total_output_size = conversion.input_lines *
         (conversion.dst.transfer_unit + conversion.dst.gap);
         (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);
         Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
 
 
     LOG_DEBUG(Service_Y2R, "called");
     LOG_DEBUG(Service_Y2R, "called");

+ 6 - 6
src/core/hw/gpu.cpp

@@ -26,7 +26,7 @@
 #include "core/tracer/recorder.h"
 #include "core/tracer/recorder.h"
 
 
 #include "video_core/command_processor.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/renderer_base.h"
 #include "video_core/utils.h"
 #include "video_core/utils.h"
 #include "video_core/video_core.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);
                     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
             // 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;
                 u32 output_gap = config.texture_copy.output_gap * 16;
 
 
                 size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap);
                 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_size = config.texture_copy.size;
                 u32 remaining_input = input_width;
                 u32 remaining_input = input_width;
@@ -205,7 +205,7 @@ inline void Write(u32 addr, const T data) {
                     config.flags);
                     config.flags);
 
 
                 size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap);
                 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);
                 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
                 break;
                 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 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);
             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 y = 0; y < output_height; ++y) {
                 for (u32 x = 0; x < output_width; ++x) {
                 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;
             g_regs.display_transfer_config.trigger = 0;
             GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
             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;
         break;
     }
     }

+ 4 - 1
src/video_core/CMakeLists.txt

@@ -11,8 +11,10 @@ set(SRCS
             pica.cpp
             pica.cpp
             primitive_assembly.cpp
             primitive_assembly.cpp
             rasterizer.cpp
             rasterizer.cpp
+            renderer_base.cpp
             shader/shader.cpp
             shader/shader.cpp
             shader/shader_interpreter.cpp
             shader/shader_interpreter.cpp
+            swrasterizer.cpp
             utils.cpp
             utils.cpp
             video_core.cpp
             video_core.cpp
             )
             )
@@ -30,13 +32,14 @@ set(HEADERS
             clipper.h
             clipper.h
             command_processor.h
             command_processor.h
             gpu_debugger.h
             gpu_debugger.h
-            hwrasterizer_base.h
             pica.h
             pica.h
             primitive_assembly.h
             primitive_assembly.h
             rasterizer.h
             rasterizer.h
+            rasterizer_interface.h
             renderer_base.h
             renderer_base.h
             shader/shader.h
             shader/shader.h
             shader/shader_interpreter.h
             shader/shader_interpreter.h
+            swrasterizer.h
             utils.h
             utils.h
             video_core.h
             video_core.h
             )
             )

+ 1 - 1
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;
     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;
     using boost::container::static_vector;
 
 
     // Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at
     // Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at

+ 1 - 1
src/video_core/clipper.h

@@ -14,7 +14,7 @@ namespace Clipper {
 
 
 using Shader::OutputVertex;
 using Shader::OutputVertex;
 
 
-void ProcessTriangle(OutputVertex& v0, OutputVertex& v1, OutputVertex& v2);
+void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2);
 
 
 } // namespace
 } // namespace
 
 

+ 10 - 17
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) {
             for (auto& range : memory_accesses.ranges) {
@@ -356,9 +351,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
                                                           range.second, range.first);
                                                           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
 #if PICA_DUMP_GEOMETRY
             geometry_dumper.Dump();
             geometry_dumper.Dump();
@@ -475,7 +468,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
             break;
             break;
     }
     }
 
 
-    VideoCore::g_renderer->hw_rasterizer->NotifyPicaRegisterChanged(id);
+    VideoCore::g_renderer->rasterizer->NotifyPicaRegisterChanged(id);
 
 
     if (g_debug_context)
     if (g_debug_context)
         g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id));
         g_debug_context->OnEvent(DebugContext::Event::PicaCommandProcessed, reinterpret_cast<void*>(&id));

+ 2 - 4
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);
         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.
         // TODO: Should stop the CPU thread here once we multithread emulation.
 
 

+ 11 - 8
src/video_core/hwrasterizer_base.h → src/video_core/rasterizer_interface.h

@@ -12,10 +12,11 @@ struct OutputVertex;
 }
 }
 }
 }
 
 
-class HWRasterizer {
+namespace VideoCore {
+
+class RasterizerInterface {
 public:
 public:
-    virtual ~HWRasterizer() {
-    }
+    virtual ~RasterizerInterface() {}
 
 
     /// Initialize API-specific GPU objects
     /// Initialize API-specific GPU objects
     virtual void InitObjects() = 0;
     virtual void InitObjects() = 0;
@@ -32,14 +33,16 @@ public:
     virtual void DrawTriangles() = 0;
     virtual void DrawTriangles() = 0;
 
 
     /// Commit the rasterizer's framebuffer contents immediately to the current 3DS memory framebuffer
     /// 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
     /// Notify rasterizer that the specified PICA register has been changed
     virtual void NotifyPicaRegisterChanged(u32 id) = 0;
     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;
 };
 };
+
+}

+ 28 - 0
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();
+    }
+}

+ 6 - 2
src/video_core/renderer_base.h

@@ -8,7 +8,7 @@
 
 
 #include "common/common_types.h"
 #include "common/common_types.h"
 
 
-#include "video_core/hwrasterizer_base.h"
+#include "video_core/rasterizer_interface.h"
 
 
 class EmuWindow;
 class EmuWindow;
 
 
@@ -54,10 +54,14 @@ public:
         return m_current_frame;
         return m_current_frame;
     }
     }
 
 
-    std::unique_ptr<HWRasterizer> hw_rasterizer;
+    void RefreshRasterizerSetting();
+
+    std::unique_ptr<VideoCore::RasterizerInterface> rasterizer;
 
 
 protected:
 protected:
     f32 m_current_fps;              ///< Current framerate, should be set by the renderer
     f32 m_current_fps;              ///< Current framerate, should be set by the renderer
     int m_current_frame;            ///< Current frame, should be set by the renderer
     int m_current_frame;            ///< Current frame, should be set by the renderer
 
 
+private:
+    bool opengl_rasterizer_active = false;
 };
 };

+ 7 - 16
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -135,7 +135,7 @@ void RasterizerOpenGL::Reset() {
 
 
     SetShader();
     SetShader();
 
 
-    res_cache.FullFlush();
+    res_cache.InvalidateAll();
 }
 }
 
 
 void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0,
 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)
     u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format)
                             * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
                             * 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();
     CommitColorBuffer();
     CommitDepthBuffer();
     CommitDepthBuffer();
 }
 }
@@ -188,9 +188,6 @@ void RasterizerOpenGL::CommitFramebuffer() {
 void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
 void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
     const auto& regs = Pica::g_state.regs;
     const auto& regs = Pica::g_state.regs;
 
 
-    if (!Settings::values.use_hw_renderer)
-        return;
-
     switch(id) {
     switch(id) {
     // Culling
     // Culling
     case PICA_REG_INDEX(cull_mode):
     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;
     const auto& regs = Pica::g_state.regs;
 
 
-    if (!Settings::values.use_hw_renderer)
-        return;
-
     PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
     PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
     u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
     u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
                             * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
                             * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
@@ -306,12 +300,9 @@ void RasterizerOpenGL::NotifyPreRead(PAddr addr, u32 size) {
         CommitDepthBuffer();
         CommitDepthBuffer();
 }
 }
 
 
-void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
+void RasterizerOpenGL::InvalidateRegion(PAddr addr, u32 size) {
     const auto& regs = Pica::g_state.regs;
     const auto& regs = Pica::g_state.regs;
 
 
-    if (!Settings::values.use_hw_renderer)
-        return;
-
     PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
     PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress();
     u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
     u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format)
                             * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
                             * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight();
@@ -328,7 +319,7 @@ void RasterizerOpenGL::NotifyFlush(PAddr addr, u32 size) {
         ReloadDepthBuffer();
         ReloadDepthBuffer();
 
 
     // Notify cache of flush in case the region touches a cached resource
     // 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() {
 void RasterizerOpenGL::SamplerInfo::Create() {

+ 5 - 20
src/video_core/renderer_opengl/gl_rasterizer.h

@@ -14,7 +14,7 @@
 #include "common/hash.h"
 #include "common/hash.h"
 
 
 #include "video_core/pica.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_rasterizer_cache.h"
 #include "video_core/renderer_opengl/gl_state.h"
 #include "video_core/renderer_opengl/gl_state.h"
 #include "video_core/shader/shader_interpreter.h"
 #include "video_core/shader/shader_interpreter.h"
@@ -102,37 +102,22 @@ struct hash<PicaShaderConfig> {
 
 
 } // namespace std
 } // namespace std
 
 
-class RasterizerOpenGL : public HWRasterizer {
+class RasterizerOpenGL : public VideoCore::RasterizerInterface {
 public:
 public:
 
 
     RasterizerOpenGL();
     RasterizerOpenGL();
     ~RasterizerOpenGL() override;
     ~RasterizerOpenGL() override;
 
 
-    /// Initialize API-specific GPU objects
     void InitObjects() override;
     void InitObjects() override;
-
-    /// Reset the rasterizer, such as flushing all caches and updating all state
     void Reset() override;
     void Reset() override;
-
-    /// Queues the primitive formed by the given vertices for rendering
     void AddTriangle(const Pica::Shader::OutputVertex& v0,
     void AddTriangle(const Pica::Shader::OutputVertex& v0,
                      const Pica::Shader::OutputVertex& v1,
                      const Pica::Shader::OutputVertex& v1,
                      const Pica::Shader::OutputVertex& v2) override;
                      const Pica::Shader::OutputVertex& v2) override;
-
-    /// Draw the current batch of triangles
     void DrawTriangles() override;
     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;
     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
     /// OpenGL shader generated for a given Pica register state
     struct PicaShader {
     struct PicaShader {

+ 3 - 4
src/video_core/renderer_opengl/gl_rasterizer_cache.cpp

@@ -15,7 +15,7 @@
 #include "video_core/renderer_opengl/pica_to_gl.h"
 #include "video_core/renderer_opengl/pica_to_gl.h"
 
 
 RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
 RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
-    FullFlush();
+    InvalidateAll();
 }
 }
 
 
 MICROPROFILE_DEFINE(OpenGL_TextureUpload, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
 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
     // 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);
     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();
     texture_cache.clear();
 }
 }

+ 4 - 4
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));
         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:
 private:
     struct CachedTexture {
     struct CachedTexture {

+ 3 - 12
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 constructor
 RendererOpenGL::RendererOpenGL() {
 RendererOpenGL::RendererOpenGL() {
-    hw_rasterizer.reset(new RasterizerOpenGL());
     resolution_width  = std::max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth);
     resolution_width  = std::max(VideoCore::kScreenTopWidth, VideoCore::kScreenBottomWidth);
     resolution_height = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight;
     resolution_height = VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight;
 }
 }
@@ -157,15 +156,7 @@ void RendererOpenGL::SwapBuffers() {
 
 
     profiler.BeginFrame();
     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) {
     if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
         Pica::g_debug_context->recorder->FrameFinished();
         Pica::g_debug_context->recorder->FrameFinished();
@@ -286,8 +277,6 @@ void RendererOpenGL::InitOpenGLObjects() {
 
 
     state.texture_units[0].texture_2d = 0;
     state.texture_units[0].texture_2d = 0;
     state.Apply();
     state.Apply();
-
-    hw_rasterizer->InitObjects();
 }
 }
 
 
 void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
 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_VENDOR: %s", glGetString(GL_VENDOR));
     LOG_INFO(Render_OpenGL, "GL_RENDERER: %s", glGetString(GL_RENDERER));
     LOG_INFO(Render_OpenGL, "GL_RENDERER: %s", glGetString(GL_RENDERER));
     InitOpenGLObjects();
     InitOpenGLObjects();
+
+    RefreshRasterizerSetting();
 }
 }
 
 
 /// Shutdown the renderer
 /// Shutdown the renderer

+ 16 - 0
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);
+}
+
+}

+ 26 - 0
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 {}
+};
+
+}