mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	gl_rasterizer: only apply AMD hack when the vendor is AMD
This commit is contained in:
		
							parent
							
								
									05eb0ccb03
								
							
						
					
					
						commit
						266f2b6242
					
				
					 6 changed files with 34 additions and 18 deletions
				
			
		|  | @ -34,11 +34,17 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192)); | |||
| MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); | ||||
| MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); | ||||
| 
 | ||||
| static bool IsVendorAmd() { | ||||
|     std::string gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))}; | ||||
|     return gpu_vendor == "ATI Technologies Inc." || gpu_vendor == "Advanced Micro Devices, Inc."; | ||||
| } | ||||
| 
 | ||||
| RasterizerOpenGL::RasterizerOpenGL() | ||||
|     : shader_dirty(true), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE), | ||||
|       uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE), | ||||
|       index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE), | ||||
|       texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE) { | ||||
|     : is_amd(IsVendorAmd()), shader_dirty(true), | ||||
|       vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd), | ||||
|       uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false), | ||||
|       index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false), | ||||
|       texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) { | ||||
| 
 | ||||
|     allow_shadow = GLAD_GL_ARB_shader_image_load_store && GLAD_GL_ARB_shader_image_size && | ||||
|                    GLAD_GL_ARB_framebuffer_no_attachments; | ||||
|  | @ -145,7 +151,7 @@ RasterizerOpenGL::RasterizerOpenGL() | |||
|     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle()); | ||||
| 
 | ||||
|     shader_program_manager = | ||||
|         std::make_unique<ShaderProgramManager>(GLAD_GL_ARB_separate_shader_objects); | ||||
|         std::make_unique<ShaderProgramManager>(GLAD_GL_ARB_separate_shader_objects, is_amd); | ||||
| 
 | ||||
|     glEnable(GL_BLEND); | ||||
| 
 | ||||
|  |  | |||
|  | @ -243,6 +243,8 @@ private: | |||
|     /// Setup geometry shader for AccelerateDrawBatch
 | ||||
|     bool SetupGeometryShader(); | ||||
| 
 | ||||
|     bool is_amd; | ||||
| 
 | ||||
|     OpenGLState state; | ||||
| 
 | ||||
|     RasterizerCacheOpenGL res_cache; | ||||
|  |  | |||
|  | @ -216,8 +216,8 @@ using FragmentShaders = | |||
| 
 | ||||
| class ShaderProgramManager::Impl { | ||||
| public: | ||||
|     explicit Impl(bool separable) | ||||
|         : separable(separable), programmable_vertex_shaders(separable), | ||||
|     explicit Impl(bool separable, bool is_amd) | ||||
|         : is_amd(is_amd), separable(separable), programmable_vertex_shaders(separable), | ||||
|           trivial_vertex_shader(separable), programmable_geometry_shaders(separable), | ||||
|           fixed_geometry_shaders(separable), fragment_shaders(separable) { | ||||
|         if (separable) | ||||
|  | @ -248,6 +248,8 @@ public: | |||
|         }; | ||||
|     }; | ||||
| 
 | ||||
|     bool is_amd; | ||||
| 
 | ||||
|     ShaderTuple current; | ||||
| 
 | ||||
|     ProgrammableVertexShaders programmable_vertex_shaders; | ||||
|  | @ -263,8 +265,8 @@ public: | |||
|     OGLPipeline pipeline; | ||||
| }; | ||||
| 
 | ||||
| ShaderProgramManager::ShaderProgramManager(bool separable) | ||||
|     : impl(std::make_unique<Impl>(separable)) {} | ||||
| ShaderProgramManager::ShaderProgramManager(bool separable, bool is_amd) | ||||
|     : impl(std::make_unique<Impl>(separable, is_amd)) {} | ||||
| 
 | ||||
| ShaderProgramManager::~ShaderProgramManager() = default; | ||||
| 
 | ||||
|  | @ -304,11 +306,15 @@ void ShaderProgramManager::UseFragmentShader(const GLShader::PicaFSConfig& confi | |||
| 
 | ||||
| void ShaderProgramManager::ApplyTo(OpenGLState& state) { | ||||
|     if (impl->separable) { | ||||
|         // Without this reseting, AMD sometimes freezes when one stage is changed but not for the
 | ||||
|         // others
 | ||||
|         glUseProgramStages(impl->pipeline.handle, | ||||
|                            GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, | ||||
|                            0); | ||||
|         if (impl->is_amd) { | ||||
|             // Without this reseting, AMD sometimes freezes when one stage is changed but not for
 | ||||
|             // the others.
 | ||||
|             // On the other hand, including this reset seems to introduce memory leak in Intel
 | ||||
|             // Graphics.
 | ||||
|             glUseProgramStages( | ||||
|                 impl->pipeline.handle, | ||||
|                 GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0); | ||||
|         } | ||||
| 
 | ||||
|         glUseProgramStages(impl->pipeline.handle, GL_VERTEX_SHADER_BIT, impl->current.vs); | ||||
|         glUseProgramStages(impl->pipeline.handle, GL_GEOMETRY_SHADER_BIT, impl->current.gs); | ||||
|  |  | |||
|  | @ -99,7 +99,7 @@ static_assert(sizeof(GSUniformData) < 16384, | |||
| /// A class that manage different shader stages and configures them with given config data.
 | ||||
| class ShaderProgramManager { | ||||
| public: | ||||
|     explicit ShaderProgramManager(bool separable); | ||||
|     ShaderProgramManager(bool separable, bool is_amd); | ||||
|     ~ShaderProgramManager(); | ||||
| 
 | ||||
|     bool UseProgrammableVertexShader(const GLShader::PicaVSConfig& config, | ||||
|  |  | |||
|  | @ -9,13 +9,14 @@ | |||
| #include "video_core/renderer_opengl/gl_state.h" | ||||
| #include "video_core/renderer_opengl/gl_stream_buffer.h" | ||||
| 
 | ||||
| OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent) | ||||
| OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool array_buffer_for_amd, | ||||
|                                  bool prefer_coherent) | ||||
|     : gl_target(target), buffer_size(size) { | ||||
|     gl_buffer.Create(); | ||||
|     glBindBuffer(gl_target, gl_buffer.handle); | ||||
| 
 | ||||
|     GLsizeiptr allocate_size = size; | ||||
|     if (target == GL_ARRAY_BUFFER) { | ||||
|     if (array_buffer_for_amd) { | ||||
|         // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer
 | ||||
|         // read position is near the end and is an out-of-bound access to the vertex buffer. This is
 | ||||
|         // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the
 | ||||
|  |  | |||
|  | @ -9,7 +9,8 @@ | |||
| 
 | ||||
| class OGLStreamBuffer : private NonCopyable { | ||||
| public: | ||||
|     explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false); | ||||
|     explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool array_buffer_for_amd, | ||||
|                              bool prefer_coherent = false); | ||||
|     ~OGLStreamBuffer(); | ||||
| 
 | ||||
|     GLuint GetHandle() const; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue