Make GLQueueRunner/RenderManager aware of device caps, use it to check for NPOT and some other stuff

This commit is contained in:
Henrik Rydgård 2022-08-07 11:09:34 +02:00
parent b91ad1d2d7
commit 6f1f482432
11 changed files with 39 additions and 38 deletions

View File

@ -267,6 +267,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
caps_.framebufferSeparateDepthCopySupported = false; // Though could be emulated with a draw.
caps_.texture3DSupported = true;
caps_.fragmentShaderInt32Supported = true;
caps_.anisoSupported = true;
D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));

View File

@ -43,7 +43,7 @@ GLuint g_defaultFBO = 0;
void GLQueueRunner::CreateDeviceObjects() {
CHECK_GL_ERROR_IF_DEBUG();
if (gl_extensions.EXT_texture_filter_anisotropic) {
if (caps_.anisoSupported) {
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel_);
} else {
maxAnisotropyLevel_ = 0.0f;
@ -208,7 +208,7 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
#if !defined(USING_GLES2)
if (step.create_program.support_dual_source) {
_dbg_assert_msg_(gl_extensions.ARB_blend_func_extended, "ARB_blend_func_extended required for dual src");
_dbg_assert_msg_(caps_.dualSourceBlend, "ARB/EXT_blend_func_extended required for dual src blend");
// Dual source alpha
glBindFragDataLocationIndexed(program->program, 0, 0, "fragColor0");
glBindFragDataLocationIndexed(program->program, 0, 1, "fragColor1");
@ -1341,16 +1341,14 @@ void GLQueueRunner::PerformCopy(const GLRStep &step) {
_dbg_assert_(srcTex);
_dbg_assert_(dstTex);
_assert_msg_(caps_.framebufferCopySupported, "Image copy extension expected");
#if defined(USING_GLES2)
#if !PPSSPP_PLATFORM(IOS)
_assert_msg_(gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image, "Image copy extension expected");
glCopyImageSubDataOES(
srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,
dstTex, target, dstLevel, dstPos.x, dstPos.y, dstZ,
srcRect.w, srcRect.h, depth);
#endif
#else
_assert_msg_(gl_extensions.ARB_copy_image || gl_extensions.NV_copy_image, "Image copy extension expected");
if (gl_extensions.ARB_copy_image) {
glCopyImageSubData(
srcTex, target, srcLevel, srcRect.x, srcRect.y, srcZ,

View File

@ -7,8 +7,10 @@
#include "Common/GPU/OpenGL/GLCommon.h"
#include "Common/GPU/DataFormat.h"
#include "Common/GPU/Shader.h"
#include "Common/GPU/thin3d.h"
#include "Common/Data/Collections/TinySet.h"
struct GLRViewport {
float x, y, w, h, minZ, maxZ;
};
@ -350,6 +352,10 @@ public:
errorCallbackUserData_ = userdata;
}
void SetDeviceCaps(const Draw::DeviceCaps &caps) {
caps_ = caps;
}
void RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls);
void RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls);
@ -388,14 +394,6 @@ private:
void PerformReadback(const GLRStep &pass);
void PerformReadbackImage(const GLRStep &pass);
void LogRenderPass(const GLRStep &pass);
void LogCopy(const GLRStep &pass);
void LogBlit(const GLRStep &pass);
void LogReadback(const GLRStep &pass);
void LogReadbackImage(const GLRStep &pass);
void ResizeReadbackBuffer(size_t requiredSize);
void fbo_ext_create(const GLRInitStep &step);
void fbo_bind_fb_target(bool read, GLuint name);
GLenum fbo_get_fb_target(bool read, GLuint **cached);
@ -405,6 +403,8 @@ private:
GLuint globalVAO_ = 0;
Draw::DeviceCaps caps_{}; // For sanity checks.
int curFBWidth_ = 0;
int curFBHeight_ = 0;
int targetWidth_ = 0;

View File

@ -26,9 +26,8 @@ static bool OnRenderThread() {
}
#endif
GLRTexture::GLRTexture(int width, int height, int depth, int numMips) {
// Should move this check to thin3d, but really only OpenGL cares, so...
if (gl_extensions.IsCoreContext || gl_extensions.GLES3 || gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot) {
GLRTexture::GLRTexture(const Draw::DeviceCaps &caps, int width, int height, int depth, int numMips) {
if (caps.textureNPOTFullySupported) {
canWrap = true;
} else {
canWrap = isPowerOf2(width) && isPowerOf2(height);
@ -116,12 +115,6 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) {
framebuffers.clear();
}
GLRenderManager::GLRenderManager() {
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
}
}
GLRenderManager::~GLRenderManager() {
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
_assert_(frameData_[i].deleter.IsEmpty());

View File

@ -25,7 +25,7 @@ constexpr int MAX_GL_TEXTURE_SLOTS = 8;
class GLRTexture {
public:
GLRTexture(int width, int height, int depth, int numMips);
GLRTexture(const Draw::DeviceCaps &caps, int width, int height, int depth, int numMips);
~GLRTexture();
GLuint texture = 0;
@ -49,15 +49,13 @@ public:
class GLRFramebuffer {
public:
GLRFramebuffer(int _width, int _height, bool z_stencil)
: color_texture(_width, _height, 1, 1), z_stencil_texture(_width, _height, 1, 1),
GLRFramebuffer(const Draw::DeviceCaps &caps, int _width, int _height, bool z_stencil)
: color_texture(caps, _width, _height, 1, 1), z_stencil_texture(caps, _width, _height, 1, 1),
width(_width), height(_height), z_stencil_(z_stencil) {
}
~GLRFramebuffer();
int numShadows = 1; // TODO: Support this.
GLuint handle = 0;
GLRTexture color_texture;
// Either z_stencil_texture, z_stencil_buffer, or (z_buffer and stencil_buffer) are set.
@ -360,12 +358,16 @@ public:
// directly in the destructor.
class GLRenderManager {
public:
GLRenderManager();
GLRenderManager() {}
~GLRenderManager();
void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
queueRunner_.SetErrorCallback(callback, userdata);
}
void SetDeviceCaps(const Draw::DeviceCaps &caps) {
queueRunner_.SetDeviceCaps(caps);
caps_ = caps;
}
void ThreadStart(Draw::DrawContext *draw);
void ThreadEnd();
@ -388,7 +390,7 @@ public:
// and then we'll also need formats and stuff.
GLRTexture *CreateTexture(GLenum target, int width, int height, int depth, int numMips) {
GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE };
step.create_texture.texture = new GLRTexture(width, height, depth, numMips);
step.create_texture.texture = new GLRTexture(caps_, width, height, depth, numMips);
step.create_texture.texture->target = target;
initSteps_.push_back(step);
return step.create_texture.texture;
@ -416,7 +418,7 @@ public:
GLRFramebuffer *CreateFramebuffer(int width, int height, bool z_stencil) {
GLRInitStep step{ GLRInitStepType::CREATE_FRAMEBUFFER };
step.create_framebuffer.framebuffer = new GLRFramebuffer(width, height, z_stencil);
step.create_framebuffer.framebuffer = new GLRFramebuffer(caps_, width, height, z_stencil);
initSteps_.push_back(step);
return step.create_framebuffer.framebuffer;
}
@ -1047,4 +1049,5 @@ private:
#ifdef _DEBUG
GLRProgram *curProgram_ = nullptr;
#endif
Draw::DeviceCaps caps_{};
};

View File

@ -541,6 +541,8 @@ OpenGLContext::OpenGLContext() {
caps_.texture3DSupported = true;
}
caps_.dualSourceBlend = gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended;
caps_.anisoSupported = gl_extensions.EXT_texture_filter_anisotropic;
caps_.framebufferCopySupported = gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image || gl_extensions.ARB_copy_image;
caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object || gl_extensions.GLES3;
caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
@ -701,6 +703,8 @@ OpenGLContext::OpenGLContext() {
shaderLanguageDesc_.lastFragData = "gl_LastFragColorARM";
}
}
renderManager_.SetDeviceCaps(caps_);
}
OpenGLContext::~OpenGLContext() {

View File

@ -45,8 +45,6 @@ public:
VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VkRenderPass renderPass, int _width, int _height, const char *tag);
~VKRFramebuffer();
int numShadows = 1; // TODO: Support this.
VkFramebuffer framebuf = VK_NULL_HANDLE;
VKRImage color{};
VKRImage depth{};

View File

@ -540,6 +540,7 @@ struct DeviceCaps {
bool framebufferFetchSupported;
bool texture3DSupported;
bool fragmentShaderInt32Supported;
bool textureNPOTFullySupported;
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
};

View File

@ -1125,6 +1125,7 @@ void TextureCacheCommon::NotifyConfigChanged() {
if (!gstate_c.Supports(GPU_SUPPORTS_TEXTURE_NPOT)) {
// Reduce the scale factor to a power of two (e.g. 2 or 4) if textures must be a power of two.
// TODO: In addition we should probably remove these options from the UI in this case.
while ((scaleFactor & (scaleFactor - 1)) != 0) {
--scaleFactor;
}

View File

@ -149,12 +149,14 @@ GPU_GLES::~GPU_GLES() {
}
// Take the raw GL extension and versioning data and turn into feature flags.
// TODO: This should use DrawContext::GetDeviceCaps() more and more, and eventually
// this can be shared between all the backends.
void GPU_GLES::CheckGPUFeatures() {
u32 features = 0;
features |= GPU_SUPPORTS_16BIT_FORMATS;
if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) {
if (draw_->GetDeviceCaps().dualSourceBlend) {
if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) {
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
}
@ -170,19 +172,19 @@ void GPU_GLES::CheckGPUFeatures() {
if ((gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA) || (gl_extensions.gpuVendor == GPU_VENDOR_AMD))
features |= GPU_PREFER_REVERSE_COLOR_ORDER;
if (gl_extensions.OES_texture_npot)
if (draw_->GetDeviceCaps().textureNPOTFullySupported)
features |= GPU_SUPPORTS_TEXTURE_NPOT;
if (gl_extensions.EXT_blend_minmax)
features |= GPU_SUPPORTS_BLEND_MINMAX;
if (!gl_extensions.IsGLES)
if (draw_->GetDeviceCaps().logicOpSupported)
features |= GPU_SUPPORTS_LOGIC_OP;
if (gl_extensions.GLES3 || !gl_extensions.IsGLES)
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
if (gl_extensions.EXT_texture_filter_anisotropic)
if (draw_->GetDeviceCaps().anisoSupported)
features |= GPU_SUPPORTS_ANISOTROPY;
bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced;

View File

@ -258,7 +258,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
if (enabledFeatures.logicOp) {
features |= GPU_SUPPORTS_LOGIC_OP;
}
if (enabledFeatures.samplerAnisotropy) {
if (draw_->GetDeviceCaps().anisoSupported) {
features |= GPU_SUPPORTS_ANISOTROPY;
}