Apple driver bug workaround. See issue #13451

This commit is contained in:
Henrik Rydgård 2020-12-16 14:25:00 +01:00
parent 381313ec9e
commit 7de7680416
12 changed files with 51 additions and 32 deletions

View file

@ -181,9 +181,10 @@ void CheckGLExtensions() {
// Just for reference: Galaxy Y has renderer == "VideoCore IV HW"
} else if (vendor == "Vivante Corporation") {
gl_extensions.gpuVendor = GPU_VENDOR_VIVANTE;
} else if (vendor == "Apple") {
} else if (vendor == "Apple Inc.") {
gl_extensions.gpuVendor = GPU_VENDOR_APPLE;
} else {
WARN_LOG(G3D, "Unknown GL vendor: '%s'", vendor.c_str());
gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
}
} else {

View file

@ -4,6 +4,8 @@
#include <algorithm>
#include <map>
#include "ppsspp_config.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Math/math_util.h"
#include "Common/Math/lin/matrix4x4.h"
@ -591,6 +593,13 @@ OpenGLContext::OpenGLContext() {
bugs_.Infest(Bugs::PVR_GENMIPMAP_HEIGHT_GREATER);
}
#if PPSSPP_PLATFORM(IOS)
// For some reason, this bug does not appear on M1.
if (caps_.vendor == GPUVendor::VENDOR_APPLE) {
bugs_.Infest(Bugs::BROKEN_FLAT_IN_SHADER);
}
#endif
shaderLanguageDesc_.Init(GLSL_1xx);
shaderLanguageDesc_.glslVersionNumber = gl_extensions.GLSLVersion();

View file

@ -315,6 +315,7 @@ public:
PVR_GENMIPMAP_HEIGHT_GREATER = 3,
BROKEN_NAN_IN_CONDITIONAL = 4,
COLORWRITEMASK_BROKEN_WITH_DEPTHTEST = 5,
BROKEN_FLAT_IN_SHADER = 6,
};
protected:

View file

@ -22,6 +22,7 @@
#include "Common/StringUtils.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
#include "Common/GPU/ShaderWriter.h"
#include "Common/GPU/thin3d.h"
#include "Core/Reporting.h"
#include "Core/Config.h"
#include "GPU/Common/GPUStateUtils.h"
@ -33,7 +34,7 @@
#define WRITE(p, ...) p.F(__VA_ARGS__)
bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLanguageDesc &compat, uint64_t *uniformMask, std::string *errorString) {
bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLanguageDesc &compat, Draw::Bugs bugs, uint64_t *uniformMask, std::string *errorString) {
*uniformMask = 0;
errorString->clear();
@ -77,7 +78,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
bool enableColorDoubling = id.Bit(FS_BIT_COLOR_DOUBLE);
bool doTextureProjection = id.Bit(FS_BIT_DO_TEXTURE_PROJ);
bool doTextureAlpha = id.Bit(FS_BIT_TEXALPHA);
bool doFlatShading = id.Bit(FS_BIT_FLATSHADE);
bool doFlatShading = id.Bit(FS_BIT_FLATSHADE) && !bugs.Has(Draw::Bugs::BROKEN_FLAT_IN_SHADER);
bool shaderDepal = id.Bit(FS_BIT_SHADER_DEPAL);
bool bgraTexture = id.Bit(FS_BIT_BGRA_TEXTURE);
bool colorWriteMask = id.Bit(FS_BIT_COLOR_WRITEMASK);

View file

@ -18,6 +18,7 @@
#pragma once
#include "Common/GPU/Shader.h"
#include "Common/GPU/thin3d.h"
struct FShaderID;
@ -37,4 +38,4 @@ struct FShaderID;
// For stencil upload
#define CONST_PS_STENCILVALUE 10
bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLanguageDesc &compat, uint64_t *uniformMask, std::string *errorString);
bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLanguageDesc &compat, Draw::Bugs bugs, uint64_t *uniformMask, std::string *errorString);

View file

@ -22,6 +22,7 @@
#include "Common/StringUtils.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
#include "Common/GPU/ShaderWriter.h"
#include "Common/GPU/thin3d.h"
#include "Core/Config.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
@ -126,7 +127,7 @@ static const char * const boneWeightDecl[9] = {
extern const char *vulkan_glsl_preamble_vs;
extern const char *hlsl_preamble_vs;
bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguageDesc &compat, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString) {
bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguageDesc &compat, Draw::Bugs bugs, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString) {
*attrMask = 0;
*uniformMask = 0;
@ -151,7 +152,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
// this is only valid for some settings of uvGenMode
GETexProjMapMode uvProjMode = static_cast<GETexProjMapMode>(id.Bits(VS_BIT_UVPROJ_MODE, 2));
bool doShadeMapping = uvGenMode == GE_TEXMAP_ENVIRONMENT_MAP;
bool doFlatShading = id.Bit(VS_BIT_FLATSHADE);
bool doFlatShading = id.Bit(VS_BIT_FLATSHADE) && !bugs.Has(Draw::Bugs::BROKEN_FLAT_IN_SHADER);
bool useHWTransform = id.Bit(VS_BIT_USE_HW_TRANSFORM);
bool hasColor = id.Bit(VS_BIT_HAS_COLOR) || !useHWTransform;

View file

@ -21,10 +21,11 @@
#include "Common/CommonTypes.h"
#include "Common/GPU/Shader.h"
#include "Common/GPU/thin3d.h"
struct VShaderID;
bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguageDesc &compat, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString);
bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguageDesc &compat, const Draw::Bugs bugs, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString);
// D3D9 constants.
enum {

View file

@ -210,7 +210,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
std::string genErrorString;
uint32_t attrMask;
uint64_t uniformMask;
GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString);
GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &attrMask, &uniformMask, &genErrorString);
vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform);
vsCache_[VSID] = vs;
} else {
@ -224,7 +224,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
// Fragment shader not in cache. Let's compile it.
std::string genErrorString;
uint64_t uniformMask;
GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &genErrorString);
GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &uniformMask, &genErrorString);
fs = new D3D11FragmentShader(device_, featureLevel_, FSID, codeBuffer_, useHWTransform);
fsCache_[FSID] = fs;
} else {

View file

@ -582,7 +582,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
std::string genErrorString;
uint32_t attrMask;
uint64_t uniformMask;
if (GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString)) {
if (GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &attrMask, &uniformMask, &genErrorString)) {
vs = new VSShader(device_, VSID, codeBuffer_, useHWTransform);
}
if (!vs || vs->Failed()) {
@ -607,7 +607,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
// Can still work with software transform.
uint32_t attrMask;
uint64_t uniformMask;
bool success = GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString);
bool success = GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &attrMask, &uniformMask, &genErrorString);
_assert_(success);
vs = new VSShader(device_, VSID, codeBuffer_, false);
}
@ -624,7 +624,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
// Fragment shader not in cache. Let's compile it.
std::string errorString;
uint64_t uniformMask;
bool success = GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &errorString);
bool success = GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &uniformMask, &errorString);
// We're supposed to handle all possible cases.
_assert_(success);
fs = new PSShader(device_, FSID, codeBuffer_);

View file

@ -635,7 +635,7 @@ void ShaderManagerGLES::DirtyLastShader() {
Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) {
uint64_t uniformMask;
std::string errorString;
if (!GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &errorString)) {
if (!GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &uniformMask, &errorString)) {
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
return nullptr;
}
@ -648,7 +648,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) {
uint32_t attrMask;
uint64_t uniformMask;
std::string errorString;
if (!GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &errorString)) {
if (!GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), draw_->GetBugs(), &attrMask, &uniformMask, &errorString)) {
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
return nullptr;
}

View file

@ -265,7 +265,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
std::string genErrorString;
uint64_t uniformMask = 0; // Not used
uint32_t attributeMask = 0; // Not used
bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, &attributeMask, &uniformMask, &genErrorString);
bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &genErrorString);
_assert_(success);
vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, useHWTransform);
vsCache_.Insert(VSID, vs);
@ -278,7 +278,7 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
// Fragment shader not in cache. Let's compile it.
std::string genErrorString;
uint64_t uniformMask = 0; // Not used
bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &genErrorString);
bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &genErrorString);
_assert_(success);
fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_);
fsCache_.Insert(FSID, fs);
@ -398,7 +398,7 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) {
std::string genErrorString;
uint32_t attributeMask = 0;
uint64_t uniformMask = 0;
if (!GenerateVertexShader(id, codeBuffer_, compat_, &attributeMask, &uniformMask, &genErrorString)) {
if (!GenerateVertexShader(id, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &genErrorString)) {
return false;
}
VulkanVertexShader *vs = new VulkanVertexShader(vulkan_, id, codeBuffer_, useHWTransform);
@ -414,7 +414,7 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) {
}
std::string genErrorString;
uint64_t uniformMask = 0;
if (!GenerateFragmentShader(id, codeBuffer_, compat_, &uniformMask, &genErrorString)) {
if (!GenerateFragmentShader(id, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &genErrorString)) {
return false;
}
VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan_, id, codeBuffer_);

View file

@ -19,67 +19,67 @@
#include "GPU/D3D9/D3DCompilerLoader.h"
#include "GPU/D3D9/D3D9ShaderCompiler.h"
bool GenerateFShader(FShaderID id, char *buffer, ShaderLanguage lang, std::string *errorString) {
bool GenerateFShader(FShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs bugs, std::string *errorString) {
uint64_t uniformMask;
switch (lang) {
case ShaderLanguage::GLSL_VULKAN:
{
ShaderLanguageDesc compat(ShaderLanguage::GLSL_VULKAN);
return GenerateFragmentShader(id, buffer, compat, &uniformMask, errorString);
return GenerateFragmentShader(id, buffer, compat, bugs, &uniformMask, errorString);
}
case ShaderLanguage::GLSL_1xx:
{
ShaderLanguageDesc compat(ShaderLanguage::GLSL_1xx);
return GenerateFragmentShader(id, buffer, compat, &uniformMask, errorString);
return GenerateFragmentShader(id, buffer, compat, bugs, &uniformMask, errorString);
}
case ShaderLanguage::GLSL_3xx:
{
ShaderLanguageDesc compat(ShaderLanguage::GLSL_1xx);
return GenerateFragmentShader(id, buffer, compat, &uniformMask, errorString);
return GenerateFragmentShader(id, buffer, compat, bugs, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D9:
{
ShaderLanguageDesc compat(ShaderLanguage::HLSL_D3D9);
return GenerateFragmentShader(id, buffer, compat, &uniformMask, errorString);
return GenerateFragmentShader(id, buffer, compat, bugs, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D11:
{
ShaderLanguageDesc compat(ShaderLanguage::HLSL_D3D11);
return GenerateFragmentShader(id, buffer, compat, &uniformMask, errorString);
return GenerateFragmentShader(id, buffer, compat, bugs, &uniformMask, errorString);
}
default:
return false;
}
}
bool GenerateVShader(VShaderID id, char *buffer, ShaderLanguage lang, std::string *errorString) {
bool GenerateVShader(VShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs bugs, std::string *errorString) {
uint32_t attrMask;
uint64_t uniformMask;
switch (lang) {
case ShaderLanguage::GLSL_VULKAN:
{
ShaderLanguageDesc compat(ShaderLanguage::GLSL_VULKAN);
return GenerateVertexShader(id, buffer, compat, &attrMask, &uniformMask, errorString);
return GenerateVertexShader(id, buffer, compat, bugs, &attrMask, &uniformMask, errorString);
}
case ShaderLanguage::GLSL_1xx:
{
ShaderLanguageDesc compat(ShaderLanguage::GLSL_1xx);
return GenerateVertexShader(id, buffer, compat, &attrMask, &uniformMask, errorString);
return GenerateVertexShader(id, buffer, compat, bugs, &attrMask, &uniformMask, errorString);
}
case ShaderLanguage::GLSL_3xx:
{
ShaderLanguageDesc compat(ShaderLanguage::GLSL_1xx);
return GenerateVertexShader(id, buffer, compat, &attrMask, &uniformMask, errorString);
return GenerateVertexShader(id, buffer, compat, bugs, &attrMask, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D9:
{
ShaderLanguageDesc compat(ShaderLanguage::HLSL_D3D9);
return GenerateVertexShader(id, buffer, compat, &attrMask, &uniformMask, errorString);
return GenerateVertexShader(id, buffer, compat, bugs, &attrMask, &uniformMask, errorString);
}
case ShaderLanguage::HLSL_D3D11:
{
ShaderLanguageDesc compat(ShaderLanguage::HLSL_D3D11);
return GenerateVertexShader(id, buffer, compat, &attrMask, &uniformMask, errorString);
return GenerateVertexShader(id, buffer, compat, bugs, &attrMask, &uniformMask, errorString);
}
default:
return false;
@ -234,6 +234,8 @@ bool TestVertexShaders() {
int successes = 0;
int count = 700;
Draw::Bugs bugs;
// Generate a bunch of random vertex shader IDs, try to generate shader source.
// Then compile it and check that it's ok.
for (int i = 0; i < count; i++) {
@ -259,7 +261,7 @@ bool TestVertexShaders() {
std::string genErrorString[numLanguages];
for (int j = 0; j < numLanguages; j++) {
generateSuccess[j] = GenerateVShader(id, buffer[j], languages[j], &genErrorString[j]);
generateSuccess[j] = GenerateVShader(id, buffer[j], languages[j], bugs, &genErrorString[j]);
if (!genErrorString[j].empty()) {
printf("%s\n", genErrorString[j].c_str());
}
@ -297,6 +299,8 @@ bool TestFragmentShaders() {
int successes = 0;
int count = 300;
Draw::Bugs bugs;
// Generate a bunch of random fragment shader IDs, try to generate shader source.
// Then compile it and check that it's ok.
for (int i = 0; i < count; i++) {
@ -318,7 +322,7 @@ bool TestFragmentShaders() {
std::string genErrorString[numLanguages];
for (int j = 0; j < numLanguages; j++) {
generateSuccess[j] = GenerateFShader(id, buffer[j], languages[j], &genErrorString[j]);
generateSuccess[j] = GenerateFShader(id, buffer[j], languages[j], bugs, &genErrorString[j]);
if (!genErrorString[j].empty()) {
printf("%s\n", genErrorString[j].c_str());
}