mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	shaders: Expose hints about used const buffers.
This commit is contained in:
		
							parent
							
								
									bb0c3fc828
								
							
						
					
					
						commit
						73d9c494ea
					
				| @ -140,6 +140,11 @@ public: | |||||||
|         return declarations.GetResult() + shader.GetResult(); |         return declarations.GetResult() + shader.GetResult(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Returns entries in the shader that are useful for external functions
 | ||||||
|  |     ShaderEntries GetEntries() const { | ||||||
|  |         return {GetConstBuffersDeclarations()}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     /// Gets the Subroutine object corresponding to the specified address.
 |     /// Gets the Subroutine object corresponding to the specified address.
 | ||||||
|     const Subroutine& GetSubroutine(u32 begin, u32 end) const { |     const Subroutine& GetSubroutine(u32 begin, u32 end) const { | ||||||
| @ -186,10 +191,9 @@ private: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Generates code representing a uniform (C buffer) register.
 |     /// Generates code representing a uniform (C buffer) register.
 | ||||||
|     std::string GetUniform(const Uniform& reg) const { |     std::string GetUniform(const Uniform& reg) { | ||||||
|         std::string index = std::to_string(reg.index); |         declr_const_buffers[reg.index].MarkAsUsed(reg.index, reg.offset); | ||||||
|         return "uniform_" + index + "[" + std::to_string(reg.offset >> 2) + "][" + |         return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']'; | ||||||
|                std::to_string(reg.offset & 3) + "]"; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @ -439,6 +443,14 @@ private: | |||||||
|         GenerateDeclarations(); |         GenerateDeclarations(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Returns a list of constant buffer declarations
 | ||||||
|  |     std::vector<ConstBufferEntry> GetConstBuffersDeclarations() const { | ||||||
|  |         std::vector<ConstBufferEntry> result; | ||||||
|  |         std::copy_if(declr_const_buffers.begin(), declr_const_buffers.end(), | ||||||
|  |                      std::back_inserter(result), [](const auto& entry) { return entry.IsUsed(); }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Add declarations for registers
 |     /// Add declarations for registers
 | ||||||
|     void GenerateDeclarations() { |     void GenerateDeclarations() { | ||||||
|         for (const auto& reg : declr_register) { |         for (const auto& reg : declr_register) { | ||||||
| @ -463,6 +475,17 @@ private: | |||||||
|                                  ") out vec4 " + GetOutputAttribute(index) + ";"); |                                  ") out vec4 " + GetOutputAttribute(index) + ";"); | ||||||
|         } |         } | ||||||
|         declarations.AddLine(""); |         declarations.AddLine(""); | ||||||
|  | 
 | ||||||
|  |         unsigned const_buffer_layout = 0; | ||||||
|  |         for (const auto& entry : GetConstBuffersDeclarations()) { | ||||||
|  |             declarations.AddLine("layout(std430, binding = " + std::to_string(const_buffer_layout) + | ||||||
|  |                                  ") buffer c" + std::to_string(entry.GetIndex()) + "_buffer"); | ||||||
|  |             declarations.AddLine("{"); | ||||||
|  |             declarations.AddLine("    float c" + std::to_string(entry.GetIndex()) + "[];"); | ||||||
|  |             declarations.AddLine("};"); | ||||||
|  |             declarations.AddLine(""); | ||||||
|  |             ++const_buffer_layout; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -478,18 +501,19 @@ private: | |||||||
|     std::set<std::string> declr_register; |     std::set<std::string> declr_register; | ||||||
|     std::set<Attribute::Index> declr_input_attribute; |     std::set<Attribute::Index> declr_input_attribute; | ||||||
|     std::set<Attribute::Index> declr_output_attribute; |     std::set<Attribute::Index> declr_output_attribute; | ||||||
| }; // namespace Decompiler
 |     std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| std::string GetCommonDeclarations() { | std::string GetCommonDeclarations() { | ||||||
|     return "bool exec_shader();"; |     return "bool exec_shader();"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| boost::optional<std::string> DecompileProgram(const ProgramCode& program_code, u32 main_offset, | boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset, | ||||||
|                                               Maxwell3D::Regs::ShaderStage stage) { |                                                 Maxwell3D::Regs::ShaderStage stage) { | ||||||
|     try { |     try { | ||||||
|         auto subroutines = ControlFlowAnalyzer(program_code, main_offset).GetSubroutines(); |         auto subroutines = ControlFlowAnalyzer(program_code, main_offset).GetSubroutines(); | ||||||
|         GLSLGenerator generator(subroutines, program_code, main_offset, stage); |         GLSLGenerator generator(subroutines, program_code, main_offset, stage); | ||||||
|         return generator.GetShaderCode(); |         return ProgramResult{generator.GetShaderCode(), generator.GetEntries()}; | ||||||
|     } catch (const DecompileFail& exception) { |     } catch (const DecompileFail& exception) { | ||||||
|         LOG_ERROR(HW_GPU, "Shader decompilation failed: %s", exception.what()); |         LOG_ERROR(HW_GPU, "Shader decompilation failed: %s", exception.what()); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -17,8 +17,8 @@ using Tegra::Engines::Maxwell3D; | |||||||
| 
 | 
 | ||||||
| std::string GetCommonDeclarations(); | std::string GetCommonDeclarations(); | ||||||
| 
 | 
 | ||||||
| boost::optional<std::string> DecompileProgram(const ProgramCode& program_code, u32 main_offset, | boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset, | ||||||
|                                               Maxwell3D::Regs::ShaderStage stage); |                                                 Maxwell3D::Regs::ShaderStage stage); | ||||||
| 
 | 
 | ||||||
| } // namespace Decompiler
 | } // namespace Decompiler
 | ||||||
| } // namespace GLShader
 | } // namespace GLShader
 | ||||||
|  | |||||||
| @ -3,18 +3,60 @@ | |||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
|  | #include "video_core/engines/maxwell_3d.h" | ||||||
|  | #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_gen.h" | ||||||
| 
 | 
 | ||||||
| namespace GLShader { | namespace GLShader { | ||||||
| 
 | 
 | ||||||
| std::string GenerateVertexShader(const ShaderSetup& setup, const MaxwellVSConfig& config) { | using Tegra::Engines::Maxwell3D; | ||||||
|     UNREACHABLE(); | 
 | ||||||
|     return {}; | static constexpr u32 PROGRAM_OFFSET{10}; | ||||||
|  | 
 | ||||||
|  | ProgramResult GenerateVertexShader(const ShaderSetup& setup, const MaxwellVSConfig& config) { | ||||||
|  |     std::string out = "#version 430 core\n"; | ||||||
|  |     out += "#extension GL_ARB_separate_shader_objects : enable\n\n"; | ||||||
|  |     out += Decompiler::GetCommonDeclarations(); | ||||||
|  | 
 | ||||||
|  |     ProgramResult program = Decompiler::DecompileProgram(setup.program_code, PROGRAM_OFFSET, | ||||||
|  |                                                          Maxwell3D::Regs::ShaderStage::Vertex) | ||||||
|  |                                 .get_value_or({}); | ||||||
|  |     out += R"( | ||||||
|  | 
 | ||||||
|  | out gl_PerVertex { | ||||||
|  |     vec4 gl_Position; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     exec_shader(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config) { | )"; | ||||||
|     UNREACHABLE(); |     out += program.first; | ||||||
|     return {}; |     return {out, program.second}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config) { | ||||||
|  |     std::string out = "#version 430 core\n"; | ||||||
|  |     out += "#extension GL_ARB_separate_shader_objects : enable\n\n"; | ||||||
|  |     out += Decompiler::GetCommonDeclarations(); | ||||||
|  | 
 | ||||||
|  |     ProgramResult program = Decompiler::DecompileProgram(setup.program_code, PROGRAM_OFFSET, | ||||||
|  |                                                          Maxwell3D::Regs::ShaderStage::Fragment) | ||||||
|  |                                 .get_value_or({}); | ||||||
|  |     out += R"( | ||||||
|  | 
 | ||||||
|  | out vec4 color; | ||||||
|  | 
 | ||||||
|  | uniform sampler2D tex[32]; | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |     exec_shader(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | )"; | ||||||
|  |     out += program.first; | ||||||
|  |     return {out, program.second}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace GLShader
 | } // namespace GLShader
 | ||||||
|  | |||||||
| @ -7,6 +7,8 @@ | |||||||
| #include <array> | #include <array> | ||||||
| #include <string> | #include <string> | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
|  | #include <utility> | ||||||
|  | #include <vector> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/hash.h" | #include "common/hash.h" | ||||||
| 
 | 
 | ||||||
| @ -16,6 +18,38 @@ constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x1000}; | |||||||
| 
 | 
 | ||||||
| using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>; | using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>; | ||||||
| 
 | 
 | ||||||
|  | class ConstBufferEntry { | ||||||
|  | public: | ||||||
|  |     void MarkAsUsed(unsigned index, unsigned offset) { | ||||||
|  |         is_used = true; | ||||||
|  |         this->index = index; | ||||||
|  |         max_offset = std::max(max_offset, offset); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool IsUsed() const { | ||||||
|  |         return is_used; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     unsigned GetIndex() const { | ||||||
|  |         return index; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     unsigned GetSize() const { | ||||||
|  |         return max_offset + 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     bool is_used{}; | ||||||
|  |     unsigned index{}; | ||||||
|  |     unsigned max_offset{}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct ShaderEntries { | ||||||
|  |     std::vector<ConstBufferEntry> const_buffer_entries; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | using ProgramResult = std::pair<std::string, ShaderEntries>; | ||||||
|  | 
 | ||||||
| struct ShaderSetup { | struct ShaderSetup { | ||||||
|     ShaderSetup(ProgramCode&& program_code) : program_code(std::move(program_code)) {} |     ShaderSetup(ProgramCode&& program_code) : program_code(std::move(program_code)) {} | ||||||
| 
 | 
 | ||||||
| @ -58,13 +92,13 @@ struct MaxwellFSConfig : Common::HashableStruct<MaxwellShaderConfigCommon> { | |||||||
|  * Generates the GLSL vertex shader program source code for the given VS program |  * Generates the GLSL vertex shader program source code for the given VS program | ||||||
|  * @returns String of the shader source code |  * @returns String of the shader source code | ||||||
|  */ |  */ | ||||||
| std::string GenerateVertexShader(const ShaderSetup& setup, const MaxwellVSConfig& config); | ProgramResult GenerateVertexShader(const ShaderSetup& setup, const MaxwellVSConfig& config); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Generates the GLSL fragment shader program source code for the given FS program |  * Generates the GLSL fragment shader program source code for the given FS program | ||||||
|  * @returns String of the shader source code |  * @returns String of the shader source code | ||||||
|  */ |  */ | ||||||
| std::string GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config); | ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config); | ||||||
| 
 | 
 | ||||||
| } // namespace GLShader
 | } // namespace GLShader
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -41,19 +41,25 @@ class OGLShaderStage { | |||||||
| public: | public: | ||||||
|     OGLShaderStage() = default; |     OGLShaderStage() = default; | ||||||
| 
 | 
 | ||||||
|     void Create(const char* source, GLenum type) { |     void Create(const ProgramResult& program_result, GLenum type) { | ||||||
|         OGLShader shader; |         OGLShader shader; | ||||||
|         shader.Create(source, type); |         shader.Create(program_result.first.c_str(), type); | ||||||
|         program.Create(true, shader.handle); |         program.Create(true, shader.handle); | ||||||
|         Impl::SetShaderUniformBlockBindings(program.handle); |         Impl::SetShaderUniformBlockBindings(program.handle); | ||||||
|         Impl::SetShaderSamplerBindings(program.handle); |         Impl::SetShaderSamplerBindings(program.handle); | ||||||
|  |         entries = program_result.second; | ||||||
|     } |     } | ||||||
|     GLuint GetHandle() const { |     GLuint GetHandle() const { | ||||||
|         return program.handle; |         return program.handle; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     ShaderEntries GetEntries() const { | ||||||
|  |         return entries; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     OGLProgram program; |     OGLProgram program; | ||||||
|  |     ShaderEntries entries; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // TODO(wwylele): beautify this doc
 | // TODO(wwylele): beautify this doc
 | ||||||
| @ -61,25 +67,28 @@ private: | |||||||
| // The double cache is needed because diffent KeyConfigType, which includes a hash of the code
 | // The double cache is needed because diffent KeyConfigType, which includes a hash of the code
 | ||||||
| // region (including its leftover unused code) can generate the same GLSL code.
 | // region (including its leftover unused code) can generate the same GLSL code.
 | ||||||
| template <typename KeyConfigType, | template <typename KeyConfigType, | ||||||
|           std::string (*CodeGenerator)(const ShaderSetup&, const KeyConfigType&), GLenum ShaderType> |           ProgramResult (*CodeGenerator)(const ShaderSetup&, const KeyConfigType&), | ||||||
|  |           GLenum ShaderType> | ||||||
| class ShaderCache { | class ShaderCache { | ||||||
| public: | public: | ||||||
|     ShaderCache() = default; |     ShaderCache() = default; | ||||||
| 
 | 
 | ||||||
|     GLuint Get(const KeyConfigType& key, const ShaderSetup& setup) { |     using Result = std::pair<GLuint, ShaderEntries>; | ||||||
|  | 
 | ||||||
|  |     Result Get(const KeyConfigType& key, const ShaderSetup& setup) { | ||||||
|         auto map_it = shader_map.find(key); |         auto map_it = shader_map.find(key); | ||||||
|         if (map_it == shader_map.end()) { |         if (map_it == shader_map.end()) { | ||||||
|             std::string program = CodeGenerator(setup, key); |             ProgramResult program = CodeGenerator(setup, key); | ||||||
| 
 | 
 | ||||||
|             auto [iter, new_shader] = shader_cache.emplace(program, OGLShaderStage{}); |             auto [iter, new_shader] = shader_cache.emplace(program.first, OGLShaderStage{}); | ||||||
|             OGLShaderStage& cached_shader = iter->second; |             OGLShaderStage& cached_shader = iter->second; | ||||||
|             if (new_shader) { |             if (new_shader) { | ||||||
|                 cached_shader.Create(program.c_str(), ShaderType); |                 cached_shader.Create(program, ShaderType); | ||||||
|             } |             } | ||||||
|             shader_map[key] = &cached_shader; |             shader_map[key] = &cached_shader; | ||||||
|             return cached_shader.GetHandle(); |             return {cached_shader.GetHandle(), program.second}; | ||||||
|         } else { |         } else { | ||||||
|             return map_it->second->GetHandle(); |             return {map_it->second->GetHandle(), map_it->second->GetEntries()}; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -98,12 +107,18 @@ public: | |||||||
|         pipeline.Create(); |         pipeline.Create(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void UseProgrammableVertexShader(const MaxwellVSConfig& config, const ShaderSetup setup) { |     ShaderEntries UseProgrammableVertexShader(const MaxwellVSConfig& config, | ||||||
|         current.vs = vertex_shaders.Get(config, setup); |                                               const ShaderSetup setup) { | ||||||
|  |         ShaderEntries result; | ||||||
|  |         std::tie(current.vs, result) = vertex_shaders.Get(config, setup); | ||||||
|  |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void UseProgrammableFragmentShader(const MaxwellFSConfig& config, const ShaderSetup setup) { |     ShaderEntries UseProgrammableFragmentShader(const MaxwellFSConfig& config, | ||||||
|         current.fs = fragment_shaders.Get(config, setup); |                                                 const ShaderSetup setup) { | ||||||
|  |         ShaderEntries result; | ||||||
|  |         std::tie(current.fs, result) = fragment_shaders.Get(config, setup); | ||||||
|  |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void UseTrivialGeometryShader() { |     void UseTrivialGeometryShader() { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei