diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index aa0be9a040..e84b5b7dce 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -518,19 +518,37 @@ void GLGSRender::on_init_thread() GSRender::on_init_thread(); gl::init(); + if (g_cfg_rsx_debug_output) gl::enable_debugging(); + LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_VERSION)); LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)); LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_VENDOR)); + auto gl_caps = gl::get_driver_caps(); + + if (!gl_caps.ARB_texture_buffer_supported) + { + fmt::throw_exception("Failed to initialize OpenGL renderer. ARB_texture_buffer_object is required but not supported by your GPU"); + } + + if (!gl_caps.ARB_dsa_supported && !gl_caps.EXT_dsa_supported) + { + fmt::throw_exception("Failed to initialize OpenGL renderer. ARB_direct_state_access or EXT_direct_state_access is required but not supported by your GPU"); + } + + //Use industry standard resource alignment values as defaults + m_uniform_buffer_offset_align = 256; + m_min_texbuffer_alignment = 256; + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_uniform_buffer_offset_align); glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &m_min_texbuffer_alignment); m_vao.create(); - const u32 texture_index_offset = - rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count; + const u32 texture_index_offset = rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count; + for (int index = 0; index < rsx::limits::vertex_count; ++index) { auto &tex = m_gl_attrib_buffers[index]; @@ -541,6 +559,12 @@ void GLGSRender::on_init_thread() tex.bind(); } + if (!gl_caps.ARB_buffer_storage_supported) + { + LOG_WARNING(RSX, "Forcing use of legacy OpenGL buffers because ARB_buffer_storage is not supported"); + g_cfg_rsx_gl_legacy_buffers = true; + } + if (g_cfg_rsx_gl_legacy_buffers) { LOG_WARNING(RSX, "Using legacy openGL buffers."); @@ -570,7 +594,13 @@ void GLGSRender::on_init_thread() m_vao.element_array_buffer = *m_index_ring_buffer; if (g_cfg_rsx_overlay) - m_text_printer.init(); + { + if (gl_caps.ARB_shader_draw_parameters_supported) + { + m_text_printer.init(); + m_text_printer.set_enabled(true); + } + } for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) { @@ -783,7 +813,7 @@ bool GLGSRender::load_program() fragment_constants_offset = mapping.second; if (fragment_constants_size) m_prog_buffer.fill_fragment_constants_buffer({ reinterpret_cast(buf), gsl::narrow(fragment_constants_size) }, fragment_program); - + // Fragment state fill_fragment_state_buffer(buf+fragment_constants_size, fragment_program); @@ -796,7 +826,7 @@ bool GLGSRender::load_program() { m_scale_offset_buffer->unmap(); m_fragment_constants_buffer->unmap(); - + if (m_transform_constants_dirty) m_transform_constants_buffer->unmap(); } @@ -896,7 +926,7 @@ void GLGSRender::flip(int buffer) { gl::screen.bind(); glViewport(0, 0, m_frame->client_width(), m_frame->client_height()); - + m_text_printer.print_text(0, 0, m_frame->client_width(), m_frame->client_height(), "draw calls: " + std::to_string(m_draw_calls)); m_text_printer.print_text(0, 18, m_frame->client_width(), m_frame->client_height(), "draw call setup: " + std::to_string(m_begin_time) + "us"); m_text_printer.print_text(0, 36, m_frame->client_width(), m_frame->client_height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us"); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 89348215e6..cf104cb93d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -17,7 +17,7 @@ struct work_item { std::condition_variable cv; std::mutex guard_mutex; - + u32 address_to_flush = 0; gl::texture_cache::cached_texture_section *section_to_flush = nullptr; @@ -30,7 +30,7 @@ struct gcm_buffer_info { u32 address = 0; u32 pitch = 0; - + bool is_depth_surface; rsx::surface_color_format color_format; @@ -67,7 +67,7 @@ private: gl::texture_cache m_gl_texture_cache; gl::texture m_gl_attrib_buffers[rsx::limits::vertex_count]; - + std::unique_ptr m_attrib_ring_buffer; std::unique_ptr m_fragment_constants_buffer; std::unique_ptr m_transform_constants_buffer; @@ -82,7 +82,7 @@ private: //Compare to see if transform matrix have changed size_t m_transform_buffer_hash = 0; - + GLint m_min_texbuffer_alignment = 256; GLint m_uniform_buffer_offset_align = 256; diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index 4c735a0465..55d8e4309d 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -4,6 +4,7 @@ namespace gl { + capabilities g_driver_caps; const fbo screen{}; GLenum draw_mode(rsx::primitive_type in) @@ -49,6 +50,14 @@ namespace gl #endif } + capabilities &get_driver_caps() + { + if (!g_driver_caps.initialized) + g_driver_caps.initialize(); + + return g_driver_caps; + } + void fbo::create() { glGenFramebuffers(1, &m_id); diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 06749ec877..2af0dcf577 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -53,7 +53,10 @@ namespace gl #define __glcheck #endif + class capabilities; + void enable_debugging(); + capabilities& get_driver_caps(); class exception : public std::exception { @@ -67,6 +70,69 @@ namespace gl } }; + class capabilities + { + public: + bool EXT_dsa_supported = false; + bool ARB_dsa_supported = false; + bool ARB_buffer_storage_supported = false; + bool ARB_texture_buffer_supported = false; + bool ARB_shader_draw_parameters_supported = false; + bool initialized = false; + + void initialize() + { + int find_count = 5; + int ext_count = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count); + + for (int i = 0; i < ext_count; i++) + { + if (!find_count) break; + + const char *ext = (const char*)glGetStringi(GL_EXTENSIONS, i); + const auto ext_name = std::string(ext); + + if (ext_name == "GL_ARB_shader_draw_parameters") + { + ARB_shader_draw_parameters_supported = true; + find_count --; + continue; + } + + if (ext_name == "GL_EXT_direct_state_access") + { + EXT_dsa_supported = true; + find_count --; + continue; + } + + if (ext_name == "GL_ARB_direct_state_access") + { + ARB_dsa_supported = true; + find_count --; + continue; + } + + if (ext_name == "GL_ARB_buffer_storage") + { + ARB_buffer_storage_supported = true; + find_count --; + continue; + } + + if (ext_name == "GL_ARB_texture_buffer_object") + { + ARB_texture_buffer_supported = true; + find_count --; + continue; + } + } + + initialized = true; + } + }; + class fence { GLsync m_value = nullptr; @@ -218,7 +284,7 @@ namespace gl depth_stencil = depth | stencil }; - + class pixel_pack_settings { bool m_swap_bytes = false; @@ -705,7 +771,7 @@ namespace gl m_fence.wait_for_signal(); remove(); } - + buffer::create(); glBindBuffer((GLenum)m_target, m_id); @@ -732,7 +798,7 @@ namespace gl { if (!m_fence.is_empty()) m_fence.wait_for_signal(); - + m_data_loc = 0; offset = 0; } @@ -792,7 +858,7 @@ namespace gl buffer::create(); buffer::data(size, data); - + m_memory_mapping = nullptr; m_data_loc = 0; m_limit = size; @@ -839,7 +905,7 @@ namespace gl //Overallocate slightly for the next allocation if requested size is too small unmap(); reserve_storage_on_heap(std::max(real_size, 4096U)); - + offset = m_data_loc; if (m_data_loc) offset = align(offset, alignment); @@ -849,7 +915,7 @@ namespace gl m_data_loc = offset + alloc_size; m_mapped_bytes -= real_size; - + u32 local_offset = (offset - m_mapping_offset); return std::make_pair(((char*)m_memory_mapping) + local_offset, offset); } @@ -1186,7 +1252,7 @@ namespace gl } glGetIntegerv(pname, &m_last_binding); - + new_binding.bind(); m_target = (GLenum)new_binding.get_target(); } @@ -1453,22 +1519,12 @@ namespace gl if (get_target() != target::textureBuffer) fmt::throw_exception("OpenGL error: texture cannot copy from buffer" HERE); -/* if (!offset) - { - copy_from(buf, gl_format_type); - return; - }*/ + auto caps = get_driver_caps(); - if (glTextureBufferRangeEXT == nullptr) - fmt::throw_exception("OpenGL error: partial buffer access for textures is unsupported on your system" HERE); - - __glcheck glTextureBufferRangeEXT(id(), (GLenum)target::textureBuffer, gl_format_type, buf.id(), offset, length); - } - - void copy_from(buffer &buf, u32 gl_format_type) - { - save_binding_state save(*this); - __glcheck glTexBuffer((GLenum)target::textureBuffer, gl_format_type, buf.id()); + if (caps.EXT_dsa_supported) + __glcheck glTextureBufferRangeEXT(id(), (GLenum)target::textureBuffer, gl_format_type, buf.id(), offset, length); + else + __glcheck glTextureBufferRange(id(), gl_format_type, buf.id(), offset, length); } void copy_from(const buffer& buf, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings) @@ -1863,7 +1919,7 @@ namespace gl void recreate(); void draw_buffer(const attachment& buffer) const; void draw_buffers(const std::initializer_list& indexes) const; - + void read_buffer(const attachment& buffer) const; void draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first = 0) const; diff --git a/rpcs3/Emu/RSX/GL/GLProcTable.h b/rpcs3/Emu/RSX/GL/GLProcTable.h index 5d03d216cf..517138bcf5 100644 --- a/rpcs3/Emu/RSX/GL/GLProcTable.h +++ b/rpcs3/Emu/RSX/GL/GLProcTable.h @@ -171,6 +171,7 @@ OPENGL_PROC(PFNGLBINDBUFFERBASEPROC, BindBufferBase); OPENGL_PROC(PFNGLMULTIDRAWARRAYSPROC, MultiDrawArrays); OPENGL_PROC(PFNGLGETTEXTUREIMAGEEXTPROC, GetTextureImageEXT); +OPENGL_PROC(PFNGLGETTEXTUREIMAGEPROC, GetTextureImage); //Sampler Objects OPENGL_PROC(PFNGLGENSAMPLERSPROC, GenSamplers); @@ -180,8 +181,8 @@ OPENGL_PROC(PFNGLSAMPLERPARAMETERIPROC, SamplerParameteri); OPENGL_PROC(PFNGLSAMPLERPARAMETERFVPROC, SamplerParameterfv); //Texture Buffers -OPENGL_PROC(PFNGLTEXBUFFERPROC, TexBuffer); OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEEXTPROC, TextureBufferRangeEXT); +OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEPROC, TextureBufferRange); //ARB_Copy_Image OPENGL_PROC(PFNGLCOPYIMAGESUBDATAPROC, CopyImageSubData); diff --git a/rpcs3/Emu/RSX/GL/GLTextOut.h b/rpcs3/Emu/RSX/GL/GLTextOut.h index ebdc1ec241..ad12a0ea5e 100644 --- a/rpcs3/Emu/RSX/GL/GLTextOut.h +++ b/rpcs3/Emu/RSX/GL/GLTextOut.h @@ -85,28 +85,6 @@ namespace gl void init() { - //Check for ARB_shader_draw_parameters - //While it is possible to draw text without full multidraw support, issuing separate draw calls per character is not effecient - - int ext_count; - glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count); - - for (int i = 0; i < ext_count; i++) - { - const char *ext = (const char*)glGetStringi(GL_EXTENSIONS, i); - if (std::string(ext) == "GL_ARB_shader_draw_parameters") - { - enabled = true; - break; - } - } - - if (!enabled) - { - LOG_ERROR(RSX, "Debug overlay could not start because ARB_shader_draw_parameters is not supported by your GPU"); - return; - } - m_text_buffer.create(); m_scale_offsets_buffer.create(); @@ -136,6 +114,11 @@ namespace gl init_program(); initialized = true; + } + + void set_enabled(bool state) + { + enabled = state; } void print_text(int x, int y, int target_w, int target_h, const std::string &text, color4f color = { 0.3f, 1.f, 0.3f, 1.f }) @@ -221,4 +204,4 @@ namespace gl } } }; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 3adde84f09..136b9c232b 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -205,7 +205,7 @@ namespace gl void reset(const u32 base, const u32 size, const bool flushable) { rsx::buffered_section::reset(base, size); - + if (flushable) init_buffer(); @@ -278,7 +278,12 @@ namespace gl glPixelStorei(GL_PACK_SWAP_BYTES, pack_unpack_swap_bytes); glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id); - glGetTextureImageEXT(vram_texture, GL_TEXTURE_2D, 0, (GLenum)format, (GLenum)type, nullptr); + + if (get_driver_caps().EXT_dsa_supported) + glGetTextureImageEXT(vram_texture, GL_TEXTURE_2D, 0, (GLenum)format, (GLenum)type, nullptr); + else + glGetTextureImage(vram_texture, 0, (GLenum)format, (GLenum)type, pbo_size, nullptr); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); m_fence.reset(); @@ -706,7 +711,7 @@ namespace gl LOG_WARNING(RSX, "Failed to copy image subresource with GL error 0x%X", err); return 0; } - + return dst_id; } @@ -1313,4 +1318,4 @@ namespace gl return true; } }; -} \ No newline at end of file +}