diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 9c09a96d39..80cef7c5ac 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -749,7 +749,7 @@ void GLGSRender::emit_geometry(u32 sub_index) if (!upload_info.index_info) { - if (draw_call.is_trivial_instanced_draw) + if (draw_call.is_trivial_instanced_draw && backend_config.supports_hw_instanced_rendering) { glDrawArraysInstanced(draw_mode, 0, upload_info.vertex_draw_count, draw_call.pass_count()); } @@ -821,7 +821,7 @@ void GLGSRender::emit_geometry(u32 sub_index) m_index_ring_buffer->bind(); - if (draw_call.is_trivial_instanced_draw) + if (draw_call.is_trivial_instanced_draw && backend_config.supports_hw_instanced_rendering) { glDrawElementsInstanced(draw_mode, upload_info.vertex_draw_count, index_type, reinterpret_cast(u64{ index_offset }), draw_call.pass_count()); } @@ -948,7 +948,7 @@ void GLGSRender::end() { emit_geometry(subdraw++); - if (draw_call.is_trivial_instanced_draw) + if (draw_call.is_trivial_instanced_draw && backend_config.supports_hw_instanced_rendering) { // We already completed. End the draw. draw_call.end(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 02233d46f4..d4c7b475da 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -49,6 +49,7 @@ GLGSRender::GLGSRender(utils::serial* ar) noexcept : GSRender(ar) backend_config.supports_multidraw = true; backend_config.supports_normalized_barycentrics = true; + backend_config.supports_hw_instanced_rendering = true; if (g_cfg.video.antialiasing_level != msaa_level::none) { @@ -176,6 +177,12 @@ void GLGSRender::on_init_thread() rsx_log.warning("Texture barriers are not supported by your GPU. Feedback loops will have undefined results."); } + if (!gl_caps.ARB_shader_storage_buffer_object_supported) + { + rsx_log.warning("[PERFORMANCE WARNING] SSBOs are not supported by your GPU. Some functionality such as hardware instancing will be unavailable."); + backend_config.supports_hw_instanced_rendering = false; + } + if (!gl_caps.ARB_bindless_texture_supported) { switch (shadermode) @@ -326,10 +333,16 @@ void GLGSRender::on_init_thread() m_vertex_layout_buffer->create(gl::buffer::target::uniform, 16 * 0x100000); m_raster_env_ring_buffer->create(gl::buffer::target::uniform, 16 * 0x100000); m_scratch_ring_buffer->create(gl::buffer::target::uniform, 16 * 0x100000); - m_instancing_ring_buffer->create(gl::buffer::target::ssbo, 128 * 0x100000); + + if (backend_config.supports_hw_instanced_rendering) + { + ensure(gl_caps.ARB_shader_storage_buffer_object_supported); + m_instancing_ring_buffer->create(gl::buffer::target::ssbo, 128 * 0x100000); + } if (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only) { + ensure(gl_caps.ARB_shader_storage_buffer_object_supported); m_vertex_instructions_buffer->create(gl::buffer::target::ssbo, 16 * 0x100000); m_fragment_instructions_buffer->create(gl::buffer::target::ssbo, 16 * 0x100000); } @@ -919,7 +932,7 @@ void GLGSRender::load_program_env() const bool update_fragment_texture_env = m_graphics_state & rsx::pipeline_state::fragment_texture_state_dirty; const bool update_instruction_buffers = !!m_interpreter_state && m_shader_interpreter.is_interpreter(m_program); const bool update_raster_env = REGS(m_ctx)->polygon_stipple_enabled() && (m_graphics_state & rsx::pipeline_state::polygon_stipple_pattern_dirty); - const bool update_instancing_data = REGS(m_ctx)->current_draw_clause.is_trivial_instanced_draw; + const bool update_instancing_data = backend_config.supports_hw_instanced_rendering && REGS(m_ctx)->current_draw_clause.is_trivial_instanced_draw; if (manually_flush_ring_buffers) { diff --git a/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp b/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp index a6999d6f9c..1a8ea39126 100644 --- a/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp +++ b/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp @@ -93,6 +93,8 @@ namespace gl CHECK_EXTENSION_SUPPORT(EXT_texture_compression_s3tc); + CHECK_EXTENSION_SUPPORT(ARB_shader_storage_buffer_object); + #undef CHECK_EXTENSION_SUPPORT // Set GLSL version diff --git a/rpcs3/Emu/RSX/GL/glutils/capabilities.h b/rpcs3/Emu/RSX/GL/glutils/capabilities.h index cfe104ffbe..2a0c1bf292 100644 --- a/rpcs3/Emu/RSX/GL/glutils/capabilities.h +++ b/rpcs3/Emu/RSX/GL/glutils/capabilities.h @@ -43,11 +43,13 @@ namespace gl bool NV_fragment_shader_barycentric_supported = false; bool ARB_shader_texture_image_samples_supported = false; bool EXT_texture_compression_s3tc_supported = false; + bool ARB_shader_storage_buffer_object_supported = false; bool vendor_INTEL = false; // has broken GLSL compiler bool vendor_AMD = false; // has broken ARB_multidraw bool vendor_NVIDIA = false; // has NaN poisoning issues bool vendor_MESA = false; // requires CLIENT_STORAGE bit set for streaming buffers + bool subvendor_RADEONSI = false; bool subvendor_NOUVEAU = false; bool subvendor_ATI = false; // Pre-GCN cards (terascale, evergreen) diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 30ff3bd346..17c72a44d6 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -86,6 +86,7 @@ namespace rsx bool supports_hw_msaa; // MSAA support bool supports_hw_a2one; // Alpha to one bool supports_hw_conditional_render; // Conditional render + bool supports_hw_instanced_rendering; // Instanced draws bool supports_passthrough_dma; // DMA passthrough bool supports_asynchronous_compute; // Async compute bool supports_host_gpu_labels; // Advanced host synchronization diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index d8ac9fccf1..e8acd2ec4c 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -640,6 +640,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) } backend_config.supports_multidraw = true; + backend_config.supports_hw_instanced_rendering = true; // NVIDIA has broken attribute interpolation backend_config.supports_normalized_barycentrics = (