@ -70,28 +70,13 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
state . clip_distance [ 0 ] = true ;
// Generate VAO and UBO
sw_vao . Create ( ) ;
uniform_buffer . Create ( ) ;
state . draw . vertex_array = sw_vao . handle ;
state . draw . uniform_buffer = uniform_buffer . handle ;
state . Apply ( ) ;
// Create render framebuffer
framebuffer . Create ( ) ;
hw_vao . Create ( ) ;
state . draw . vertex_buffer = buffer_cache . GetHandle ( ) ;
shader_program_manager = std : : make_unique < GLShader : : ProgramManager > ( ) ;
state . draw . shader_program = 0 ;
state . draw . vertex_array = hw_vao . handle ;
state . Apply ( ) ;
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , buffer_cache . GetHandle ( ) ) ;
glEnable ( GL_BLEND ) ;
glGetIntegerv ( GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT , & uniform_buffer_alignment ) ;
@ -106,7 +91,54 @@ void RasterizerOpenGL::SetupVertexArrays() {
const auto & gpu = Core : : System : : GetInstance ( ) . GPU ( ) . Maxwell3D ( ) ;
const auto & regs = gpu . regs ;
state . draw . vertex_array = hw_vao . handle ;
auto [ iter , is_cache_miss ] = vertex_array_cache . try_emplace ( regs . vertex_attrib_format ) ;
auto & VAO = iter - > second ;
if ( is_cache_miss ) {
VAO . Create ( ) ;
state . draw . vertex_array = VAO . handle ;
state . Apply ( ) ;
// The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work
// around.
glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , buffer_cache . GetHandle ( ) ) ;
// 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 ( unsigned 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 ( HW_GPU ,
" vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={} " ,
index , attrib . ComponentCount ( ) , attrib . SizeString ( ) , attrib . TypeString ( ) ,
attrib . offset . Value ( ) , attrib . IsNormalized ( ) ) ;
ASSERT ( buffer . IsEnabled ( ) ) ;
glEnableVertexAttribArray ( index ) ;
if ( attrib . type = = Tegra : : Engines : : Maxwell3D : : Regs : : VertexAttribute : : Type : : SignedInt | |
attrib . type = =
Tegra : : Engines : : Maxwell3D : : Regs : : 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 ) ;
}
}
state . draw . vertex_array = VAO . handle ;
state . draw . vertex_buffer = buffer_cache . GetHandle ( ) ;
state . Apply ( ) ;
@ -142,38 +174,6 @@ void RasterizerOpenGL::SetupVertexArrays() {
glVertexBindingDivisor ( index , 0 ) ;
}
}
// 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 ( unsigned index = 0 ; index < 16 ; + + index ) {
auto & attrib = regs . vertex_attrib_format [ index ] ;
// Ignore invalid attributes.
if ( ! attrib . IsValid ( ) )
continue ;
auto & buffer = regs . vertex_array [ attrib . buffer ] ;
LOG_TRACE ( HW_GPU , " vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={} " ,
index , attrib . ComponentCount ( ) , attrib . SizeString ( ) , attrib . TypeString ( ) ,
attrib . offset . Value ( ) , attrib . IsNormalized ( ) ) ;
ASSERT ( buffer . IsEnabled ( ) ) ;
glEnableVertexAttribArray ( index ) ;
if ( attrib . type = = Tegra : : Engines : : Maxwell3D : : Regs : : VertexAttribute : : Type : : SignedInt | |
attrib . type = = Tegra : : Engines : : Maxwell3D : : Regs : : 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 : : SetupShaders ( ) {