From 2c86217552f04f421ff459fab2728d2f7c12d5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Nov 2017 15:42:01 +0100 Subject: [PATCH] Cleanup GPU vendor detection a bit, use it to avoid the issue mentioned in #9545 --- GPU/Common/SoftwareTransformCommon.cpp | 2 +- GPU/D3D11/GPU_D3D11.cpp | 4 ++- GPU/Directx9/GPU_DX9.cpp | 4 ++- GPU/GLES/FragmentShaderGeneratorGLES.cpp | 8 +++--- GPU/GLES/ShaderManagerGLES.cpp | 2 +- GPU/Vulkan/GPU_Vulkan.cpp | 2 +- ext/native/gfx_es2/gpu_features.cpp | 6 ++--- ext/native/gfx_es2/gpu_features.h | 4 +-- ext/native/thin3d/thin3d.h | 12 +++++++++ ext/native/thin3d/thin3d_d3d11.cpp | 11 ++++++++ ext/native/thin3d/thin3d_d3d9.cpp | 12 +++++++++ ext/native/thin3d/thin3d_gl.cpp | 34 +++++++++++++++++------- ext/native/thin3d/thin3d_vulkan.cpp | 11 ++++++++ 13 files changed, 88 insertions(+), 24 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index fa34e321d5..4ec1aa4e70 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -400,7 +400,7 @@ void SoftwareTransform( int scissorY2 = gstate.getScissorY2() + 1; reallyAClear = IsReallyAClear(transformed, maxIndex, scissorX2, scissorY2); } - if (reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) { + if (reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_IMGTEC) { // If alpha is not allowed to be separate, it must match for both depth/stencil and color. Vulkan requires this. bool alphaMatchesColor = gstate.isClearModeColorMask() == gstate.isClearModeAlphaMask(); bool depthMatchesStencil = gstate.isClearModeAlphaMask() == gstate.isClearModeDepthMask(); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 154013555c..3c8490394b 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -206,7 +206,9 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_BLEND_MINMAX; features |= GPU_PREFER_CPU_DOWNLOAD; - if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth) { + + // Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545 + if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || draw_->GetDeviceCaps().vendor == Draw::GPUVendor::AMD) { features |= GPU_SUPPORTS_ACCURATE_DEPTH; // Breaks text in PaRappa for some reason. } diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index d11cbd40b2..5286e90166 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -187,7 +187,9 @@ void GPU_DX9::CheckGPUFeatures() { features |= GPU_SUPPORTS_BLEND_MINMAX; features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL; features |= GPU_PREFER_CPU_DOWNLOAD; - if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth) { + + // Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545 + if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || draw_->GetDeviceCaps().vendor == Draw::GPUVendor::AMD) { features |= GPU_SUPPORTS_ACCURATE_DEPTH; } diff --git a/GPU/GLES/FragmentShaderGeneratorGLES.cpp b/GPU/GLES/FragmentShaderGeneratorGLES.cpp index 8c5486687a..c9ccc22e23 100644 --- a/GPU/GLES/FragmentShaderGeneratorGLES.cpp +++ b/GPU/GLES/FragmentShaderGeneratorGLES.cpp @@ -243,7 +243,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM if (enableAlphaTest && !alphaTestAgainstZero) { if (bitwiseOps) { WRITE(p, "int roundAndScaleTo255i(in float x) { return int(floor(x * 255.0 + 0.5)); }\n"); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n"); } else { WRITE(p, "float roundAndScaleTo255f(in float x) { return floor(x * 255.0 + 0.5); }\n"); @@ -252,7 +252,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM if (enableColorTest && !colorTestAgainstZero) { if (bitwiseOps) { WRITE(p, "ivec3 roundAndScaleTo255iv(in vec3 x) { return ivec3(floor(x * 255.0 + 0.5)); }\n"); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { WRITE(p, "vec3 roundTo255thv(in vec3 x) { vec3 y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n"); } else { WRITE(p, "vec3 roundAndScaleTo255v(in vec3 x) { return floor(x * 255.0 + 0.5); }\n"); @@ -436,7 +436,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM if (alphaTestFuncs[alphaTestFunc][0] != '#') { if (bitwiseOps) { WRITE(p, " if ((roundAndScaleTo255i(v.a) & u_alphacolormask.a) %s int(u_alphacolorref.a)) discard;\n", alphaTestFuncs[alphaTestFunc]); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { // Work around bad PVR driver problem where equality check + discard just doesn't work. if (alphaTestFunc != GE_COMP_NOTEQUAL) { WRITE(p, " if (roundTo255thf(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]); @@ -485,7 +485,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM const char *maskedFragColor = "ivec3(v_scaled.r & u_alphacolormask.r, v_scaled.g & u_alphacolormask.g, v_scaled.b & u_alphacolormask.b)"; const char *maskedColorRef = "ivec3(int(u_alphacolorref.r) & u_alphacolormask.r, int(u_alphacolorref.g) & u_alphacolormask.g, int(u_alphacolorref.b) & u_alphacolormask.b)"; WRITE(p, " if (%s %s %s) discard;\n", maskedFragColor, colorTestFuncs[colorTestFunc], maskedColorRef); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { WRITE(p, " if (roundTo255thv(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]); } else { WRITE(p, " if (roundAndScaleTo255v(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index cf48631d02..461384eb70 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -283,7 +283,7 @@ static void SetColorUniform3Alpha(int uniform, u32 color, u8 alpha) { // This passes colors unscaled (e.g. 0 - 255 not 0 - 1.) static void SetColorUniform3Alpha255(int uniform, u32 color, u8 alpha) { - if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { const float col[4] = { (float)((color & 0xFF) >> 0) * (1.0f / 255.0f), (float)((color & 0xFF00) >> 8) * (1.0f / 255.0f), diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index efee4d9aa1..334d98e552 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -177,7 +177,7 @@ GPU_Vulkan::~GPU_Vulkan() { void GPU_Vulkan::CheckGPUFeatures() { uint32_t features = 0; - // Accurate depth is required on AMD so we ignore the compat flag to disable it on those. + // Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545 if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || vulkan_->GetPhysicalDeviceProperties().vendorID == VULKAN_VENDOR_AMD) { features |= GPU_SUPPORTS_ACCURATE_DEPTH; } diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index 56711f541a..c758645fc9 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -64,7 +64,7 @@ void ProcessGPUFeatures() { gl_extensions.bugs |= BUG_FBO_UNUSABLE; } - if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { if (!strcmp(gl_extensions.model, "PowerVR SGX 543") || !strcmp(gl_extensions.model, "PowerVR SGX 540") || !strcmp(gl_extensions.model, "PowerVR SGX 530") || @@ -120,9 +120,9 @@ void CheckGLExtensions() { } else if (vendor == "ARM") { gl_extensions.gpuVendor = GPU_VENDOR_ARM; } else if (vendor == "Imagination Technologies") { - gl_extensions.gpuVendor = GPU_VENDOR_POWERVR; + gl_extensions.gpuVendor = GPU_VENDOR_IMGTEC; } else if (vendor == "Qualcomm") { - gl_extensions.gpuVendor = GPU_VENDOR_ADRENO; + gl_extensions.gpuVendor = GPU_VENDOR_QUALCOMM; } else if (vendor == "Broadcom") { gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM; // Just for reference: Galaxy Y has renderer == "VideoCore IV HW" diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index 3bc237c3f0..2f405546b8 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -12,8 +12,8 @@ enum { GPU_VENDOR_AMD = 2, GPU_VENDOR_INTEL = 3, GPU_VENDOR_ARM = 4, // Mali - GPU_VENDOR_POWERVR = 5, - GPU_VENDOR_ADRENO = 6, + GPU_VENDOR_IMGTEC = 5, + GPU_VENDOR_QUALCOMM = 6, GPU_VENDOR_BROADCOM = 7, GPU_VENDOR_UNKNOWN = 0, }; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 9373489833..9671bfa21b 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -250,6 +250,17 @@ enum InfoField { DRIVER, }; +enum class GPUVendor { + UNKNOWN, + NVIDIA, + INTEL, + AMD, + ARM, // Mali + QUALCOMM, + IMGTEC, // PowerVR + BROADCOM, // Raspberry +}; + enum class NativeObject { CONTEXT, CONTEXT_EX, @@ -483,6 +494,7 @@ struct PipelineDesc { }; struct DeviceCaps { + GPUVendor vendor; DataFormat preferredDepthBufferFormat; DataFormat preferredShadowMapFormatLow; DataFormat preferredShadowMapFormatHigh; diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index 72e73fe951..b5d53ef930 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -221,6 +221,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de caps_.framebufferDepthBlitSupported = false; caps_.framebufferDepthCopySupported = true; + D3D11_FEATURE_DATA_D3D11_OPTIONS options{}; HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options)); if (SUCCEEDED(result)) { @@ -241,6 +242,16 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de DXGI_ADAPTER_DESC desc; adapter->GetDesc(&desc); adapterDesc_ = ConvertWStringToUTF8(desc.Description); + switch (desc.VendorId) { + case 0x10DE: caps_.vendor = GPUVendor::NVIDIA; break; + case 0x1002: + case 0x1022: caps_.vendor = GPUVendor::AMD; break; + case 0x163C: + case 0x8086: + case 0x8087: caps_.vendor = GPUVendor::INTEL; break; + default: + caps_.vendor = GPUVendor::UNKNOWN; + } adapter->Release(); } dxgiDevice->Release(); diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index 3ac3058575..e2b17b1ce9 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -588,11 +588,23 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID if (FAILED(d3d->GetAdapterIdentifier(adapterId, 0, &identifier_))) { ELOG("Failed to get adapter identifier: %d", adapterId); } + switch (identifier_.VendorId) { + case 0x10DE: caps_.vendor = GPUVendor::NVIDIA; break; + case 0x1002: + case 0x1022: caps_.vendor = GPUVendor::AMD; break; + case 0x163C: + case 0x8086: + case 0x8087: caps_.vendor = GPUVendor::INTEL; break; + default: + caps_.vendor = GPUVendor::UNKNOWN; + } + if (!FAILED(device->GetDeviceCaps(&d3dCaps_))) { sprintf(shadeLangVersion_, "PS: %04x VS: %04x", d3dCaps_.PixelShaderVersion & 0xFFFF, d3dCaps_.VertexShaderVersion & 0xFFFF); } else { strcpy(shadeLangVersion_, "N/A"); } + caps_.multiViewport = false; caps_.anisoSupported = true; caps_.depthRangeMinusOneToOne = false; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 36532fabe9..c56745899d 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -540,15 +540,15 @@ public: } case VENDORSTRING: return (const char *)glGetString(GL_VENDOR); case VENDOR: - switch (gl_extensions.gpuVendor) { - case GPU_VENDOR_AMD: return "VENDOR_AMD"; - case GPU_VENDOR_POWERVR: return "VENDOR_POWERVR"; - case GPU_VENDOR_NVIDIA: return "VENDOR_NVIDIA"; - case GPU_VENDOR_INTEL: return "VENDOR_INTEL"; - case GPU_VENDOR_ADRENO: return "VENDOR_ADRENO"; - case GPU_VENDOR_ARM: return "VENDOR_ARM"; - case GPU_VENDOR_BROADCOM: return "VENDOR_BROADCOM"; - case GPU_VENDOR_UNKNOWN: + switch (caps_.vendor) { + case GPUVendor::AMD: return "VENDOR_AMD"; + case GPUVendor::IMGTEC: return "VENDOR_POWERVR"; + case GPUVendor::NVIDIA: return "VENDOR_NVIDIA"; + case GPUVendor::INTEL: return "VENDOR_INTEL"; + case GPUVendor::QUALCOMM: return "VENDOR_ADRENO"; + case GPUVendor::ARM: return "VENDOR_ARM"; + case GPUVendor::BROADCOM: return "VENDOR_BROADCOM"; + case GPUVendor::UNKNOWN: default: return "VENDOR_UNKNOWN"; } @@ -603,6 +603,20 @@ OpenGLContext::OpenGLContext() { } caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object; caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported; + + switch (gl_extensions.gpuVendor) { + case GPU_VENDOR_AMD: caps_.vendor = GPUVendor::AMD; break; + case GPU_VENDOR_NVIDIA: caps_.vendor = GPUVendor::NVIDIA; break; + case GPU_VENDOR_ARM: caps_.vendor = GPUVendor::ARM; break; + case GPU_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::QUALCOMM; break; + case GPU_VENDOR_BROADCOM: caps_.vendor = GPUVendor::BROADCOM; break; + case GPU_VENDOR_INTEL: caps_.vendor = GPUVendor::INTEL; break; + case GPU_VENDOR_IMGTEC: caps_.vendor = GPUVendor::IMGTEC; break; + case GPU_VENDOR_UNKNOWN: + default: + caps_.vendor = GPUVendor::UNKNOWN; + break; + } } OpenGLContext::~OpenGLContext() { @@ -929,7 +943,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit } // Apply the correct alignment. glPixelStorei(GL_PACK_ALIGNMENT, alignment); - if (!gl_extensions.IsGLES || (gl_extensions.GLES3 && gl_extensions.gpuVendor != GPU_VENDOR_NVIDIA)) { + if (!gl_extensions.IsGLES || (gl_extensions.GLES3 && caps_.vendor != GPUVendor::NVIDIA)) { // Some drivers seem to require we specify this. See #8254. glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride); } diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 504f900275..1e651b9e1b 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -687,6 +687,17 @@ VKContext::VKContext(VulkanContext *vulkan) caps_.framebufferDepthCopySupported = true; // Will pretty much always be the case. caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan. + switch (vulkan->GetPhysicalDeviceProperties().vendorID) { + case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::AMD; break; + case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::ARM; break; + case VULKAN_VENDOR_IMGTEC: caps_.vendor = GPUVendor::IMGTEC; break; + case VULKAN_VENDOR_NVIDIA: caps_.vendor = GPUVendor::NVIDIA; break; + case VULKAN_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::QUALCOMM; break; + case VULKAN_VENDOR_INTEL: caps_.vendor = GPUVendor::INTEL; break; + default: + caps_.vendor = GPUVendor::UNKNOWN; + } + device_ = vulkan->GetDevice(); queue_ = vulkan->GetGraphicsQueue();