mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Apple driver bug workaround. See issue #13451
This commit is contained in:
parent
381313ec9e
commit
7de7680416
12 changed files with 51 additions and 32 deletions
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue