diff options
Diffstat (limited to 'src/video_core')
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 |
