Merge pull request #1019 from Subv/vertex_divisor
Rasterizer: Manually implemented instanced rendering.
This commit is contained in:
commit
727136a9c9
7 changed files with 28 additions and 5 deletions
|
@ -222,6 +222,18 @@ void Maxwell3D::DrawArrays() {
|
||||||
debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
|
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};
|
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
|
||||||
rasterizer.AccelerateDrawBatch(is_indexed);
|
rasterizer.AccelerateDrawBatch(is_indexed);
|
||||||
|
|
||||||
|
|
|
@ -638,6 +638,8 @@ public:
|
||||||
union {
|
union {
|
||||||
u32 vertex_begin_gl;
|
u32 vertex_begin_gl;
|
||||||
BitField<0, 16, PrimitiveTopology> topology;
|
BitField<0, 16, PrimitiveTopology> topology;
|
||||||
|
BitField<26, 1, u32> instance_next;
|
||||||
|
BitField<27, 1, u32> instance_cont;
|
||||||
};
|
};
|
||||||
} draw;
|
} draw;
|
||||||
|
|
||||||
|
@ -830,6 +832,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
|
std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
|
||||||
|
u32 current_instance = 0; ///< Current instance to be used to simulate instanced rendering.
|
||||||
};
|
};
|
||||||
|
|
||||||
State state{};
|
State state{};
|
||||||
|
|
|
@ -124,7 +124,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
|
||||||
glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset,
|
glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset,
|
||||||
vertex_array.stride);
|
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.
|
// 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
|
// vertex shader, and what's the value of the fourth element when inside a Tess Eval
|
||||||
// shader.
|
// shader.
|
||||||
ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex);
|
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:
|
default:
|
||||||
const u32 index{static_cast<u32>(attribute) -
|
const u32 index{static_cast<u32>(attribute) -
|
||||||
static_cast<u32>(Attribute::Index::Attribute_0)};
|
static_cast<u32>(Attribute::Index::Attribute_0)};
|
||||||
|
|
|
@ -38,6 +38,7 @@ out vec4 position;
|
||||||
|
|
||||||
layout (std140) uniform vs_config {
|
layout (std140) uniform vs_config {
|
||||||
vec4 viewport_flip;
|
vec4 viewport_flip;
|
||||||
|
uvec4 instance_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -90,6 +91,7 @@ out vec4 color;
|
||||||
|
|
||||||
layout (std140) uniform fs_config {
|
layout (std140) uniform fs_config {
|
||||||
vec4 viewport_flip;
|
vec4 viewport_flip;
|
||||||
|
uvec4 instance_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -37,11 +37,16 @@ void SetShaderUniformBlockBindings(GLuint shader) {
|
||||||
} // namespace Impl
|
} // namespace Impl
|
||||||
|
|
||||||
void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {
|
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
|
// TODO(bunnei): Support more than one viewport
|
||||||
viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
|
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;
|
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
|
} // namespace GLShader
|
||||||
|
|
|
@ -24,14 +24,15 @@ void SetShaderUniformBlockBindings(GLuint shader);
|
||||||
} // namespace Impl
|
} // namespace Impl
|
||||||
|
|
||||||
/// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
|
/// 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.
|
// 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.
|
// Not following that rule will cause problems on some AMD drivers.
|
||||||
struct MaxwellUniformData {
|
struct MaxwellUniformData {
|
||||||
void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
|
void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
|
||||||
alignas(16) GLvec4 viewport_flip;
|
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,
|
static_assert(sizeof(MaxwellUniformData) < 16384,
|
||||||
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
|
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue