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 PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) {
|
||||||
PicaShaderConfig res;
|
PicaShaderConfig res;
|
||||||
|
|
||||||
|
@ -206,11 +237,11 @@ static std::string SampleTexture(const PicaShaderConfig& config, unsigned textur
|
||||||
// Only unit 0 respects the texturing type
|
// Only unit 0 respects the texturing type
|
||||||
switch (state.texture0_type) {
|
switch (state.texture0_type) {
|
||||||
case TexturingRegs::TextureConfig::Texture2D:
|
case TexturingRegs::TextureConfig::Texture2D:
|
||||||
return "texture(tex[0], texcoord[0])";
|
return "texture(tex0, texcoord0)";
|
||||||
case TexturingRegs::TextureConfig::Projection2D:
|
case TexturingRegs::TextureConfig::Projection2D:
|
||||||
return "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))";
|
return "textureProj(tex0, vec3(texcoord0, texcoord0_w))";
|
||||||
case TexturingRegs::TextureConfig::TextureCube:
|
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::Shadow2D:
|
||||||
case TexturingRegs::TextureConfig::ShadowCube:
|
case TexturingRegs::TextureConfig::ShadowCube:
|
||||||
NGLOG_CRITICAL(HW_GPU, "Unhandled shadow texture");
|
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",
|
LOG_CRITICAL(HW_GPU, "Unhandled texture type %x",
|
||||||
static_cast<int>(state.texture0_type));
|
static_cast<int>(state.texture0_type));
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
return "texture(tex[0], texcoord[0])";
|
return "texture(tex0, texcoord0)";
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
return "texture(tex[1], texcoord[1])";
|
return "texture(tex1, texcoord1)";
|
||||||
case 2:
|
case 2:
|
||||||
if (state.texture2_use_coord1)
|
if (state.texture2_use_coord1)
|
||||||
return "texture(tex[2], texcoord[1])";
|
return "texture(tex2, texcoord1)";
|
||||||
else
|
else
|
||||||
return "texture(tex[2], texcoord[2])";
|
return "texture(tex2, texcoord2)";
|
||||||
case 3:
|
case 3:
|
||||||
if (state.proctex.enable) {
|
if (state.proctex.enable) {
|
||||||
return "ProcTex()";
|
return "ProcTex()";
|
||||||
|
@ -1019,7 +1050,12 @@ float ProcTexNoiseCoef(vec2 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
out += "vec4 ProcTex() {\n";
|
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
|
// Get shift offset before noise generation
|
||||||
out += "float u_shift = ";
|
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;
|
const auto& state = config.state;
|
||||||
|
|
||||||
std::string out = R"(
|
std::string out = "#version 330 core\n";
|
||||||
#version 330 core
|
if (separable_shader) {
|
||||||
|
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
||||||
|
}
|
||||||
|
|
||||||
in vec4 primary_color;
|
out += GetVertexInterfaceDeclaration(false, separable_shader);
|
||||||
in vec2 texcoord[3];
|
|
||||||
in float texcoord0_w;
|
|
||||||
in vec4 normquat;
|
|
||||||
in vec3 view;
|
|
||||||
|
|
||||||
|
out += R"(
|
||||||
in vec4 gl_FragCoord;
|
in vec4 gl_FragCoord;
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
uniform sampler2D tex[3];
|
uniform sampler2D tex0;
|
||||||
|
uniform sampler2D tex1;
|
||||||
|
uniform sampler2D tex2;
|
||||||
uniform samplerCube tex_cube;
|
uniform samplerCube tex_cube;
|
||||||
uniform samplerBuffer lighting_lut;
|
uniform samplerBuffer lighting_lut;
|
||||||
uniform samplerBuffer fog_lut;
|
uniform samplerBuffer fog_lut;
|
||||||
|
@ -1228,8 +1265,11 @@ vec4 secondary_fragment_color = vec4(0.0);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateVertexShader() {
|
std::string GenerateTrivialVertexShader(bool separable_shader) {
|
||||||
std::string out = "#version 330 core\n";
|
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) +
|
out += "layout(location = " + std::to_string((int)ATTRIBUTE_POSITION) +
|
||||||
") in vec4 vert_position;\n";
|
") in vec4 vert_position;\n";
|
||||||
|
@ -1246,14 +1286,7 @@ std::string GenerateVertexShader() {
|
||||||
") in vec4 vert_normquat;\n";
|
") in vec4 vert_normquat;\n";
|
||||||
out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW) + ") in vec3 vert_view;\n";
|
out += "layout(location = " + std::to_string((int)ATTRIBUTE_VIEW) + ") in vec3 vert_view;\n";
|
||||||
|
|
||||||
out += R"(
|
out += GetVertexInterfaceDeclaration(true, separable_shader);
|
||||||
out vec4 primary_color;
|
|
||||||
out vec2 texcoord[3];
|
|
||||||
out float texcoord0_w;
|
|
||||||
out vec4 normquat;
|
|
||||||
out vec3 view;
|
|
||||||
|
|
||||||
)";
|
|
||||||
|
|
||||||
out += UniformBlockDef;
|
out += UniformBlockDef;
|
||||||
|
|
||||||
|
@ -1261,9 +1294,9 @@ out vec3 view;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
primary_color = vert_color;
|
primary_color = vert_color;
|
||||||
texcoord[0] = vert_texcoord0;
|
texcoord0 = vert_texcoord0;
|
||||||
texcoord[1] = vert_texcoord1;
|
texcoord1 = vert_texcoord1;
|
||||||
texcoord[2] = vert_texcoord2;
|
texcoord2 = vert_texcoord2;
|
||||||
texcoord0_w = vert_texcoord0_w;
|
texcoord0_w = vert_texcoord0_w;
|
||||||
normquat = vert_normquat;
|
normquat = vert_normquat;
|
||||||
view = vert_view;
|
view = vert_view;
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include "common/hash.h"
|
||||||
#include "video_core/regs.h"
|
#include "video_core/regs.h"
|
||||||
|
#include "video_core/shader/shader.h"
|
||||||
|
|
||||||
namespace GLShader {
|
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
|
* @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
|
* 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
|
* @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!)
|
* 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
|
* @returns String of the shader source code
|
||||||
*/
|
*/
|
||||||
std::string GenerateFragmentShader(const PicaShaderConfig& config);
|
std::string GenerateFragmentShader(const PicaShaderConfig& config, bool separable_shader);
|
||||||
|
|
||||||
} // namespace GLShader
|
} // namespace GLShader
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue