|  |  |  | @@ -81,6 +81,21 @@ struct DrawParameters { | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer, | 
		
	
		
			
				|  |  |  |  |                                       const GLShader::ConstBufferEntry& entry) { | 
		
	
		
			
				|  |  |  |  |     if (!entry.IsIndirect()) { | 
		
	
		
			
				|  |  |  |  |         return entry.GetSize(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     if (buffer.size > Maxwell::MaxConstBufferSize) { | 
		
	
		
			
				|  |  |  |  |         LOG_WARNING(Render_OpenGL, "Indirect constbuffer size {} exceeds maximum {}", buffer.size, | 
		
	
		
			
				|  |  |  |  |                     Maxwell::MaxConstBufferSize); | 
		
	
		
			
				|  |  |  |  |         return Maxwell::MaxConstBufferSize; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     return buffer.size; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, | 
		
	
		
			
				|  |  |  |  |                                    ScreenInfo& info) | 
		
	
		
			
				|  |  |  |  |     : texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device}, | 
		
	
	
		
			
				
					
					|  |  |  | @@ -634,8 +649,8 @@ void RasterizerOpenGL::DrawArrays() { | 
		
	
		
			
				|  |  |  |  |                       Maxwell::MaxShaderStage; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // Add space for at least 18 constant buffers | 
		
	
		
			
				|  |  |  |  |     buffer_size += | 
		
	
		
			
				|  |  |  |  |         Maxwell::MaxConstBuffers * (MaxConstbufferSize + device.GetUniformBufferAlignment()); | 
		
	
		
			
				|  |  |  |  |     buffer_size += Maxwell::MaxConstBuffers * | 
		
	
		
			
				|  |  |  |  |                    (Maxwell::MaxConstBufferSize + device.GetUniformBufferAlignment()); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // Prepare the vertex array. | 
		
	
		
			
				|  |  |  |  |     buffer_cache.Map(buffer_size); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -762,11 +777,9 @@ void RasterizerOpenGL::SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::Sh | 
		
	
		
			
				|  |  |  |  |     MICROPROFILE_SCOPE(OpenGL_UBO); | 
		
	
		
			
				|  |  |  |  |     const auto stage_index = static_cast<std::size_t>(stage); | 
		
	
		
			
				|  |  |  |  |     const auto& shader_stage = system.GPU().Maxwell3D().state.shader_stages[stage_index]; | 
		
	
		
			
				|  |  |  |  |     const auto& entries = shader->GetShaderEntries().const_buffers; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // Upload only the enabled buffers from the 16 constbuffers of each shader stage | 
		
	
		
			
				|  |  |  |  |     for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | 
		
	
		
			
				|  |  |  |  |         const auto& entry = entries[bindpoint]; | 
		
	
		
			
				|  |  |  |  |     for (const auto& entry : shader->GetShaderEntries().const_buffers) { | 
		
	
		
			
				|  |  |  |  |         SetupConstBuffer(shader_stage.const_buffers[entry.GetIndex()], entry); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -779,25 +792,9 @@ void RasterizerOpenGL::SetupConstBuffer(const Tegra::Engines::ConstBufferInfo& b | 
		
	
		
			
				|  |  |  |  |         return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     std::size_t size; | 
		
	
		
			
				|  |  |  |  |     if (entry.IsIndirect()) { | 
		
	
		
			
				|  |  |  |  |         // Buffer is accessed indirectly, so upload the entire thing | 
		
	
		
			
				|  |  |  |  |         size = buffer.size; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         if (size > MaxConstbufferSize) { | 
		
	
		
			
				|  |  |  |  |             LOG_WARNING(Render_OpenGL, "Indirect constbuffer size {} exceeds maximum {}", size, | 
		
	
		
			
				|  |  |  |  |                         MaxConstbufferSize); | 
		
	
		
			
				|  |  |  |  |             size = MaxConstbufferSize; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |         // Buffer is accessed directly, upload just what we use | 
		
	
		
			
				|  |  |  |  |         size = entry.GetSize(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // Align the actual size so it ends up being a multiple of vec4 to meet the OpenGL std140 | 
		
	
		
			
				|  |  |  |  |     // UBO alignment requirements. | 
		
	
		
			
				|  |  |  |  |     size = Common::AlignUp(size, sizeof(GLvec4)); | 
		
	
		
			
				|  |  |  |  |     ASSERT_MSG(size <= MaxConstbufferSize, "Constant buffer is too big"); | 
		
	
		
			
				|  |  |  |  |     const std::size_t size = Common::AlignUp(GetConstBufferSize(buffer, entry), sizeof(GLvec4)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     const auto alignment = device.GetUniformBufferAlignment(); | 
		
	
		
			
				|  |  |  |  |     const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -811,10 +808,7 @@ void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::Shade | 
		
	
		
			
				|  |  |  |  |     const auto cbufs{gpu.Maxwell3D().state.shader_stages[static_cast<std::size_t>(stage)]}; | 
		
	
		
			
				|  |  |  |  |     const auto alignment{device.GetShaderStorageBufferAlignment()}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     const auto& entries = shader->GetShaderEntries().global_memory_entries; | 
		
	
		
			
				|  |  |  |  |     for (std::size_t bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | 
		
	
		
			
				|  |  |  |  |         const auto& entry{entries[bindpoint]}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     for (const auto& entry : shader->GetShaderEntries().global_memory_entries) { | 
		
	
		
			
				|  |  |  |  |         const auto addr{cbufs.const_buffers[entry.GetCbufIndex()].address + entry.GetCbufOffset()}; | 
		
	
		
			
				|  |  |  |  |         const auto actual_addr{memory_manager.Read<u64>(addr)}; | 
		
	
		
			
				|  |  |  |  |         const auto size{memory_manager.Read<u32>(addr + 8)}; | 
		
	
	
		
			
				
					
					|  |  |  |   |