summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_program.cpp27
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_program.h1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h51
3 files changed, 56 insertions, 23 deletions
diff --git a/src/video_core/renderer_opengl/gl_graphics_program.cpp b/src/video_core/renderer_opengl/gl_graphics_program.cpp
index 4ac026502..b5d75aa13 100644
--- a/src/video_core/renderer_opengl/gl_graphics_program.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_program.cpp
@@ -42,6 +42,9 @@ GraphicsProgram::GraphicsProgram(TextureCache& texture_cache_, BufferCache& buff
std::ranges::transform(infos, stage_infos.begin(),
[](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
+ for (size_t stage = 0; stage < 5; ++stage) {
+ enabled_stages_mask |= (assembly_programs[stage].handle != 0 ? 1 : 0) << stage;
+ }
u32 num_textures{};
u32 num_images{};
for (size_t stage = 0; stage < base_uniform_bindings.size() - 1; ++stage) {
@@ -182,6 +185,9 @@ void GraphicsProgram::Configure(bool is_indexed) {
const std::span indices_span(image_view_indices.data(), image_view_index);
texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
+ texture_cache.UpdateRenderTargets(false);
+ state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
+
ImageId* texture_buffer_index{image_view_ids.data()};
const auto bind_stage_info{[&](size_t stage) {
size_t index{};
@@ -240,14 +246,8 @@ void GraphicsProgram::Configure(bool is_indexed) {
buffer_cache.UpdateGraphicsBuffers(is_indexed);
buffer_cache.BindHostGeometryBuffers(is_indexed);
- // FIXME: Unhack this
if (assembly_programs[0].handle != 0) {
- // TODO: State track this
- glEnable(GL_VERTEX_PROGRAM_NV);
- glEnable(GL_FRAGMENT_PROGRAM_NV);
- glBindProgramARB(GL_VERTEX_PROGRAM_NV, assembly_programs[0].handle);
- glBindProgramARB(GL_FRAGMENT_PROGRAM_NV, assembly_programs[4].handle);
- program_manager.BindProgram(0);
+ program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
} else {
program_manager.BindProgram(program.handle);
}
@@ -300,19 +300,6 @@ void GraphicsProgram::Configure(bool is_indexed) {
if (image_binding != 0) {
glBindImageTextures(0, image_binding, images.data());
}
- texture_cache.UpdateRenderTargets(false);
-
- state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
- if (assembly_programs[0].handle != 0) {
- // TODO: State track this
- glEnable(GL_VERTEX_PROGRAM_NV);
- glEnable(GL_FRAGMENT_PROGRAM_NV);
- glBindProgramARB(GL_VERTEX_PROGRAM_NV, assembly_programs[0].handle);
- glBindProgramARB(GL_FRAGMENT_PROGRAM_NV, assembly_programs[4].handle);
- program_manager.BindProgram(0);
- } else {
- program_manager.BindProgram(program.handle);
- }
}
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_graphics_program.h b/src/video_core/renderer_opengl/gl_graphics_program.h
index 58aa4b0bc..18292bb16 100644
--- a/src/video_core/renderer_opengl/gl_graphics_program.h
+++ b/src/video_core/renderer_opengl/gl_graphics_program.h
@@ -89,6 +89,7 @@ private:
OGLProgram program;
std::array<OGLAssemblyProgram, 5> assembly_programs;
+ u32 enabled_stages_mask{};
std::array<Shader::Info, 5> stage_infos{};
std::array<u32, 5> base_uniform_bindings{};
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 70781d6f5..48669b3cd 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -4,24 +4,69 @@
#pragma once
+#include <array>
+#include <span>
+
#include <glad/glad.h>
+#include "video_core/renderer_opengl/gl_resource_manager.h"
+
+#pragma optimize("", off)
+
namespace OpenGL {
class ProgramManager {
+ static constexpr size_t NUM_STAGES = 5;
+
+ static constexpr std::array ASSEMBLY_PROGRAM_ENUMS{
+ GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV,
+ GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV,
+ };
+
public:
void BindProgram(GLuint program) {
- if (bound_program == program) {
+ if (current_source_program == program) {
return;
}
- bound_program = program;
+ current_source_program = program;
glUseProgram(program);
}
+ void BindAssemblyPrograms(std::span<const OGLAssemblyProgram, NUM_STAGES> programs,
+ u32 stage_mask) {
+ const u32 changed_mask = current_assembly_mask ^ stage_mask;
+ current_assembly_mask = stage_mask;
+
+ if (changed_mask != 0) {
+ for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
+ if (((changed_mask >> stage) & 1) != 0) {
+ if (((stage_mask >> stage) & 1) != 0) {
+ glEnable(ASSEMBLY_PROGRAM_ENUMS[stage]);
+ } else {
+ glDisable(ASSEMBLY_PROGRAM_ENUMS[stage]);
+ }
+ }
+ }
+ }
+ for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
+ if (current_assembly_programs[stage] != programs[stage].handle) {
+ current_assembly_programs[stage] = programs[stage].handle;
+ glBindProgramARB(ASSEMBLY_PROGRAM_ENUMS[stage], programs[stage].handle);
+ }
+ }
+ if (current_source_program != 0) {
+ current_source_program = 0;
+ glUseProgram(0);
+ }
+ }
+
void RestoreGuestCompute() {}
private:
- GLuint bound_program = 0;
+ GLuint current_source_program = 0;
+
+ u32 current_assembly_mask = 0;
+ std::array<GLuint, NUM_STAGES> current_assembly_programs;
};
} // namespace OpenGL