mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	gl_shader_gen: accept an option to generate separable shaders
This commit is contained in:
		
							parent
							
								
									bdab18d2d9
								
							
						
					
					
						commit
						36bc92273b
					
				
					 2 changed files with 70 additions and 32 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue