Merge pull request #1827 from ReinUsesLisp/clip-and-shader
gl_rasterizer: Enable clip distances when set in register and in shader
This commit is contained in:
		@@ -42,6 +42,7 @@ public:
 | 
			
		||||
        static constexpr std::size_t NumVertexArrays = 32;
 | 
			
		||||
        static constexpr std::size_t NumVertexAttributes = 32;
 | 
			
		||||
        static constexpr std::size_t NumTextureSamplers = 32;
 | 
			
		||||
        static constexpr std::size_t NumClipDistances = 8;
 | 
			
		||||
        static constexpr std::size_t MaxShaderProgram = 6;
 | 
			
		||||
        static constexpr std::size_t MaxShaderStage = 5;
 | 
			
		||||
        // Maximum number of const buffers per shader stage.
 | 
			
		||||
 
 | 
			
		||||
@@ -282,6 +282,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
			
		||||
    // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
 | 
			
		||||
    u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
 | 
			
		||||
    u32 current_texture_bindpoint = 0;
 | 
			
		||||
    std::array<bool, Maxwell::NumClipDistances> clip_distances{};
 | 
			
		||||
 | 
			
		||||
    for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
 | 
			
		||||
        const auto& shader_config = gpu.regs.shader_config[index];
 | 
			
		||||
@@ -342,12 +343,22 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
			
		||||
        current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
 | 
			
		||||
                                                  primitive_mode, current_texture_bindpoint);
 | 
			
		||||
 | 
			
		||||
        // Workaround for Intel drivers.
 | 
			
		||||
        // When a clip distance is enabled but not set in the shader it crops parts of the screen
 | 
			
		||||
        // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the
 | 
			
		||||
        // clip distances only when it's written by a shader stage.
 | 
			
		||||
        for (std::size_t i = 0; i < Maxwell::NumClipDistances; ++i) {
 | 
			
		||||
            clip_distances[i] |= shader->GetShaderEntries().clip_distances[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // When VertexA is enabled, we have dual vertex shaders
 | 
			
		||||
        if (program == Maxwell::ShaderProgram::VertexA) {
 | 
			
		||||
            // VertexB was combined with VertexA, so we skip the VertexB iteration
 | 
			
		||||
            index++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SyncClipEnabled(clip_distances);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
 | 
			
		||||
@@ -629,7 +640,6 @@ void RasterizerOpenGL::DrawArrays() {
 | 
			
		||||
    SyncCullMode();
 | 
			
		||||
    SyncPrimitiveRestart();
 | 
			
		||||
    SyncScissorTest(state);
 | 
			
		||||
    SyncClipEnabled();
 | 
			
		||||
    // Alpha Testing is synced on shaders.
 | 
			
		||||
    SyncTransformFeedback();
 | 
			
		||||
    SyncPointState();
 | 
			
		||||
@@ -1006,20 +1016,23 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
 | 
			
		||||
    state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SyncClipEnabled() {
 | 
			
		||||
void RasterizerOpenGL::SyncClipEnabled(
 | 
			
		||||
    const std::array<bool, Maxwell::Regs::NumClipDistances>& clip_mask) {
 | 
			
		||||
 | 
			
		||||
    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
			
		||||
    state.clip_distance[0] = regs.clip_distance_enabled.c0 != 0;
 | 
			
		||||
    state.clip_distance[1] = regs.clip_distance_enabled.c1 != 0;
 | 
			
		||||
    state.clip_distance[2] = regs.clip_distance_enabled.c2 != 0;
 | 
			
		||||
    state.clip_distance[3] = regs.clip_distance_enabled.c3 != 0;
 | 
			
		||||
    state.clip_distance[4] = regs.clip_distance_enabled.c4 != 0;
 | 
			
		||||
    state.clip_distance[5] = regs.clip_distance_enabled.c5 != 0;
 | 
			
		||||
    state.clip_distance[6] = regs.clip_distance_enabled.c6 != 0;
 | 
			
		||||
    state.clip_distance[7] = regs.clip_distance_enabled.c7 != 0;
 | 
			
		||||
    const std::array<bool, Maxwell::Regs::NumClipDistances> reg_state{
 | 
			
		||||
        regs.clip_distance_enabled.c0 != 0, regs.clip_distance_enabled.c1 != 0,
 | 
			
		||||
        regs.clip_distance_enabled.c2 != 0, regs.clip_distance_enabled.c3 != 0,
 | 
			
		||||
        regs.clip_distance_enabled.c4 != 0, regs.clip_distance_enabled.c5 != 0,
 | 
			
		||||
        regs.clip_distance_enabled.c6 != 0, regs.clip_distance_enabled.c7 != 0};
 | 
			
		||||
 | 
			
		||||
    for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) {
 | 
			
		||||
        state.clip_distance[i] = reg_state[i] && clip_mask[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SyncClipCoef() {
 | 
			
		||||
    UNREACHABLE();
 | 
			
		||||
    UNIMPLEMENTED();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SyncCullMode() {
 | 
			
		||||
 
 | 
			
		||||
@@ -128,7 +128,8 @@ private:
 | 
			
		||||
    void SyncViewport(OpenGLState& current_state);
 | 
			
		||||
 | 
			
		||||
    /// Syncs the clip enabled status to match the guest state
 | 
			
		||||
    void SyncClipEnabled();
 | 
			
		||||
    void SyncClipEnabled(
 | 
			
		||||
        const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& clip_mask);
 | 
			
		||||
 | 
			
		||||
    /// Syncs the clip coefficients to match the guest state
 | 
			
		||||
    void SyncClipCoef();
 | 
			
		||||
 
 | 
			
		||||
@@ -525,6 +525,7 @@ public:
 | 
			
		||||
                ((header.vtg.clip_distances >> index) & 1) == 0,
 | 
			
		||||
                "Shader is setting gl_ClipDistance{} without enabling it in the header", index);
 | 
			
		||||
 | 
			
		||||
            clip_distances[index] = true;
 | 
			
		||||
            fixed_pipeline_output_attributes_used.insert(attribute);
 | 
			
		||||
            shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';');
 | 
			
		||||
            break;
 | 
			
		||||
@@ -602,6 +603,11 @@ public:
 | 
			
		||||
        return used_samplers;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns an array of the used clip distances.
 | 
			
		||||
    const std::array<bool, Maxwell::NumClipDistances>& GetClipDistances() const {
 | 
			
		||||
        return clip_distances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
 | 
			
		||||
    /// necessary.
 | 
			
		||||
    std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
 | 
			
		||||
@@ -975,6 +981,7 @@ private:
 | 
			
		||||
    const std::string& suffix;
 | 
			
		||||
    const Tegra::Shader::Header& header;
 | 
			
		||||
    std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used;
 | 
			
		||||
    std::array<bool, Maxwell::NumClipDistances> clip_distances{};
 | 
			
		||||
    u64 local_memory_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -997,7 +1004,8 @@ public:
 | 
			
		||||
 | 
			
		||||
    /// Returns entries in the shader that are useful for external functions
 | 
			
		||||
    ShaderEntries GetEntries() const {
 | 
			
		||||
        return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), shader_length};
 | 
			
		||||
        return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), regs.GetClipDistances(),
 | 
			
		||||
                shader_length};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 
 | 
			
		||||
@@ -163,6 +163,7 @@ private:
 | 
			
		||||
struct ShaderEntries {
 | 
			
		||||
    std::vector<ConstBufferEntry> const_buffer_entries;
 | 
			
		||||
    std::vector<SamplerEntry> texture_samplers;
 | 
			
		||||
    std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> clip_distances;
 | 
			
		||||
    std::size_t shader_length;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user