renderer_opengl: State track assembly programs
This commit is contained in:
parent
0a54291c9c
commit
c5ca4fe451
|
@ -42,6 +42,9 @@ GraphicsProgram::GraphicsProgram(TextureCache& texture_cache_, BufferCache& buff
|
||||||
std::ranges::transform(infos, stage_infos.begin(),
|
std::ranges::transform(infos, stage_infos.begin(),
|
||||||
[](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
|
[](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_textures{};
|
||||||
u32 num_images{};
|
u32 num_images{};
|
||||||
for (size_t stage = 0; stage < base_uniform_bindings.size() - 1; ++stage) {
|
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);
|
const std::span indices_span(image_view_indices.data(), image_view_index);
|
||||||
texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
|
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()};
|
ImageId* texture_buffer_index{image_view_ids.data()};
|
||||||
const auto bind_stage_info{[&](size_t stage) {
|
const auto bind_stage_info{[&](size_t stage) {
|
||||||
size_t index{};
|
size_t index{};
|
||||||
|
@ -240,14 +246,8 @@ void GraphicsProgram::Configure(bool is_indexed) {
|
||||||
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
||||||
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
||||||
|
|
||||||
// FIXME: Unhack this
|
|
||||||
if (assembly_programs[0].handle != 0) {
|
if (assembly_programs[0].handle != 0) {
|
||||||
// TODO: State track this
|
program_manager.BindAssemblyPrograms(assembly_programs, enabled_stages_mask);
|
||||||
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 {
|
} else {
|
||||||
program_manager.BindProgram(program.handle);
|
program_manager.BindProgram(program.handle);
|
||||||
}
|
}
|
||||||
|
@ -300,19 +300,6 @@ void GraphicsProgram::Configure(bool is_indexed) {
|
||||||
if (image_binding != 0) {
|
if (image_binding != 0) {
|
||||||
glBindImageTextures(0, image_binding, images.data());
|
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
|
} // namespace OpenGL
|
||||||
|
|
|
@ -89,6 +89,7 @@ private:
|
||||||
|
|
||||||
OGLProgram program;
|
OGLProgram program;
|
||||||
std::array<OGLAssemblyProgram, 5> assembly_programs;
|
std::array<OGLAssemblyProgram, 5> assembly_programs;
|
||||||
|
u32 enabled_stages_mask{};
|
||||||
|
|
||||||
std::array<Shader::Info, 5> stage_infos{};
|
std::array<Shader::Info, 5> stage_infos{};
|
||||||
std::array<u32, 5> base_uniform_bindings{};
|
std::array<u32, 5> base_uniform_bindings{};
|
||||||
|
|
|
@ -4,24 +4,69 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
class ProgramManager {
|
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:
|
public:
|
||||||
void BindProgram(GLuint program) {
|
void BindProgram(GLuint program) {
|
||||||
if (bound_program == program) {
|
if (current_source_program == program) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bound_program = program;
|
current_source_program = program;
|
||||||
glUseProgram(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() {}
|
void RestoreGuestCompute() {}
|
||||||
|
|
||||||
private:
|
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
|
} // namespace OpenGL
|
||||||
|
|
Reference in New Issue