mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-31 07:59:02 -05:00 
			
		
		
		
	Merge pull request #1019 from Subv/vertex_divisor
Rasterizer: Manually implemented instanced rendering.
This commit is contained in:
		| @@ -222,6 +222,18 @@ void Maxwell3D::DrawArrays() { | ||||
|         debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr); | ||||
|     } | ||||
|  | ||||
|     // Both instance configuration registers can not be set at the same time. | ||||
|     ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont, | ||||
|                "Illegal combination of instancing parameters"); | ||||
|  | ||||
|     if (regs.draw.instance_next) { | ||||
|         // Increment the current instance *before* drawing. | ||||
|         state.current_instance += 1; | ||||
|     } else if (!regs.draw.instance_cont) { | ||||
|         // Reset the current instance to 0. | ||||
|         state.current_instance = 0; | ||||
|     } | ||||
|  | ||||
|     const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; | ||||
|     rasterizer.AccelerateDrawBatch(is_indexed); | ||||
|  | ||||
|   | ||||
| @@ -638,6 +638,8 @@ public: | ||||
|                     union { | ||||
|                         u32 vertex_begin_gl; | ||||
|                         BitField<0, 16, PrimitiveTopology> topology; | ||||
|                         BitField<26, 1, u32> instance_next; | ||||
|                         BitField<27, 1, u32> instance_cont; | ||||
|                     }; | ||||
|                 } draw; | ||||
|  | ||||
| @@ -830,6 +832,7 @@ public: | ||||
|         }; | ||||
|  | ||||
|         std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages; | ||||
|         u32 current_instance = 0; ///< Current instance to be used to simulate instanced rendering. | ||||
|     }; | ||||
|  | ||||
|     State state{}; | ||||
|   | ||||
| @@ -124,7 +124,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, | ||||
|         glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset, | ||||
|                            vertex_array.stride); | ||||
|  | ||||
|         ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented"); | ||||
|         ASSERT_MSG(vertex_array.divisor == 0, "Instanced vertex arrays are not supported"); | ||||
|     } | ||||
|  | ||||
|     // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. | ||||
|   | ||||
| @@ -541,7 +541,7 @@ private: | ||||
|             // vertex shader, and what's the value of the fourth element when inside a Tess Eval | ||||
|             // shader. | ||||
|             ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex); | ||||
|             return "vec4(0, 0, uintBitsToFloat(gl_InstanceID), uintBitsToFloat(gl_VertexID))"; | ||||
|             return "vec4(0, 0, uintBitsToFloat(instance_id.x), uintBitsToFloat(gl_VertexID))"; | ||||
|         default: | ||||
|             const u32 index{static_cast<u32>(attribute) - | ||||
|                             static_cast<u32>(Attribute::Index::Attribute_0)}; | ||||
|   | ||||
| @@ -38,6 +38,7 @@ out vec4 position; | ||||
|  | ||||
| layout (std140) uniform vs_config { | ||||
|     vec4 viewport_flip; | ||||
|     uvec4 instance_id; | ||||
| }; | ||||
|  | ||||
| void main() { | ||||
| @@ -90,6 +91,7 @@ out vec4 color; | ||||
|  | ||||
| layout (std140) uniform fs_config { | ||||
|     vec4 viewport_flip; | ||||
|     uvec4 instance_id; | ||||
| }; | ||||
|  | ||||
| void main() { | ||||
|   | ||||
| @@ -37,11 +37,16 @@ void SetShaderUniformBlockBindings(GLuint shader) { | ||||
| } // namespace Impl | ||||
|  | ||||
| void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) { | ||||
|     const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||||
|     const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | ||||
|     const auto& regs = gpu.regs; | ||||
|     const auto& state = gpu.state; | ||||
|  | ||||
|     // TODO(bunnei): Support more than one viewport | ||||
|     viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; | ||||
|     viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; | ||||
|  | ||||
|     // We only assign the instance to the first component of the vector, the rest is just padding. | ||||
|     instance_id[0] = state.current_instance; | ||||
| } | ||||
|  | ||||
| } // namespace GLShader | ||||
|   | ||||
| @@ -24,14 +24,15 @@ void SetShaderUniformBlockBindings(GLuint shader); | ||||
| } // namespace Impl | ||||
|  | ||||
| /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned | ||||
| // NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at | ||||
| // NOTE: Always keep a vec4 at the end. The GL spec is not clear whether the alignment at | ||||
| //       the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. | ||||
| //       Not following that rule will cause problems on some AMD drivers. | ||||
| struct MaxwellUniformData { | ||||
|     void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); | ||||
|     alignas(16) GLvec4 viewport_flip; | ||||
|     alignas(16) GLuvec4 instance_id; | ||||
| }; | ||||
| static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect"); | ||||
| static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect"); | ||||
| static_assert(sizeof(MaxwellUniformData) < 16384, | ||||
|               "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei