mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-08-20 04:03:22 +02:00
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.
This commit is contained in:
parent
3aad82b1a3
commit
c5284efd4f
@ -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.
|
||||||
|
@ -538,7 +538,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 New Issue
Block a user