renderer_opengl: Add driver class to report info/bugs

This commit is contained in:
emufan4568
2022-09-09 12:43:19 +03:00
committed by GPUCode
parent 553c85456e
commit 8d35118f63
17 changed files with 869 additions and 158 deletions

View File

@ -59,6 +59,60 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
#endif // _MSC_VER ndef
#define DECLARE_ENUM_FLAG_OPERATORS(type) \
[[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator&(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator^(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) ^ static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator<<(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) << static_cast<T>(b)); \
} \
[[nodiscard]] constexpr type operator>>(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(static_cast<T>(a) >> static_cast<T>(b)); \
} \
constexpr type& operator|=(type& a, type b) noexcept { \
a = a | b; \
return a; \
} \
constexpr type& operator&=(type& a, type b) noexcept { \
a = a & b; \
return a; \
} \
constexpr type& operator^=(type& a, type b) noexcept { \
a = a ^ b; \
return a; \
} \
constexpr type& operator<<=(type& a, type b) noexcept { \
a = a << b; \
return a; \
} \
constexpr type& operator>>=(type& a, type b) noexcept { \
a = a >> b; \
return a; \
} \
[[nodiscard]] constexpr type operator~(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<type>(~static_cast<T>(key)); \
} \
[[nodiscard]] constexpr bool True(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<T>(key) != 0; \
} \
[[nodiscard]] constexpr bool False(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<T>(key) == 0; \
}
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.

View File

@ -41,6 +41,8 @@ add_library(video_core STATIC
rasterizer_cache/texture_runtime.h
renderer_opengl/frame_dumper_opengl.cpp
renderer_opengl/frame_dumper_opengl.h
renderer_opengl/gl_driver.cpp
renderer_opengl/gl_driver.h
renderer_opengl/gl_rasterizer.cpp
renderer_opengl/gl_rasterizer.h
renderer_opengl/gl_resource_manager.cpp

View File

@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#pragma once
#include <list>
#include "common/assert.h"
#include "core/custom_tex_cache.h"
#include "video_core/rasterizer_cache/surface_params.h"
@ -78,7 +77,7 @@ public:
std::shared_ptr<SurfaceWatcher> CreateWatcher() {
auto watcher = std::make_shared<SurfaceWatcher>(weak_from_this());
watchers.push_front(watcher);
watchers[watcher_count++] = watcher;
return watcher;
}
@ -98,7 +97,8 @@ public:
}
}
watchers.clear();
watchers = {};
watcher_count = 0;
}
public:
@ -111,7 +111,6 @@ public:
std::array<u8, 4> fill_data;
OGLTexture texture;
// level_watchers[i] watches the (i+1)-th level mipmap source surface
std::array<std::shared_ptr<SurfaceWatcher>, 7> level_watchers;
u32 max_level = 0;
@ -122,7 +121,8 @@ public:
private:
RasterizerCache& owner;
TextureRuntime& runtime;
std::list<std::weak_ptr<SurfaceWatcher>> watchers;
u32 watcher_count = 0;
std::array<std::weak_ptr<SurfaceWatcher>, 8> watchers;
};
struct CachedTextureCube {

View File

@ -203,8 +203,8 @@ static Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams&
return match_surface;
}
RasterizerCache::RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer)
: rasterizer(rasterizer) {
RasterizerCache::RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer, Driver& driver)
: rasterizer(rasterizer), runtime(driver) {
resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
texture_filterer = std::make_unique<TextureFilterer>(
Settings::values.texture_filter_name.GetValue(), resolution_scale_factor);

View File

@ -38,13 +38,14 @@ enum class ScaleMatch {
Ignore // Accept every scaled res
};
class Driver;
class TextureDownloaderES;
class TextureFilterer;
class FormatReinterpreterOpenGL;
class RasterizerCache : NonCopyable {
public:
RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer);
RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer, Driver& driver);
~RasterizerCache();
/// Blit one surface's texture to another

View File

@ -5,8 +5,8 @@
#include "common/scope_exit.h"
#include "video_core/rasterizer_cache/utils.h"
#include "video_core/rasterizer_cache/texture_runtime.h"
#include "video_core/renderer_opengl/gl_driver.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_vars.h"
namespace OpenGL {
@ -27,7 +27,7 @@ GLbitfield MakeBufferMask(SurfaceType type) {
return GL_COLOR_BUFFER_BIT;
}
TextureRuntime::TextureRuntime() {
TextureRuntime::TextureRuntime(Driver& driver) : driver(driver) {
read_fbo.Create();
draw_fbo.Create();
}
@ -225,18 +225,20 @@ const StagingBuffer& TextureRuntime::FindStaging(u32 size, bool upload) {
// Allocate a new buffer and map the data to the host
void* data = nullptr;
if (GLES) {
if (driver.IsOpenGLES() && driver.HasExtBufferStorage()) {
const GLbitfield storage = upload ? GL_MAP_WRITE_BIT : GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT_EXT;
glBufferStorageEXT(GL_PIXEL_UNPACK_BUFFER, size, nullptr, storage | GL_MAP_PERSISTENT_BIT_EXT |
GL_MAP_COHERENT_BIT_EXT);
data = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size, access | GL_MAP_PERSISTENT_BIT_EXT |
GL_MAP_COHERENT_BIT_EXT);
} else {
} else if (driver.HasArbBufferStorage()) {
const GLbitfield storage = upload ? GL_MAP_WRITE_BIT : GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT;
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, size, nullptr, storage | GL_MAP_PERSISTENT_BIT |
GL_MAP_COHERENT_BIT);
data = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size, access | GL_MAP_PERSISTENT_BIT |
GL_MAP_COHERENT_BIT);
} else {
UNIMPLEMENTED();
}
// Insert it to the cache and return the memory

View File

@ -22,13 +22,15 @@ struct StagingBuffer {
}
};
class Driver;
/**
* Provides texture manipulation functions to the rasterizer cache
* Separating this into a class makes it easier to abstract graphics API code
*/
class TextureRuntime {
public:
TextureRuntime();
TextureRuntime(Driver& driver);
~TextureRuntime() = default;
/// Copies the GPU pixel data to the provided pixels buffer
@ -51,6 +53,7 @@ public:
const StagingBuffer& FindStaging(u32 size, bool upload);
private:
Driver& driver;
OGLFramebuffer read_fbo, draw_fbo;
std::set<StagingBuffer> upload_buffers;
std::set<StagingBuffer> download_buffers;

View File

@ -5,9 +5,6 @@
#include <memory>
#include "core/frontend/emu_window.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/swrasterizer/swrasterizer.h"
#include "video_core/video_core.h"
RendererBase::RendererBase(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window_)
: render_window{window}, secondary_window{secondary_window_} {}
@ -25,19 +22,6 @@ void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) {
}
}
void RendererBase::RefreshRasterizerSetting() {
bool hw_renderer_enabled = VideoCore::g_hw_renderer_enabled;
if (rasterizer == nullptr || opengl_rasterizer_active != hw_renderer_enabled) {
opengl_rasterizer_active = hw_renderer_enabled;
if (hw_renderer_enabled) {
rasterizer = std::make_unique<OpenGL::RasterizerOpenGL>(render_window);
} else {
rasterizer = std::make_unique<VideoCore::SWRasterizer>();
}
}
}
void RendererBase::Sync() {
rasterizer->SyncEntireState();
}

View File

@ -66,7 +66,6 @@ public:
return render_window;
}
void RefreshRasterizerSetting();
void Sync();
protected:
@ -75,7 +74,4 @@ protected:
std::unique_ptr<VideoCore::RasterizerInterface> rasterizer;
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
int m_current_frame = 0; ///< Current frame, should be set by the renderer
private:
bool opengl_rasterizer_active = false;
};

View File

@ -0,0 +1,152 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <glad/glad.h>
#include "common/assert.h"
#include "core/core.h"
#include "video_core/renderer_opengl/gl_driver.h"
namespace OpenGL {
DECLARE_ENUM_FLAG_OPERATORS(DriverBug);
inline std::string_view GetSource(GLenum source) {
#define RET(s) \
case GL_DEBUG_SOURCE_##s: \
return #s
switch (source) {
RET(API);
RET(WINDOW_SYSTEM);
RET(SHADER_COMPILER);
RET(THIRD_PARTY);
RET(APPLICATION);
RET(OTHER);
default:
UNREACHABLE();
}
#undef RET
return std::string_view{};
}
inline std::string_view GetType(GLenum type) {
#define RET(t) \
case GL_DEBUG_TYPE_##t: \
return #t
switch (type) {
RET(ERROR);
RET(DEPRECATED_BEHAVIOR);
RET(UNDEFINED_BEHAVIOR);
RET(PORTABILITY);
RET(PERFORMANCE);
RET(OTHER);
RET(MARKER);
default:
UNREACHABLE();
}
#undef RET
return std::string_view{};
}
static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* user_param) {
Log::Level level = Log::Level::Info;
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH:
level = Log::Level::Critical;
break;
case GL_DEBUG_SEVERITY_MEDIUM:
level = Log::Level::Warning;
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
case GL_DEBUG_SEVERITY_LOW:
level = Log::Level::Debug;
break;
}
LOG_GENERIC(Log::Class::Render_OpenGL, level, "{} {} {}: {}", GetSource(source), GetType(type),
id, message);
}
Driver::Driver(bool gles) : is_gles{gles} {
#ifndef ANDROID
if (!gladLoadGL()) {
return;
}
/*
* Qualcomm has some spammy info messages that are marked as errors but not important
* https://developer.qualcomm.com/comment/11845
*/
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(DebugHandler, nullptr);
#endif
ReportDriverInfo();
DeduceVendor();
CheckExtensionSupport();
FindBugs();
}
bool Driver::HasBug(DriverBug bug) const {
return True(bugs & bug);
}
void Driver::ReportDriverInfo() {
// Report the context version and the vendor string
gl_version = std::string_view{reinterpret_cast<const char*>(glGetString(GL_VERSION))};
gpu_vendor = std::string_view{reinterpret_cast<const char*>(glGetString(GL_VENDOR))};
gpu_model = std::string_view{reinterpret_cast<const char*>(glGetString(GL_RENDERER))};
LOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
LOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
// Add the information to the telemetry system
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
constexpr auto user_system = Common::Telemetry::FieldType::UserSystem;
telemetry_session.AddField(user_system, "GPU_Vendor", std::string{gpu_vendor});
telemetry_session.AddField(user_system, "GPU_Model", std::string{gpu_model});
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string{gl_version});
}
void Driver::DeduceVendor() {
if (gpu_vendor.contains("NVIDIA")) {
vendor = Vendor::Nvidia;
} else if (gpu_vendor.contains("ATI") ||
gpu_vendor.contains("Advanced Micro Devices")) {
vendor = Vendor::AMD;
} else if (gpu_vendor.contains("Intel")) {
vendor = Vendor::Intel;
} else if (gpu_vendor.contains("GDI Generic")) {
vendor = Vendor::Generic;
}
}
void Driver::CheckExtensionSupport() {
ext_buffer_storage = GLAD_GL_EXT_buffer_storage;
arb_buffer_storage = GLAD_GL_ARB_buffer_storage;
ext_clip_cull_distance = GLAD_GL_EXT_clip_cull_distance;
arb_direct_state_access = GLAD_GL_ARB_direct_state_access;
}
void Driver::FindBugs() {
#ifdef __unix__
const bool is_linux = true;
#else
const bool is_linux = false;
#endif
// TODO: Check if these have been fixed in the newer driver
if (vendor == Vendor::AMD) {
bugs |= DriverBug::ShaderStageChangeFreeze | DriverBug::VertexArrayOutOfBound;
}
if (vendor == Vendor::AMD || (vendor == Vendor::Intel && !is_linux)) {
bugs |= DriverBug::BrokenTextureView;
}
}
} // namespace OpenGL

View File

@ -0,0 +1,86 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string_view>
namespace OpenGL {
enum class Vendor {
Unknown = 0,
AMD = 1,
Nvidia = 2,
Intel = 3,
Generic = 4
};
enum class DriverBug {
// AMD drivers sometimes freeze when one shader stage is changed but not the others.
ShaderStageChangeFreeze = 1 << 0,
// On AMD drivers there is a strange crash in indexed drawing. The crash happens when the buffer
// read position is near the end and is an out-of-bound access to the vertex buffer. This is
// probably a bug in the driver and is related to the usage of vec3<byte> attributes in the
// vertex array. Doubling the allocation size for the vertex buffer seems to avoid the crash.
VertexArrayOutOfBound = 1 << 1,
// On AMD and Intel drivers on Windows glTextureView produces incorrect results
BrokenTextureView = 1 << 2,
};
/**
* Utility class that loads the OpenGL function pointers and reports
* information about the graphics device and driver used
*/
class Driver {
public:
Driver(bool gles);
/// Returns true of the driver has a particular bug stated in the DriverBug enum
bool HasBug(DriverBug bug) const;
Vendor GetVendor() const {
return vendor;
}
bool IsOpenGLES() const {
return is_gles;
}
bool HasArbBufferStorage() const {
return arb_buffer_storage;
}
bool HasExtBufferStorage() const {
return ext_buffer_storage;
}
bool HasExtClipCullDistance() const {
return ext_clip_cull_distance;
}
bool HasArbDirectStateAccess() const {
return arb_direct_state_access;
}
private:
void ReportDriverInfo();
void DeduceVendor();
void CheckExtensionSupport();
void FindBugs();
private:
Vendor vendor = Vendor::Unknown;
DriverBug bugs{};
bool is_gles{};
bool ext_buffer_storage{};
bool arb_buffer_storage{};
bool ext_clip_cull_distance{};
bool arb_direct_state_access{};
std::string_view gl_version{};
std::string_view gpu_vendor{};
std::string_view gpu_model{};
};
} // namespace OpenGL

View File

@ -10,6 +10,7 @@
#include "video_core/pica_state.h"
#include "video_core/regs_framebuffer.h"
#include "video_core/regs_rasterizer.h"
#include "video_core/renderer_opengl/gl_driver.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/renderer_opengl/gl_vars.h"
@ -37,8 +38,8 @@ static bool IsVendorIntel() {
}
#endif
RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window)
: is_amd(IsVendorAmd()), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd),
RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driver)
: driver(driver), is_amd(IsVendorAmd()), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd),
uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false),
index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false),
texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false),

View File

@ -20,11 +20,12 @@ class EmuWindow;
}
namespace OpenGL {
class Driver;
class ShaderProgramManager;
class RasterizerOpenGL : public VideoCore::RasterizerAccelerated {
public:
explicit RasterizerOpenGL(Frontend::EmuWindow& emu_window);
explicit RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driver);
~RasterizerOpenGL() override;
void LoadDiskResources(const std::atomic_bool& stop_loading,
@ -247,8 +248,8 @@ private:
/// Setup geometry shader for AccelerateDrawBatch
bool SetupGeometryShader();
bool is_amd;
private:
Driver& driver;
OpenGLState state;
GLuint default_texture;
@ -256,6 +257,7 @@ private:
std::vector<HardwareVertex> vertex_batch;
bool is_amd;
bool shader_dirty = true;
struct {

View File

@ -16,6 +16,7 @@
#include "core/tracer/recorder.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_vars.h"
@ -353,7 +354,7 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
}
RendererOpenGL::RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window)
: RendererBase{window, secondary_window},
: RendererBase{window, secondary_window}, driver{Settings::values.graphics_api == Settings::GraphicsAPI::OpenGLES},
frame_dumper(Core::System::GetInstance().VideoDumper(), window) {
window.mailbox = std::make_unique<OGLTextureMailbox>();
if (secondary_window) {
@ -364,6 +365,27 @@ RendererOpenGL::RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow*
RendererOpenGL::~RendererOpenGL() = default;
/// Initialize the renderer
VideoCore::ResultStatus RendererOpenGL::Init() {
const Vendor vendor = driver.GetVendor();
switch (vendor) {
case Vendor::Generic:
return VideoCore::ResultStatus::ErrorGenericDrivers;
case Vendor::Unknown:
return VideoCore::ResultStatus::ErrorRendererInit;
default:
break;
}
InitOpenGLObjects();
rasterizer = std::make_unique<RasterizerOpenGL>(render_window, driver);
return VideoCore::ResultStatus::Success;
}
/// Shutdown the renderer
void RendererOpenGL::ShutDown() {}
MICROPROFILE_DEFINE(OpenGL_RenderFrame, "OpenGL", "Render Frame", MP_RGB(128, 128, 64));
MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128));
@ -398,16 +420,15 @@ void RendererOpenGL::SwapBuffers() {
m_current_frame++;
Core::System::GetInstance().perf_stats->EndSystemFrame();
Core::System& system = Core::System::GetInstance();
system.perf_stats->EndSystemFrame();
render_window.PollEvents();
Core::System::GetInstance().frame_limiter.DoFrameLimiting(
Core::System::GetInstance().CoreTiming().GetGlobalTimeUs());
Core::System::GetInstance().perf_stats->BeginSystemFrame();
system.frame_limiter.DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs());
system.perf_stats->BeginSystemFrame();
prev_state.Apply();
RefreshRasterizerSetting();
if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
Pica::g_debug_context->recorder->FrameFinished();
@ -1193,111 +1214,4 @@ void RendererOpenGL::CleanupVideoDumping() {
mailbox->free_cv.notify_one();
}
static const char* GetSource(GLenum source) {
#define RET(s) \
case GL_DEBUG_SOURCE_##s: \
return #s
switch (source) {
RET(API);
RET(WINDOW_SYSTEM);
RET(SHADER_COMPILER);
RET(THIRD_PARTY);
RET(APPLICATION);
RET(OTHER);
default:
UNREACHABLE();
}
#undef RET
return "";
}
static const char* GetType(GLenum type) {
#define RET(t) \
case GL_DEBUG_TYPE_##t: \
return #t
switch (type) {
RET(ERROR);
RET(DEPRECATED_BEHAVIOR);
RET(UNDEFINED_BEHAVIOR);
RET(PORTABILITY);
RET(PERFORMANCE);
RET(OTHER);
RET(MARKER);
default:
UNREACHABLE();
}
#undef RET
return "";
}
static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* user_param) {
Log::Level level;
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH:
level = Log::Level::Critical;
break;
case GL_DEBUG_SEVERITY_MEDIUM:
level = Log::Level::Warning;
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
case GL_DEBUG_SEVERITY_LOW:
level = Log::Level::Debug;
break;
}
LOG_GENERIC(Log::Class::Render_OpenGL, level, "{} {} {}: {}", GetSource(source), GetType(type),
id, message);
}
/// Initialize the renderer
VideoCore::ResultStatus RendererOpenGL::Init() {
#ifndef ANDROID
if (!gladLoadGL()) {
return VideoCore::ResultStatus::ErrorRendererInit;
}
// Qualcomm has some spammy info messages that are marked as errors but not important
// https://developer.qualcomm.com/comment/11845
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(DebugHandler, nullptr);
#endif
const std::string_view gl_version{reinterpret_cast<char const*>(glGetString(GL_VERSION))};
const std::string_view gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
const std::string_view gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};
LOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
LOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
LOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
constexpr auto user_system = Common::Telemetry::FieldType::UserSystem;
telemetry_session.AddField(user_system, "GPU_Vendor", std::string{gpu_vendor});
telemetry_session.AddField(user_system, "GPU_Model", std::string{gpu_model});
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string{gl_version});
if (gpu_vendor == "GDI Generic") {
return VideoCore::ResultStatus::ErrorGenericDrivers;
}
if (!(GLAD_GL_VERSION_4_4 || GLAD_GL_ES_VERSION_3_2)) {
return VideoCore::ResultStatus::ErrorRendererInit;
}
// We require glBufferStorage(EXT)
if (GLES && !GLAD_GL_EXT_buffer_storage) {
return VideoCore::ResultStatus::ErrorRendererInit;
}
InitOpenGLObjects();
RefreshRasterizerSetting();
return VideoCore::ResultStatus::Success;
}
/// Shutdown the renderer
void RendererOpenGL::ShutDown() {}
} // namespace OpenGL

View File

@ -7,6 +7,7 @@
#include <array>
#include "core/hw/gpu.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/gl_driver.h"
#include "video_core/renderer_opengl/frame_dumper_opengl.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_state.h"
@ -104,6 +105,8 @@ private:
// Fills active OpenGL texture with the given RGB color.
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
private:
Driver driver;
OpenGLState state;
// OpenGL object IDs