mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-15 07:50:07 +00:00
gl_shader_gen: accept an option to generate separable shaders
This commit is contained in:
parent
bdab18d2d9
commit
36bc92273b
@ -61,6 +61,37 @@ layout (std140) uniform shader_data {
|
||||
};
|
||||
)";
|
||||
|
||||
static std::string GetVertexInterfaceDeclaration(bool is_output, bool separable_shader) {
|
||||
std::string out;
|
||||
|
||||
auto append_variable = [&](const char* var, int location) {
|
||||
if (separable_shader) {
|
||||
out += "layout (location=" + std::to_string(location) + ") ";
|
||||
}
|
||||
out += std::string(is_output ? "out " : "in ") + var + ";\n";
|
||||
};
|
||||
|
||||
append_variable("vec4 primary_color", ATTRIBUTE_COLOR);
|
||||
append_variable("vec2 texcoord0", ATTRIBUTE_TEXCOORD0);
|
||||
append_variable("vec2 texcoord1", ATTRIBUTE_TEXCOORD1);
|
||||
append_variable("vec2 texcoord2", ATTRIBUTE_TEXCOORD2);
|
||||
append_variable("float texcoord0_w", ATTRIBUTE_TEXCOORD0_W);
|
||||
append_variable("vec4 normquat", ATTRIBUTE_NORMQUAT);
|
||||
append_variable("vec3 view", ATTRIBUTE_VIEW);
|
||||
|
||||
if (is_output && separable_shader) {
|
||||
// gl_PerVertex redeclaration is required for separate shader object
|
||||
out += R"(
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
float gl_ClipDistance[2];
|
||||
};
|
||||
)";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) {
|
||||
PicaShaderConfig res;
|
||||
|
||||
@ -206,11 +237,11 @@ static std::string SampleTexture(const PicaShaderConfig& config, unsigned textur
|
||||
// Only unit 0 respects the texturing type
|
||||
switch (state.texture0_type) {
|
||||
case TexturingRegs::TextureConfig::Texture2D:
|
||||
return "texture(tex[0], texcoord[0])";
|
||||
return "texture(tex0, texcoord0)";
|
||||
case TexturingRegs::TextureConfig::Projection2D:
|
||||
return "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))";
|
||||
return "textureProj(tex0, vec3(texcoord0, texcoord0_w))";
|
||||
case TexturingRegs::TextureConfig::TextureCube:
|
||||
return "texture(tex_cube, vec3(texcoord[0], texcoord0_w))";
|
||||
return "texture(tex_cube, vec3(texcoord0, texcoord0_w))";
|
||||
case TexturingRegs::TextureConfig::Shadow2D:
|
||||
case TexturingRegs::TextureConfig::ShadowCube:
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled shadow texture");
|
||||
@ -220,15 +251,15 @@ static std::string SampleTexture(const PicaShaderConfig& config, unsigned textur
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled texture type %x",
|
||||
static_cast<int>(state.texture0_type));
|
||||
UNIMPLEMENTED();
|
||||
return "texture(tex[0], texcoord[0])";
|
||||
return "texture(tex0, texcoord0)";
|
||||
}
|
||||
case 1:
|
||||
return "texture(tex[1], texcoord[1])";
|
||||
return "texture(tex1, texcoord1)";
|
||||
case 2:
|
||||
if (state.texture2_use_coord1)
|
||||
return "texture(tex[2], texcoord[1])";
|
||||
return "texture(tex2, texcoord1)";
|
||||
else
|
||||
return "texture(tex[2], texcoord[2])";
|
||||
return "texture(tex2, texcoord2)";
|
||||
case 3:
|
||||
if (state.proctex.enable) {
|
||||
return "ProcTex()";
|
||||
@ -1019,7 +1050,12 @@ float ProcTexNoiseCoef(vec2 x) {
|
||||
}
|
||||
|
||||
out += "vec4 ProcTex() {\n";
|
||||
out += "vec2 uv = abs(texcoord[" + std::to_string(config.state.proctex.coord) + "]);\n";
|
||||
if (config.state.proctex.coord < 3) {
|
||||
out += "vec2 uv = abs(texcoord" + std::to_string(config.state.proctex.coord) + ");\n";
|
||||
} else {
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unexpected proctex.coord >= 3");
|
||||
out += "vec2 uv = abs(texcoord0);\n";
|
||||
}
|
||||
|
||||
// Get shift offset before noise generation
|
||||
out += "float u_shift = ";
|
||||
@ -1084,23 +1120,24 @@ float ProcTexNoiseCoef(vec2 x) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenerateFragmentShader(const PicaShaderConfig& config) {
|
||||
std::string GenerateFragmentShader(const PicaShaderConfig& config, bool separable_shader) {
|
||||
const auto& state = config.state;
|
||||
|
||||
std::string out = R"(
|
||||
#version 330 core
|
||||
std::string out = "#version 330 core\n";
|
||||
if (separable_shader) {
|
||||
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
||||
}
|
||||
|
||||
in vec4 primary_color;
|
||||
in vec2 texcoord[3];
|
||||
in float texcoord0_w;
|
||||
in vec4 normquat;
|
||||
in vec3 view;
|
||||
out += GetVertexInterfaceDeclaration(false, separable_shader);
|
||||
|
||||
out += R"(
|
||||
in vec4 gl_FragCoord;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D tex[3];
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
uniform samplerCube tex_cube;
|
||||
uniform samplerBuffer lighting_lut;
|
||||
uniform samplerBuffer fog_lut;
|
||||
@ -1228,8 +1265,11 @@ vec4 secondary_fragment_color = vec4(0.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string GenerateVertexShader() {
|
||||
std::string GenerateTrivialVertexShader(bool separable_shader) {
|
||||
std::string out = "#version 330 core\n";
|
||||
if (separable_shader) {
|
||||
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
||||
}
|
||||
|
||||
out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION) +
|
||||
") in vec4 vert_position;\n";
|
||||
@ -1246,14 +1286,7 @@ std::string GenerateVertexShader() {
|
||||
") in vec4 vert_normquat;\n";
|
||||
out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW) + ") in vec3 vert_view;\n";
|
||||
|
||||
out += R"(
|
||||
out vec4 primary_color;
|
||||
out vec2 texcoord[3];
|
||||
out float texcoord0_w;
|
||||
out vec4 normquat;
|
||||
out vec3 view;
|
||||
|
||||
)";
|
||||
out += GetVertexInterfaceDeclaration(true, separable_shader);
|
||||
|
||||
out += UniformBlockDef;
|
||||
|
||||
@ -1261,9 +1294,9 @@ out vec3 view;
|
||||
|
||||
void main() {
|
||||
primary_color = vert_color;
|
||||
texcoord[0] = vert_texcoord0;
|
||||
texcoord[1] = vert_texcoord1;
|
||||
texcoord[2] = vert_texcoord2;
|
||||
texcoord0 = vert_texcoord0;
|
||||
texcoord1 = vert_texcoord1;
|
||||
texcoord2 = vert_texcoord2;
|
||||
texcoord0_w = vert_texcoord0_w;
|
||||
normquat = vert_normquat;
|
||||
view = vert_view;
|
||||
|
@ -9,7 +9,9 @@
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include "common/hash.h"
|
||||
#include "video_core/regs.h"
|
||||
#include "video_core/shader/shader.h"
|
||||
|
||||
namespace GLShader {
|
||||
|
||||
@ -132,18 +134,21 @@ struct PicaShaderConfig : Common::HashableStruct<PicaShaderConfigState> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates the GLSL vertex shader program source code for the current Pica state
|
||||
* Generates the GLSL vertex shader program source code that accepts vertices from software shader
|
||||
* and directly passes them to the fragment shader.
|
||||
* @param separable_shader generates shader that can be used for separate shader object
|
||||
* @returns String of the shader source code
|
||||
*/
|
||||
std::string GenerateVertexShader();
|
||||
std::string GenerateTrivialVertexShader(bool separable_shader);
|
||||
|
||||
/**
|
||||
* Generates the GLSL fragment shader program source code for the current Pica state
|
||||
* @param config ShaderCacheKey object generated for the current Pica state, used for the shader
|
||||
* configuration (NOTE: Use state in this struct only, not the Pica registers!)
|
||||
* @param separable_shader generates shader that can be used for separate shader object
|
||||
* @returns String of the shader source code
|
||||
*/
|
||||
std::string GenerateFragmentShader(const PicaShaderConfig& config);
|
||||
std::string GenerateFragmentShader(const PicaShaderConfig& config, bool separable_shader);
|
||||
|
||||
} // namespace GLShader
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user