diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 4 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/macro_interpreter.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/morton.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_base.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_base.h | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 43 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 9 | ||||
| -rw-r--r-- | src/video_core/surface.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/video_core.h | 2 |
16 files changed, 138 insertions, 10 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 25bb7604a..0faff6fdf 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -164,6 +164,7 @@ public: return 3; default: UNREACHABLE(); + return 1; } } @@ -871,6 +872,7 @@ public: return 4; } UNREACHABLE(); + return 1; } GPUVAddr StartAddress() const { diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 2efeb6e1a..e53c77f2b 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1049,7 +1049,7 @@ union Instruction { BitField<49, 1, u64> nodep_flag; BitField<50, 3, u64> component_mask_selector; BitField<53, 4, u64> texture_info; - BitField<60, 1, u64> fp32_flag; + BitField<59, 1, u64> fp32_flag; TextureType GetTextureType() const { // The TEXS instruction has a weird encoding for the texture type. @@ -1065,6 +1065,7 @@ union Instruction { LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}", static_cast<u32>(texture_info.Value())); UNREACHABLE(); + return TextureType::Texture1D; } TextureProcessMode GetTextureProcessMode() const { @@ -1145,6 +1146,7 @@ union Instruction { LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}", static_cast<u32>(texture_info.Value())); UNREACHABLE(); + return TextureType::Texture1D; } TextureProcessMode GetTextureProcessMode() const { diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 88c45a423..08cf6268f 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -102,6 +102,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { return 1; default: UNIMPLEMENTED_MSG("Unimplemented render target format {}", static_cast<u32>(format)); + return 1; } } @@ -119,6 +120,7 @@ u32 DepthFormatBytesPerPixel(DepthFormat format) { return 2; default: UNIMPLEMENTED_MSG("Unimplemented Depth format {}", static_cast<u32>(format)); + return 1; } } diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp index 9c55e9f1e..64f75db43 100644 --- a/src/video_core/macro_interpreter.cpp +++ b/src/video_core/macro_interpreter.cpp @@ -171,6 +171,7 @@ u32 MacroInterpreter::GetALUResult(ALUOperation operation, u32 src_a, u32 src_b) default: UNIMPLEMENTED_MSG("Unimplemented ALU operation {}", static_cast<u32>(operation)); + return 0; } } @@ -268,6 +269,7 @@ bool MacroInterpreter::EvaluateBranchCondition(BranchCondition cond, u32 value) return value != 0; } UNREACHABLE(); + return true; } } // namespace Tegra diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp index a310491a8..47e76d8fe 100644 --- a/src/video_core/morton.cpp +++ b/src/video_core/morton.cpp @@ -192,6 +192,7 @@ static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFor return linear_to_morton_fns[static_cast<std::size_t>(format)]; } UNREACHABLE(); + return morton_to_linear_fns[static_cast<std::size_t>(format)]; } /// 8x8 Z-Order coordinate from 2D coordinates diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index 1482cdb40..94223f45f 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp @@ -27,4 +27,16 @@ void RendererBase::UpdateCurrentFramebufferLayout() { render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height); } +void RendererBase::RequestScreenshot(void* data, std::function<void()> callback, + const Layout::FramebufferLayout& layout) { + if (renderer_settings.screenshot_requested) { + LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request"); + return; + } + renderer_settings.screenshot_bits = data; + renderer_settings.screenshot_complete_callback = std::move(callback); + renderer_settings.screenshot_framebuffer_layout = layout; + renderer_settings.screenshot_requested = true; +} + } // namespace VideoCore diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 669e26e15..1d54c3723 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -9,6 +9,7 @@ #include <optional> #include "common/common_types.h" +#include "core/frontend/emu_window.h" #include "video_core/gpu.h" #include "video_core/rasterizer_interface.h" @@ -21,6 +22,12 @@ namespace VideoCore { struct RendererSettings { std::atomic_bool use_framelimiter{false}; std::atomic_bool set_background_color{false}; + + // Screenshot + std::atomic<bool> screenshot_requested{false}; + void* screenshot_bits; + std::function<void()> screenshot_complete_callback; + Layout::FramebufferLayout screenshot_framebuffer_layout; }; class RendererBase : NonCopyable { @@ -57,9 +64,29 @@ public: return *rasterizer; } + Core::Frontend::EmuWindow& GetRenderWindow() { + return render_window; + } + + const Core::Frontend::EmuWindow& GetRenderWindow() const { + return render_window; + } + + RendererSettings& Settings() { + return renderer_settings; + } + + const RendererSettings& Settings() const { + return renderer_settings; + } + /// Refreshes the settings common to all renderers void RefreshBaseSettings(); + /// Request a screenshot of the next frame + void RequestScreenshot(void* data, std::function<void()> callback, + const Layout::FramebufferLayout& layout); + protected: Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. std::unique_ptr<RasterizerInterface> rasterizer; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 5f4cdd119..7ea07631a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -101,8 +101,18 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, params.srgb_conversion = config.tic.IsSrgbConversionEnabled(); params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(), params.srgb_conversion); + + if (params.pixel_format == PixelFormat::R16U && config.tsc.depth_compare_enabled) { + // Some titles create a 'R16U' (normalized 16-bit) texture with depth_compare enabled, + // then attempt to sample from it via a shadow sampler. Convert format to Z16 (which also + // causes GetFormatType to properly return 'Depth' below). + params.pixel_format = PixelFormat::Z16; + } + params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); params.type = GetFormatType(params.pixel_format); + UNIMPLEMENTED_IF(params.type == SurfaceType::ColorTexture && config.tsc.depth_compare_enabled); + params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); params.unaligned_height = config.tic.Height(); @@ -257,7 +267,7 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, ComponentType::UInt, false}, // R8UI {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, ComponentType::Float, false}, // RGBA16F {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UNorm, false}, // RGBA16U - {GL_RGBA16UI, GL_RGBA, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI + {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, ComponentType::UInt, false}, // RGBA16UI {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, ComponentType::Float, false}, // R11FG11FB10F {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RGBA32UI diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index b4ef6030d..de3671acf 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -67,6 +67,7 @@ public: 6, "ShaderTrianglesAdjacency"); default: UNREACHABLE_MSG("Unknown primitive mode."); + return LazyGeometryProgram(geometry_programs.points, "points", 1, "ShaderPoints"); } } diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index a7d8c404d..76d9b3538 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -364,6 +364,7 @@ public: return value; default: UNREACHABLE_MSG("Unimplemented conversion size: {}", static_cast<u32>(size)); + return value; } } @@ -626,6 +627,7 @@ public: return "floatBitsToInt(" + value + ')'; } else { UNREACHABLE(); + return value; } } @@ -1753,7 +1755,7 @@ private: instr.tlds.GetTextureProcessMode() == Tegra::Shader::TextureProcessMode::LL; constexpr std::array<const char*, 4> coord_container{ - {"", "int coord = (", "ivec2 coord = ivec2(", "ivec3 coord = ivec3("}}; + {"", "int coords = (", "ivec2 coords = ivec2(", "ivec3 coords = ivec3("}}; std::string coord = coord_container[total_coord_count]; @@ -2062,6 +2064,8 @@ private: std::to_string(instr.alu.GetSignedImm20_20())}; default: UNREACHABLE(); + return {regs.GetRegisterAsInteger(instr.gpr39, 0, false), + std::to_string(instr.alu.GetSignedImm20_20())}; } }(); const std::string offset = '(' + packed_shift + " & 0xff)"; @@ -3312,6 +3316,7 @@ private: return std::to_string(instr.r2p.immediate_mask); default: UNREACHABLE(); + return std::to_string(instr.r2p.immediate_mask); } }(); const std::string mask = '(' + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + @@ -3775,7 +3780,10 @@ private: } break; } - default: { UNIMPLEMENTED_MSG("Unhandled instruction: {}", opcode->get().GetName()); } + default: { + UNIMPLEMENTED_MSG("Unhandled instruction: {}", opcode->get().GetName()); + break; + } } break; @@ -3930,4 +3938,4 @@ std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u return {}; } -} // namespace OpenGL::GLShader::Decompiler
\ No newline at end of file +} // namespace OpenGL::GLShader::Decompiler diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 4fd0d66c5..235732d86 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -138,7 +138,12 @@ void RendererOpenGL::SwapBuffers( // Load the framebuffer from memory, draw it to the screen, and swap buffers LoadFBToScreenInfo(*framebuffer); - DrawScreen(); + + if (renderer_settings.screenshot_requested) + CaptureScreenshot(); + + DrawScreen(render_window.GetFramebufferLayout()); + render_window.SwapBuffers(); } @@ -383,14 +388,13 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, /** * Draws the emulated screens to the emulator window. */ -void RendererOpenGL::DrawScreen() { +void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { if (renderer_settings.set_background_color) { // Update background color before drawing glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, 0.0f); } - const auto& layout = render_window.GetFramebufferLayout(); const auto& screen = layout.screen; glViewport(0, 0, layout.width, layout.height); @@ -414,6 +418,37 @@ void RendererOpenGL::DrawScreen() { /// Updates the framerate void RendererOpenGL::UpdateFramerate() {} +void RendererOpenGL::CaptureScreenshot() { + // Draw the current frame to the screenshot framebuffer + screenshot_framebuffer.Create(); + GLuint old_read_fb = state.draw.read_framebuffer; + GLuint old_draw_fb = state.draw.draw_framebuffer; + state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle; + state.Apply(); + + Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; + + GLuint renderbuffer; + glGenRenderbuffers(1, &renderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, layout.width, layout.height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); + + DrawScreen(layout); + + glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + renderer_settings.screenshot_bits); + + screenshot_framebuffer.Release(); + state.draw.read_framebuffer = old_read_fb; + state.draw.draw_framebuffer = old_draw_fb; + state.Apply(); + glDeleteRenderbuffers(1, &renderbuffer); + + renderer_settings.screenshot_complete_callback(); + renderer_settings.screenshot_requested = false; +} + static const char* GetSource(GLenum source) { #define RET(s) \ case GL_DEBUG_SOURCE_##s: \ @@ -427,6 +462,7 @@ static const char* GetSource(GLenum source) { RET(OTHER); default: UNREACHABLE(); + return "Unknown source"; } #undef RET } @@ -445,6 +481,7 @@ static const char* GetType(GLenum type) { RET(MARKER); default: UNREACHABLE(); + return "Unknown type"; } #undef RET } diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index c0868c0e4..b85cc262f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -16,6 +16,10 @@ namespace Core::Frontend { class EmuWindow; } +namespace Layout { +struct FramebufferLayout; +} + namespace OpenGL { /// Structure used for storing information about the textures for the Switch screen @@ -66,10 +70,12 @@ private: void ConfigureFramebufferTexture(TextureInfo& texture, const Tegra::FramebufferConfig& framebuffer); - void DrawScreen(); + void DrawScreen(const Layout::FramebufferLayout& layout); void DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, float h); void UpdateFramerate(); + void CaptureScreenshot(); + // Loads framebuffer from emulated memory into the display information structure void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); // Fills active OpenGL texture with the given RGBA color. @@ -82,6 +88,7 @@ private: OGLVertexArray vertex_array; OGLBuffer vertex_buffer; OGLProgram shader; + OGLFramebuffer screenshot_framebuffer; /// Display information for Switch screen ScreenInfo screen_info; diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 9582dd2ca..a97b1562b 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -65,6 +65,7 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); + return PixelFormat::S8Z24; } } @@ -141,6 +142,7 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); + return PixelFormat::RGBA8_SRGB; } } @@ -327,6 +329,7 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, LOG_CRITICAL(HW_GPU, "Unimplemented format={}, component_type={}", static_cast<u32>(format), static_cast<u32>(component_type)); UNREACHABLE(); + return PixelFormat::ABGR8U; } } @@ -346,6 +349,7 @@ ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) { default: LOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type)); UNREACHABLE(); + return ComponentType::UNorm; } } @@ -393,6 +397,7 @@ ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) { default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); + return ComponentType::UNorm; } } @@ -403,6 +408,7 @@ PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); + return PixelFormat::ABGR8U; } } @@ -418,6 +424,7 @@ ComponentType ComponentTypeFromDepthFormat(Tegra::DepthFormat format) { default: LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); + return ComponentType::UNorm; } } diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index bbae9285f..5db75de22 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -226,7 +226,7 @@ u32 BytesPerPixel(TextureFormat format) { return 8; default: UNIMPLEMENTED_MSG("Format not implemented"); - break; + return 1; } } diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 07e3a7d24..f7de3471b 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -3,6 +3,8 @@ // Refer to the license.txt file included. #include <memory> +#include "core/core.h" +#include "core/settings.h" #include "video_core/renderer_base.h" #include "video_core/renderer_opengl/renderer_opengl.h" #include "video_core/video_core.h" @@ -13,4 +15,10 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind return std::make_unique<OpenGL::RendererOpenGL>(emu_window); } +u16 GetResolutionScaleFactor(const RendererBase& renderer) { + return !Settings::values.resolution_factor + ? renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio() + : Settings::values.resolution_factor; +} + } // namespace VideoCore diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index f79f85dfe..5b373bcb1 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -22,4 +22,6 @@ class RendererBase; */ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window); +u16 GetResolutionScaleFactor(const RendererBase& renderer); + } // namespace VideoCore |
