diff options
| author | bunnei <bunneidev@gmail.com> | 2019-11-15 12:09:19 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-11-15 12:09:19 -0500 | 
| commit | a8295d2c533d1628887bd45d3bfd8adb66281834 (patch) | |
| tree | ddfd5d15ff0a055cdd4b4aa5df85c0b2bfc56713 /src/video_core | |
| parent | 3e0e4f146b3f2ad7f1935a61141c38cdce87e04f (diff) | |
| parent | e9d2fad9849ff7fba8d63a16c838b79a3e752327 (diff) | |
Merge pull request #3047 from ReinUsesLisp/clip-control
gl_rasterizer: Emulate viewport flipping with ARB_clip_control
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 24 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 20 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 5 | 
7 files changed, 42 insertions, 79 deletions
| diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e43ba9d6b..05f8e511b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -257,10 +257,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {              continue;          } -        const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5 -          GLShader::MaxwellUniformData ubo{}; -        ubo.SetFromRegs(gpu, stage); +        ubo.SetFromRegs(gpu);          const auto [buffer, offset] =              buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); @@ -269,10 +267,11 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {          Shader shader{shader_cache.GetStageProgram(program)}; -        const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage); -        SetupDrawConstBuffers(stage_enum, shader); -        SetupDrawGlobalMemory(stage_enum, shader); -        const auto texture_buffer_usage{SetupDrawTextures(stage_enum, shader, base_bindings)}; +        // Stage indices are 0 - 5 +        const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1); +        SetupDrawConstBuffers(stage, shader); +        SetupDrawGlobalMemory(stage, shader); +        const auto texture_buffer_usage{SetupDrawTextures(stage, shader, base_bindings)};          const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage};          const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant); @@ -1055,6 +1054,15 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {      }      state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0;      state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; + +    bool flip_y = false; +    if (regs.viewport_transform[0].scale_y < 0.0) { +        flip_y = !flip_y; +    } +    if (regs.screen_y_control.y_negate != 0) { +        flip_y = !flip_y; +    } +    state.clip_control.origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT;  }  void RasterizerOpenGL::SyncClipEnabled( @@ -1077,28 +1085,14 @@ void RasterizerOpenGL::SyncClipCoef() {  }  void RasterizerOpenGL::SyncCullMode() { -    auto& maxwell3d = system.GPU().Maxwell3D(); - -    const auto& regs = maxwell3d.regs; +    const auto& regs = system.GPU().Maxwell3D().regs;      state.cull.enabled = regs.cull.enabled != 0;      if (state.cull.enabled) { -        state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);          state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); - -        const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 || -                                  regs.viewport_transform[0].scale_y < 0.0f}; - -        // If the GPU is configured to flip the rasterized triangles, then we need to flip the -        // notion of front and back. Note: We flip the triangles when the value of the register is 0 -        // because OpenGL already does it for us. -        if (flip_triangles) { -            if (state.cull.front_face == GL_CCW) -                state.cull.front_face = GL_CW; -            else if (state.cull.front_face == GL_CW) -                state.cull.front_face = GL_CCW; -        }      } + +    state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);  }  void RasterizerOpenGL::SyncPrimitiveRestart() { diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index e56ed51de..4f2b49170 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1892,10 +1892,6 @@ private:      Expression EmitVertex(Operation operation) {          ASSERT_MSG(stage == ProgramType::Geometry,                     "EmitVertex is expected to be used in a geometry shader."); - -        // If a geometry shader is attached, it will always flip (it's the last stage before -        // fragment). For more info about flipping, refer to gl_shader_gen.cpp. -        code.AddLine("gl_Position.xy *= viewport_flip.xy;");          code.AddLine("EmitVertex();");          return {};      } @@ -1903,14 +1899,12 @@ private:      Expression EndPrimitive(Operation operation) {          ASSERT_MSG(stage == ProgramType::Geometry,                     "EndPrimitive is expected to be used in a geometry shader."); -          code.AddLine("EndPrimitive();");          return {};      }      Expression YNegate(Operation operation) { -        // Config pack's third value is Y_NEGATE's state. -        return {"config_pack[2]", Type::Uint}; +        return {"y_direction", Type::Float};      }      template <u32 element> diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 0e22eede9..af17216bd 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -20,8 +20,7 @@ std::string GenerateVertexShader(const Device& device, const ShaderIR& ir, const      std::string out = GetCommonDeclarations();      out += R"(  layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { -    vec4 viewport_flip; -    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding +    float y_direction;  };  )"; @@ -35,23 +34,10 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {  void main() {      execute_vertex();  )"; -      if (ir_b) {          out += "    execute_vertex_b();";      } - -    out += R"( - -    // Set Position Y direction -    gl_Position.y *= utof(config_pack[2]); -    // Check if the flip stage is VertexB -    // Config pack's second value is flip_stage -    if (config_pack[1] == 1) { -        // Viewport can be flipped, which is unsupported by glViewport -        gl_Position.xy *= viewport_flip.xy; -    } -} -)"; +    out += "}\n";      return out;  } @@ -59,8 +45,7 @@ std::string GenerateGeometryShader(const Device& device, const ShaderIR& ir) {      std::string out = GetCommonDeclarations();      out += R"(  layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { -    vec4 viewport_flip; -    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding +    float y_direction;  };  )"; @@ -87,8 +72,7 @@ layout (location = 6) out vec4 FragColor6;  layout (location = 7) out vec4 FragColor7;  layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config { -    vec4 viewport_flip; -    uvec4 config_pack; // instance_id, flip_stage, y_direction, padding +    float y_direction;  };  )"; diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index b05f90f20..75d3fac04 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -40,27 +40,11 @@ void ProgramManager::UpdatePipeline() {      old_state = current_state;  } -void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) { +void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) {      const auto& regs = maxwell.regs; -    const auto& state = maxwell.state; - -    // TODO(bunnei): Support more than one viewport -    viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; -    viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; - -    instance_id = state.current_instance; - -    // Assign in which stage the position has to be flipped -    // (the last stage before the fragment shader). -    constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry); -    if (maxwell.regs.shader_config[geometry_index].enable) { -        flip_stage = geometry_index; -    } else { -        flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB); -    }      // Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value. -    y_direction = regs.screen_y_control.y_negate == 0 ? 1.f : -1.f; +    y_direction = regs.screen_y_control.y_negate == 0 ? 1.0f : -1.0f;  }  } // namespace OpenGL::GLShader diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 6961e702a..3703e7018 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -18,17 +18,12 @@ namespace OpenGL::GLShader {  /// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at  ///       the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.  ///       Not following that rule will cause problems on some AMD drivers. -struct MaxwellUniformData { -    void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage); - -    alignas(16) GLvec4 viewport_flip; -    struct alignas(16) { -        GLuint instance_id; -        GLuint flip_stage; -        GLfloat y_direction; -    }; +struct alignas(16) MaxwellUniformData { +    void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell); + +    GLfloat y_direction;  }; -static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect"); +static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");  static_assert(sizeof(MaxwellUniformData) < 16384,                "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index f25148362..ccbe5912e 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -410,6 +410,12 @@ void OpenGLState::ApplyAlphaTest() {      }  } +void OpenGLState::ApplyClipControl() { +    if (UpdateValue(cur_state.clip_control.origin, clip_control.origin)) { +        glClipControl(clip_control.origin, GL_NEGATIVE_ONE_TO_ONE); +    } +} +  void OpenGLState::ApplyTextures() {      if (const auto update = UpdateArray(cur_state.textures, textures)) {          glBindTextures(update->first, update->second, textures.data() + update->first); @@ -453,6 +459,7 @@ void OpenGLState::Apply() {      ApplyImages();      ApplyPolygonOffset();      ApplyAlphaTest(); +    ApplyClipControl();  }  void OpenGLState::EmulateViewportWithScissor() { diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index cca25206b..eaff22bda 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -146,6 +146,10 @@ public:      std::array<bool, 8> clip_distance = {}; // GL_CLIP_DISTANCE +    struct { +        GLenum origin = GL_LOWER_LEFT; +    } clip_control; +      OpenGLState();      /// Get the currently active OpenGL state @@ -182,6 +186,7 @@ public:      void ApplyDepthClamp();      void ApplyPolygonOffset();      void ApplyAlphaTest(); +    void ApplyClipControl();      /// Resets any references to the given resource      OpenGLState& UnbindTexture(GLuint handle); | 
