aboutsummaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp12
-rw-r--r--src/video_core/engines/maxwell_3d.h8
-rw-r--r--src/video_core/gpu.cpp6
-rw-r--r--src/video_core/gpu.h7
-rw-r--r--src/video_core/macro_interpreter.cpp4
-rw-r--r--src/video_core/macro_interpreter.h4
-rw-r--r--src/video_core/renderer_base.cpp18
-rw-r--r--src/video_core/renderer_base.h29
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp17
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp23
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h36
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp17
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h6
-rw-r--r--src/video_core/renderer_opengl/gl_state.h5
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp30
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h17
-rw-r--r--src/video_core/textures/decoders.cpp4
-rw-r--r--src/video_core/video_core.cpp28
-rw-r--r--src/video_core/video_core.h24
21 files changed, 172 insertions, 137 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 0e205ed72..5c0ae8009 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -19,8 +19,8 @@ namespace Engines {
/// First register id that is actually a Macro call.
constexpr u32 MacroRegistersStart = 0xE00;
-Maxwell3D::Maxwell3D(MemoryManager& memory_manager)
- : memory_manager(memory_manager), macro_interpreter(*this) {}
+Maxwell3D::Maxwell3D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager)
+ : memory_manager(memory_manager), rasterizer{rasterizer}, macro_interpreter(*this) {}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
auto macro_code = uploaded_macros.find(method);
@@ -130,7 +130,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
break;
}
- VideoCore::g_renderer->Rasterizer()->NotifyMaxwellRegisterChanged(method);
+ rasterizer.NotifyMaxwellRegisterChanged(method);
if (debug_context) {
debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr);
@@ -218,7 +218,7 @@ void Maxwell3D::DrawArrays() {
}
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
- VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(is_indexed);
+ rasterizer.AccelerateDrawBatch(is_indexed);
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
// the game is trying to draw indexed or direct mode. This needs to be verified on HW still -
@@ -285,8 +285,6 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
// TODO(Subv): Different data types for separate components are not supported
ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
- // TODO(Subv): Only UNORM formats are supported for now.
- ASSERT(r_type == Texture::ComponentType::UNORM);
return tic_entry;
}
@@ -393,7 +391,7 @@ void Maxwell3D::ProcessClearBuffers() {
regs.clear_buffers.R == regs.clear_buffers.B &&
regs.clear_buffers.R == regs.clear_buffers.A);
- VideoCore::g_renderer->Rasterizer()->Clear();
+ rasterizer.Clear();
}
} // namespace Engines
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 3c32f1067..4d0ff96a5 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -17,6 +17,10 @@
#include "video_core/memory_manager.h"
#include "video_core/textures/texture.h"
+namespace VideoCore {
+class RasterizerInterface;
+}
+
namespace Tegra::Engines {
#define MAXWELL3D_REG_INDEX(field_name) \
@@ -24,7 +28,7 @@ namespace Tegra::Engines {
class Maxwell3D final {
public:
- explicit Maxwell3D(MemoryManager& memory_manager);
+ explicit Maxwell3D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager);
~Maxwell3D() = default;
/// Register structure of the Maxwell3D engine.
@@ -818,6 +822,8 @@ public:
Texture::FullTextureInfo GetStageTexture(Regs::ShaderStage stage, size_t offset) const;
private:
+ VideoCore::RasterizerInterface& rasterizer;
+
std::unordered_map<u32, std::vector<u32>> uploaded_macros;
/// Macro method that is currently being executed / being fed parameters.
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 60c49d672..b2a83ce0b 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -7,12 +7,13 @@
#include "video_core/engines/maxwell_compute.h"
#include "video_core/engines/maxwell_dma.h"
#include "video_core/gpu.h"
+#include "video_core/rasterizer_interface.h"
namespace Tegra {
-GPU::GPU() {
+GPU::GPU(VideoCore::RasterizerInterface& rasterizer) {
memory_manager = std::make_unique<MemoryManager>();
- maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager);
+ maxwell_3d = std::make_unique<Engines::Maxwell3D>(rasterizer, *memory_manager);
fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);
maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(*memory_manager);
@@ -40,6 +41,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
case RenderTargetFormat::RGBA8_UNORM:
case RenderTargetFormat::RGB10_A2_UNORM:
case RenderTargetFormat::BGRA8_UNORM:
+ case RenderTargetFormat::R32_FLOAT:
return 4;
default:
UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format));
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index c464fc6d1..440505c9d 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -11,6 +11,10 @@
#include "core/hle/service/nvflinger/buffer_queue.h"
#include "video_core/memory_manager.h"
+namespace VideoCore {
+class RasterizerInterface;
+}
+
namespace Tegra {
enum class RenderTargetFormat : u32 {
@@ -29,6 +33,7 @@ enum class RenderTargetFormat : u32 {
RG16_UINT = 0xDD,
RG16_FLOAT = 0xDE,
R11G11B10_FLOAT = 0xE0,
+ R32_FLOAT = 0xE5,
R16_FLOAT = 0xF2,
R8_UNORM = 0xF3,
};
@@ -97,7 +102,7 @@ enum class EngineID {
class GPU final {
public:
- GPU();
+ explicit GPU(VideoCore::RasterizerInterface& rasterizer);
~GPU();
/// Processes a command list stored at the specified address in GPU memory.
diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp
index 44ece01c1..377bd66ab 100644
--- a/src/video_core/macro_interpreter.cpp
+++ b/src/video_core/macro_interpreter.cpp
@@ -102,11 +102,11 @@ bool MacroInterpreter::Step(const std::vector<u32>& code, bool is_delay_slot) {
if (taken) {
// Ignore the delay slot if the branch has the annul bit.
if (opcode.branch_annul) {
- pc = base_address + (opcode.immediate << 2);
+ pc = base_address + opcode.GetBranchTarget();
return true;
}
- delayed_pc = base_address + (opcode.immediate << 2);
+ delayed_pc = base_address + opcode.GetBranchTarget();
// Execute one more instruction due to the delay slot.
return Step(code, true);
}
diff --git a/src/video_core/macro_interpreter.h b/src/video_core/macro_interpreter.h
index a71e359d8..7d836b816 100644
--- a/src/video_core/macro_interpreter.h
+++ b/src/video_core/macro_interpreter.h
@@ -91,6 +91,10 @@ private:
u32 GetBitfieldMask() const {
return (1 << bf_size) - 1;
}
+
+ s32 GetBranchTarget() const {
+ return static_cast<s32>(immediate * sizeof(u32));
+ }
};
union MethodAddress {
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index 30075b23c..3ca350243 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -2,14 +2,26 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <atomic>
#include <memory>
+#include "core/frontend/emu_window.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
-#include "video_core/video_core.h"
+
+namespace VideoCore {
+
+RendererBase::RendererBase(EmuWindow& window) : render_window{window} {}
+RendererBase::~RendererBase() = default;
+
+void RendererBase::UpdateCurrentFramebufferLayout() {
+ const Layout::FramebufferLayout& layout = render_window.GetFramebufferLayout();
+
+ render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
+}
void RendererBase::RefreshRasterizerSetting() {
if (rasterizer == nullptr) {
- rasterizer = std::make_unique<RasterizerOpenGL>();
+ rasterizer = std::make_unique<RasterizerOpenGL>(render_window);
}
}
+
+} // namespace VideoCore
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 89a960eaf..235de23a1 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -13,28 +13,28 @@
class EmuWindow;
+namespace VideoCore {
+
class RendererBase : NonCopyable {
public:
/// Used to reference a framebuffer
enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture };
- virtual ~RendererBase() {}
+ explicit RendererBase(EmuWindow& window);
+ virtual ~RendererBase();
/// Swap buffers (render frame)
virtual void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) = 0;
- /**
- * Set the emulator window to use for renderer
- * @param window EmuWindow handle to emulator window to use for rendering
- */
- virtual void SetWindow(EmuWindow* window) = 0;
-
/// Initialize the renderer
virtual bool Init() = 0;
/// Shutdown the renderer
virtual void ShutDown() = 0;
+ /// Updates the framebuffer layout of the contained render window handle.
+ void UpdateCurrentFramebufferLayout();
+
// Getter/setter functions:
// ------------------------
@@ -46,16 +46,21 @@ public:
return m_current_frame;
}
- VideoCore::RasterizerInterface* Rasterizer() const {
- return rasterizer.get();
+ RasterizerInterface& Rasterizer() {
+ return *rasterizer;
+ }
+
+ const RasterizerInterface& Rasterizer() const {
+ return *rasterizer;
}
void RefreshRasterizerSetting();
protected:
- std::unique_ptr<VideoCore::RasterizerInterface> rasterizer;
+ EmuWindow& render_window; ///< Reference to the render window handle.
+ std::unique_ptr<RasterizerInterface> rasterizer;
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
int m_current_frame = 0; ///< Current frame, should be set by the renderer
-
-private:
};
+
+} // namespace VideoCore
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a1c47bae9..c2a931469 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -14,7 +14,6 @@
#include "common/logging/log.h"
#include "common/math_util.h"
#include "common/microprofile.h"
-#include "common/scope_exit.h"
#include "core/core.h"
#include "core/frontend/emu_window.h"
#include "core/hle/kernel/process.h"
@@ -37,7 +36,7 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
-RasterizerOpenGL::RasterizerOpenGL() {
+RasterizerOpenGL::RasterizerOpenGL(EmuWindow& window) : emu_window{window} {
// Create sampler objects
for (size_t i = 0; i < texture_samplers.size(); ++i) {
texture_samplers[i].Create();
@@ -170,8 +169,14 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
ASSERT(buffer.IsEnabled());
glEnableVertexAttribArray(index);
- glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
- attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
+ if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt ||
+ attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) {
+ glVertexAttribIFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
+ attrib.offset);
+ } else {
+ glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
+ attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
+ }
glVertexAttribBinding(index, attrib.buffer);
}
@@ -395,7 +400,7 @@ void RasterizerOpenGL::Clear() {
if (clear_mask == 0)
return;
- ScopeAcquireGLContext acquire_context;
+ ScopeAcquireGLContext acquire_context{emu_window};
auto [dirty_color_surface, dirty_depth_surface] =
ConfigureFramebuffers(use_color_fb, use_depth_fb);
@@ -425,7 +430,7 @@ void RasterizerOpenGL::DrawArrays() {
MICROPROFILE_SCOPE(OpenGL_Drawing);
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
- ScopeAcquireGLContext acquire_context;
+ ScopeAcquireGLContext acquire_context{emu_window};
auto [dirty_color_surface, dirty_depth_surface] =
ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index e150be58f..6d6d85cc1 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -21,11 +21,12 @@
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
+class EmuWindow;
struct ScreenInfo;
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
- RasterizerOpenGL();
+ explicit RasterizerOpenGL(EmuWindow& renderer);
~RasterizerOpenGL() override;
void DrawArrays() override;
@@ -144,6 +145,8 @@ private:
RasterizerCacheOpenGL res_cache;
+ EmuWindow& emu_window;
+
std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
OGLVertexArray sw_vao;
OGLVertexArray hw_vao;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index a4d9707cb..257aa9571 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -46,6 +46,8 @@ struct FormatTuple {
params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
params.unaligned_height = config.tic.Height();
params.size_in_bytes = params.SizeInBytes();
+ params.cache_width = Common::AlignUp(params.width, 16);
+ params.cache_height = Common::AlignUp(params.height, 16);
return params;
}
@@ -63,6 +65,8 @@ struct FormatTuple {
params.height = config.height;
params.unaligned_height = config.height;
params.size_in_bytes = params.SizeInBytes();
+ params.cache_width = Common::AlignUp(params.width, 16);
+ params.cache_height = Common::AlignUp(params.height, 16);
return params;
}
@@ -82,6 +86,8 @@ struct FormatTuple {
params.height = zeta_height;
params.unaligned_height = zeta_height;
params.size_in_bytes = params.SizeInBytes();
+ params.cache_width = Common::AlignUp(params.width, 16);
+ params.cache_height = Common::AlignUp(params.height, 16);
return params;
}
@@ -118,6 +124,7 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
{GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RG16UI
{GL_RG16I, GL_RG_INTEGER, GL_SHORT, ComponentType::SInt, false}, // RG16I
{GL_RG16_SNORM, GL_RG, GL_SHORT, ComponentType::SNorm, false}, // RG16S
+ {GL_RGB32F, GL_RGB, GL_FLOAT, ComponentType::Float, false}, // RGB32F
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // SRGBA8
// DepthStencil formats
@@ -218,9 +225,10 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
MortonCopy<true, PixelFormat::R16UNORM>, MortonCopy<true, PixelFormat::RG16>,
MortonCopy<true, PixelFormat::RG16F>, MortonCopy<true, PixelFormat::RG16UI>,
MortonCopy<true, PixelFormat::RG16I>, MortonCopy<true, PixelFormat::RG16S>,
- MortonCopy<true, PixelFormat::SRGBA8>, MortonCopy<true, PixelFormat::Z24S8>,
- MortonCopy<true, PixelFormat::S8Z24>, MortonCopy<true, PixelFormat::Z32F>,
- MortonCopy<true, PixelFormat::Z16>, MortonCopy<true, PixelFormat::Z32FS8>,
+ MortonCopy<true, PixelFormat::RGB32F>, MortonCopy<true, PixelFormat::SRGBA8>,
+ MortonCopy<true, PixelFormat::Z24S8>, MortonCopy<true, PixelFormat::S8Z24>,
+ MortonCopy<true, PixelFormat::Z32F>, MortonCopy<true, PixelFormat::Z16>,
+ MortonCopy<true, PixelFormat::Z32FS8>,
};
static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
@@ -253,6 +261,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr),
MortonCopy<false, PixelFormat::RG16UI>,
MortonCopy<false, PixelFormat::RG16I>,
MortonCopy<false, PixelFormat::RG16S>,
+ MortonCopy<false, PixelFormat::RGB32F>,
MortonCopy<false, PixelFormat::SRGBA8>,
MortonCopy<false, PixelFormat::Z24S8>,
MortonCopy<false, PixelFormat::S8Z24>,
@@ -677,12 +686,12 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) {
// If use_accurate_framebuffers is enabled, always load from memory
FlushSurface(surface);
UnregisterSurface(surface);
- } else if (surface->GetSurfaceParams() != params) {
- // If surface parameters changed, recreate the surface from the old one
- return RecreateSurface(surface, params);
- } else {
+ } else if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
// Use the cached surface as-is
return surface;
+ } else {
+ // If surface parameters changed, recreate the surface from the old one
+ return RecreateSurface(surface, params);
}
}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index bf0458b94..0c6652c7a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -9,6 +9,7 @@
#include <memory>
#include <vector>
#include <boost/icl/interval_map.hpp>
+
#include "common/common_types.h"
#include "common/math_util.h"
#include "video_core/engines/maxwell_3d.h"
@@ -48,16 +49,17 @@ struct SurfaceParams {
RG16UI = 23,
RG16I = 24,
RG16S = 25,
- SRGBA8 = 26,
+ RGB32F = 26,
+ SRGBA8 = 27,
MaxColorFormat,
// DepthStencil formats
- Z24S8 = 27,
- S8Z24 = 28,
- Z32F = 29,
- Z16 = 30,
- Z32FS8 = 31,
+ Z24S8 = 28,
+ S8Z24 = 29,
+ Z32F = 30,
+ Z16 = 31,
+ Z32FS8 = 32,
MaxDepthStencilFormat,
@@ -121,6 +123,7 @@ struct SurfaceParams {
1, // RG16UI
1, // RG16I
1, // RG16S
+ 1, // RGB32F
1, // SRGBA8
1, // Z24S8
1, // S8Z24
@@ -164,6 +167,7 @@ struct SurfaceParams {
32, // RG16UI
32, // RG16I
32, // RG16S
+ 96, // RGB32F
32, // SRGBA8
32, // Z24S8
32, // S8Z24
@@ -200,8 +204,9 @@ struct SurfaceParams {
static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
switch (format) {
+ // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the
+ // gamma.
case Tegra::RenderTargetFormat::RGBA8_SRGB:
- return PixelFormat::SRGBA8;
case Tegra::RenderTargetFormat::RGBA8_UNORM:
return PixelFormat::ABGR8;
case Tegra::RenderTargetFormat::BGRA8_UNORM:
@@ -232,6 +237,8 @@ struct SurfaceParams {
return PixelFormat::RG16S;
case Tegra::RenderTargetFormat::R16_FLOAT:
return PixelFormat::R16F;
+ case Tegra::RenderTargetFormat::R32_FLOAT:
+ return PixelFormat::R32F;
default:
LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
UNREACHABLE();
@@ -270,6 +277,8 @@ struct SurfaceParams {
UNREACHABLE();
case Tegra::Texture::TextureFormat::R32_G32:
return PixelFormat::RG32F;
+ case Tegra::Texture::TextureFormat::R32_G32_B32:
+ return PixelFormat::RGB32F;
case Tegra::Texture::TextureFormat::R16:
switch (component_type) {
case Tegra::Texture::ComponentType::FLOAT:
@@ -361,6 +370,8 @@ struct SurfaceParams {
return Tegra::Texture::TextureFormat::A8R8G8B8;
case PixelFormat::RGBA32F:
return Tegra::Texture::TextureFormat::R32_G32_B32_A32;
+ case PixelFormat::RGB32F:
+ return Tegra::Texture::TextureFormat::R32_G32_B32;
case PixelFormat::RG32F:
return Tegra::Texture::TextureFormat::R32_G32;
case PixelFormat::R32F:
@@ -439,6 +450,7 @@ struct SurfaceParams {
case Tegra::RenderTargetFormat::RG32_FLOAT:
case Tegra::RenderTargetFormat::RG16_FLOAT:
case Tegra::RenderTargetFormat::R16_FLOAT:
+ case Tegra::RenderTargetFormat::R32_FLOAT:
return ComponentType::Float;
case Tegra::RenderTargetFormat::RGBA32_UINT:
case Tegra::RenderTargetFormat::RG16_UINT:
@@ -536,6 +548,12 @@ struct SurfaceParams {
return !operator==(other);
}
+ /// Checks if surfaces are compatible for caching
+ bool IsCompatibleSurface(const SurfaceParams& other) const {
+ return std::tie(pixel_format, type, cache_width, cache_height) ==
+ std::tie(other.pixel_format, other.type, other.cache_width, other.cache_height);
+ }
+
Tegra::GPUVAddr addr;
bool is_tiled;
u32 block_height;
@@ -546,6 +564,10 @@ struct SurfaceParams {
u32 height;
u32 unaligned_height;
size_t size_in_bytes;
+
+ // Parameters used for caching only
+ u32 cache_width;
+ u32 cache_height;
};
class CachedSurface final {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index acf067050..e3217db81 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -412,7 +412,6 @@ public:
}
declarations.AddNewLine();
- unsigned const_buffer_layout = 0;
for (const auto& entry : GetConstBuffersDeclarations()) {
declarations.AddLine("layout(std140) uniform " + entry.GetName());
declarations.AddLine('{');
@@ -420,7 +419,6 @@ public:
"[MAX_CONSTBUFFER_ELEMENTS];");
declarations.AddLine("};");
declarations.AddNewLine();
- ++const_buffer_layout;
}
declarations.AddNewLine();
@@ -768,13 +766,16 @@ private:
// goes into gpr28+0 and gpr28+1
size_t texs_offset{};
+ size_t src_elem{};
for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
+ size_t dest_elem{};
for (unsigned elem = 0; elem < 2; ++elem) {
- if (!instr.texs.IsComponentEnabled(elem)) {
+ if (!instr.texs.IsComponentEnabled(src_elem++)) {
// Skip disabled components
continue;
}
- regs.SetRegisterToFloat(dest, elem + texs_offset, texture, 1, 4, false, elem);
+ regs.SetRegisterToFloat(dest, elem + texs_offset, texture, 1, 4, false,
+ dest_elem++);
}
if (!instr.texs.HasTwoDestinations()) {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index e81fcbbc4..415d42fda 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -13,15 +13,16 @@ namespace Impl {
static void SetShaderUniformBlockBinding(GLuint shader, const char* name,
Maxwell3D::Regs::ShaderStage binding,
size_t expected_size) {
- GLuint ub_index = glGetUniformBlockIndex(shader, name);
- if (ub_index != GL_INVALID_INDEX) {
- GLint ub_size = 0;
- glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size);
- ASSERT_MSG(ub_size == expected_size,
- "Uniform block size did not match! Got {}, expected {}",
- static_cast<int>(ub_size), expected_size);
- glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding));
+ const GLuint ub_index = glGetUniformBlockIndex(shader, name);
+ if (ub_index == GL_INVALID_INDEX) {
+ return;
}
+
+ GLint ub_size = 0;
+ glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size);
+ ASSERT_MSG(static_cast<size_t>(ub_size) == expected_size,
+ "Uniform block size did not match! Got {}, expected {}", ub_size, expected_size);
+ glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding));
}
void SetShaderUniformBlockBindings(GLuint shader) {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index e29d551e1..716933a0b 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -105,20 +105,20 @@ public:
}
ShaderEntries UseProgrammableVertexShader(const MaxwellVSConfig& config,
- const ShaderSetup setup) {
+ const ShaderSetup& setup) {
ShaderEntries result;
std::tie(current.vs, result) = vertex_shaders.Get(config, setup);
return result;
}
ShaderEntries UseProgrammableFragmentShader(const MaxwellFSConfig& config,
- const ShaderSetup setup) {
+ const ShaderSetup& setup) {
ShaderEntries result;
std::tie(current.fs, result) = fragment_shaders.Get(config, setup);
return result;
}
- GLuint GetCurrentProgramStage(Maxwell3D::Regs::ShaderStage stage) {
+ GLuint GetCurrentProgramStage(Maxwell3D::Regs::ShaderStage stage) const {
switch (stage) {
case Maxwell3D::Regs::ShaderStage::Vertex:
return current.vs;
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 3398d7c04..24b1d956b 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -82,7 +82,7 @@ public:
GLenum logic_op; // GL_LOGIC_OP_MODE
// 3 texture units - one for each that is used in PICA fragment shader emulation
- struct {
+ struct TextureUnit {
GLuint texture_2d; // GL_TEXTURE_BINDING_2D
GLuint sampler; // GL_SAMPLER_BINDING
struct {
@@ -104,7 +104,8 @@ public:
Unbind();
sampler = 0;
}
- } texture_units[32];
+ };
+ std::array<TextureUnit, 32> texture_units;
struct {
GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 7810b9147..bf9131193 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -92,23 +92,23 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
return matrix;
}
-ScopeAcquireGLContext::ScopeAcquireGLContext() {
+ScopeAcquireGLContext::ScopeAcquireGLContext(EmuWindow& emu_window_) : emu_window{emu_window_} {
if (Settings::values.use_multi_core) {
- VideoCore::g_emu_window->MakeCurrent();
+ emu_window.MakeCurrent();
}
}
ScopeAcquireGLContext::~ScopeAcquireGLContext() {
if (Settings::values.use_multi_core) {
- VideoCore::g_emu_window->DoneCurrent();
+ emu_window.DoneCurrent();
}
}
-RendererOpenGL::RendererOpenGL() = default;
+RendererOpenGL::RendererOpenGL(EmuWindow& window) : VideoCore::RendererBase{window} {}
RendererOpenGL::~RendererOpenGL() = default;
/// Swap buffers (render frame)
void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) {
- ScopeAcquireGLContext acquire_context;
+ ScopeAcquireGLContext acquire_context{render_window};
Core::System::GetInstance().perf_stats.EndSystemFrame();
@@ -130,10 +130,10 @@ void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&
// Load the framebuffer from memory, draw it to the screen, and swap buffers
LoadFBToScreenInfo(*framebuffer, screen_info);
DrawScreen();
- render_window->SwapBuffers();
+ render_window.SwapBuffers();
}
- render_window->PollEvents();
+ render_window.PollEvents();
Core::System::GetInstance().frame_limiter.DoFrameLimiting(CoreTiming::GetGlobalTimeUs());
Core::System::GetInstance().perf_stats.BeginSystemFrame();
@@ -160,8 +160,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
// only allows rows to have a memory alignement of 4.
ASSERT(framebuffer.stride % 4 == 0);
- if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride,
- screen_info)) {
+ if (!rasterizer->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride,
+ screen_info)) {
// Reset the screen info's display texture to its own permanent texture
screen_info.display_texture = screen_info.texture.resource.handle;
@@ -356,7 +356,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
* Draws the emulated screens to the emulator window.
*/
void RendererOpenGL::DrawScreen() {
- const auto& layout = render_window->GetFramebufferLayout();
+ const auto& layout = render_window.GetFramebufferLayout();
const auto& screen = layout.screen;
glViewport(0, 0, layout.width, layout.height);
@@ -380,14 +380,6 @@ void RendererOpenGL::DrawScreen() {
/// Updates the framerate
void RendererOpenGL::UpdateFramerate() {}
-/**
- * Set the emulator window to use for renderer
- * @param window EmuWindow handle to emulator window to use for rendering
- */
-void RendererOpenGL::SetWindow(EmuWindow* window) {
- render_window = window;
-}
-
static const char* GetSource(GLenum source) {
#define RET(s) \
case GL_DEBUG_SOURCE_##s: \
@@ -445,7 +437,7 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum
/// Initialize the renderer
bool RendererOpenGL::Init() {
- ScopeAcquireGLContext acquire_context;
+ ScopeAcquireGLContext acquire_context{render_window};
if (GLAD_GL_KHR_debug) {
glEnable(GL_DEBUG_OUTPUT);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 59d92a3dc..428afa3b7 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -34,24 +34,21 @@ struct ScreenInfo {
/// Helper class to acquire/release OpenGL context within a given scope
class ScopeAcquireGLContext : NonCopyable {
public:
- ScopeAcquireGLContext();
+ explicit ScopeAcquireGLContext(EmuWindow& window);
~ScopeAcquireGLContext();
+
+private:
+ EmuWindow& emu_window;
};
-class RendererOpenGL : public RendererBase {
+class RendererOpenGL : public VideoCore::RendererBase {
public:
- RendererOpenGL();
+ explicit RendererOpenGL(EmuWindow& window);
~RendererOpenGL() override;
/// Swap buffers (render frame)
void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) override;
- /**
- * Set the emulator window to use for renderer
- * @param window EmuWindow handle to emulator window to use for rendering
- */
- void SetWindow(EmuWindow* window) override;
-
/// Initialize the renderer
bool Init() override;
@@ -72,8 +69,6 @@ private:
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
const TextureInfo& texture);
- EmuWindow* render_window; ///< Handle to render window
-
OpenGLState state;
// OpenGL object IDs
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index d794f8402..65db84ad3 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -57,6 +57,8 @@ u32 BytesPerPixel(TextureFormat format) {
case TextureFormat::BC7U:
// In this case a 'pixel' actually refers to a 4x4 tile.
return 16;
+ case TextureFormat::R32_G32_B32:
+ return 12;
case TextureFormat::ASTC_2D_4X4:
case TextureFormat::A8R8G8B8:
case TextureFormat::A2B10G10R10:
@@ -131,6 +133,7 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
case TextureFormat::R16_G16:
case TextureFormat::BF10GF11RF11:
case TextureFormat::ASTC_2D_4X4:
+ case TextureFormat::R32_G32_B32:
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
unswizzled_data.data(), true, block_height);
break;
@@ -190,6 +193,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
case TextureFormat::R32:
case TextureFormat::R16:
case TextureFormat::R16_G16:
+ case TextureFormat::R32_G32_B32:
// TODO(Subv): For the time being just forward the same data without any decoding.
rgba_data = texture_data;
break;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 289140f31..5085ef96b 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -3,40 +3,16 @@
// Refer to the license.txt file included.
#include <memory>
-#include "common/logging/log.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
#include "video_core/video_core.h"
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Video Core namespace
-
namespace VideoCore {
-EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
-std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
-
std::atomic<bool> g_toggle_framelimit_enabled;
-/// Initialize the video core
-bool Init(EmuWindow* emu_window) {
- g_emu_window = emu_window;
- g_renderer = std::make_unique<RendererOpenGL>();
- g_renderer->SetWindow(g_emu_window);
- if (g_renderer->Init()) {
- LOG_DEBUG(Render, "initialized OK");
- } else {
- LOG_CRITICAL(Render, "initialization failed !");
- return false;
- }
- return true;
-}
-
-/// Shutdown the video core
-void Shutdown() {
- g_renderer.reset();
-
- LOG_DEBUG(Render, "shutdown OK");
+std::unique_ptr<RendererBase> CreateRenderer(EmuWindow& emu_window) {
+ return std::make_unique<RendererOpenGL>(emu_window);
}
} // namespace VideoCore
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h
index 37da62436..7c01c0b8d 100644
--- a/src/video_core/video_core.h
+++ b/src/video_core/video_core.h
@@ -8,29 +8,23 @@
#include <memory>
class EmuWindow;
-class RendererBase;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Video Core namespace
namespace VideoCore {
-enum class Renderer { Software, OpenGL };
+class RendererBase;
-extern std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
-extern EmuWindow* g_emu_window; ///< Emu window
+enum class Renderer { Software, OpenGL };
// TODO: Wrap these in a user settings struct along with any other graphics settings (often set from
// qt ui)
extern std::atomic<bool> g_toggle_framelimit_enabled;
-/// Start the video core
-void Start();
-
-/// Initialize the video core
-bool Init(EmuWindow* emu_window);
-
-/// Shutdown the video core
-void Shutdown();
+/**
+ * Creates a renderer instance.
+ *
+ * @note The returned renderer instance is simply allocated. Its Init()
+ * function still needs to be called to fully complete its setup.
+ */
+std::unique_ptr<RendererBase> CreateRenderer(EmuWindow& emu_window);
} // namespace VideoCore