mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	gl_state: Split textures and samplers into two arrays
This commit is contained in:
		@@ -991,7 +991,7 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
 | 
			
		||||
    const auto& maxwell3d = gpu.Maxwell3D();
 | 
			
		||||
    const auto& entries = shader->GetShaderEntries().samplers;
 | 
			
		||||
 | 
			
		||||
    ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.texture_units),
 | 
			
		||||
    ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.textures),
 | 
			
		||||
               "Exceeded the number of active textures.");
 | 
			
		||||
 | 
			
		||||
    TextureBufferUsage texture_buffer_usage{0};
 | 
			
		||||
@@ -1019,16 +1019,15 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
 | 
			
		||||
bool RasterizerOpenGL::SetupTexture(const Shader& shader, u32 binding,
 | 
			
		||||
                                    const Tegra::Texture::FullTextureInfo& texture,
 | 
			
		||||
                                    const GLShader::SamplerEntry& entry) {
 | 
			
		||||
    auto& unit{state.texture_units[binding]};
 | 
			
		||||
    unit.sampler = sampler_cache.GetSampler(texture.tsc);
 | 
			
		||||
    state.samplers[binding] = sampler_cache.GetSampler(texture.tsc);
 | 
			
		||||
 | 
			
		||||
    const auto view = texture_cache.GetTextureSurface(texture.tic, entry);
 | 
			
		||||
    if (!view) {
 | 
			
		||||
        // Can occur when texture addr is null or its memory is unmapped/invalid
 | 
			
		||||
        unit.texture = 0;
 | 
			
		||||
        state.textures[binding] = 0;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    unit.texture = view->GetTexture();
 | 
			
		||||
    state.textures[binding] = view->GetTexture();
 | 
			
		||||
 | 
			
		||||
    if (view->GetSurfaceParams().IsBuffer()) {
 | 
			
		||||
        return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,25 @@ bool UpdateTie(T1 current_value, const T2 new_value) {
 | 
			
		||||
    return changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
std::optional<std::pair<GLuint, GLsizei>> UpdateArray(T& current_values, const T& new_values) {
 | 
			
		||||
    std::optional<std::size_t> first;
 | 
			
		||||
    std::size_t last;
 | 
			
		||||
    for (std::size_t i = 0; i < std::size(current_values); ++i) {
 | 
			
		||||
        if (!UpdateValue(current_values[i], new_values[i])) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (!first) {
 | 
			
		||||
            first = i;
 | 
			
		||||
        }
 | 
			
		||||
        last = i;
 | 
			
		||||
    }
 | 
			
		||||
    if (!first) {
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
    return std::make_pair(static_cast<GLuint>(*first), static_cast<GLsizei>(last - *first + 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Enable(GLenum cap, bool enable) {
 | 
			
		||||
    if (enable) {
 | 
			
		||||
        glEnable(cap);
 | 
			
		||||
@@ -134,10 +153,6 @@ OpenGLState::OpenGLState() {
 | 
			
		||||
    logic_op.enabled = false;
 | 
			
		||||
    logic_op.operation = GL_COPY;
 | 
			
		||||
 | 
			
		||||
    for (auto& texture_unit : texture_units) {
 | 
			
		||||
        texture_unit.Reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw.read_framebuffer = 0;
 | 
			
		||||
    draw.draw_framebuffer = 0;
 | 
			
		||||
    draw.vertex_array = 0;
 | 
			
		||||
@@ -496,72 +511,20 @@ void OpenGLState::ApplyAlphaTest() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplyTextures() const {
 | 
			
		||||
    bool has_delta{};
 | 
			
		||||
    std::size_t first{};
 | 
			
		||||
    std::size_t last{};
 | 
			
		||||
    std::array<GLuint, Maxwell::NumTextureSamplers> textures;
 | 
			
		||||
 | 
			
		||||
    for (std::size_t i = 0; i < std::size(texture_units); ++i) {
 | 
			
		||||
        const auto& texture_unit = texture_units[i];
 | 
			
		||||
        auto& cur_state_texture_unit = cur_state.texture_units[i];
 | 
			
		||||
        textures[i] = texture_unit.texture;
 | 
			
		||||
        if (cur_state_texture_unit.texture == textures[i]) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        cur_state_texture_unit.texture = textures[i];
 | 
			
		||||
        if (!has_delta) {
 | 
			
		||||
            first = i;
 | 
			
		||||
            has_delta = true;
 | 
			
		||||
        }
 | 
			
		||||
        last = i;
 | 
			
		||||
    }
 | 
			
		||||
    if (has_delta) {
 | 
			
		||||
        glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
 | 
			
		||||
                       textures.data() + first);
 | 
			
		||||
    if (const auto update = UpdateArray(cur_state.textures, textures)) {
 | 
			
		||||
        glBindTextures(update->first, update->second, textures.data() + update->first);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplySamplers() const {
 | 
			
		||||
    bool has_delta{};
 | 
			
		||||
    std::size_t first{};
 | 
			
		||||
    std::size_t last{};
 | 
			
		||||
    std::array<GLuint, Maxwell::NumTextureSamplers> samplers;
 | 
			
		||||
 | 
			
		||||
    for (std::size_t i = 0; i < std::size(samplers); ++i) {
 | 
			
		||||
        samplers[i] = texture_units[i].sampler;
 | 
			
		||||
        if (cur_state.texture_units[i].sampler == texture_units[i].sampler) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        cur_state.texture_units[i].sampler = texture_units[i].sampler;
 | 
			
		||||
        if (!has_delta) {
 | 
			
		||||
            first = i;
 | 
			
		||||
            has_delta = true;
 | 
			
		||||
        }
 | 
			
		||||
        last = i;
 | 
			
		||||
    }
 | 
			
		||||
    if (has_delta) {
 | 
			
		||||
        glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
 | 
			
		||||
                       samplers.data() + first);
 | 
			
		||||
    if (const auto update = UpdateArray(cur_state.samplers, samplers)) {
 | 
			
		||||
        glBindSamplers(update->first, update->second, samplers.data() + update->first);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplyImages() const {
 | 
			
		||||
    bool has_delta{};
 | 
			
		||||
    std::size_t first{};
 | 
			
		||||
    std::size_t last{};
 | 
			
		||||
    for (std::size_t i = 0; i < std::size(images); ++i) {
 | 
			
		||||
        if (!UpdateValue(cur_state.images[i], images[i])) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (!has_delta) {
 | 
			
		||||
            first = i;
 | 
			
		||||
            has_delta = true;
 | 
			
		||||
        }
 | 
			
		||||
        last = i;
 | 
			
		||||
    }
 | 
			
		||||
    if (has_delta) {
 | 
			
		||||
        glBindImageTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
 | 
			
		||||
                            images.data() + first);
 | 
			
		||||
    if (const auto update = UpdateArray(cur_state.images, images)) {
 | 
			
		||||
        glBindImageTextures(update->first, update->second, images.data() + update->first);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -627,18 +590,18 @@ void OpenGLState::EmulateViewportWithScissor() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenGLState& OpenGLState::UnbindTexture(GLuint handle) {
 | 
			
		||||
    for (auto& unit : texture_units) {
 | 
			
		||||
        if (unit.texture == handle) {
 | 
			
		||||
            unit.Unbind();
 | 
			
		||||
    for (auto& texture : textures) {
 | 
			
		||||
        if (texture == handle) {
 | 
			
		||||
            texture = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenGLState& OpenGLState::ResetSampler(GLuint handle) {
 | 
			
		||||
    for (auto& unit : texture_units) {
 | 
			
		||||
        if (unit.sampler == handle) {
 | 
			
		||||
            unit.sampler = 0;
 | 
			
		||||
    for (auto& sampler : samplers) {
 | 
			
		||||
        if (sampler == handle) {
 | 
			
		||||
            sampler = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
 
 | 
			
		||||
@@ -118,22 +118,8 @@ public:
 | 
			
		||||
        GLenum operation;
 | 
			
		||||
    } logic_op;
 | 
			
		||||
 | 
			
		||||
    // 3 texture units - one for each that is used in PICA fragment shader emulation
 | 
			
		||||
    struct TextureUnit {
 | 
			
		||||
        GLuint texture; // GL_TEXTURE_BINDING_2D
 | 
			
		||||
        GLuint sampler; // GL_SAMPLER_BINDING
 | 
			
		||||
 | 
			
		||||
        void Unbind() {
 | 
			
		||||
            texture = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void Reset() {
 | 
			
		||||
            Unbind();
 | 
			
		||||
            sampler = 0;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units;
 | 
			
		||||
 | 
			
		||||
    std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures{};
 | 
			
		||||
    std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers{};
 | 
			
		||||
    std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images{};
 | 
			
		||||
 | 
			
		||||
    struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -342,7 +342,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
 | 
			
		||||
        ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v),
 | 
			
		||||
    }};
 | 
			
		||||
 | 
			
		||||
    state.texture_units[0].texture = screen_info.display_texture;
 | 
			
		||||
    state.textures[0] = screen_info.display_texture;
 | 
			
		||||
    // Workaround brigthness problems in SMO by enabling sRGB in the final output
 | 
			
		||||
    // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
 | 
			
		||||
    state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
 | 
			
		||||
@@ -352,7 +352,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
 | 
			
		||||
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 | 
			
		||||
    // Restore default state
 | 
			
		||||
    state.framebuffer_srgb.enabled = false;
 | 
			
		||||
    state.texture_units[0].texture = 0;
 | 
			
		||||
    state.textures[0] = 0;
 | 
			
		||||
    state.AllDirty();
 | 
			
		||||
    state.Apply();
 | 
			
		||||
    // Clear sRGB state for the next frame
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user