Skip to content

Commit

Permalink
Apple driver bug workaround. See issue #13451
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Dec 16, 2020
1 parent 64898c7 commit 73ed08d
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 32 deletions.
3 changes: 2 additions & 1 deletion Common/GPU/OpenGL/GLFeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions Common/GPU/OpenGL/thin3d_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/thin3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ class Bugs {
PVR_GENMIPMAP_HEIGHT_GREATER = 3,
BROKEN_NAN_IN_CONDITIONAL = 4,
COLORWRITEMASK_BROKEN_WITH_DEPTHTEST = 5,
BROKEN_FLAT_IN_SHADER = 6,
};

protected:
Expand Down
5 changes: 3 additions & 2 deletions GPU/Common/FragmentShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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();

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion GPU/Common/FragmentShaderGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include "Common/GPU/Shader.h"
#include "Common/GPU/thin3d.h"

struct FShaderID;

Expand All @@ -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);
5 changes: 3 additions & 2 deletions GPU/Common/VertexShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion GPU/Common/VertexShaderGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions GPU/D3D11/ShaderManagerD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions GPU/Directx9/ShaderManagerDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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);
}
Expand All @@ -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_);
Expand Down
4 changes: 2 additions & 2 deletions GPU/GLES/ShaderManagerGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
8 changes: 4 additions & 4 deletions GPU/Vulkan/ShaderManagerVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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_);
Expand Down
32 changes: 18 additions & 14 deletions unittest/TestShaderGenerators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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++) {
Expand All @@ -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());
}
Expand Down Expand Up @@ -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++) {
Expand All @@ -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());
}
Expand Down

0 comments on commit 73ed08d

Please sign in to comment.