diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index b81fc44586..dd0c52991a 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -465,6 +465,7 @@ target_sources(rpcs3_emu PRIVATE RSX/Capture/rsx_replay.cpp RSX/GL/glutils/blitter.cpp RSX/GL/glutils/buffer_object.cpp + RSX/GL/glutils/capabilities.cpp RSX/GL/glutils/common.cpp RSX/GL/glutils/fbo.cpp RSX/GL/glutils/image.cpp diff --git a/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp b/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp new file mode 100644 index 0000000000..14aa74134d --- /dev/null +++ b/rpcs3/Emu/RSX/GL/glutils/capabilities.cpp @@ -0,0 +1,230 @@ +#include "stdafx.h" +#include "capabilities.h" + +namespace gl +{ + version_info::version_info(const char* version_string, int major_scale) + { + auto tokens = fmt::split(version_string, { "." }); + if (tokens.size() < 2) + { + rsx_log.warning("Invalid version string: '%s'", version_string); + version = version_major = version_minor = 0; + return; + } + + version_major = static_cast(std::stoi(tokens[0])); + version_minor = static_cast(std::stoi(tokens[1])); + version = static_cast(version_major * major_scale) + version_minor; + } + + bool capabilities::check(const std::string& ext_name, const char* test) + { + if (ext_name == test) + { + rsx_log.notice("Extension %s is supported", ext_name); + return true; + } + + return false; + } + + void capabilities::initialize() + { + int find_count = 15; + int ext_count = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count); + + if (!ext_count) + { + rsx_log.error("Coult not initialize GL driver capabilities. Is OpenGL initialized?"); + return; + } + + std::string vendor_string = reinterpret_cast(glGetString(GL_VENDOR)); + std::string version_string = reinterpret_cast(glGetString(GL_VERSION)); + std::string renderer_string = reinterpret_cast(glGetString(GL_RENDERER)); + + for (int i = 0; i < ext_count; i++) + { + if (!find_count) break; + + const std::string ext_name = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); + + if (check(ext_name, "GL_ARB_shader_draw_parameters")) + { + ARB_shader_draw_parameters_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_EXT_direct_state_access")) + { + EXT_dsa_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_direct_state_access")) + { + ARB_dsa_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_bindless_texture")) + { + ARB_bindless_texture_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_buffer_storage")) + { + ARB_buffer_storage_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_texture_buffer_object")) + { + ARB_texture_buffer_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_depth_buffer_float")) + { + ARB_depth_buffer_float_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_texture_barrier")) + { + ARB_texture_barrier_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_NV_texture_barrier")) + { + NV_texture_barrier_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_NV_gpu_shader5")) + { + NV_gpu_shader5_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_AMD_gpu_shader_half_float")) + { + AMD_gpu_shader_half_float_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_compute_shader")) + { + ARB_compute_shader_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_EXT_depth_bounds_test")) + { + EXT_depth_bounds_test = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_NV_depth_buffer_float")) + { + NV_depth_buffer_float_supported = true; + find_count--; + continue; + } + + if (check(ext_name, "GL_ARB_shader_stencil_export")) + { + ARB_shader_stencil_export_supported = true; + find_count--; + continue; + } + } + + // Set GLSL version + glsl_version = version_info(reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION))); + + // Check GL_VERSION and GL_RENDERER for the presence of Mesa + if (version_string.find("Mesa") != umax || renderer_string.find("Mesa") != umax) + { + vendor_MESA = true; + + if (vendor_string.find("nouveau") != umax) + { + subvendor_NOUVEAU = true; + } + else if (vendor_string.find("AMD") != umax) + { + subvendor_RADEONSI = true; + } + } + + // Workaround for intel drivers which have terrible capability reporting + if (!vendor_string.empty()) + { + std::transform(vendor_string.begin(), vendor_string.end(), vendor_string.begin(), ::tolower); + } + else + { + rsx_log.error("Failed to get vendor string from driver. Are we missing a context?"); + vendor_string = "intel"; // lowest acceptable value + } + + if (!vendor_MESA && vendor_string.find("intel") != umax) + { + int version_major = 0; + int version_minor = 0; + + glGetIntegerv(GL_MAJOR_VERSION, &version_major); + glGetIntegerv(GL_MINOR_VERSION, &version_minor); + + vendor_INTEL = true; + + // Texture buffers moved into core at GL 3.3 + if (version_major > 3 || (version_major == 3 && version_minor >= 3)) + ARB_texture_buffer_supported = true; + + // Check for expected library entry-points for some required functions + if (!ARB_buffer_storage_supported && glNamedBufferStorage && glMapNamedBufferRange) + ARB_buffer_storage_supported = true; + + if (!ARB_dsa_supported && glGetTextureImage && glTextureBufferRange) + ARB_dsa_supported = true; + + if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT) + EXT_dsa_supported = true; + } + else if (!vendor_MESA && vendor_string.find("nvidia") != umax) + { + vendor_NVIDIA = true; + } +#ifdef _WIN32 + else if (vendor_string.find("amd") != umax || vendor_string.find("ati") != umax) + { + vendor_AMD = true; + + // NOTE: Some of the later rebrands ended up in the 7000 line with 'AMD Radeon' branding. + // However, they all are stuck at GLSL 4.40 and below. + subvendor_ATI = renderer_string.find("ATI Radeon") != umax || glsl_version.version < 450; + } +#endif + + initialized = true; + } +} diff --git a/rpcs3/Emu/RSX/GL/glutils/capabilities.h b/rpcs3/Emu/RSX/GL/glutils/capabilities.h new file mode 100644 index 0000000000..af93c4c19c --- /dev/null +++ b/rpcs3/Emu/RSX/GL/glutils/capabilities.h @@ -0,0 +1,59 @@ +#pragma once + +#include "../OpenGL.h" +#include +#include +#include + +#include "Utilities/StrUtil.h" + +namespace gl +{ + struct version_info + { + u8 version_major = 0; + u8 version_minor = 0; + u16 version = 0; + + version_info() = default; + version_info(const char* version_string, int major_scale = 100); + }; + + class capabilities + { + public: + bool initialized = false; + version_info glsl_version; + + bool EXT_dsa_supported = false; + bool EXT_depth_bounds_test = false; + bool ARB_dsa_supported = false; + bool ARB_bindless_texture_supported = false; + bool ARB_buffer_storage_supported = false; + bool ARB_texture_buffer_supported = false; + bool ARB_shader_draw_parameters_supported = false; + bool ARB_depth_buffer_float_supported = false; + bool ARB_texture_barrier_supported = false; + bool ARB_shader_stencil_export_supported = false; + bool NV_texture_barrier_supported = false; + bool NV_gpu_shader5_supported = false; + bool AMD_gpu_shader_half_float_supported = false; + bool ARB_compute_shader_supported = false; + bool NV_depth_buffer_float_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) + + void initialize(); + + private: + bool check(const std::string& ext_name, const char* test); + }; + + const capabilities& get_driver_caps(); +} diff --git a/rpcs3/Emu/RSX/GL/glutils/capabilities.hpp b/rpcs3/Emu/RSX/GL/glutils/capabilities.hpp deleted file mode 100644 index 44a2207696..0000000000 --- a/rpcs3/Emu/RSX/GL/glutils/capabilities.hpp +++ /dev/null @@ -1,243 +0,0 @@ -#pragma once - -#include "../OpenGL.h" -#include -#include -#include - -namespace gl -{ - class capabilities - { - public: - bool EXT_dsa_supported = false; - bool EXT_depth_bounds_test = false; - bool ARB_dsa_supported = false; - bool ARB_bindless_texture_supported = false; - bool ARB_buffer_storage_supported = false; - bool ARB_texture_buffer_supported = false; - bool ARB_shader_draw_parameters_supported = false; - bool ARB_depth_buffer_float_supported = false; - bool ARB_texture_barrier_supported = false; - bool ARB_shader_stencil_export_supported = false; - bool NV_texture_barrier_supported = false; - bool NV_gpu_shader5_supported = false; - bool AMD_gpu_shader_half_float_supported = false; - bool ARB_compute_shader_supported = false; - bool NV_depth_buffer_float_supported = false; - bool initialized = 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; - - bool check(const std::string& ext_name, const char* test) - { - if (ext_name == test) - { - rsx_log.notice("Extension %s is supported", ext_name); - return true; - } - - return false; - } - - void initialize() - { - int find_count = 15; - int ext_count = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &ext_count); - - if (!ext_count) - { - rsx_log.error("Coult not initialize GL driver capabilities. Is OpenGL initialized?"); - return; - } - - std::string vendor_string = reinterpret_cast(glGetString(GL_VENDOR)); - std::string version_string = reinterpret_cast(glGetString(GL_VERSION)); - std::string renderer_string = reinterpret_cast(glGetString(GL_RENDERER)); - - for (int i = 0; i < ext_count; i++) - { - if (!find_count) break; - - const std::string ext_name = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); - - if (check(ext_name, "GL_ARB_shader_draw_parameters")) - { - ARB_shader_draw_parameters_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_EXT_direct_state_access")) - { - EXT_dsa_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_direct_state_access")) - { - ARB_dsa_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_bindless_texture")) - { - ARB_bindless_texture_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_buffer_storage")) - { - ARB_buffer_storage_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_texture_buffer_object")) - { - ARB_texture_buffer_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_depth_buffer_float")) - { - ARB_depth_buffer_float_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_texture_barrier")) - { - ARB_texture_barrier_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_NV_texture_barrier")) - { - NV_texture_barrier_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_NV_gpu_shader5")) - { - NV_gpu_shader5_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_AMD_gpu_shader_half_float")) - { - AMD_gpu_shader_half_float_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_compute_shader")) - { - ARB_compute_shader_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_EXT_depth_bounds_test")) - { - EXT_depth_bounds_test = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_NV_depth_buffer_float")) - { - NV_depth_buffer_float_supported = true; - find_count--; - continue; - } - - if (check(ext_name, "GL_ARB_shader_stencil_export")) - { - ARB_shader_stencil_export_supported = true; - find_count--; - continue; - } - } - - // Check GL_VERSION and GL_RENDERER for the presence of Mesa - if (version_string.find("Mesa") != umax || renderer_string.find("Mesa") != umax) - { - vendor_MESA = true; - - if (vendor_string.find("nouveau") != umax) - { - subvendor_NOUVEAU = true; - } - else if (vendor_string.find("AMD") != umax) - { - subvendor_RADEONSI = true; - } - } - - // Workaround for intel drivers which have terrible capability reporting - if (!vendor_string.empty()) - { - std::transform(vendor_string.begin(), vendor_string.end(), vendor_string.begin(), ::tolower); - } - else - { - rsx_log.error("Failed to get vendor string from driver. Are we missing a context?"); - vendor_string = "intel"; // lowest acceptable value - } - - if (!vendor_MESA && vendor_string.find("intel") != umax) - { - int version_major = 0; - int version_minor = 0; - - glGetIntegerv(GL_MAJOR_VERSION, &version_major); - glGetIntegerv(GL_MINOR_VERSION, &version_minor); - - vendor_INTEL = true; - - // Texture buffers moved into core at GL 3.3 - if (version_major > 3 || (version_major == 3 && version_minor >= 3)) - ARB_texture_buffer_supported = true; - - // Check for expected library entry-points for some required functions - if (!ARB_buffer_storage_supported && glNamedBufferStorage && glMapNamedBufferRange) - ARB_buffer_storage_supported = true; - - if (!ARB_dsa_supported && glGetTextureImage && glTextureBufferRange) - ARB_dsa_supported = true; - - if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT) - EXT_dsa_supported = true; - } - else if (!vendor_MESA && vendor_string.find("nvidia") != umax) - { - vendor_NVIDIA = true; - } -#ifdef _WIN32 - else if (vendor_string.find("amd") != umax || vendor_string.find("ati") != umax) - { - vendor_AMD = true; - subvendor_ATI = vendor_string.find("ati") != umax; - } -#endif - - initialized = true; - } - }; - - const capabilities& get_driver_caps(); -} diff --git a/rpcs3/Emu/RSX/GL/glutils/common.h b/rpcs3/Emu/RSX/GL/glutils/common.h index b4c75762f1..9104bb2ee6 100644 --- a/rpcs3/Emu/RSX/GL/glutils/common.h +++ b/rpcs3/Emu/RSX/GL/glutils/common.h @@ -1,6 +1,6 @@ #pragma once -#include "capabilities.hpp" +#include "capabilities.h" #define GL_FRAGMENT_TEXTURES_START 0 #define GL_VERTEX_TEXTURES_START (GL_FRAGMENT_TEXTURES_START + 16) diff --git a/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp b/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp index 13ede16a64..f12a397f6e 100644 --- a/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp +++ b/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp @@ -1,6 +1,6 @@ #pragma once -#include "capabilities.hpp" +#include "capabilities.h" #include "Utilities/geometry.h" #include diff --git a/rpcs3/GLGSRender.vcxproj b/rpcs3/GLGSRender.vcxproj index 9b6b848b9b..be8c034d81 100644 --- a/rpcs3/GLGSRender.vcxproj +++ b/rpcs3/GLGSRender.vcxproj @@ -62,7 +62,7 @@ - + @@ -91,6 +91,7 @@ + diff --git a/rpcs3/GLGSRender.vcxproj.filters b/rpcs3/GLGSRender.vcxproj.filters index 1ec2b74013..f3cc05833d 100644 --- a/rpcs3/GLGSRender.vcxproj.filters +++ b/rpcs3/GLGSRender.vcxproj.filters @@ -41,6 +41,9 @@ glutils + + glutils + @@ -68,7 +71,7 @@ glutils - + glutils