mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 23:06:43 +08:00 
			
		
		
		
	Merge pull request #1827 from ReinUsesLisp/clip-and-shader
gl_rasterizer: Enable clip distances when set in register and in shader
This commit is contained in:
		
						commit
						7ce17b2cf6
					
				| @ -42,6 +42,7 @@ public: | ||||
|         static constexpr std::size_t NumVertexArrays = 32; | ||||
|         static constexpr std::size_t NumVertexAttributes = 32; | ||||
|         static constexpr std::size_t NumTextureSamplers = 32; | ||||
|         static constexpr std::size_t NumClipDistances = 8; | ||||
|         static constexpr std::size_t MaxShaderProgram = 6; | ||||
|         static constexpr std::size_t MaxShaderStage = 5; | ||||
|         // Maximum number of const buffers per shader stage.
 | ||||
|  | ||||
| @ -282,6 +282,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | ||||
|     // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
 | ||||
|     u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; | ||||
|     u32 current_texture_bindpoint = 0; | ||||
|     std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | ||||
| 
 | ||||
|     for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | ||||
|         const auto& shader_config = gpu.regs.shader_config[index]; | ||||
| @ -342,12 +343,22 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | ||||
|         current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader, | ||||
|                                                   primitive_mode, current_texture_bindpoint); | ||||
| 
 | ||||
|         // Workaround for Intel drivers.
 | ||||
|         // When a clip distance is enabled but not set in the shader it crops parts of the screen
 | ||||
|         // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the
 | ||||
|         // clip distances only when it's written by a shader stage.
 | ||||
|         for (std::size_t i = 0; i < Maxwell::NumClipDistances; ++i) { | ||||
|             clip_distances[i] |= shader->GetShaderEntries().clip_distances[i]; | ||||
|         } | ||||
| 
 | ||||
|         // When VertexA is enabled, we have dual vertex shaders
 | ||||
|         if (program == Maxwell::ShaderProgram::VertexA) { | ||||
|             // VertexB was combined with VertexA, so we skip the VertexB iteration
 | ||||
|             index++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     SyncClipEnabled(clip_distances); | ||||
| } | ||||
| 
 | ||||
| std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { | ||||
| @ -629,7 +640,6 @@ void RasterizerOpenGL::DrawArrays() { | ||||
|     SyncCullMode(); | ||||
|     SyncPrimitiveRestart(); | ||||
|     SyncScissorTest(state); | ||||
|     SyncClipEnabled(); | ||||
|     // Alpha Testing is synced on shaders.
 | ||||
|     SyncTransformFeedback(); | ||||
|     SyncPointState(); | ||||
| @ -1006,20 +1016,23 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { | ||||
|     state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncClipEnabled() { | ||||
| void RasterizerOpenGL::SyncClipEnabled( | ||||
|     const std::array<bool, Maxwell::Regs::NumClipDistances>& clip_mask) { | ||||
| 
 | ||||
|     const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||||
|     state.clip_distance[0] = regs.clip_distance_enabled.c0 != 0; | ||||
|     state.clip_distance[1] = regs.clip_distance_enabled.c1 != 0; | ||||
|     state.clip_distance[2] = regs.clip_distance_enabled.c2 != 0; | ||||
|     state.clip_distance[3] = regs.clip_distance_enabled.c3 != 0; | ||||
|     state.clip_distance[4] = regs.clip_distance_enabled.c4 != 0; | ||||
|     state.clip_distance[5] = regs.clip_distance_enabled.c5 != 0; | ||||
|     state.clip_distance[6] = regs.clip_distance_enabled.c6 != 0; | ||||
|     state.clip_distance[7] = regs.clip_distance_enabled.c7 != 0; | ||||
|     const std::array<bool, Maxwell::Regs::NumClipDistances> reg_state{ | ||||
|         regs.clip_distance_enabled.c0 != 0, regs.clip_distance_enabled.c1 != 0, | ||||
|         regs.clip_distance_enabled.c2 != 0, regs.clip_distance_enabled.c3 != 0, | ||||
|         regs.clip_distance_enabled.c4 != 0, regs.clip_distance_enabled.c5 != 0, | ||||
|         regs.clip_distance_enabled.c6 != 0, regs.clip_distance_enabled.c7 != 0}; | ||||
| 
 | ||||
|     for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) { | ||||
|         state.clip_distance[i] = reg_state[i] && clip_mask[i]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncClipCoef() { | ||||
|     UNREACHABLE(); | ||||
|     UNIMPLEMENTED(); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncCullMode() { | ||||
|  | ||||
| @ -128,7 +128,8 @@ private: | ||||
|     void SyncViewport(OpenGLState& current_state); | ||||
| 
 | ||||
|     /// Syncs the clip enabled status to match the guest state
 | ||||
|     void SyncClipEnabled(); | ||||
|     void SyncClipEnabled( | ||||
|         const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& clip_mask); | ||||
| 
 | ||||
|     /// Syncs the clip coefficients to match the guest state
 | ||||
|     void SyncClipCoef(); | ||||
|  | ||||
| @ -525,6 +525,7 @@ public: | ||||
|                 ((header.vtg.clip_distances >> index) & 1) == 0, | ||||
|                 "Shader is setting gl_ClipDistance{} without enabling it in the header", index); | ||||
| 
 | ||||
|             clip_distances[index] = true; | ||||
|             fixed_pipeline_output_attributes_used.insert(attribute); | ||||
|             shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';'); | ||||
|             break; | ||||
| @ -602,6 +603,11 @@ public: | ||||
|         return used_samplers; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns an array of the used clip distances.
 | ||||
|     const std::array<bool, Maxwell::NumClipDistances>& GetClipDistances() const { | ||||
|         return clip_distances; | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
 | ||||
|     /// necessary.
 | ||||
|     std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, | ||||
| @ -975,6 +981,7 @@ private: | ||||
|     const std::string& suffix; | ||||
|     const Tegra::Shader::Header& header; | ||||
|     std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used; | ||||
|     std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | ||||
|     u64 local_memory_size; | ||||
| }; | ||||
| 
 | ||||
| @ -997,7 +1004,8 @@ public: | ||||
| 
 | ||||
|     /// Returns entries in the shader that are useful for external functions
 | ||||
|     ShaderEntries GetEntries() const { | ||||
|         return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), shader_length}; | ||||
|         return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), regs.GetClipDistances(), | ||||
|                 shader_length}; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|  | ||||
| @ -163,6 +163,7 @@ private: | ||||
| struct ShaderEntries { | ||||
|     std::vector<ConstBufferEntry> const_buffer_entries; | ||||
|     std::vector<SamplerEntry> texture_samplers; | ||||
|     std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> clip_distances; | ||||
|     std::size_t shader_length; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user