gl_state_tracker: Add dirty flags for buffers and divisors

This commit is contained in:
ReinUsesLisp 2019-12-29 01:28:53 -03:00
parent 9b08698a0c
commit 758ad3f75d
4 changed files with 56 additions and 22 deletions

View file

@ -164,12 +164,22 @@ void RasterizerOpenGL::SetupVertexFormat() {
void RasterizerOpenGL::SetupVertexBuffer() { void RasterizerOpenGL::SetupVertexBuffer() {
auto& gpu = system.GPU().Maxwell3D(); auto& gpu = system.GPU().Maxwell3D();
const auto& regs = gpu.regs; auto& flags = gpu.dirty.flags;
if (!flags[Dirty::VertexBuffers]) {
return;
}
flags[Dirty::VertexBuffers] = false;
MICROPROFILE_SCOPE(OpenGL_VB); MICROPROFILE_SCOPE(OpenGL_VB);
// Upload all guest vertex arrays sequentially to our buffer // Upload all guest vertex arrays sequentially to our buffer
for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) { const auto& regs = gpu.regs;
for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
if (!flags[Dirty::VertexBuffer0 + index]) {
continue;
}
flags[Dirty::VertexBuffer0 + index] = false;
const auto& vertex_array = regs.vertex_array[index]; const auto& vertex_array = regs.vertex_array[index];
if (!vertex_array.IsEnabled()) { if (!vertex_array.IsEnabled()) {
continue; continue;
@ -183,33 +193,30 @@ void RasterizerOpenGL::SetupVertexBuffer() {
const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size); const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size);
// Bind the vertex array to the buffer at the current offset. // Bind the vertex array to the buffer at the current offset.
vertex_array_pushbuffer.SetVertexBuffer(index, vertex_buffer, vertex_buffer_offset, vertex_array_pushbuffer.SetVertexBuffer(static_cast<GLuint>(index), vertex_buffer,
vertex_array.stride); vertex_buffer_offset, vertex_array.stride);
if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
// Enable vertex buffer instancing with the specified divisor.
glVertexBindingDivisor(index, vertex_array.divisor);
} else {
// Disable the vertex buffer instancing.
glVertexBindingDivisor(index, 0);
}
} }
} }
void RasterizerOpenGL::SetupVertexInstances() { void RasterizerOpenGL::SetupVertexInstances() {
auto& gpu = system.GPU().Maxwell3D(); auto& gpu = system.GPU().Maxwell3D();
const auto& regs = gpu.regs; auto& flags = gpu.dirty.flags;
if (!flags[Dirty::VertexInstances]) {
// Upload all guest vertex arrays sequentially to our buffer return;
for (u32 index = 0; index < 16; ++index) {
if (regs.instanced_arrays.IsInstancingEnabled(index) &&
regs.vertex_array[index].divisor != 0) {
// Enable vertex buffer instancing with the specified divisor.
glVertexBindingDivisor(index, regs.vertex_array[index].divisor);
} else {
// Disable the vertex buffer instancing.
glVertexBindingDivisor(index, 0);
} }
flags[Dirty::VertexInstances] = false;
const auto& regs = gpu.regs;
for (std::size_t index = 0; index < 16; ++index) {
if (!flags[Dirty::VertexInstance0 + index]) {
continue;
}
flags[Dirty::VertexInstance0 + index] = false;
const auto gl_index = static_cast<GLuint>(index);
const bool instancing_enabled = regs.instanced_arrays.IsInstancingEnabled(gl_index);
const GLuint divisor = instancing_enabled ? regs.vertex_array[index].divisor : 0;
glVertexBindingDivisor(gl_index, divisor);
} }
} }

View file

@ -71,6 +71,26 @@ void SetupDirtyColorMasks(Tables& tables) {
FillBlock(tables[1], OFF(color_mask), NUM(color_mask), ColorMasks); FillBlock(tables[1], OFF(color_mask), NUM(color_mask), ColorMasks);
} }
void SetupDirtyVertexArrays(Tables& tables) {
static constexpr std::size_t num_array = 3;
static constexpr std::size_t instance_base_offset = 3;
for (std::size_t i = 0; i < Regs::NumVertexArrays; ++i) {
const std::size_t array_offset = OFF(vertex_array) + i * NUM(vertex_array[0]);
const std::size_t limit_offset = OFF(vertex_array_limit) + i * NUM(vertex_array_limit[0]);
FillBlock(tables, array_offset, num_array, VertexBuffer0 + i, VertexBuffers);
FillBlock(tables, limit_offset, NUM(vertex_array_limit), VertexBuffer0 + i, VertexBuffers);
const std::size_t instance_array_offset = array_offset + instance_base_offset;
tables[0][instance_array_offset] = static_cast<u8>(VertexInstance0 + i);
tables[1][instance_array_offset] = VertexInstances;
const std::size_t instance_offset = OFF(instanced_arrays) + i;
tables[0][instance_offset] = static_cast<u8>(VertexInstance0 + i);
tables[1][instance_offset] = VertexInstances;
}
}
void SetupDirtyVertexFormat(Tables& tables) { void SetupDirtyVertexFormat(Tables& tables) {
for (std::size_t i = 0; i < Regs::NumVertexAttributes; ++i) { for (std::size_t i = 0; i < Regs::NumVertexAttributes; ++i) {
const std::size_t offset = OFF(vertex_attrib_format) + i * NUM(vertex_attrib_format[0]); const std::size_t offset = OFF(vertex_attrib_format) + i * NUM(vertex_attrib_format[0]);
@ -115,6 +135,7 @@ void StateTracker::Initialize() {
SetupDirtyColorMasks(tables); SetupDirtyColorMasks(tables);
SetupDirtyViewports(tables); SetupDirtyViewports(tables);
SetupDirtyScissors(tables); SetupDirtyScissors(tables);
SetupDirtyVertexArrays(tables);
SetupDirtyVertexFormat(tables); SetupDirtyVertexFormat(tables);
auto& store = dirty.on_write_stores; auto& store = dirty.on_write_stores;

View file

@ -78,6 +78,10 @@ public:
flags[OpenGL::Dirty::VertexBuffers] = true; flags[OpenGL::Dirty::VertexBuffers] = true;
flags[OpenGL::Dirty::VertexBuffer0] = true; flags[OpenGL::Dirty::VertexBuffer0] = true;
flags[OpenGL::Dirty::VertexInstances] = true;
flags[OpenGL::Dirty::VertexInstance0 + 0] = true;
flags[OpenGL::Dirty::VertexInstance0 + 1] = true;
} }
void NotifyViewport0() { void NotifyViewport0() {

View file

@ -611,6 +611,8 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
glEnableVertexAttribArray(PositionLocation); glEnableVertexAttribArray(PositionLocation);
glEnableVertexAttribArray(TexCoordLocation); glEnableVertexAttribArray(TexCoordLocation);
glVertexAttribDivisor(PositionLocation, 0);
glVertexAttribDivisor(TexCoordLocation, 0);
glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE, glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE,
offsetof(ScreenRectVertex, position)); offsetof(ScreenRectVertex, position));
glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE, glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE,