summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
42 std::ranges::transform(infos, stage_infos.begin(), 42 std::ranges::transform(infos, stage_infos.begin(),
43 [](const Shader::Info* info) { return info ? *info : Shader::Info{}; }); 43 [](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
44 44
45 for (size_t stage = 0; stage < 5; ++stage) {
46 enabled_stages_mask |= (assembly_programs[stage].handle != 0 ? 1 : 0) << stage;
47 }
45 u32 num_textures{}; 48 u32 num_textures{};
46 u32 num_images{}; 49 u32 num_images{};
47 for (size_t stage = 0; stage < base_uniform_bindings.size() - 1; ++stage) { 50 for (size_t stage = 0; stage < base_uniform_bindings.size() - 1; ++stage) {
@@ -182,6 +185,9 @@ void GraphicsProgram::Configure(bool is_indexed) {
182 const std::span indices_span(image_view_indices.data(), image_view_index); 185 const std::span indices_span(image_view_indices.data(), image_view_index);
183 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); 186 texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
184 187
188 texture_cache.UpdateRenderTargets(false);
189 state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
190
185 ImageId* texture_buffer_index{image_view_ids.data()}; 191 ImageId* texture_buffer_index{image_view_ids.data()};
186 const auto bind_stage_info{[&](size_t stage) { 192 const auto bind_stage_info{[&](size_t stage) {
187 size_t index{}; 193 size_t index{};
@@ -240,14 +246,8 @@ void GraphicsProgram::Configure(bool is_indexed) {
240 buffer_cache.UpdateGraphicsBuffers(is_indexed); 246 buffer_cache.UpdateGraphicsBuffers(is_indexed);
241 buffer_cache.BindHostGeometryBuffers(is_indexed); 247 buffer_cache.BindHostGeometryBuffers(is_indexed);
242 248
243 // FIXME: Unhack this
244 if (assembly_programs[0].handle != 0) { 249 if (assembly_programs[0].handle != 0) {
245 // TODO: State track this 250 program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
246 glEnable(GL_VERTEX_PROGRAM_NV);
247 glEnable(GL_FRAGMENT_PROGRAM_NV);
248 glBindProgramARB(GL_VERTEX_PROGRAM_NV, assembly_programs[0].handle);
249 glBindProgramARB(GL_FRAGMENT_PROGRAM_NV, assembly_programs[4].handle);
250 program_manager.BindProgram(0);
251 } else { 251 } else {
252 program_manager.BindProgram(program.handle); 252 program_manager.BindProgram(program.handle);
253 } 253 }
@@ -300,19 +300,6 @@ void GraphicsProgram::Configure(bool is_indexed) {
300 if (image_binding != 0) { 300 if (image_binding != 0) {
301 glBindImageTextures(0, image_binding, images.data()); 301 glBindImageTextures(0, image_binding, images.data());
302 } 302 }
303 texture_cache.UpdateRenderTargets(false);
304
305 state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle());
306 if (assembly_programs[0].handle != 0) {
307 // TODO: State track this
308 glEnable(GL_VERTEX_PROGRAM_NV);
309 glEnable(GL_FRAGMENT_PROGRAM_NV);
310 glBindProgramARB(GL_VERTEX_PROGRAM_NV, assembly_programs[0].handle);
311 glBindProgramARB(GL_FRAGMENT_PROGRAM_NV, assembly_programs[4].handle);
312 program_manager.BindProgram(0);
313 } else {
314 program_manager.BindProgram(program.handle);
315 }
316} 303}
317 304
318} // namespace OpenGL 305} // 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:
89 89
90 OGLProgram program; 90 OGLProgram program;
91 std::array<OGLAssemblyProgram, 5> assembly_programs; 91 std::array<OGLAssemblyProgram, 5> assembly_programs;
92 u32 enabled_stages_mask{};
92 93
93 std::array<Shader::Info, 5> stage_infos{}; 94 std::array<Shader::Info, 5> stage_infos{};
94 std::array<u32, 5> base_uniform_bindings{}; 95 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <span>
9
7#include <glad/glad.h> 10#include <glad/glad.h>
8 11
12#include "video_core/renderer_opengl/gl_resource_manager.h"
13
14#pragma optimize("", off)
15
9namespace OpenGL { 16namespace OpenGL {
10 17
11class ProgramManager { 18class ProgramManager {
19 static constexpr size_t NUM_STAGES = 5;
20
21 static constexpr std::array ASSEMBLY_PROGRAM_ENUMS{
22 GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV,
23 GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV,
24 };
25
12public: 26public:
13 void BindProgram(GLuint program) { 27 void BindProgram(GLuint program) {
14 if (bound_program == program) { 28 if (current_source_program == program) {
15 return; 29 return;
16 } 30 }
17 bound_program = program; 31 current_source_program = program;
18 glUseProgram(program); 32 glUseProgram(program);
19 } 33 }
20 34
35 void BindAssemblyPrograms(std::span<const OGLAssemblyProgram, NUM_STAGES> programs,
36 u32 stage_mask) {
37 const u32 changed_mask = current_assembly_mask ^ stage_mask;
38 current_assembly_mask = stage_mask;
39
40 if (changed_mask != 0) {
41 for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
42 if (((changed_mask >> stage) & 1) != 0) {
43 if (((stage_mask >> stage) & 1) != 0) {
44 glEnable(ASSEMBLY_PROGRAM_ENUMS[stage]);
45 } else {
46 glDisable(ASSEMBLY_PROGRAM_ENUMS[stage]);
47 }
48 }
49 }
50 }
51 for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
52 if (current_assembly_programs[stage] != programs[stage].handle) {
53 current_assembly_programs[stage] = programs[stage].handle;
54 glBindProgramARB(ASSEMBLY_PROGRAM_ENUMS[stage], programs[stage].handle);
55 }
56 }
57 if (current_source_program != 0) {
58 current_source_program = 0;
59 glUseProgram(0);
60 }
61 }
62
21 void RestoreGuestCompute() {} 63 void RestoreGuestCompute() {}
22 64
23private: 65private:
24 GLuint bound_program = 0; 66 GLuint current_source_program = 0;
67
68 u32 current_assembly_mask = 0;
69 std::array<GLuint, NUM_STAGES> current_assembly_programs;
25}; 70};
26 71
27} // namespace OpenGL 72} // namespace OpenGL