|
|
@@ -107,7 +107,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
|
|
|
state.draw.shader_program = 0;
|
|
|
state.Apply();
|
|
|
|
|
|
- LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
|
|
|
CheckExtensions();
|
|
|
}
|
|
|
|
|
|
@@ -121,66 +120,41 @@ void RasterizerOpenGL::CheckExtensions() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-GLuint RasterizerOpenGL::SetupVertexFormat() {
|
|
|
+void RasterizerOpenGL::SetupVertexFormat() {
|
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
|
const auto& regs = gpu.regs;
|
|
|
|
|
|
MICROPROFILE_SCOPE(OpenGL_VAO);
|
|
|
|
|
|
- auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format);
|
|
|
- auto& vao_entry = iter->second;
|
|
|
-
|
|
|
- if (is_cache_miss) {
|
|
|
- vao_entry.Create();
|
|
|
- const GLuint vao = vao_entry.handle;
|
|
|
-
|
|
|
- // Eventhough we are using DSA to create this vertex array, there is a bug on Intel's blob
|
|
|
- // that fails to properly create the vertex array if it's not bound even after creating it
|
|
|
- // with glCreateVertexArrays
|
|
|
- state.draw.vertex_array = vao;
|
|
|
- state.ApplyVertexArrayState();
|
|
|
-
|
|
|
- // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
|
|
|
- // Enables the first 16 vertex attributes always, as we don't know which ones are actually
|
|
|
- // used until shader time. Note, Tegra technically supports 32, but we're capping this to 16
|
|
|
- // for now to avoid OpenGL errors.
|
|
|
- // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
|
|
|
- // assume every shader uses them all.
|
|
|
- for (u32 index = 0; index < 16; ++index) {
|
|
|
- const auto& attrib = regs.vertex_attrib_format[index];
|
|
|
-
|
|
|
- // Ignore invalid attributes.
|
|
|
- if (!attrib.IsValid())
|
|
|
- continue;
|
|
|
-
|
|
|
- const auto& buffer = regs.vertex_array[attrib.buffer];
|
|
|
- LOG_TRACE(Render_OpenGL,
|
|
|
- "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
|
|
|
- index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
|
|
|
- attrib.offset.Value(), attrib.IsNormalized());
|
|
|
-
|
|
|
- ASSERT(buffer.IsEnabled());
|
|
|
-
|
|
|
- glEnableVertexArrayAttrib(vao, index);
|
|
|
- if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt ||
|
|
|
- attrib.type ==
|
|
|
- Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) {
|
|
|
- glVertexArrayAttribIFormat(vao, index, attrib.ComponentCount(),
|
|
|
- MaxwellToGL::VertexType(attrib), attrib.offset);
|
|
|
- } else {
|
|
|
- glVertexArrayAttribFormat(
|
|
|
- vao, index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
|
|
|
- attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
|
|
|
- }
|
|
|
- glVertexArrayAttribBinding(vao, index, attrib.buffer);
|
|
|
+ // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. Enables
|
|
|
+ // the first 16 vertex attributes always, as we don't know which ones are actually used until
|
|
|
+ // shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now to
|
|
|
+ // avoid OpenGL errors.
|
|
|
+ // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
|
|
|
+ // assume every shader uses them all.
|
|
|
+ for (u32 index = 0; index < 16; ++index) {
|
|
|
+ const auto& attrib = regs.vertex_attrib_format[index];
|
|
|
+
|
|
|
+ // Ignore invalid attributes.
|
|
|
+ if (!attrib.IsValid()) {
|
|
|
+ glDisableVertexAttribArray(index);
|
|
|
+ continue;
|
|
|
}
|
|
|
- }
|
|
|
+ glEnableVertexAttribArray(index);
|
|
|
|
|
|
- state.draw.vertex_array = vao_entry.handle;
|
|
|
- return vao_entry.handle;
|
|
|
+ if (attrib.type == Maxwell::VertexAttribute::Type::SignedInt ||
|
|
|
+ attrib.type == Maxwell::VertexAttribute::Type::UnsignedInt) {
|
|
|
+ glVertexAttribIFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
|
|
|
+ attrib.offset);
|
|
|
+ } else {
|
|
|
+ glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
|
|
|
+ attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
|
|
|
+ }
|
|
|
+ glVertexAttribBinding(index, attrib.buffer);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
|
|
|
+void RasterizerOpenGL::SetupVertexBuffer() {
|
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
|
const auto& regs = gpu.regs;
|
|
|
|
|
|
@@ -189,8 +163,9 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
|
|
|
// Upload all guest vertex arrays sequentially to our buffer
|
|
|
for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
|
|
const auto& vertex_array = regs.vertex_array[index];
|
|
|
- if (!vertex_array.IsEnabled())
|
|
|
+ if (!vertex_array.IsEnabled()) {
|
|
|
continue;
|
|
|
+ }
|
|
|
|
|
|
const GPUVAddr start = vertex_array.StartAddress();
|
|
|
const GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
|
|
|
@@ -205,15 +180,15 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
|
|
|
|
|
|
if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
|
|
|
// Enable vertex buffer instancing with the specified divisor.
|
|
|
- glVertexArrayBindingDivisor(vao, index, vertex_array.divisor);
|
|
|
+ glVertexBindingDivisor(index, vertex_array.divisor);
|
|
|
} else {
|
|
|
// Disable the vertex buffer instancing.
|
|
|
- glVertexArrayBindingDivisor(vao, index, 0);
|
|
|
+ glVertexBindingDivisor(index, 0);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void RasterizerOpenGL::SetupVertexInstances(GLuint vao) {
|
|
|
+void RasterizerOpenGL::SetupVertexInstances() {
|
|
|
auto& gpu = system.GPU().Maxwell3D();
|
|
|
const auto& regs = gpu.regs;
|
|
|
|
|
|
@@ -222,10 +197,10 @@ void RasterizerOpenGL::SetupVertexInstances(GLuint vao) {
|
|
|
if (regs.instanced_arrays.IsInstancingEnabled(index) &&
|
|
|
regs.vertex_array[index].divisor != 0) {
|
|
|
// Enable vertex buffer instancing with the specified divisor.
|
|
|
- glVertexArrayBindingDivisor(vao, index, regs.vertex_array[index].divisor);
|
|
|
+ glVertexBindingDivisor(index, regs.vertex_array[index].divisor);
|
|
|
} else {
|
|
|
// Disable the vertex buffer instancing.
|
|
|
- glVertexArrayBindingDivisor(vao, index, 0);
|
|
|
+ glVertexBindingDivisor(index, 0);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -559,13 +534,12 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
|
|
buffer_cache.Map(buffer_size);
|
|
|
|
|
|
// Prepare vertex array format.
|
|
|
- const GLuint vao = SetupVertexFormat();
|
|
|
- vertex_array_pushbuffer.Setup(vao);
|
|
|
+ SetupVertexFormat();
|
|
|
+ vertex_array_pushbuffer.Setup();
|
|
|
|
|
|
// Upload vertex and index data.
|
|
|
- SetupVertexBuffer(vao);
|
|
|
- SetupVertexInstances(vao);
|
|
|
-
|
|
|
+ SetupVertexBuffer();
|
|
|
+ SetupVertexInstances();
|
|
|
GLintptr index_buffer_offset;
|
|
|
if (is_indexed) {
|
|
|
index_buffer_offset = SetupIndexBuffer();
|