Merge pull request #1104 from Subv/instanced_arrays

GLRasterizer: Implemented instanced vertex arrays.
master
bunnei 2018-08-20 14:32:50 +07:00 committed by GitHub
commit 028d90eb79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 4 deletions

@ -679,7 +679,19 @@ public:
INSERT_PADDING_WORDS(0x7); INSERT_PADDING_WORDS(0x7);
INSERT_PADDING_WORDS(0x46); INSERT_PADDING_WORDS(0x20);
struct {
u32 is_instanced[NumVertexArrays];
/// Returns whether the vertex array specified by index is supposed to be
/// accessed per instance or not.
bool IsInstancingEnabled(u32 index) const {
return is_instanced[index];
}
} instanced_arrays;
INSERT_PADDING_WORDS(0x6);
Cull cull; Cull cull;
@ -928,6 +940,7 @@ ASSERT_REG_POSITION(point_coord_replace, 0x581);
ASSERT_REG_POSITION(code_address, 0x582); ASSERT_REG_POSITION(code_address, 0x582);
ASSERT_REG_POSITION(draw, 0x585); ASSERT_REG_POSITION(draw, 0x585);
ASSERT_REG_POSITION(index_array, 0x5F2); ASSERT_REG_POSITION(index_array, 0x5F2);
ASSERT_REG_POSITION(instanced_arrays, 0x620);
ASSERT_REG_POSITION(cull, 0x646); ASSERT_REG_POSITION(cull, 0x646);
ASSERT_REG_POSITION(clear_buffers, 0x674); ASSERT_REG_POSITION(clear_buffers, 0x674);
ASSERT_REG_POSITION(query, 0x6C0); ASSERT_REG_POSITION(query, 0x6C0);

@ -98,7 +98,8 @@ RasterizerOpenGL::~RasterizerOpenGL() {}
std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr, std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
GLintptr buffer_offset) { GLintptr buffer_offset) {
MICROPROFILE_SCOPE(OpenGL_VAO); MICROPROFILE_SCOPE(OpenGL_VAO);
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
const auto& regs = gpu.regs;
state.draw.vertex_array = hw_vao.handle; state.draw.vertex_array = hw_vao.handle;
state.draw.vertex_buffer = stream_buffer.GetHandle(); state.draw.vertex_buffer = stream_buffer.GetHandle();
@ -110,9 +111,13 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
if (!vertex_array.IsEnabled()) if (!vertex_array.IsEnabled())
continue; continue;
const Tegra::GPUVAddr start = vertex_array.StartAddress(); Tegra::GPUVAddr start = vertex_array.StartAddress();
const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
start += vertex_array.stride * (gpu.state.current_instance / vertex_array.divisor);
}
ASSERT(end > start); ASSERT(end > start);
u64 size = end - start + 1; u64 size = end - start + 1;
@ -124,7 +129,15 @@ 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, "Instanced vertex arrays are not supported"); if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
// Tell OpenGL that this is an instanced vertex buffer to prevent accessing different
// indexes on each vertex. We do the instance indexing manually by incrementing the
// start address of the vertex buffer.
glVertexBindingDivisor(index, 1);
} else {
// Disable the vertex buffer instancing.
glVertexBindingDivisor(index, 0);
}
} }
// 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.