rend: shader builder utility

This commit is contained in:
Flyinghead 2021-07-19 12:49:47 +02:00
parent 4f11ff76a5
commit 117f47e3a2
11 changed files with 435 additions and 395 deletions

View File

@ -29,13 +29,11 @@ static GLuint g_quadBuffer;
static GLuint g_quadIndexBuffer;
static GLuint g_quadVertexArray;
#define MAX_PIXELS_PER_FRAGMENT "32"
constexpr int MAX_PIXELS_PER_FRAGMENT = 32;
static const char *final_shader_source = SHADER_HEADER
"#define MAX_PIXELS_PER_FRAGMENT " MAX_PIXELS_PER_FRAGMENT
R"(
static const char *final_shader_source = R"(
layout(binding = 0) uniform sampler2D tex;
uniform highp float shade_scale_factor;
uniform float shade_scale_factor;
out vec4 FragColor;
@ -178,8 +176,7 @@ void main(void)
}
)";
static const char *clear_shader_source = SHADER_HEADER
R"(
static const char *clear_shader_source = R"(
void main(void)
{
ivec2 coords = ivec2(gl_FragCoord.xy);
@ -192,11 +189,7 @@ void main(void)
}
)";
static const char *tr_modvol_shader_source = SHADER_HEADER
"#define MAX_PIXELS_PER_FRAGMENT " MAX_PIXELS_PER_FRAGMENT
R"(
#define MV_MODE %d
static const char *tr_modvol_shader_source = R"(
// Must match ModifierVolumeMode enum values
#define MV_XOR 0
#define MV_OR 1
@ -242,10 +235,8 @@ void main(void)
}
)";
static const char* VertexShaderSource =
R"(#version 430
in highp vec3 in_pos;
static const char* VertexShaderSource = R"(
in vec3 in_pos;
void main()
{
@ -301,17 +292,33 @@ void initABuffer()
glCheck();
}
OpenGl4Source vertexShader;
vertexShader.addSource(VertexShaderSource);
if (g_abuffer_final_shader.program == 0)
gl4CompilePipelineShader(&g_abuffer_final_shader, final_shader_source, VertexShaderSource);
{
OpenGl4Source finalShader;
finalShader.addConstant("MAX_PIXELS_PER_FRAGMENT", MAX_PIXELS_PER_FRAGMENT)
.addSource(ShaderHeader)
.addSource(final_shader_source);
gl4CompilePipelineShader(&g_abuffer_final_shader, finalShader.generate().c_str(), vertexShader.generate().c_str());
}
if (g_abuffer_clear_shader.program == 0)
gl4CompilePipelineShader(&g_abuffer_clear_shader, clear_shader_source, VertexShaderSource);
{
OpenGl4Source clearShader;
clearShader.addSource(ShaderHeader)
.addSource(clear_shader_source);
gl4CompilePipelineShader(&g_abuffer_clear_shader, clearShader.generate().c_str(), vertexShader.generate().c_str());
}
if (g_abuffer_tr_modvol_shaders[0].program == 0)
{
char source[16384];
OpenGl4Source modVolShader;
modVolShader.addConstant("MAX_PIXELS_PER_FRAGMENT", MAX_PIXELS_PER_FRAGMENT)
.addSource(ShaderHeader)
.addSource(tr_modvol_shader_source);
for (int mode = 0; mode < ModeCount; mode++)
{
sprintf(source, tr_modvol_shader_source, mode);
gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], source, VertexShaderSource);
modVolShader.setConstant("MV_MODE", mode);
gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], modVolShader.generate().c_str(), vertexShader.generate().c_str());
}
}
if (g_quadBuffer == 0)

View File

@ -89,7 +89,7 @@ extern int max_image_width;
extern int max_image_height;
extern const char *gl4PixelPipelineShader;
bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *pixel_source = gl4PixelPipelineShader, const char *vertex_source = NULL);
bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *pixel_source = nullptr, const char *vertex_source = nullptr);
void initABuffer();
void termABuffer();
@ -106,33 +106,37 @@ extern GLuint geom_fbo;
extern GLuint texSamplers[2];
extern GLuint depth_fbo;
#define SHADER_HEADER "#version 430 \n\
\n\
layout(r32ui, binding = 4) uniform coherent restrict uimage2D abufferPointerImg; \n\
\n\
layout(binding = 0, offset = 0) uniform atomic_uint buffer_index; \n\
\n" \
OIT_POLY_PARAM \
"\
layout (binding = 0, std430) coherent restrict buffer PixelBuffer { \n\
Pixel pixels[]; \n\
}; \n\
\n\
uint getNextPixelIndex() \n\
{ \n\
uint index = atomicCounterIncrement(buffer_index); \n\
if (index >= pixels.length()) \n\
// Buffer overflow \n\
discard; \n\
\n\
return index; \n\
} \n\
\n\
layout (binding = 1, std430) readonly buffer TrPolyParamBuffer { \n\
PolyParam tr_poly_params[]; \n\
}; \n\
\n\
"
static const char* ShaderHeader = R"(
layout(r32ui, binding = 4) uniform coherent restrict uimage2D abufferPointerImg;
layout(binding = 0, offset = 0) uniform atomic_uint buffer_index;
)"
OIT_POLY_PARAM
R"(
layout (binding = 0, std430) coherent restrict buffer PixelBuffer {
Pixel pixels[];
};
uint getNextPixelIndex()
{
uint index = atomicCounterIncrement(buffer_index);
if (index >= pixels.length())
// Buffer overflow
discard;
return index;
}
layout (binding = 1, std430) readonly buffer TrPolyParamBuffer {
PolyParam tr_poly_params[];
};
)";
class OpenGl4Source : public ShaderSource
{
public:
OpenGl4Source() : ShaderSource("#version 430") {}
};
void gl4SetupMainVBO();
void gl4SetupModvolVBO();

View File

@ -23,9 +23,7 @@
//Fragment and vertex shaders code
static const char* VertexShaderSource = R"(#version 140
#define pp_Gouraud %d
static const char* VertexShaderSource = R"(
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
@ -67,24 +65,7 @@ void main()
}
)";
const char* gl4PixelPipelineShader = SHADER_HEADER
R"(
#define cp_AlphaTest %d
#define pp_ClipInside %d
#define pp_UseAlpha %d
#define pp_Texture %d
#define pp_IgnoreTexA %d
#define pp_ShadInstr %d
#define pp_Offset %d
#define pp_FogCtrl %d
#define pp_TwoVolumes %d
#define pp_Gouraud %d
#define pp_BumpMap %d
#define FogClamping %d
#define pp_Palette %d
#define NOUVEAU %d
#define PASS %d
const char* gl4PixelPipelineShader = R"(
#define PI 3.1415926
#define PASS_DEPTH 0
@ -166,7 +147,7 @@ vec4 fog_clamp(vec4 col)
vec4 palettePixel(sampler2D tex, vec2 coords)
{
int color_idx = int(floor(texture(tex, coords).r * 255.0 + 0.5)) + palette_index;
ivec2 c = ivec2(color_idx %% 32, color_idx / 32);
ivec2 c = ivec2(color_idx % 32, color_idx / 32);
return texelFetch(palette, c, 0);
}
@ -393,36 +374,62 @@ void main()
}
)";
static const char* ModifierVolumeShader = SHADER_HEADER
R"(
static const char* ModifierVolumeShader = R"(
void main()
{
setFragDepth();
}
)";
class Vertex4Source : public OpenGl4Source
{
public:
Vertex4Source(bool gouraud) : OpenGl4Source() {
addConstant("pp_Gouraud", gouraud);
addSource(VertexShaderSource);
}
};
class Fragment4ShaderSource : public OpenGl4Source
{
public:
Fragment4ShaderSource(const gl4PipelineShader* s) : OpenGl4Source()
{
addConstant("cp_AlphaTest", s->cp_AlphaTest);
addConstant("pp_ClipInside", s->pp_InsideClipping);
addConstant("pp_UseAlpha", s->pp_UseAlpha);
addConstant("pp_Texture", s->pp_Texture);
addConstant("pp_IgnoreTexA", s->pp_IgnoreTexA);
addConstant("pp_ShadInstr", s->pp_ShadInstr);
addConstant("pp_Offset", s->pp_Offset);
addConstant("pp_FogCtrl", s->pp_FogCtrl);
addConstant("pp_TwoVolumes", s->pp_TwoVolumes);
addConstant("pp_Gouraud", s->pp_Gouraud);
addConstant("pp_BumpMap", s->pp_BumpMap);
addConstant("FogClamping", s->fog_clamping);
addConstant("pp_Palette", s->palette);
addConstant("NOUVEAU", gl.mesa_nouveau);
addConstant("PASS", (int)s->pass);
addSource(ShaderHeader);
addSource(gl4PixelPipelineShader);
}
};
gl4_ctx gl4;
struct gl4ShaderUniforms_t gl4ShaderUniforms;
int max_image_width;
int max_image_height;
bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *pixel_source /* = PixelPipelineShader */, const char *vertex_source /* = NULL */)
bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *fragment_source /* = nullptr */, const char *vertex_source /* = nullptr */)
{
char vshader[16384];
Vertex4Source vertexSource(s->pp_Gouraud);
Fragment4ShaderSource fragmentSource(s);
sprintf(vshader, vertex_source == NULL ? VertexShaderSource : vertex_source, s->pp_Gouraud);
char pshader[16384];
sprintf(pshader, pixel_source,
s->cp_AlphaTest, s->pp_InsideClipping, s->pp_UseAlpha,
s->pp_Texture, s->pp_IgnoreTexA, s->pp_ShadInstr, s->pp_Offset, s->pp_FogCtrl,
s->pp_TwoVolumes, s->pp_Gouraud, s->pp_BumpMap, s->fog_clamping, s->palette,
gl.mesa_nouveau,
(int)s->pass);
s->program = gl_CompileAndLink(vshader, pshader);
s->program = gl_CompileAndLink(vertex_source != nullptr ? vertex_source : vertexSource.generate().c_str(),
fragment_source != nullptr ? fragment_source : fragmentSource.generate().c_str());
//setup texture 0 as the input for the shader
GLint gu = glGetUniformLocation(s->program, "tex0");
@ -524,11 +531,13 @@ static void create_modvol_shader()
{
if (gl4.modvol_shader.program != 0)
return;
char vshader[16384];
sprintf(vshader, VertexShaderSource, 1);
Vertex4Source vertexShader(true);
OpenGl4Source fragmentShader;
fragmentShader.addSource(ShaderHeader)
.addSource(ModifierVolumeShader);
gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader);
gl4.modvol_shader.normal_matrix = glGetUniformLocation(gl4.modvol_shader.program, "normal_matrix");
gl4.modvol_shader.program = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentShader.generate().c_str());
gl4.modvol_shader.normal_matrix = glGetUniformLocation(gl4.modvol_shader.program, "normal_matrix");
}
static bool gl_create_resources()

View File

@ -29,11 +29,7 @@
//Fragment and vertex shaders code
static const char* VertexShaderSource = "%s"
VTX_SHADER_COMPAT
R"(
#define pp_Gouraud %d
static const char* GouraudSource = R"(
#if TARGET_GL == GL3 || TARGET_GL == GLES3
#if pp_Gouraud == 0
#define INTERPOLATION flat
@ -43,7 +39,9 @@ R"(
#else
#define INTERPOLATION
#endif
)";
static const char* VertexShaderSource = R"(
/* Vertex constants*/
uniform highp vec4 depth_scale;
uniform highp mat4 normal_matrix;
@ -80,33 +78,7 @@ void main()
}
)";
const char* PixelPipelineShader = "%s"
PIX_SHADER_COMPAT
R"(
#define cp_AlphaTest %d
#define pp_ClipInside %d
#define pp_UseAlpha %d
#define pp_Texture %d
#define pp_IgnoreTexA %d
#define pp_ShadInstr %d
#define pp_Offset %d
#define pp_FogCtrl %d
#define pp_Gouraud %d
#define pp_BumpMap %d
#define FogClamping %d
#define pp_TriLinear %d
#define pp_Palette %d
#if TARGET_GL == GL3 || TARGET_GL == GLES3
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
#define INTERPOLATION smooth
#endif
#else
#define INTERPOLATION
#endif
const char* PixelPipelineShader = R"(
#define PI 3.1415926
/* Shader program params*/
@ -164,7 +136,7 @@ lowp vec4 palettePixel(highp vec2 coords)
highp vec2 c = vec2((mod(float(color_idx), 32.0) * 2.0 + 1.0) / 64.0, (float(color_idx / 32) * 2.0 + 1.0) / 64.0);
return texture(palette, c);
#else
highp ivec2 c = ivec2(color_idx %% 32, color_idx / 32);
highp ivec2 c = ivec2(color_idx % 32, color_idx / 32);
return texelFetch(palette, c, 0);
#endif
}
@ -267,10 +239,9 @@ void main()
}
)";
static const char* ModifierVolumeShader = "%s"
PIX_SHADER_COMPAT
R"(
static const char* ModifierVolumeShader = R"(
uniform lowp float sp_ShaderColor;
/* Vertex input*/
void main()
{
@ -282,9 +253,7 @@ void main()
}
)";
const char* OSD_VertexShader = "%s"
VTX_SHADER_COMPAT
R"(
const char* OSD_VertexShader = R"(
uniform highp vec4 scale;
in highp vec4 in_pos;
@ -307,9 +276,7 @@ void main()
}
)";
const char* OSD_Shader = "%s"
PIX_SHADER_COMPAT
R"(
const char* OSD_Shader = R"(
in lowp vec4 vtx_base;
in mediump vec2 vtx_uv;
@ -632,23 +599,49 @@ PipelineShader *GetProgram(bool cp_AlphaTest, bool pp_InsideClipping,
return shader;
}
bool CompilePipelineShader( PipelineShader* s)
class VertexSource : public OpenGlSource
{
char vshader[8192];
public:
VertexSource(bool gouraud) : OpenGlSource() {
addConstant("pp_Gouraud", gouraud);
int rc = sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud);
verify(rc + 1 <= (int)sizeof(vshader));
addSource(VertexCompatShader);
addSource(GouraudSource);
addSource(VertexShaderSource);
}
};
char pshader[8192];
class FragmentShaderSource : public OpenGlSource
{
public:
FragmentShaderSource(const PipelineShader* s) : OpenGlSource()
{
addConstant("cp_AlphaTest", s->cp_AlphaTest);
addConstant("pp_ClipInside", s->pp_InsideClipping);
addConstant("pp_UseAlpha", s->pp_UseAlpha);
addConstant("pp_Texture", s->pp_Texture);
addConstant("pp_IgnoreTexA", s->pp_IgnoreTexA);
addConstant("pp_ShadInstr", s->pp_ShadInstr);
addConstant("pp_Offset", s->pp_Offset);
addConstant("pp_FogCtrl", s->pp_FogCtrl);
addConstant("pp_Gouraud", s->pp_Gouraud);
addConstant("pp_BumpMap", s->pp_BumpMap);
addConstant("FogClamping", s->fog_clamping);
addConstant("pp_TriLinear", s->trilinear);
addConstant("pp_Palette", s->palette);
rc = sprintf(pshader,PixelPipelineShader, gl.glsl_version_header, gl.gl_version,
s->cp_AlphaTest,s->pp_InsideClipping,s->pp_UseAlpha,
s->pp_Texture,s->pp_IgnoreTexA,s->pp_ShadInstr,s->pp_Offset,s->pp_FogCtrl, s->pp_Gouraud, s->pp_BumpMap,
s->fog_clamping, s->trilinear, s->palette);
verify(rc + 1 <= (int)sizeof(pshader));
addSource(PixelCompatShader);
addSource(GouraudSource);
addSource(PixelPipelineShader);
}
};
s->program=gl_CompileAndLink(vshader, pshader);
bool CompilePipelineShader(PipelineShader* s)
{
VertexSource vertexSource(s->pp_Gouraud);
FragmentShaderSource fragmentSource(s);
s->program = gl_CompileAndLink(vertexSource.generate().c_str(), fragmentSource.generate().c_str());
//setup texture 0 as the input for the shader
GLint gu = glGetUniformLocation(s->program, "tex");
@ -743,13 +736,14 @@ static void SetupOSDVBO()
void gl_load_osd_resources()
{
char vshader[8192];
char fshader[8192];
OpenGlSource vertexSource;
vertexSource.addSource(VertexCompatShader)
.addSource(OSD_VertexShader);
OpenGlSource fragmentSource;
fragmentSource.addSource(PixelCompatShader)
.addSource(OSD_Shader);
sprintf(vshader, OSD_VertexShader, gl.glsl_version_header, gl.gl_version);
sprintf(fshader, OSD_Shader, gl.glsl_version_header, gl.gl_version);
gl.OSD_SHADER.program = gl_CompileAndLink(vshader, fshader);
gl.OSD_SHADER.program = gl_CompileAndLink(vertexSource.generate().c_str(), fragmentSource.generate().c_str());
gl.OSD_SHADER.scale = glGetUniformLocation(gl.OSD_SHADER.program, "scale");
glUniform1i(glGetUniformLocation(gl.OSD_SHADER.program, "tex"), 0); //bind osd texture to slot 0
@ -794,12 +788,13 @@ static void create_modvol_shader()
{
if (gl.modvol_shader.program != 0)
return;
char vshader[8192];
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1);
char fshader[8192];
sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version);
VertexSource vertexShader(true);
gl.modvol_shader.program = gl_CompileAndLink(vshader, fshader);
OpenGlSource fragmentShader;
fragmentShader.addSource(PixelCompatShader)
.addSource(ModifierVolumeShader);
gl.modvol_shader.program = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentShader.generate().c_str());
gl.modvol_shader.normal_matrix = glGetUniformLocation(gl.modvol_shader.program, "normal_matrix");
gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor");
gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale");

View File

@ -5,6 +5,7 @@
#include "wsi/gl_context.h"
#include "glcache.h"
#include "postprocess.h"
#include "rend/shader_util.h"
#include <unordered_map>
#include <glm/glm.hpp>
@ -297,46 +298,53 @@ void initQuad();
void termQuad();
void drawQuad(GLuint texId, bool rotate = false, bool swapY = false);
#define SHADER_COMPAT " \n\
#define TARGET_GL %s \n\
\n\
#define GLES2 0 \n\
#define GLES3 1 \n\
#define GL2 2 \n\
#define GL3 3 \n\
\n\
#if TARGET_GL == GL2 \n\
#define highp \n\
#define lowp \n\
#define mediump \n\
#endif \n\
#if TARGET_GL == GLES3 \n\
out highp vec4 FragColor; \n\
#define gl_FragColor FragColor \n\
#define FOG_CHANNEL a \n\
#elif TARGET_GL == GL3 \n\
out highp vec4 FragColor; \n\
#define gl_FragColor FragColor \n\
#define FOG_CHANNEL r \n\
#else \n\
#define texture texture2D \n\
#define FOG_CHANNEL a \n\
#endif \n\
\n\
"
static const char* ShaderCompatSource = R"(
#define GLES2 0
#define GLES3 1
#define GL2 2
#define GL3 3
#if TARGET_GL == GL2
#define highp
#define lowp
#define mediump
#endif
#if TARGET_GL == GLES3
out highp vec4 FragColor;
#define gl_FragColor FragColor
#define FOG_CHANNEL a
#elif TARGET_GL == GL3
out highp vec4 FragColor;
#define gl_FragColor FragColor
#define FOG_CHANNEL r
#else
#define texture texture2D
#define FOG_CHANNEL a
#endif
)";
#define VTX_SHADER_COMPAT SHADER_COMPAT \
"#if TARGET_GL == GLES2 || TARGET_GL == GL2 \n\
#define in attribute \n\
#define out varying \n\
#endif \n\
"
static const char *VertexCompatShader = R"(
#if TARGET_GL == GLES2 || TARGET_GL == GL2
#define in attribute
#define out varying
#endif
)";
static const char *PixelCompatShader = R"(
#if TARGET_GL == GLES2 || TARGET_GL == GL2
#define in varying
#endif
)";
class OpenGlSource : public ShaderSource
{
public:
OpenGlSource() : ShaderSource(gl.glsl_version_header) {
addConstant("TARGET_GL", gl.gl_version);
addSource(ShaderCompatSource);
}
};
#define PIX_SHADER_COMPAT SHADER_COMPAT \
"#if TARGET_GL == GLES2 || TARGET_GL == GL2 \n\
#define in varying \n\
#endif \n\
"
#ifdef LIBRETRO
extern "C" struct retro_hw_render_callback hw_render;
void termVmuLightgun();

View File

@ -23,21 +23,8 @@
PostProcessor postProcessor;
static const char* VertexShaderSource = R"(%s
#define TARGET_GL %s
#define GLES2 0
#define GLES3 1
#define GL2 2
#define GL3 3
#if TARGET_GL == GL3 || TARGET_GL == GLES3
#define COMPAT_VARYING in
#else
#define COMPAT_VARYING attribute
#endif
COMPAT_VARYING vec3 in_pos;
static const char* VertexShaderSource = R"(
in vec3 in_pos;
void main()
{
@ -45,32 +32,11 @@ void main()
}
)";
static const char* FragmentShaderSource = R"(%s
#define TARGET_GL %s
#define DITHERING %d
#define INTERLACED %d
#define VGASIGNAL %d
static const char* FragmentShaderSource = R"(
#define LUMBOOST 0
#define GLES2 0
#define GLES3 1
#define GL2 2
#define GL3 3
#if TARGET_GL == GLES2 || TARGET_GL == GLES3
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
#if TARGET_GL == GL3 || TARGET_GL == GLES3
#define COMPAT_TEXTURE texture
out vec4 FragColor;
#else
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif
uniform int FrameCount;
@ -102,7 +68,7 @@ void main()
vec2 texcoord2 = vTexCoord;
texcoord2.x *= float(TextureSize.x);
texcoord2.y *= float(TextureSize.y);
vec4 color = COMPAT_TEXTURE(Source, texcoord);
vec4 color = texture(Source, texcoord);
float fc = mod(float(FrameCount), 2.0);
#if INTERLACED == 1
@ -117,7 +83,7 @@ void main()
for (bl=0;bl<taps;bl++)
{
texcoord4.y += tap;
ble.rgb += (COMPAT_TEXTURE(Source, texcoord4).rgb / float(taps+1));
ble.rgb += (texture(Source, texcoord4).rgb / float(taps+1));
}
color.rgb = (color.rgb / float(taps+1)) + ( ble.rgb );
#endif
@ -170,7 +136,7 @@ void main()
vec2 texcoord4 = vTexCoord;
texcoord4.x = texcoord4.x + (2.0/640.0);
texcoord4.y = texcoord4.y;
vec4 blur1 = COMPAT_TEXTURE(Source, texcoord4);
vec4 blur1 = texture(Source, texcoord4);
int bl;
vec4 ble;
for (bl=0;bl<taps;bl++)
@ -179,7 +145,7 @@ void main()
if (bl>=3)
e=0.35;
texcoord4.x -= (tap / 640);
ble.rgb += (COMPAT_TEXTURE(Source, texcoord4).rgb * e) / (taps/(bl+1));
ble.rgb += (texture(Source, texcoord4).rgb * e) / (taps/(bl+1));
}
color.rgb += ble.rgb * 0.015;
@ -217,13 +183,18 @@ public:
private:
void compile(bool dither, bool interlaced, bool vga)
{
char vshader[16384];
sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version);
OpenGlSource vertexShader;
vertexShader.addSource(VertexCompatShader)
.addSource(VertexShaderSource);
char pshader[16384];
sprintf(pshader, FragmentShaderSource, gl.glsl_version_header, gl.gl_version, (int)dither, (int)interlaced, (int)vga);
OpenGlSource fragmentShader;
fragmentShader.addConstant("DITHERING", dither)
.addConstant("INTERLACED", interlaced)
.addConstant("VGASIGNAL", vga)
.addSource(PixelCompatShader)
.addSource(FragmentShaderSource);
program = gl_CompileAndLink(vshader, pshader);
program = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentShader.generate().c_str());
//setup texture 0 as the input for the shader
GLint gu = glGetUniformLocation(program, "Texture");

View File

@ -18,11 +18,7 @@
*/
#include "gles.h"
static const char* VertexShader = "%s"
VTX_SHADER_COMPAT
R"(
#define ROTATE %d
static const char* VertexShader = R"(
in highp vec3 in_pos;
in mediump vec2 in_uv;
out mediump vec2 vtx_uv;
@ -38,9 +34,7 @@ void main()
}
)";
static const char* FragmentShader = "%s"
PIX_SHADER_COMPAT
R"(
static const char* FragmentShader = R"(
in mediump vec2 vtx_uv;
uniform sampler2D tex;
@ -82,24 +76,23 @@ void initQuad()
{
if (shader == 0)
{
size_t shaderLength = strlen(FragmentShader) * 2;
char *frag = new char[shaderLength];
snprintf(frag, shaderLength, FragmentShader, gl.glsl_version_header, gl.gl_version);
OpenGlSource fragmentShader;
fragmentShader.addSource(PixelCompatShader)
.addSource(FragmentShader);
OpenGlSource vertexShader;
vertexShader.addConstant("ROTATE", 0)
.addSource(VertexCompatShader)
.addSource(VertexShader);
shaderLength = strlen(VertexShader) * 2;
char *vtx = new char[shaderLength];
snprintf(vtx, shaderLength, VertexShader, gl.glsl_version_header, gl.gl_version, 0);
shader = gl_CompileAndLink(vtx, frag);
const std::string fragmentGlsl = fragmentShader.generate();
shader = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentGlsl.c_str());
GLint tex = glGetUniformLocation(shader, "tex");
glUniform1i(tex, 0); // texture 0
snprintf(vtx, shaderLength, VertexShader, gl.glsl_version_header, gl.gl_version, 1);
rot90shader = gl_CompileAndLink(vtx, frag);
vertexShader.setConstant("ROTATE", 1);
rot90shader = gl_CompileAndLink(vertexShader.generate().c_str(), fragmentGlsl.c_str());
tex = glGetUniformLocation(rot90shader, "tex");
glUniform1i(tex, 0); // texture 0
delete [] vtx;
delete [] frag;
}
#ifndef GLES2
if (quadVertexArray == 0 && gl.gl_major >= 3)

82
core/rend/shader_util.h Normal file
View File

@ -0,0 +1,82 @@
/*
Copyright 2021 flyinghead
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <vector>
class ShaderSource
{
public:
ShaderSource(const std::string& header = "") : header(header) {}
ShaderSource& setHeader(const std::string& source) {
header = source;
return *this;
}
ShaderSource& addSource(const std::string& source) {
segments.push_back(source);
return *this;
}
ShaderSource& addConstant(const std::string& name, const std::string& value = "0") {
constants.emplace_back(name, value);
return *this;
}
ShaderSource& addConstant(const std::string& name, int value) {
addConstant(name, std::to_string(value));
return *this;
}
ShaderSource& setConstant(const std::string& name, const std::string& value) {
for (Constant& c : constants)
if (c.name == name)
{
c.value = value;
return *this;
}
return addConstant(name, value);
}
ShaderSource& setConstant(const std::string& name, int value) {
setConstant(name, std::to_string(value));
return *this;
}
std::string generate()
{
std::string result(header + "\n");
for (const Constant& c : constants)
result += "#define " + c.name + " " + c.value + "\n";
for (const std::string& s : segments)
result += s + "\n";
return result;
}
private:
struct Constant
{
Constant(const std::string& name, const std::string& defaultValue = "0") : name(name), value(defaultValue) {}
const std::string name;
std::string value;
};
std::string header;
std::vector<std::string> segments;
std::vector<Constant> constants;
};

View File

@ -22,16 +22,7 @@
#include "../compiler.h"
#include "rend/gl4/glsl.h"
static const char OITVertexShaderSource[] = R"(#version 450
#define pp_Gouraud %d
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
#define INTERPOLATION smooth
#endif
static const char OITVertexShaderSource[] = R"(
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
{
mat4 normal_matrix;
@ -68,8 +59,7 @@ void main()
}
)";
static const char OITShaderHeader[] = R"(#version 450
static const char OITShaderHeader[] = R"(
layout (std140, set = 0, binding = 1) uniform FragmentShaderUniforms
{
vec4 colorClampMin;
@ -111,20 +101,6 @@ layout (set = 0, binding = 3, std430) readonly buffer TrPolyParamBuffer {
)";
static const char OITFragmentShaderSource[] = R"(
#define cp_AlphaTest %d
#define pp_ClipInside %d
#define pp_UseAlpha %d
#define pp_Texture %d
#define pp_IgnoreTexA %d
#define pp_ShadInstr %d
#define pp_Offset %d
#define pp_FogCtrl %d
#define pp_TwoVolumes %d
#define pp_Gouraud %d
#define pp_BumpMap %d
#define ColorClamping %d
#define pp_Palette %d
#define PASS %d
#define PI 3.1415926
#define PASS_DEPTH 0
@ -142,12 +118,6 @@ layout (location = 0) out vec4 FragColor;
#define IF(x)
#endif
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
#define INTERPOLATION smooth
#endif
layout (push_constant) uniform pushBlock
{
vec4 clipTest;
@ -444,18 +414,15 @@ void main()
)";
static const char OITModifierVolumeShader[] = R"(
void main()
{
setFragDepth();
}
)";
#define MAX_PIXELS_PER_FRAGMENT "32"
constexpr int MAX_PIXELS_PER_FRAGMENT = 32;
static const char OITFinalShaderSource[] =
"#define MAX_PIXELS_PER_FRAGMENT " MAX_PIXELS_PER_FRAGMENT
R"(
static const char OITFinalShaderSource[] = R"(
layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput tex;
layout (location = 0) out vec4 FragColor;
@ -609,11 +576,7 @@ void main(void)
}
)";
static const char OITTranslucentModvolShaderSource[] =
"#define MAX_PIXELS_PER_FRAGMENT " MAX_PIXELS_PER_FRAGMENT
R"(
#define MV_MODE %d
static const char OITTranslucentModvolShaderSource[] = R"(
// Must match ModifierVolumeMode enum values
#define MV_XOR 0
#define MV_OR 1
@ -657,8 +620,7 @@ void main()
}
)";
static const char OITFinalVertexShaderSource[] = R"(#version 430
static const char OITFinalVertexShaderSource[] = R"(
layout (location = 0) in vec3 in_pos;
void main()
@ -671,57 +633,75 @@ extern const char ModVolVertexShaderSource[];
vk::UniqueShaderModule OITShaderManager::compileShader(const VertexShaderParams& params)
{
char buf[sizeof(OITVertexShaderSource) * 2];
sprintf(buf, OITVertexShaderSource, (int)params.gouraud);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, buf);
VulkanSource src;
src.addConstant("pp_Gouraud", (int)params.gouraud)
.addSource(GouraudSource)
.addSource(OITVertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, src.generate());
}
vk::UniqueShaderModule OITShaderManager::compileShader(const FragmentShaderParams& params)
{
char buf[(sizeof(OITShaderHeader) + sizeof(OITFragmentShaderSource)) * 2];
strcpy(buf, OITShaderHeader);
sprintf(buf + strlen(buf), OITFragmentShaderSource, (int)params.alphaTest, (int)params.insideClipTest, (int)params.useAlpha,
(int)params.texture, (int)params.ignoreTexAlpha, params.shaderInstr, (int)params.offset, params.fog,
(int)params.twoVolume, (int)params.gouraud, (int)params.bumpmap, (int)params.clamping, (int)params.palette,
(int)params.pass);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, buf);
VulkanSource src;
src.addConstant("cp_AlphaTest", (int)params.alphaTest)
.addConstant("pp_ClipInside", (int)params.insideClipTest)
.addConstant("pp_UseAlpha", (int)params.useAlpha)
.addConstant("pp_Texture", (int)params.texture)
.addConstant("pp_IgnoreTexA", (int)params.ignoreTexAlpha)
.addConstant("pp_ShadInstr", params.shaderInstr)
.addConstant("pp_Offset", (int)params.offset)
.addConstant("pp_FogCtrl", params.fog)
.addConstant("pp_TwoVolumes", (int)params.twoVolume)
.addConstant("pp_Gouraud", (int)params.gouraud)
.addConstant("pp_BumpMap", (int)params.bumpmap)
.addConstant("ColorClamping", (int)params.clamping)
.addConstant("pp_Palette", (int)params.palette)
.addConstant("PASS", (int)params.pass)
.addSource(GouraudSource)
.addSource(OITShaderHeader)
.addSource(OITFragmentShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
}
vk::UniqueShaderModule OITShaderManager::compileFinalShader()
{
std::string source = OITShaderHeader;
source += OITFinalShaderSource;
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, source);
VulkanSource src;
src.addConstant("MAX_PIXELS_PER_FRAGMENT", MAX_PIXELS_PER_FRAGMENT)
.addSource(OITShaderHeader)
.addSource(OITFinalShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
}
vk::UniqueShaderModule OITShaderManager::compileFinalVertexShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, OITFinalVertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(OITFinalVertexShaderSource).generate());
}
vk::UniqueShaderModule OITShaderManager::compileClearShader()
{
std::string source = OITShaderHeader;
source += OITClearShaderSource;
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, source);
VulkanSource src;
src.addSource(OITShaderHeader)
.addSource(OITClearShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
}
vk::UniqueShaderModule OITShaderManager::compileModVolVertexShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, ModVolVertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(ModVolVertexShaderSource).generate());
}
vk::UniqueShaderModule OITShaderManager::compileModVolFragmentShader()
{
std::string source = OITShaderHeader;
source += OITModifierVolumeShader;
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, source);
VulkanSource src;
src.addSource(OITShaderHeader)
.addSource(OITModifierVolumeShader);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
}
void OITShaderManager::compileTrModVolFragmentShader(ModVolMode mode)
{
if (trModVolShaders.empty())
trModVolShaders.resize((size_t)ModVolMode::Final);
char buf[(sizeof(OITShaderHeader) + sizeof(OITTranslucentModvolShaderSource)) * 2];
strcpy(buf, OITShaderHeader);
sprintf(buf + strlen(buf), OITTranslucentModvolShaderSource, (int)mode);
trModVolShaders[(size_t)mode] = ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, buf);
VulkanSource src;
src.addConstant("MAX_PIXELS_PER_FRAGMENT", MAX_PIXELS_PER_FRAGMENT)
.addConstant("MV_MODE", (int)mode)
.addSource(OITShaderHeader)
.addSource(OITTranslucentModvolShaderSource);
trModVolShaders[(size_t)mode] = ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
}

View File

@ -21,17 +21,9 @@
#include "vulkan.h"
#include "shaders.h"
#include "compiler.h"
#include "utils.h"
static const char VertexShaderSource[] = R"(#version 450
#define pp_Gouraud %d
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
#define INTERPOLATION smooth
#endif
static const char VertexShaderSource[] = R"(
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
{
mat4 normal_matrix;
@ -59,32 +51,12 @@ void main()
}
)";
static const char FragmentShaderSource[] = R"(#version 450
#define cp_AlphaTest %d
#define pp_ClipInside %d
#define pp_UseAlpha %d
#define pp_Texture %d
#define pp_IgnoreTexA %d
#define pp_ShadInstr %d
#define pp_Offset %d
#define pp_FogCtrl %d
#define pp_Gouraud %d
#define pp_BumpMap %d
#define ColorClamping %d
#define pp_TriLinear %d
#define pp_Palette %d
static const char FragmentShaderSource[] = R"(
#define PI 3.1415926
layout (location = 0) out vec4 FragColor;
#define gl_FragColor FragColor
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
#define INTERPOLATION smooth
#endif
layout (std140, set = 0, binding = 1) uniform FragmentShaderUniforms
{
vec4 colorClampMin;
@ -243,8 +215,7 @@ void main()
}
)";
extern const char ModVolVertexShaderSource[] = R"(#version 450
extern const char ModVolVertexShaderSource[] = R"(
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
{
mat4 normal_matrix;
@ -269,8 +240,7 @@ void main()
}
)";
static const char ModVolFragmentShaderSource[] = R"(#version 450
static const char ModVolFragmentShaderSource[] = R"(
layout (location = 0) out vec4 FragColor;
layout (push_constant) uniform pushBlock
@ -286,10 +256,7 @@ void main()
}
)";
static const char QuadVertexShaderSource[] = R"(#version 450
#define ROTATE %d
static const char QuadVertexShaderSource[] = R"(
layout (location = 0) in vec3 in_pos;
layout (location = 1) in vec2 in_uv;
@ -306,8 +273,7 @@ void main()
}
)";
static const char QuadFragmentShaderSource[] = R"(#version 450
static const char QuadFragmentShaderSource[] = R"(
layout (set = 0, binding = 0) uniform sampler2D tex;
layout (push_constant) uniform pushBlock
@ -324,8 +290,7 @@ void main()
}
)";
static const char OSDVertexShaderSource[] = R"(#version 450
static const char OSDVertexShaderSource[] = R"(
layout (location = 0) in vec4 inPos;
layout (location = 1) in uvec4 inColor;
layout (location = 2) in vec2 inUV;
@ -340,8 +305,7 @@ void main()
}
)";
static const char OSDFragmentShaderSource[] = R"(#version 450
static const char OSDFragmentShaderSource[] = R"(
layout (binding = 0) uniform sampler2D tex;
layout (location = 0) in lowp vec4 inColor;
layout (location = 1) in mediump vec2 inUV;
@ -355,51 +319,63 @@ void main()
vk::UniqueShaderModule ShaderManager::compileShader(const VertexShaderParams& params)
{
char buf[sizeof(VertexShaderSource) * 2];
sprintf(buf, VertexShaderSource, (int)params.gouraud);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, buf);
VulkanSource src;
src.addConstant("pp_Gouraud", (int)params.gouraud)
.addSource(GouraudSource)
.addSource(VertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, src.generate());
}
vk::UniqueShaderModule ShaderManager::compileShader(const FragmentShaderParams& params)
{
char buf[sizeof(FragmentShaderSource) * 2];
sprintf(buf, FragmentShaderSource, (int)params.alphaTest, (int)params.insideClipTest, (int)params.useAlpha, (int)params.texture,
(int)params.ignoreTexAlpha, params.shaderInstr, (int)params.offset, params.fog, (int)params.gouraud,
(int)params.bumpmap, (int)params.clamping, (int)params.trilinear, (int)params.palette);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, buf);
VulkanSource src;
src.addConstant("cp_AlphaTest", (int)params.alphaTest)
.addConstant("pp_ClipInside", (int)params.insideClipTest)
.addConstant("pp_UseAlpha", (int)params.useAlpha)
.addConstant("pp_Texture", (int)params.texture)
.addConstant("pp_IgnoreTexA", (int)params.ignoreTexAlpha)
.addConstant("pp_ShadInstr", params.shaderInstr)
.addConstant("pp_Offset", (int)params.offset)
.addConstant("pp_FogCtrl", params.fog)
.addConstant("pp_Gouraud", (int)params.gouraud)
.addConstant("pp_BumpMap", (int)params.bumpmap)
.addConstant("ColorClamping", (int)params.clamping)
.addConstant("pp_TriLinear", (int)params.trilinear)
.addConstant("pp_Palette", (int)params.palette)
.addSource(GouraudSource)
.addSource(FragmentShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
}
vk::UniqueShaderModule ShaderManager::compileModVolVertexShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, ModVolVertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(ModVolVertexShaderSource).generate());
}
vk::UniqueShaderModule ShaderManager::compileModVolFragmentShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, ModVolFragmentShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, VulkanSource().addSource(ModVolFragmentShaderSource).generate());
}
vk::UniqueShaderModule ShaderManager::compileQuadVertexShader(bool rotate)
{
char buf[sizeof(QuadVertexShaderSource) * 2];
sprintf(buf, QuadVertexShaderSource, (int)rotate);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, buf);
VulkanSource src;
src.addConstant("ROTATE", (int)rotate)
.addSource(QuadVertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, src.generate());
}
vk::UniqueShaderModule ShaderManager::compileQuadFragmentShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, QuadFragmentShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, VulkanSource().addSource(QuadFragmentShaderSource).generate());
}
vk::UniqueShaderModule ShaderManager::compileOSDVertexShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, OSDVertexShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(OSDVertexShaderSource).generate());
}
vk::UniqueShaderModule ShaderManager::compileOSDFragmentShader()
{
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, OSDFragmentShaderSource);
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, VulkanSource().addSource(OSDFragmentShaderSource).generate());
}

View File

@ -20,6 +20,7 @@
*/
#pragma once
#include "vulkan.h"
#include "rend/shader_util.h"
enum class ModVolMode { Xor, Or, Inclusion, Exclusion, Final };
@ -75,3 +76,17 @@ static inline u32 findMemoryType(vk::PhysicalDeviceMemoryProperties const& memor
verify(typeIndex != u32(~0));
return typeIndex;
}
static const char GouraudSource[] = R"(
#if pp_Gouraud == 0
#define INTERPOLATION flat
#else
#define INTERPOLATION smooth
#endif
)";
class VulkanSource : public ShaderSource
{
public:
VulkanSource() : ShaderSource("#version 450") {}
};