Merge pull request #1272 from yuriks/merge-rasterizer
VideoCore: Unify interface to OpenGL and SW rasterizers
This commit is contained in:
commit
31764c48fb
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -336,19 +336,14 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::values.use_hw_renderer) {
|
// Send to renderer
|
||||||
// Send to hardware renderer
|
using Pica::Shader::OutputVertex;
|
||||||
static auto AddHWTriangle = [](const Pica::Shader::OutputVertex& v0,
|
auto AddTriangle = [](
|
||||||
const Pica::Shader::OutputVertex& v1,
|
const OutputVertex& v0, const OutputVertex& v1, const OutputVertex& v2) {
|
||||||
const Pica::Shader::OutputVertex& v2) {
|
VideoCore::g_renderer->rasterizer->AddTriangle(v0, v1, v2);
|
||||||
VideoCore::g_renderer->hw_rasterizer->AddTriangle(v0, v1, v2);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
primitive_assembler.SubmitVertex(output, AddHWTriangle);
|
primitive_assembler.SubmitVertex(output, AddTriangle);
|
||||||
} else {
|
|
||||||
// Send to triangle clipper
|
|
||||||
primitive_assembler.SubmitVertex(output, Clipper::ProcessTriangle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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->rasterizer->DrawTriangles();
|
||||||
VideoCore::g_renderer->hw_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));
|
||||||
|
|
|
@ -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
|
||||||
// Commit the hardware renderer's framebuffer so it will show on debug widgets
|
VideoCore::g_renderer->rasterizer->FlushFramebuffer();
|
||||||
VideoCore::g_renderer->hw_rasterizer->CommitFramebuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Should stop the CPU thread here once we multithread emulation.
|
// TODO: Should stop the CPU thread here once we multithread emulation.
|
||||||
|
|
||||||
|
|
|
@ -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
|
/// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory.
|
||||||
virtual void NotifyPreRead(PAddr addr, u32 size) = 0;
|
virtual void FlushRegion(PAddr addr, u32 size) = 0;
|
||||||
|
|
||||||
/// Notify rasterizer that a 3DS memory region has been changed
|
/// Notify rasterizer that any caches of the specified region should be discraded and reloaded from 3DS memory.
|
||||||
virtual void NotifyFlush(PAddr addr, u32 size) = 0;
|
virtual void InvalidateRegion(PAddr addr, u32 size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.InvalidateInRange(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_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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
void FlushFramebuffer() 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 NotifyPicaRegisterChanged(u32 id) override;
|
void NotifyPicaRegisterChanged(u32 id) override;
|
||||||
|
void FlushRegion(PAddr addr, u32 size) override;
|
||||||
/// Notify rasterizer that the specified 3DS memory region will be read from after this notification
|
void InvalidateRegion(PAddr addr, u32 size) override;
|
||||||
void NotifyPreRead(PAddr addr, u32 size) override;
|
|
||||||
|
|
||||||
/// Notify rasterizer that a 3DS memory region has been changed
|
|
||||||
void NotifyFlush(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 {
|
||||||
|
|
|
@ -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) {
|
void RasterizerCacheOpenGL::InvalidateInRange(PAddr addr, u32 size, bool ignore_hash) {
|
||||||
// Flush any texture that falls in the flushed region
|
|
||||||
// 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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
/// Invalidate any cached resource intersecting the specified region.
|
||||||
void NotifyFlush(PAddr addr, u32 size, bool ignore_hash = false);
|
void InvalidateInRange(PAddr addr, u32 size, bool ignore_hash = false);
|
||||||
|
|
||||||
/// Flush all cached OpenGL resources tracked by this cache manager
|
/// Invalidate all cached OpenGL resources tracked by this cache manager
|
||||||
void FullFlush();
|
void InvalidateAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CachedTexture {
|
struct CachedTexture {
|
||||||
|
|
|
@ -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;
|
RefreshRasterizerSetting();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Reference in New Issue