mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-09-12 12:37:49 +02:00
gl_shader_util: Move shader utility code to a separate file
This commit is contained in:
parent
12fe7210d2
commit
b1ed64ac18
@ -83,18 +83,6 @@ void OGLSampler::Release() {
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
void OGLShader::Create(std::string_view source, GLenum type) {
|
||||
if (handle != 0) {
|
||||
return;
|
||||
}
|
||||
if (source.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
|
||||
handle = GLShader::LoadShader(source, type);
|
||||
}
|
||||
|
||||
void OGLShader::Release() {
|
||||
if (handle == 0)
|
||||
return;
|
||||
@ -104,21 +92,6 @@ void OGLShader::Release() {
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
void OGLProgram::CreateFromSource(const char* vert_shader, const char* geo_shader,
|
||||
const char* frag_shader, bool separable_program,
|
||||
bool hint_retrievable) {
|
||||
OGLShader vert, geo, frag;
|
||||
if (vert_shader)
|
||||
vert.Create(vert_shader, GL_VERTEX_SHADER);
|
||||
if (geo_shader)
|
||||
geo.Create(geo_shader, GL_GEOMETRY_SHADER);
|
||||
if (frag_shader)
|
||||
frag.Create(frag_shader, GL_FRAGMENT_SHADER);
|
||||
|
||||
MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
|
||||
Create(separable_program, hint_retrievable, vert.handle, geo.handle, frag.handle);
|
||||
}
|
||||
|
||||
void OGLProgram::Release() {
|
||||
if (handle == 0)
|
||||
return;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <utility>
|
||||
#include <glad/glad.h>
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
@ -128,8 +127,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Create(std::string_view source, GLenum type);
|
||||
|
||||
void Release();
|
||||
|
||||
GLuint handle = 0;
|
||||
@ -151,17 +148,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void Create(bool separable_program, bool hint_retrievable, T... shaders) {
|
||||
if (handle != 0)
|
||||
return;
|
||||
handle = GLShader::LoadProgram(separable_program, hint_retrievable, shaders...);
|
||||
}
|
||||
|
||||
/// Creates a new internal OpenGL resource and stores the handle
|
||||
void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader,
|
||||
bool separable_program = false, bool hint_retrievable = false);
|
||||
|
||||
/// Deletes the internal OpenGL resource
|
||||
void Release();
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/gl_state_tracker.h"
|
||||
#include "video_core/shader_cache.h"
|
||||
#include "video_core/shader_environment.h"
|
||||
@ -53,77 +54,6 @@ auto MakeSpan(Container& container) {
|
||||
return std::span(container.data(), container.size());
|
||||
}
|
||||
|
||||
void AddShader(GLenum stage, GLuint program, std::span<const u32> code) {
|
||||
OGLShader shader;
|
||||
shader.handle = glCreateShader(stage);
|
||||
|
||||
glShaderBinary(1, &shader.handle, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, code.data(),
|
||||
static_cast<GLsizei>(code.size_bytes()));
|
||||
glSpecializeShader(shader.handle, "main", 0, nullptr, nullptr);
|
||||
glAttachShader(program, shader.handle);
|
||||
if (!Settings::values.renderer_debug) {
|
||||
return;
|
||||
}
|
||||
GLint shader_status{};
|
||||
glGetShaderiv(shader.handle, GL_COMPILE_STATUS, &shader_status);
|
||||
if (shader_status == GL_FALSE) {
|
||||
LOG_ERROR(Render_OpenGL, "Failed to build shader");
|
||||
}
|
||||
GLint log_length{};
|
||||
glGetShaderiv(shader.handle, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length == 0) {
|
||||
return;
|
||||
}
|
||||
std::string log(log_length, 0);
|
||||
glGetShaderInfoLog(shader.handle, log_length, nullptr, log.data());
|
||||
if (shader_status == GL_FALSE) {
|
||||
LOG_ERROR(Render_OpenGL, "{}", log);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "{}", log);
|
||||
}
|
||||
}
|
||||
|
||||
void LinkProgram(GLuint program) {
|
||||
glLinkProgram(program);
|
||||
if (!Settings::values.renderer_debug) {
|
||||
return;
|
||||
}
|
||||
GLint link_status{};
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
|
||||
|
||||
GLint log_length{};
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length == 0) {
|
||||
return;
|
||||
}
|
||||
std::string log(log_length, 0);
|
||||
glGetProgramInfoLog(program, log_length, nullptr, log.data());
|
||||
if (link_status == GL_FALSE) {
|
||||
LOG_ERROR(Render_OpenGL, "{}", log);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "{}", log);
|
||||
}
|
||||
}
|
||||
|
||||
OGLAssemblyProgram CompileProgram(std::string_view code, GLenum target) {
|
||||
OGLAssemblyProgram program;
|
||||
glGenProgramsARB(1, &program.handle);
|
||||
glNamedProgramStringEXT(program.handle, target, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
static_cast<GLsizei>(code.size()), code.data());
|
||||
if (Settings::values.renderer_debug) {
|
||||
const auto err = reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_NV));
|
||||
if (err && *err) {
|
||||
if (std::strstr(err, "error")) {
|
||||
LOG_CRITICAL(Render_OpenGL, "\n{}", err);
|
||||
LOG_INFO(Render_OpenGL, "\n{}", code);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "\n{}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
GLenum Stage(size_t stage_index) {
|
||||
switch (stage_index) {
|
||||
case 0:
|
||||
@ -492,9 +422,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
|
||||
if (!device.UseAssemblyShaders()) {
|
||||
source_program.handle = glCreateProgram();
|
||||
}
|
||||
|
||||
for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram;
|
||||
++index) {
|
||||
const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0;
|
||||
for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) {
|
||||
if (key.unique_hashes[index] == 0) {
|
||||
continue;
|
||||
}
|
||||
@ -510,7 +439,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
|
||||
assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index));
|
||||
} else {
|
||||
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)};
|
||||
AddShader(Stage(stage_index), source_program.handle, code);
|
||||
AttachShader(Stage(stage_index), source_program.handle, code);
|
||||
}
|
||||
}
|
||||
if (!device.UseAssemblyShaders()) {
|
||||
@ -565,7 +494,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools&
|
||||
} else {
|
||||
const std::vector<u32> code{EmitSPIRV(profile, program)};
|
||||
source_program.handle = glCreateProgram();
|
||||
AddShader(GL_COMPUTE_SHADER, source_program.handle, code);
|
||||
AttachShader(GL_COMPUTE_SHADER, source_program.handle, code);
|
||||
LinkProgram(source_program.handle);
|
||||
}
|
||||
return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, gpu_memory,
|
||||
|
@ -5,57 +5,100 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
|
||||
namespace OpenGL::GLShader {
|
||||
namespace OpenGL {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string_view StageDebugName(GLenum type) {
|
||||
switch (type) {
|
||||
case GL_VERTEX_SHADER:
|
||||
return "vertex";
|
||||
case GL_GEOMETRY_SHADER:
|
||||
return "geometry";
|
||||
case GL_FRAGMENT_SHADER:
|
||||
return "fragment";
|
||||
case GL_COMPUTE_SHADER:
|
||||
return "compute";
|
||||
static void LogShader(GLuint shader) {
|
||||
GLint shader_status{};
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_status);
|
||||
if (shader_status == GL_FALSE) {
|
||||
LOG_ERROR(Render_OpenGL, "Failed to build shader");
|
||||
}
|
||||
GLint log_length{};
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length == 0) {
|
||||
return;
|
||||
}
|
||||
std::string log(log_length, 0);
|
||||
glGetShaderInfoLog(shader, log_length, nullptr, log.data());
|
||||
if (shader_status == GL_FALSE) {
|
||||
LOG_ERROR(Render_OpenGL, "{}", log);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "{}", log);
|
||||
}
|
||||
UNIMPLEMENTED();
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
void AttachShader(GLenum stage, GLuint program, std::string_view code) {
|
||||
OGLShader shader;
|
||||
shader.handle = glCreateShader(stage);
|
||||
|
||||
GLuint LoadShader(std::string_view source, GLenum type) {
|
||||
const std::string_view debug_type = StageDebugName(type);
|
||||
const GLuint shader_id = glCreateShader(type);
|
||||
const GLint length = static_cast<GLint>(code.size());
|
||||
const GLchar* const code_ptr = code.data();
|
||||
glShaderSource(shader.handle, 1, &code_ptr, &length);
|
||||
glCompileShader(shader.handle);
|
||||
glAttachShader(program, shader.handle);
|
||||
if (Settings::values.renderer_debug) {
|
||||
LogShader(shader.handle);
|
||||
}
|
||||
}
|
||||
|
||||
const GLchar* source_string = source.data();
|
||||
const GLint source_length = static_cast<GLint>(source.size());
|
||||
void AttachShader(GLenum stage, GLuint program, std::span<const u32> code) {
|
||||
OGLShader shader;
|
||||
shader.handle = glCreateShader(stage);
|
||||
|
||||
glShaderSource(shader_id, 1, &source_string, &source_length);
|
||||
LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type);
|
||||
glCompileShader(shader_id);
|
||||
glShaderBinary(1, &shader.handle, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, code.data(),
|
||||
static_cast<GLsizei>(code.size_bytes()));
|
||||
glSpecializeShader(shader.handle, "main", 0, nullptr, nullptr);
|
||||
glAttachShader(program, shader.handle);
|
||||
if (Settings::values.renderer_debug) {
|
||||
LogShader(shader.handle);
|
||||
}
|
||||
}
|
||||
|
||||
GLint result = GL_FALSE;
|
||||
GLint info_log_length;
|
||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result);
|
||||
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
void LinkProgram(GLuint program) {
|
||||
glLinkProgram(program);
|
||||
if (!Settings::values.renderer_debug) {
|
||||
return;
|
||||
}
|
||||
GLint link_status{};
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
|
||||
|
||||
if (info_log_length > 1) {
|
||||
std::string shader_error(info_log_length, ' ');
|
||||
glGetShaderInfoLog(shader_id, info_log_length, nullptr, &shader_error[0]);
|
||||
if (result == GL_TRUE) {
|
||||
LOG_DEBUG(Render_OpenGL, "{}", shader_error);
|
||||
} else {
|
||||
LOG_ERROR(Render_OpenGL, "Error compiling {} shader:\n{}", debug_type, shader_error);
|
||||
GLint log_length{};
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length == 0) {
|
||||
return;
|
||||
}
|
||||
std::string log(log_length, 0);
|
||||
glGetProgramInfoLog(program, log_length, nullptr, log.data());
|
||||
if (link_status == GL_FALSE) {
|
||||
LOG_ERROR(Render_OpenGL, "{}", log);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "{}", log);
|
||||
}
|
||||
}
|
||||
|
||||
OGLAssemblyProgram CompileProgram(std::string_view code, GLenum target) {
|
||||
OGLAssemblyProgram program;
|
||||
glGenProgramsARB(1, &program.handle);
|
||||
glNamedProgramStringEXT(program.handle, target, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
static_cast<GLsizei>(code.size()), code.data());
|
||||
if (Settings::values.renderer_debug) {
|
||||
const auto err = reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_NV));
|
||||
if (err && *err) {
|
||||
if (std::strstr(err, "error")) {
|
||||
LOG_CRITICAL(Render_OpenGL, "\n{}", err);
|
||||
LOG_INFO(Render_OpenGL, "\n{}", code);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "\n{}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return shader_id;
|
||||
return program;
|
||||
}
|
||||
|
||||
} // namespace OpenGL::GLShader
|
||||
} // namespace OpenGL
|
||||
|
@ -4,92 +4,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
|
||||
namespace OpenGL::GLShader {
|
||||
namespace OpenGL {
|
||||
|
||||
/**
|
||||
* Utility function to log the source code of a list of shaders.
|
||||
* @param shaders The OpenGL shaders whose source we will print.
|
||||
*/
|
||||
template <typename... T>
|
||||
void LogShaderSource(T... shaders) {
|
||||
auto shader_list = {shaders...};
|
||||
void AttachShader(GLenum stage, GLuint program, std::string_view code);
|
||||
|
||||
for (const auto& shader : shader_list) {
|
||||
if (shader == 0)
|
||||
continue;
|
||||
void AttachShader(GLenum stage, GLuint program, std::span<const u32> code);
|
||||
|
||||
GLint source_length;
|
||||
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
|
||||
void LinkProgram(GLuint program);
|
||||
|
||||
std::string source(source_length, ' ');
|
||||
glGetShaderSource(shader, source_length, nullptr, &source[0]);
|
||||
LOG_INFO(Render_OpenGL, "Shader source {}", source);
|
||||
}
|
||||
}
|
||||
OGLAssemblyProgram CompileProgram(std::string_view code, GLenum target);
|
||||
|
||||
/**
|
||||
* Utility function to create and compile an OpenGL GLSL shader
|
||||
* @param source String of the GLSL shader program
|
||||
* @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER)
|
||||
*/
|
||||
GLuint LoadShader(std::string_view source, GLenum type);
|
||||
|
||||
/**
|
||||
* Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader)
|
||||
* @param separable_program whether to create a separable program
|
||||
* @param shaders ID of shaders to attach to the program
|
||||
* @returns Handle of the newly created OpenGL program object
|
||||
*/
|
||||
template <typename... T>
|
||||
GLuint LoadProgram(bool separable_program, bool hint_retrievable, T... shaders) {
|
||||
// Link the program
|
||||
LOG_DEBUG(Render_OpenGL, "Linking program...");
|
||||
|
||||
GLuint program_id = glCreateProgram();
|
||||
|
||||
((shaders == 0 ? (void)0 : glAttachShader(program_id, shaders)), ...);
|
||||
|
||||
if (separable_program) {
|
||||
glProgramParameteri(program_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
|
||||
}
|
||||
if (hint_retrievable) {
|
||||
glProgramParameteri(program_id, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
}
|
||||
|
||||
glLinkProgram(program_id);
|
||||
|
||||
// Check the program
|
||||
GLint result = GL_FALSE;
|
||||
GLint info_log_length;
|
||||
glGetProgramiv(program_id, GL_LINK_STATUS, &result);
|
||||
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
|
||||
if (info_log_length > 1) {
|
||||
std::string program_error(info_log_length, ' ');
|
||||
glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
|
||||
if (result == GL_TRUE) {
|
||||
LOG_DEBUG(Render_OpenGL, "{}", program_error);
|
||||
} else {
|
||||
LOG_ERROR(Render_OpenGL, "Error linking shader:\n{}", program_error);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == GL_FALSE) {
|
||||
// There was a problem linking the shader, print the source for debugging purposes.
|
||||
LogShaderSource(shaders...);
|
||||
}
|
||||
|
||||
ASSERT_MSG(result == GL_TRUE, "Shader not linked");
|
||||
|
||||
((shaders == 0 ? (void)0 : glDetachShader(program_id, shaders)), ...);
|
||||
|
||||
return program_id;
|
||||
}
|
||||
|
||||
} // namespace OpenGL::GLShader
|
||||
} // namespace OpenGL
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "video_core/host_shaders/opengl_present_frag.h"
|
||||
#include "video_core/host_shaders/opengl_present_vert.h"
|
||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||
#include "video_core/renderer_opengl/renderer_opengl.h"
|
||||
#include "video_core/textures/decoders.h"
|
||||
@ -230,13 +231,10 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
|
||||
|
||||
void RendererOpenGL::InitOpenGLObjects() {
|
||||
// Create shader programs
|
||||
OGLShader vertex_shader;
|
||||
vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
|
||||
|
||||
OGLShader fragment_shader;
|
||||
fragment_shader.Create(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
|
||||
|
||||
present_program.Create(false, false, vertex_shader.handle, fragment_shader.handle);
|
||||
present_program.handle = glCreateProgram();
|
||||
AttachShader(GL_VERTEX_SHADER, present_program.handle, HostShaders::OPENGL_PRESENT_VERT);
|
||||
AttachShader(GL_FRAGMENT_SHADER, present_program.handle, HostShaders::OPENGL_PRESENT_FRAG);
|
||||
LinkProgram(present_program.handle);
|
||||
|
||||
// Generate presentation sampler
|
||||
present_sampler.Create();
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "video_core/host_shaders/opengl_copy_bgra_comp.h"
|
||||
#include "video_core/host_shaders/pitch_unswizzle_comp.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/gl_texture_cache.h"
|
||||
#include "video_core/renderer_opengl/util_shaders.h"
|
||||
#include "video_core/texture_cache/accelerated_swizzle.h"
|
||||
@ -40,13 +41,12 @@ using VideoCommon::Accelerated::MakeBlockLinearSwizzle3DParams;
|
||||
using VideoCore::Surface::BytesPerBlock;
|
||||
|
||||
namespace {
|
||||
|
||||
OGLProgram MakeProgram(std::string_view source) {
|
||||
OGLShader shader;
|
||||
shader.Create(source, GL_COMPUTE_SHADER);
|
||||
|
||||
OGLProgram program;
|
||||
program.Create(true, false, shader.handle);
|
||||
OGLShader shader;
|
||||
program.handle = glCreateProgram();
|
||||
AttachShader(GL_COMPUTE_SHADER, program.handle, source);
|
||||
LinkProgram(program.handle);
|
||||
return program;
|
||||
}
|
||||
|
||||
@ -54,7 +54,6 @@ size_t NumPixelsInCopy(const VideoCommon::ImageCopy& copy) {
|
||||
return static_cast<size_t>(copy.extent.width * copy.extent.height *
|
||||
copy.src_subresource.num_layers);
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
UtilShaders::UtilShaders(ProgramManager& program_manager_)
|
||||
|
Loading…
Reference in New Issue
Block a user