mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	video_core: add workarounds to enable GLES support
video_core: shorten GetGLSLVersionString video_core: make GLES version and extensions consistent video_core: move some logic to LoadShader video_core: deduplicate fragment shader precision specifier
This commit is contained in:
		
							parent
							
								
									cd21abe50f
								
							
						
					
					
						commit
						d63acfc1e9
					
				
					 10 changed files with 204 additions and 37 deletions
				
			
		| 
						 | 
				
			
			@ -28,6 +28,7 @@
 | 
			
		|||
#include "video_core/renderer_base.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_vars.h"
 | 
			
		||||
#include "video_core/utils.h"
 | 
			
		||||
#include "video_core/video_core.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,17 @@ static constexpr std::array<FormatTuple, 5> fb_format_tuples = {{
 | 
			
		|||
    {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},   // RGBA4
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
// Same as above, with minor changes for OpenGL ES. Replaced
 | 
			
		||||
// GL_UNSIGNED_INT_8_8_8_8 with GL_UNSIGNED_BYTE and
 | 
			
		||||
// GL_BGR with GL_RGB
 | 
			
		||||
static constexpr std::array<FormatTuple, 5> fb_format_tuples_oes = {{
 | 
			
		||||
    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},            // RGBA8
 | 
			
		||||
    {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},              // RGB8
 | 
			
		||||
    {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, // RGB5A1
 | 
			
		||||
    {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},     // RGB565
 | 
			
		||||
    {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},   // RGBA4
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
static constexpr std::array<FormatTuple, 4> depth_format_tuples = {{
 | 
			
		||||
    {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16
 | 
			
		||||
    {},
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +75,9 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
 | 
			
		|||
    const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
 | 
			
		||||
    if (type == SurfaceType::Color) {
 | 
			
		||||
        ASSERT(static_cast<std::size_t>(pixel_format) < fb_format_tuples.size());
 | 
			
		||||
        if (GLES) {
 | 
			
		||||
            return fb_format_tuples_oes[static_cast<unsigned int>(pixel_format)];
 | 
			
		||||
        }
 | 
			
		||||
        return fb_format_tuples[static_cast<unsigned int>(pixel_format)];
 | 
			
		||||
    } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
 | 
			
		||||
        std::size_t tuple_idx = static_cast<std::size_t>(pixel_format) - 14;
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +87,77 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
 | 
			
		|||
    return tex_tuple;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OpenGL ES does not support glGetTexImage. Obtain the pixels by attaching the
 | 
			
		||||
 * texture to a framebuffer.
 | 
			
		||||
 * Originally from https://github.com/apitrace/apitrace/blob/master/retrace/glstate_images.cpp
 | 
			
		||||
 */
 | 
			
		||||
static inline void GetTexImageOES(GLenum target, GLint level, GLenum format, GLenum type,
 | 
			
		||||
                                  GLint height, GLint width, GLint depth, GLubyte* pixels) {
 | 
			
		||||
 | 
			
		||||
    memset(pixels, 0x80, height * width * 4);
 | 
			
		||||
 | 
			
		||||
    GLenum texture_binding = GL_NONE;
 | 
			
		||||
    switch (target) {
 | 
			
		||||
    case GL_TEXTURE_2D:
 | 
			
		||||
        texture_binding = GL_TEXTURE_BINDING_2D;
 | 
			
		||||
        break;
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
 | 
			
		||||
        texture_binding = GL_TEXTURE_BINDING_CUBE_MAP;
 | 
			
		||||
        break;
 | 
			
		||||
    case GL_TEXTURE_3D_OES:
 | 
			
		||||
        texture_binding = GL_TEXTURE_BINDING_3D_OES;
 | 
			
		||||
    default:
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GLint texture = 0;
 | 
			
		||||
    glGetIntegerv(texture_binding, &texture);
 | 
			
		||||
    if (!texture) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GLint prev_fbo = 0;
 | 
			
		||||
    GLuint fbo = 0;
 | 
			
		||||
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
 | 
			
		||||
    glGenFramebuffers(1, &fbo);
 | 
			
		||||
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 | 
			
		||||
 | 
			
		||||
    switch (target) {
 | 
			
		||||
    case GL_TEXTURE_2D:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
 | 
			
		||||
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: {
 | 
			
		||||
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level);
 | 
			
		||||
        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 | 
			
		||||
        if (status != GL_FRAMEBUFFER_COMPLETE) {
 | 
			
		||||
            LOG_DEBUG(Render_OpenGL, "Framebuffer is incomplete, status: {:X}", status);
 | 
			
		||||
        }
 | 
			
		||||
        glReadPixels(0, 0, width, height, format, type, pixels);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case GL_TEXTURE_3D_OES:
 | 
			
		||||
        for (int i = 0; i < depth; i++) {
 | 
			
		||||
            glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture,
 | 
			
		||||
                                   level, i);
 | 
			
		||||
            glReadPixels(0, 0, width, height, format, type, pixels + 4 * i * width * height);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
 | 
			
		||||
 | 
			
		||||
    glDeleteFramebuffers(1, &fbo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Map, typename Interval>
 | 
			
		||||
constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
 | 
			
		||||
    return boost::make_iterator_range(map.equal_range(interval));
 | 
			
		||||
| 
						 | 
				
			
			@ -841,7 +927,12 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
 | 
			
		|||
        state.Apply();
 | 
			
		||||
 | 
			
		||||
        glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
        glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, &gl_buffer[buffer_offset]);
 | 
			
		||||
        if (GLES) {
 | 
			
		||||
            GetTexImageOES(GL_TEXTURE_2D, 0, tuple.format, tuple.type, height, width, 0,
 | 
			
		||||
                           &gl_buffer[buffer_offset]);
 | 
			
		||||
        } else {
 | 
			
		||||
            glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, &gl_buffer[buffer_offset]);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        state.ResetTexture(texture.handle);
 | 
			
		||||
        state.draw.read_framebuffer = read_fb_handle;
 | 
			
		||||
| 
						 | 
				
			
			@ -982,16 +1073,15 @@ RasterizerCacheOpenGL::RasterizerCacheOpenGL() {
 | 
			
		|||
    d24s8_abgr_buffer.Create();
 | 
			
		||||
    d24s8_abgr_buffer_size = 0;
 | 
			
		||||
 | 
			
		||||
    const char* vs_source = R"(
 | 
			
		||||
#version 330 core
 | 
			
		||||
    std::string vs_source = R"(
 | 
			
		||||
const vec2 vertices[4] = vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0));
 | 
			
		||||
void main() {
 | 
			
		||||
    gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
 | 
			
		||||
}
 | 
			
		||||
)";
 | 
			
		||||
    const char* fs_source = R"(
 | 
			
		||||
#version 330 core
 | 
			
		||||
 | 
			
		||||
    std::string fs_source = GLES ? fragment_shader_precision_OES : "";
 | 
			
		||||
    fs_source += R"(
 | 
			
		||||
uniform samplerBuffer tbo;
 | 
			
		||||
uniform vec2 tbo_size;
 | 
			
		||||
uniform vec4 viewport;
 | 
			
		||||
| 
						 | 
				
			
			@ -1004,7 +1094,7 @@ void main() {
 | 
			
		|||
    color = texelFetch(tbo, tbo_offset).rabg;
 | 
			
		||||
}
 | 
			
		||||
)";
 | 
			
		||||
    d24s8_abgr_shader.Create(vs_source, fs_source);
 | 
			
		||||
    d24s8_abgr_shader.Create(vs_source.c_str(), fs_source.c_str());
 | 
			
		||||
 | 
			
		||||
    OpenGLState state = OpenGLState::GetCurState();
 | 
			
		||||
    GLuint old_program = state.draw.shader_program;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_util.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_vars.h"
 | 
			
		||||
#include "video_core/video_core.h"
 | 
			
		||||
 | 
			
		||||
using Pica::FramebufferRegs;
 | 
			
		||||
| 
						 | 
				
			
			@ -1250,7 +1251,6 @@ std::string GenerateFragmentShader(const PicaFSConfig& config, bool separable_sh
 | 
			
		|||
    const auto& state = config.state;
 | 
			
		||||
 | 
			
		||||
    std::string out = R"(
 | 
			
		||||
#version 330 core
 | 
			
		||||
#extension GL_ARB_shader_image_load_store : enable
 | 
			
		||||
#extension GL_ARB_shader_image_size : enable
 | 
			
		||||
#define ALLOW_SHADOW (defined(GL_ARB_shader_image_load_store) && defined(GL_ARB_shader_image_size))
 | 
			
		||||
| 
						 | 
				
			
			@ -1260,10 +1260,16 @@ std::string GenerateFragmentShader(const PicaFSConfig& config, bool separable_sh
 | 
			
		|||
        out += "#extension GL_ARB_separate_shader_objects : enable\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (GLES) {
 | 
			
		||||
        out += fragment_shader_precision_OES;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    out += GetVertexInterfaceDeclaration(false, separable_shader);
 | 
			
		||||
 | 
			
		||||
    out += R"(
 | 
			
		||||
#ifndef CITRA_GLES
 | 
			
		||||
in vec4 gl_FragCoord;
 | 
			
		||||
#endif // CITRA_GLES
 | 
			
		||||
 | 
			
		||||
out vec4 color;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1300,13 +1306,13 @@ float LookupLightingLUT(int lut_index, int index, float delta) {
 | 
			
		|||
 | 
			
		||||
float LookupLightingLUTUnsigned(int lut_index, float pos) {
 | 
			
		||||
    int index = clamp(int(pos * 256.0), 0, 255);
 | 
			
		||||
    float delta = pos * 256.0 - index;
 | 
			
		||||
    float delta = pos * 256.0 - float(index);
 | 
			
		||||
    return LookupLightingLUT(lut_index, index, delta);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float LookupLightingLUTSigned(int lut_index, float pos) {
 | 
			
		||||
    int index = clamp(int(pos * 128.0), -128, 127);
 | 
			
		||||
    float delta = pos * 128.0 - index;
 | 
			
		||||
    float delta = pos * 128.0 - float(index);
 | 
			
		||||
    if (index < 0) index += 256;
 | 
			
		||||
    return LookupLightingLUT(lut_index, index, delta);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1494,10 +1500,10 @@ vec4 secondary_fragment_color = vec4(0.0);
 | 
			
		|||
        // Negate the condition if we have to keep only the pixels outside the scissor box
 | 
			
		||||
        if (state.scissor_test_mode == RasterizerRegs::ScissorMode::Include)
 | 
			
		||||
            out += "!";
 | 
			
		||||
        out += "(gl_FragCoord.x >= scissor_x1 && "
 | 
			
		||||
               "gl_FragCoord.y >= scissor_y1 && "
 | 
			
		||||
               "gl_FragCoord.x < scissor_x2 && "
 | 
			
		||||
               "gl_FragCoord.y < scissor_y2)) discard;\n";
 | 
			
		||||
        out += "(gl_FragCoord.x >= float(scissor_x1) && "
 | 
			
		||||
               "gl_FragCoord.y >= float(scissor_y1) && "
 | 
			
		||||
               "gl_FragCoord.x < float(scissor_x2) && "
 | 
			
		||||
               "gl_FragCoord.y < float(scissor_y2))) discard;\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // After perspective divide, OpenGL transform z_over_w from [-1, 1] to [near, far]. Here we use
 | 
			
		||||
| 
						 | 
				
			
			@ -1529,7 +1535,7 @@ vec4 secondary_fragment_color = vec4(0.0);
 | 
			
		|||
    if (state.fog_mode == TexturingRegs::FogMode::Fog) {
 | 
			
		||||
        // Get index into fog LUT
 | 
			
		||||
        if (state.fog_flip) {
 | 
			
		||||
            out += "float fog_index = (1.0 - depth) * 128.0;\n";
 | 
			
		||||
            out += "float fog_index = (1.0 - float(depth)) * 128.0;\n";
 | 
			
		||||
        } else {
 | 
			
		||||
            out += "float fog_index = depth * 128.0;\n";
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1591,7 +1597,7 @@ do {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
std::string GenerateTrivialVertexShader(bool separable_shader) {
 | 
			
		||||
    std::string out = "#version 330 core\n";
 | 
			
		||||
    std::string out = "";
 | 
			
		||||
    if (separable_shader) {
 | 
			
		||||
        out += "#extension GL_ARB_separate_shader_objects : enable\n";
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1626,8 +1632,10 @@ void main() {
 | 
			
		|||
    normquat = vert_normquat;
 | 
			
		||||
    view = vert_view;
 | 
			
		||||
    gl_Position = vert_position;
 | 
			
		||||
#if !defined(CITRA_GLES) || defined(GL_EXT_clip_cull_distance)
 | 
			
		||||
    gl_ClipDistance[0] = -vert_position.z; // fixed PICA clipping plane z <= 0
 | 
			
		||||
    gl_ClipDistance[1] = dot(clip_coef, vert_position);
 | 
			
		||||
#endif // !defined(CITRA_GLES) || defined(GL_EXT_clip_cull_distance)
 | 
			
		||||
}
 | 
			
		||||
)";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1636,7 +1644,7 @@ void main() {
 | 
			
		|||
 | 
			
		||||
std::optional<std::string> GenerateVertexShader(const Pica::Shader::ShaderSetup& setup,
 | 
			
		||||
                                                const PicaVSConfig& config, bool separable_shader) {
 | 
			
		||||
    std::string out = "#version 330 core\n";
 | 
			
		||||
    std::string out = "";
 | 
			
		||||
    if (separable_shader) {
 | 
			
		||||
        out += "#extension GL_ARB_separate_shader_objects : enable\n";
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1744,9 +1752,12 @@ struct Vertex {
 | 
			
		|||
           semantic(VSOutputAttributes::POSITION_Y) + ", " +
 | 
			
		||||
           semantic(VSOutputAttributes::POSITION_Z) + ", " +
 | 
			
		||||
           semantic(VSOutputAttributes::POSITION_W) + ");\n";
 | 
			
		||||
    semantic(VSOutputAttributes::POSITION_W) + ");\n";
 | 
			
		||||
    out += "    gl_Position = vtx_pos;\n";
 | 
			
		||||
    out += "#if !defined(CITRA_GLES) || defined(GL_EXT_clip_cull_distance)\n";
 | 
			
		||||
    out += "    gl_ClipDistance[0] = -vtx_pos.z;\n"; // fixed PICA clipping plane z <= 0
 | 
			
		||||
    out += "    gl_ClipDistance[1] = dot(clip_coef, vtx_pos);\n\n";
 | 
			
		||||
    out += "    gl_ClipDistance[1] = dot(clip_coef, vtx_pos);\n";
 | 
			
		||||
    out += "#endif // !defined(CITRA_GLES) || defined(GL_EXT_clip_cull_distance)\n\n";
 | 
			
		||||
 | 
			
		||||
    out += "    vec4 vtx_quat = GetVertexQuaternion(vtx);\n";
 | 
			
		||||
    out += "    normquat = mix(vtx_quat, -vtx_quat, bvec4(quats_opposite));\n\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -1789,7 +1800,7 @@ void EmitPrim(Vertex vtx0, Vertex vtx1, Vertex vtx2) {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
std::string GenerateFixedGeometryShader(const PicaFixedGSConfig& config, bool separable_shader) {
 | 
			
		||||
    std::string out = "#version 330 core\n";
 | 
			
		||||
    std::string out = "";
 | 
			
		||||
    if (separable_shader) {
 | 
			
		||||
        out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1824,7 +1835,7 @@ void main() {
 | 
			
		|||
std::optional<std::string> GenerateGeometryShader(const Pica::Shader::ShaderSetup& setup,
 | 
			
		||||
                                                  const PicaGSConfig& config,
 | 
			
		||||
                                                  bool separable_shader) {
 | 
			
		||||
    std::string out = "#version 330 core\n";
 | 
			
		||||
    std::string out = "";
 | 
			
		||||
    if (separable_shader) {
 | 
			
		||||
        out += "#extension GL_ARB_separate_shader_objects : enable\n";
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,15 +2,33 @@
 | 
			
		|||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <glad/glad.h>
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_util.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_vars.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
GLuint LoadShader(const char* source, GLenum type) {
 | 
			
		||||
    const std::string version = GLES ? R"(
 | 
			
		||||
#version 310 es
 | 
			
		||||
 | 
			
		||||
#define CITRA_GLES
 | 
			
		||||
 | 
			
		||||
#if defined(GL_ANDROID_extension_pack_es31a)
 | 
			
		||||
#extension GL_ANDROID_extension_pack_es31a : enable
 | 
			
		||||
#endif // defined(GL_ANDROID_extension_pack_es31a)
 | 
			
		||||
 | 
			
		||||
#if defined(GL_EXT_clip_cull_distance)
 | 
			
		||||
#extension GL_EXT_clip_cull_distance : enable
 | 
			
		||||
#endif // defined(GL_EXT_clip_cull_distance)
 | 
			
		||||
)"
 | 
			
		||||
                                     : "#version 330\n";
 | 
			
		||||
 | 
			
		||||
    const char* debug_type;
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case GL_VERTEX_SHADER:
 | 
			
		||||
| 
						 | 
				
			
			@ -26,8 +44,9 @@ GLuint LoadShader(const char* source, GLenum type) {
 | 
			
		|||
        UNREACHABLE();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::array<const char*, 2> src_arr{version.data(), source};
 | 
			
		||||
    GLuint shader_id = glCreateShader(type);
 | 
			
		||||
    glShaderSource(shader_id, 1, &source, nullptr);
 | 
			
		||||
    glShaderSource(shader_id, static_cast<GLsizei>(src_arr.size()), src_arr.data(), nullptr);
 | 
			
		||||
    LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type);
 | 
			
		||||
    glCompileShader(shader_id);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +63,7 @@ GLuint LoadShader(const char* source, GLenum type) {
 | 
			
		|||
        } else {
 | 
			
		||||
            LOG_ERROR(Render_OpenGL, "Error compiling {} shader:\n{}", debug_type,
 | 
			
		||||
                      &shader_error[0]);
 | 
			
		||||
            LOG_ERROR(Render_OpenGL, "Shader source code:\n{}", source);
 | 
			
		||||
            LOG_ERROR(Render_OpenGL, "Shader source code:\n{}{}", src_arr[0], src_arr[1]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return shader_id;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,17 @@
 | 
			
		|||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
// High precision may or may not supported in GLES3. If it isn't, use medium precision instead.
 | 
			
		||||
static constexpr char fragment_shader_precision_OES[] = R"(
 | 
			
		||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
 | 
			
		||||
    precision highp float;
 | 
			
		||||
precision highp samplerBuffer;
 | 
			
		||||
#else
 | 
			
		||||
    precision mediump float;
 | 
			
		||||
precision mediump samplerBuffer;
 | 
			
		||||
#endif // GL_FRAGMENT_PRECISION_HIGH
 | 
			
		||||
)";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Utility function to create and compile an OpenGL GLSL shader
 | 
			
		||||
 * @param source String of the GLSL shader program
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_vars.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -193,8 +194,13 @@ void OpenGLState::Apply() const {
 | 
			
		|||
        glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (logic_op != cur_state.logic_op) {
 | 
			
		||||
        glLogicOp(logic_op);
 | 
			
		||||
    // GLES3 does not support glLogicOp
 | 
			
		||||
    if (!GLES) {
 | 
			
		||||
        if (logic_op != cur_state.logic_op) {
 | 
			
		||||
            glLogicOp(logic_op);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG_TRACE(Render_OpenGL, "glLogicOps are unimplemented...");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Textures
 | 
			
		||||
| 
						 | 
				
			
			@ -319,12 +325,14 @@ void OpenGLState::Apply() const {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // Clip distance
 | 
			
		||||
    for (std::size_t i = 0; i < clip_distance.size(); ++i) {
 | 
			
		||||
        if (clip_distance[i] != cur_state.clip_distance[i]) {
 | 
			
		||||
            if (clip_distance[i]) {
 | 
			
		||||
                glEnable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i));
 | 
			
		||||
            } else {
 | 
			
		||||
                glDisable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i));
 | 
			
		||||
    if (!GLES || GLAD_GL_EXT_clip_cull_distance) {
 | 
			
		||||
        for (size_t i = 0; i < clip_distance.size(); ++i) {
 | 
			
		||||
            if (clip_distance[i] != cur_state.clip_distance[i]) {
 | 
			
		||||
                if (clip_distance[i]) {
 | 
			
		||||
                    glEnable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i));
 | 
			
		||||
                } else {
 | 
			
		||||
                    glDisable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										9
									
								
								src/video_core/renderer_opengl/gl_vars.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/video_core/renderer_opengl/gl_vars.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
// Copyright 2019 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "video_core/renderer_opengl/gl_vars.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
bool GLES;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								src/video_core/renderer_opengl/gl_vars.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/video_core/renderer_opengl/gl_vars.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
// Copyright 2019 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
extern bool GLES;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -21,14 +21,13 @@
 | 
			
		|||
#include "core/tracer/recorder.h"
 | 
			
		||||
#include "video_core/debug_utils/debug_utils.h"
 | 
			
		||||
#include "video_core/rasterizer_interface.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_vars.h"
 | 
			
		||||
#include "video_core/renderer_opengl/renderer_opengl.h"
 | 
			
		||||
#include "video_core/video_core.h"
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
static const char vertex_shader[] = R"(
 | 
			
		||||
#version 150 core
 | 
			
		||||
 | 
			
		||||
in vec2 vert_position;
 | 
			
		||||
in vec2 vert_tex_coord;
 | 
			
		||||
out vec2 frag_tex_coord;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +49,6 @@ void main() {
 | 
			
		|||
)";
 | 
			
		||||
 | 
			
		||||
static const char fragment_shader[] = R"(
 | 
			
		||||
#version 150 core
 | 
			
		||||
 | 
			
		||||
in vec2 frag_tex_coord;
 | 
			
		||||
out vec4 color;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -279,7 +276,13 @@ void RendererOpenGL::InitOpenGLObjects() {
 | 
			
		|||
                 0.0f);
 | 
			
		||||
 | 
			
		||||
    // Link shaders and get variable locations
 | 
			
		||||
    shader.Create(vertex_shader, fragment_shader);
 | 
			
		||||
    if (GLES) {
 | 
			
		||||
        std::string frag_source(fragment_shader_precision_OES);
 | 
			
		||||
        frag_source += fragment_shader;
 | 
			
		||||
        shader.Create(vertex_shader, frag_source.data());
 | 
			
		||||
    } else {
 | 
			
		||||
        shader.Create(vertex_shader, fragment_shader);
 | 
			
		||||
    }
 | 
			
		||||
    state.draw.shader_program = shader.handle;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
    uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
 | 
			
		||||
| 
						 | 
				
			
			@ -344,7 +347,7 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
 | 
			
		|||
    case GPU::Regs::PixelFormat::RGBA8:
 | 
			
		||||
        internal_format = GL_RGBA;
 | 
			
		||||
        texture.gl_format = GL_RGBA;
 | 
			
		||||
        texture.gl_type = GL_UNSIGNED_INT_8_8_8_8;
 | 
			
		||||
        texture.gl_type = GLES ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT_8_8_8_8;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case GPU::Regs::PixelFormat::RGB8:
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +356,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
 | 
			
		|||
        // mostly everywhere) for words or half-words.
 | 
			
		||||
        // TODO: check how those behave on big-endian processors.
 | 
			
		||||
        internal_format = GL_RGB;
 | 
			
		||||
        texture.gl_format = GL_BGR;
 | 
			
		||||
 | 
			
		||||
        // GLES Dosen't support BGR , Use RGB instead
 | 
			
		||||
        texture.gl_format = GLES ? GL_RGB : GL_BGR;
 | 
			
		||||
        texture.gl_type = GL_UNSIGNED_BYTE;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -555,7 +560,7 @@ Core::System::ResultStatus RendererOpenGL::Init() {
 | 
			
		|||
        return Core::System::ResultStatus::ErrorVideoCore_ErrorGenericDrivers;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!GLAD_GL_VERSION_3_3) {
 | 
			
		||||
    if (!(GLAD_GL_VERSION_3_3 || GLAD_GL_ES_VERSION_3_1)) {
 | 
			
		||||
        return Core::System::ResultStatus::ErrorVideoCore_ErrorBelowGL33;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue