gl_state: Split textures and samplers into two arrays
This commit is contained in:
parent
6170337001
commit
04cdecb7a1
4 changed files with 39 additions and 91 deletions
|
@ -991,7 +991,7 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
|
||||||
const auto& maxwell3d = gpu.Maxwell3D();
|
const auto& maxwell3d = gpu.Maxwell3D();
|
||||||
const auto& entries = shader->GetShaderEntries().samplers;
|
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.");
|
"Exceeded the number of active textures.");
|
||||||
|
|
||||||
TextureBufferUsage texture_buffer_usage{0};
|
TextureBufferUsage texture_buffer_usage{0};
|
||||||
|
@ -1019,16 +1019,15 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
|
||||||
bool RasterizerOpenGL::SetupTexture(const Shader& shader, u32 binding,
|
bool RasterizerOpenGL::SetupTexture(const Shader& shader, u32 binding,
|
||||||
const Tegra::Texture::FullTextureInfo& texture,
|
const Tegra::Texture::FullTextureInfo& texture,
|
||||||
const GLShader::SamplerEntry& entry) {
|
const GLShader::SamplerEntry& entry) {
|
||||||
auto& unit{state.texture_units[binding]};
|
state.samplers[binding] = sampler_cache.GetSampler(texture.tsc);
|
||||||
unit.sampler = sampler_cache.GetSampler(texture.tsc);
|
|
||||||
|
|
||||||
const auto view = texture_cache.GetTextureSurface(texture.tic, entry);
|
const auto view = texture_cache.GetTextureSurface(texture.tic, entry);
|
||||||
if (!view) {
|
if (!view) {
|
||||||
// Can occur when texture addr is null or its memory is unmapped/invalid
|
// Can occur when texture addr is null or its memory is unmapped/invalid
|
||||||
unit.texture = 0;
|
state.textures[binding] = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unit.texture = view->GetTexture();
|
state.textures[binding] = view->GetTexture();
|
||||||
|
|
||||||
if (view->GetSurfaceParams().IsBuffer()) {
|
if (view->GetSurfaceParams().IsBuffer()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -34,6 +34,25 @@ bool UpdateTie(T1 current_value, const T2 new_value) {
|
||||||
return changed;
|
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) {
|
void Enable(GLenum cap, bool enable) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
glEnable(cap);
|
glEnable(cap);
|
||||||
|
@ -134,10 +153,6 @@ OpenGLState::OpenGLState() {
|
||||||
logic_op.enabled = false;
|
logic_op.enabled = false;
|
||||||
logic_op.operation = GL_COPY;
|
logic_op.operation = GL_COPY;
|
||||||
|
|
||||||
for (auto& texture_unit : texture_units) {
|
|
||||||
texture_unit.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
draw.read_framebuffer = 0;
|
draw.read_framebuffer = 0;
|
||||||
draw.draw_framebuffer = 0;
|
draw.draw_framebuffer = 0;
|
||||||
draw.vertex_array = 0;
|
draw.vertex_array = 0;
|
||||||
|
@ -496,72 +511,20 @@ void OpenGLState::ApplyAlphaTest() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyTextures() const {
|
void OpenGLState::ApplyTextures() const {
|
||||||
bool has_delta{};
|
if (const auto update = UpdateArray(cur_state.textures, textures)) {
|
||||||
std::size_t first{};
|
glBindTextures(update->first, update->second, textures.data() + update->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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplySamplers() const {
|
void OpenGLState::ApplySamplers() const {
|
||||||
bool has_delta{};
|
if (const auto update = UpdateArray(cur_state.samplers, samplers)) {
|
||||||
std::size_t first{};
|
glBindSamplers(update->first, update->second, samplers.data() + update->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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyImages() const {
|
void OpenGLState::ApplyImages() const {
|
||||||
bool has_delta{};
|
if (const auto update = UpdateArray(cur_state.images, images)) {
|
||||||
std::size_t first{};
|
glBindImageTextures(update->first, update->second, images.data() + update->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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,18 +590,18 @@ void OpenGLState::EmulateViewportWithScissor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLState& OpenGLState::UnbindTexture(GLuint handle) {
|
OpenGLState& OpenGLState::UnbindTexture(GLuint handle) {
|
||||||
for (auto& unit : texture_units) {
|
for (auto& texture : textures) {
|
||||||
if (unit.texture == handle) {
|
if (texture == handle) {
|
||||||
unit.Unbind();
|
texture = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLState& OpenGLState::ResetSampler(GLuint handle) {
|
OpenGLState& OpenGLState::ResetSampler(GLuint handle) {
|
||||||
for (auto& unit : texture_units) {
|
for (auto& sampler : samplers) {
|
||||||
if (unit.sampler == handle) {
|
if (sampler == handle) {
|
||||||
unit.sampler = 0;
|
sampler = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -118,22 +118,8 @@ public:
|
||||||
GLenum operation;
|
GLenum operation;
|
||||||
} logic_op;
|
} logic_op;
|
||||||
|
|
||||||
// 3 texture units - one for each that is used in PICA fragment shader emulation
|
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures{};
|
||||||
struct TextureUnit {
|
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers{};
|
||||||
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::NumImages> images{};
|
std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumImages> images{};
|
||||||
|
|
||||||
struct {
|
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),
|
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
|
// 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
|
// if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
|
||||||
state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
|
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);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
// Restore default state
|
// Restore default state
|
||||||
state.framebuffer_srgb.enabled = false;
|
state.framebuffer_srgb.enabled = false;
|
||||||
state.texture_units[0].texture = 0;
|
state.textures[0] = 0;
|
||||||
state.AllDirty();
|
state.AllDirty();
|
||||||
state.Apply();
|
state.Apply();
|
||||||
// Clear sRGB state for the next frame
|
// Clear sRGB state for the next frame
|
||||||
|
|
Loading…
Reference in a new issue