diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 78ba29fc1a..27ef865a21 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "common/assert.h" #include "core/core.h" #include "core/core_timing.h" @@ -19,7 +20,24 @@ namespace Tegra::Engines { constexpr u32 MacroRegistersStart = 0xE00; Maxwell3D::Maxwell3D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) - : memory_manager(memory_manager), rasterizer{rasterizer}, macro_interpreter(*this) {} + : memory_manager(memory_manager), rasterizer{rasterizer}, macro_interpreter(*this) { + InitializeRegisterDefaults(); +} + +void Maxwell3D::InitializeRegisterDefaults() { + // Initializes registers to their default values - what games expect them to be at boot. This is + // for certain registers that may not be explicitly set by games. + + // Reset all registers to zero + std::memset(®s, 0, sizeof(regs)); + + // Depth range near/far is not always set, but is expected to be the default 0.0f, 1.0f. This is + // needed for ARMS. + for (std::size_t viewport{}; viewport < Regs::NumViewports; ++viewport) { + regs.viewport[viewport].depth_range_near = 0.0f; + regs.viewport[viewport].depth_range_far = 1.0f; + } +} void Maxwell3D::CallMacroMethod(u32 method, std::vector parameters) { // Reset the current macro. diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 0e09a7ee55..754a149fa6 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -984,6 +984,8 @@ public: Texture::FullTextureInfo GetStageTexture(Regs::ShaderStage stage, std::size_t offset) const; private: + void InitializeRegisterDefaults(); + VideoCore::RasterizerInterface& rasterizer; std::unordered_map> uploaded_macros; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index be51c5215f..b472f421fa 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -570,6 +570,7 @@ void RasterizerOpenGL::DrawArrays() { SyncBlendState(); SyncLogicOpState(); SyncCullMode(); + SyncDepthRange(); SyncScissorTest(); // Alpha Testing is synced on shaders. SyncTransformFeedback(); @@ -923,12 +924,11 @@ void RasterizerOpenGL::SyncCullMode() { } } -void RasterizerOpenGL::SyncDepthScale() { - UNREACHABLE(); -} +void RasterizerOpenGL::SyncDepthRange() { + const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; -void RasterizerOpenGL::SyncDepthOffset() { - UNREACHABLE(); + state.depth.depth_range_near = regs.viewport->depth_range_near; + state.depth.depth_range_far = regs.viewport->depth_range_far; } void RasterizerOpenGL::SyncDepthTestState() { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 0e90a31f5e..731a336d58 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -144,11 +144,8 @@ private: /// Syncs the cull mode to match the guest state void SyncCullMode(); - /// Syncs the depth scale to match the guest state - void SyncDepthScale(); - - /// Syncs the depth offset to match the guest state - void SyncDepthOffset(); + /// Syncs the depth range to match the guest state + void SyncDepthRange(); /// Syncs the depth test state to match the guest state void SyncDepthTestState(); diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 1fe26a2a9a..ba6c6919a6 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -21,6 +21,8 @@ OpenGLState::OpenGLState() { depth.test_enabled = false; depth.test_func = GL_LESS; depth.write_mask = GL_TRUE; + depth.depth_range_near = 0.0f; + depth.depth_range_far = 1.0f; color_mask.red_enabled = GL_TRUE; color_mask.green_enabled = GL_TRUE; @@ -119,6 +121,12 @@ void OpenGLState::Apply() const { glDepthMask(depth.write_mask); } + // Depth range + if (depth.depth_range_near != cur_state.depth.depth_range_near || + depth.depth_range_far != cur_state.depth.depth_range_far) { + glDepthRange(depth.depth_range_near, depth.depth_range_far); + } + // Color mask if (color_mask.red_enabled != cur_state.color_mask.red_enabled || color_mask.green_enabled != cur_state.color_mask.green_enabled || diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index dc21a2ee3a..daf7eb5338 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -42,9 +42,11 @@ public: } cull; struct { - bool test_enabled; // GL_DEPTH_TEST - GLenum test_func; // GL_DEPTH_FUNC - GLboolean write_mask; // GL_DEPTH_WRITEMASK + bool test_enabled; // GL_DEPTH_TEST + GLenum test_func; // GL_DEPTH_FUNC + GLboolean write_mask; // GL_DEPTH_WRITEMASK + GLfloat depth_range_near; // GL_DEPTH_RANGE + GLfloat depth_range_far; // GL_DEPTH_RANGE } depth; struct {