From c5284efd4f04bca05b1f5c61dce59090a7edf61e Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 11 Aug 2018 19:21:31 -0500 Subject: Rasterizer: Implemented instanced rendering. We keep track of the current instance and update an uniform in the shaders to let them know which instance they are. Instanced vertex arrays are not yet implemented. --- src/video_core/engines/maxwell_3d.cpp | 12 ++++++++++++ src/video_core/engines/maxwell_3d.h | 3 +++ src/video_core/renderer_opengl/gl_rasterizer.cpp | 2 +- src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 2 +- src/video_core/renderer_opengl/gl_shader_gen.cpp | 2 ++ src/video_core/renderer_opengl/gl_shader_manager.cpp | 7 ++++++- src/video_core/renderer_opengl/gl_shader_manager.h | 5 +++-- 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index a46ed4bd7..68f91cc75 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -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); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 1b30ce018..771eb5abc 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -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 shader_stages; + u32 current_instance = 0; ///< Current instance to be used to simulate instanced rendering. }; State state{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 9d1549fe9..93eadde7a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -124,7 +124,7 @@ std::pair 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. diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index dabf98b74..5a05c79ef 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -538,7 +538,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(attribute) - static_cast(Attribute::Index::Attribute_0)}; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 129c777d1..57e0e1726 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -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() { diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 415d42fda..f0886caac 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -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 diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 716933a0b..75fa73605 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -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"); -- cgit v1.2.3