diff --git a/Source/Android/res/values/prefvalues.xml b/Source/Android/res/values/prefvalues.xml index 3f67dcbe5b..77354f76a4 100644 --- a/Source/Android/res/values/prefvalues.xml +++ b/Source/Android/res/values/prefvalues.xml @@ -12,7 +12,7 @@ Software Renderer - + OpenGL diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 89b6828281..1bbc69a150 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -4,6 +4,7 @@ set(SRCS Src/BPFunctions.cpp Src/CPMemory.cpp Src/CommandProcessor.cpp Src/Debugger.cpp + Src/DriverDetails.cpp Src/Fifo.cpp Src/FPSCounter.cpp Src/FramebufferManagerBase.cpp diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp new file mode 100644 index 0000000000..8d3c2d9cf7 --- /dev/null +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -0,0 +1,69 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include + +#include "LogManager.h" +#include "DriverDetails.h" + +namespace DriverDetails +{ + struct BugInfo + { + Bug m_bug; // Which bug it is + u32 m_devfamily; // Which device(family) has the error + double m_versionstart; // When it started + double m_versionend; // When it ended + bool m_hasbug; // Does it have it? + }; + + // Local members + Vendor m_vendor = VENDOR_UNKNOWN; + u32 m_devfamily = 0; + double m_version = 0.0; + + // This is a list of all known bugs for each vendor + // We use this to check if the device and driver has a issue + BugInfo m_qualcommbugs[] = { + {BUG_NODYNUBOACCESS, 300, 14.0, -1.0}, + {BUG_BROKENCENTROID, 300, 14.0, -1.0}, + }; + + std::map, BugInfo> m_bugs; + + // Private function + void InitBugMap() + { + switch(m_vendor) + { + case VENDOR_QUALCOMM: + for (int a = 0; a < (sizeof(m_qualcommbugs) / sizeof(BugInfo)); ++a) + m_bugs[std::make_pair(m_vendor, m_qualcommbugs[a].m_bug)] = m_qualcommbugs[a]; + break; + default: + break; + } + } + + void Init(Vendor vendor, const u32 devfamily, const double version) + { + m_vendor = vendor; + m_devfamily = devfamily; + m_version = version; + InitBugMap(); + + for (auto it = m_bugs.begin(); it != m_bugs.end(); ++it) + if (it->second.m_devfamily == m_devfamily) + if (it->second.m_versionend == -1.0 || (it->second.m_versionstart <= m_version && it->second.m_versionend > m_version)) + it->second.m_hasbug = true; + } + + const bool HasBug(Bug bug) + { + auto it = m_bugs.find(std::make_pair(m_vendor, bug)); + if (it == m_bugs.end()) + return false; + return it->second.m_hasbug; + } +} diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h new file mode 100644 index 0000000000..524825f10b --- /dev/null +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -0,0 +1,52 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. +#pragma once +#include "CommonTypes.h" + +namespace DriverDetails +{ + // Enum of known vendors + // Tegra and Nvidia are separated out due to such substantial differences + enum Vendor + { + VENDOR_NVIDIA = 0, + VENDOR_ATI, + VENDOR_INTEL, + VENDOR_ARM, + VENDOR_QUALCOMM, + VENDOR_IMGTEC, + VENDOR_TEGRA, + VENDOR_VIVANTE, + VENDOR_UNKNOWN + }; + + // Enum of known bugs + // These can be vendor specific, but we put them all in here + // For putting a new bug in here, make sure to put a detailed comment above the enum + // This'll ensure we know exactly what the issue is. + enum Bug + { + // Bug: No Dynamic UBO array object access + // Affected Devices: Qualcomm/Adreno + // Started Version: 14 + // Ended Version: -1 + // Accessing UBO array members dynamically causes the Adreno shader compiler to crash + // Errors out with "Internal Error" + BUG_NODYNUBOACCESS = 0, + // Bug: Centroid is broken in shaders + // Affected devices: Qualcomm/Adreno + // Started Version: 14 + // Ended Version: -1 + // Centroid in/out, used in the shaders, is used for multisample buffers to get the texel correctly + // When MSAA is disabled, it acts like a regular in/out + // Tends to cause the driver to render full white or black + BUG_BROKENCENTROID, + }; + + // Initializes our internal vendor, device family, and driver version + void Init(Vendor vendor, const u32 devfamily, const double version); + + // Once Vendor and driver version is set, this will return if it has the applicable bug passed to it. + const bool HasBug(Bug bug); +} diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index d2f77a58cc..f2f72251ef 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -9,6 +9,7 @@ #include "BPMemory.h" #include "CPMemory.h" +#include "DriverDetails.h" #include "LightingShaderGen.h" #include "VertexShaderGen.h" #include "VideoConfig.h" @@ -322,13 +323,22 @@ const char *GenerateVertexShaderCode(u32 components, API_TYPE ApiType) WRITE(p, "int posmtx = int(fposmtx);\n"); } - WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+2], rawpos), 1);\n"); - - if (components & VB_HAS_NRMALL) { - WRITE(p, "int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n"); - WRITE(p, "float3 N0 = " I_NORMALMATRICES"[normidx].xyz, N1 = " I_NORMALMATRICES"[normidx+1].xyz, N2 = " I_NORMALMATRICES"[normidx+2].xyz;\n"); + if (DriverDetails::HasBug(DriverDetails::BUG_NODYNUBOACCESS)) + { + // This'll cause issues, but it can't be helped + WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES"[0], rawpos), dot(" I_TRANSFORMMATRICES"[1], rawpos), dot(" I_TRANSFORMMATRICES"[2], rawpos), 1);\n"); + if (components & VB_HAS_NRMALL) + WRITE(p, "float3 N0 = " I_NORMALMATRICES"[0].xyz, N1 = " I_NORMALMATRICES"[1].xyz, N2 = " I_NORMALMATRICES"[2].xyz;\n"); } + else + { + WRITE(p, "float4 pos = float4(dot(" I_TRANSFORMMATRICES"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+2], rawpos), 1);\n"); + if (components & VB_HAS_NRMALL) { + WRITE(p, "int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n"); + WRITE(p, "float3 N0 = " I_NORMALMATRICES"[normidx].xyz, N1 = " I_NORMALMATRICES"[normidx+1].xyz, N2 = " I_NORMALMATRICES"[normidx+2].xyz;\n"); + } + } if (components & VB_HAS_NRM0) WRITE(p, "float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, rawnorm0)));\n"); if (components & VB_HAS_NRM1) diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index f785cb5c84..f66dfc6b01 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -182,6 +182,7 @@ + @@ -229,6 +230,7 @@ + @@ -302,4 +304,4 @@ - \ No newline at end of file + diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt index 3d4e225932..f3d7ce4e4f 100644 --- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt @@ -24,9 +24,10 @@ if(USE_EGL) EGL) endif() -if(USE_GLES) +if(USE_GLES3) set(LIBS ${LIBS} GLESv2) + set(SRCS ${SRCS} Src/GLFunctions.cpp) else() set(LIBS ${LIBS} GLEW diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLFunctions.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLFunctions.cpp new file mode 100644 index 0000000000..6b8b01562a --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLFunctions.cpp @@ -0,0 +1,93 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. +#include "GLFunctions.h" +#include "Log.h" +#ifdef USE_GLES3 +PFNGLMAPBUFFERPROC glMapBuffer; +PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +PFNGLUNMAPBUFFERPROC glUnmapBuffer; +PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + +PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; + +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; +PFNGLBINDVERTEXARRAYPROC glBindVertexArray; + +PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +PFNGLDELETESYNCPROC glDeleteSync; +PFNGLFENCESYNCPROC glFenceSync; + +PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf; +PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri; +PFNGLSAMPLERPARAMETERFVPROC glSamplerParameterfv; +PFNGLBINDSAMPLERPROC glBindSampler; +PFNGLDELETESAMPLERSPROC glDeleteSamplers; +PFNGLGENSAMPLERSPROC glGenSamplers; + +PFNGLGETPROGRAMBINARYPROC glGetProgramBinary; +PFNGLPROGRAMBINARYPROC glProgramBinary; +PFNGLPROGRAMPARAMETERIPROC glProgramParameteri; + +PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex; +PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding; + +PFNGLBEGINQUERYPROC glBeginQuery; +PFNGLENDQUERYPROC glEndQuery; +PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; +PFNGLDELETEQUERIESPROC glDeleteQueries; +PFNGLGENQUERIESPROC glGenQueries; +#endif +namespace GLFunc +{ + void LoadFunction(const char *name, void **func) + { +#ifdef USE_GLES3 + *func = (void*)eglGetProcAddress(name); + if (*func == NULL) + { + ERROR_LOG(VIDEO, "Couldn't load function %s", name); + exit(0); + } +#endif + } + + void Init() + { + LoadFunction("glBeginQuery", (void**)&glBeginQuery); + LoadFunction("glEndQuery", (void**)&glEndQuery); + LoadFunction("glGetQueryObjectuiv", (void**)&glGetQueryObjectuiv); + LoadFunction("glDeleteQueries", (void**)&glDeleteQueries); + LoadFunction("glGenQueries", (void**)&glGenQueries); + { + LoadFunction("glMapBuffer", (void**)&glMapBuffer); + LoadFunction("glUnmapBuffer", (void**)&glUnmapBuffer); + LoadFunction("glMapBufferRange", (void**)&glMapBufferRange); + LoadFunction("glBindBufferRange", (void**)&glBindBufferRange); + + LoadFunction("glBlitFramebuffer", (void**)&glBlitFramebuffer); + + LoadFunction("glGenVertexArrays", (void**)&glGenVertexArrays); + LoadFunction("glDeleteVertexArrays", (void**)&glDeleteVertexArrays); + LoadFunction("glBindVertexArray", (void**)&glBindVertexArray); + + LoadFunction("glClientWaitSync", (void**)&glClientWaitSync); + LoadFunction("glDeleteSync", (void**)&glDeleteSync); + LoadFunction("glFenceSync", (void**)&glFenceSync); + LoadFunction("glSamplerParameterf", (void**)&glSamplerParameterf); + LoadFunction("glSamplerParameteri", (void**)&glSamplerParameteri); + LoadFunction("glSamplerParameterfv", (void**)&glSamplerParameterfv); + LoadFunction("glBindSampler", (void**)&glBindSampler); + LoadFunction("glDeleteSamplers", (void**)&glDeleteSamplers); + LoadFunction("glGenSamplers", (void**)&glGenSamplers); + } + + LoadFunction("glGetProgramBinary", (void**)&glGetProgramBinary); + LoadFunction("glProgramBinary", (void**)&glProgramBinary); + LoadFunction("glProgramParameteri", (void**)&glProgramParameteri); + + LoadFunction("glGetUniformBlockIndex", (void**)&glGetUniformBlockIndex); + LoadFunction("glUniformBlockBinding", (void**)&glUniformBlockBinding); + } +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLFunctions.h b/Source/Plugins/Plugin_VideoOGL/Src/GLFunctions.h new file mode 100644 index 0000000000..e8ff77690d --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLFunctions.h @@ -0,0 +1,90 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. +#ifndef GLFUNCTIONS_H_ +#define GLFUNCTIONS_H_ +#include "GLInterface.h" + +#ifdef USE_GLES3 +typedef GLvoid* (*PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLvoid* (*PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (*PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef GLboolean (*PFNGLUNMAPBUFFERPROC) (GLenum target); + +typedef void (*PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +// VAOS +typedef void (*PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); +typedef void (*PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); +typedef void (*PFNGLBINDVERTEXARRAYPROC) (GLuint array); + +// Sync +typedef GLenum (*PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); +typedef void (*PFNGLDELETESYNCPROC) (GLsync GLsync); +typedef GLsync (*PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags); + +//Sampler +typedef void (*PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (*PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (*PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params); +typedef void (*PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (*PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers); +typedef void (*PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers); + +//Program binar +typedef void (*PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); +typedef void (*PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); +typedef void (*PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); + +typedef GLuint (*PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar* uniformBlockName); +typedef void (*PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + +//Query +typedef void (*PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (*PFNGLENDQUERYPROC) (GLenum target); +typedef void (*PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (*PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); +typedef void (*PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); + +// ptrs +extern PFNGLBEGINQUERYPROC glBeginQuery; +extern PFNGLENDQUERYPROC glEndQuery; +extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; +extern PFNGLDELETEQUERIESPROC glDeleteQueries; +extern PFNGLGENQUERIESPROC glGenQueries; + +extern PFNGLMAPBUFFERPROC glMapBuffer; +extern PFNGLUNMAPBUFFERPROC glUnmapBuffer; +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; + +extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; + +extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; +extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; +extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; + +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLFENCESYNCPROC glFenceSync; + +extern PFNGLGETPROGRAMBINARYPROC glGetProgramBinary; +extern PFNGLPROGRAMBINARYPROC glProgramBinary; +extern PFNGLPROGRAMPARAMETERIPROC glProgramParameteri; + +//Sampler +extern PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf; +extern PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri; +extern PFNGLSAMPLERPARAMETERFVPROC glSamplerParameterfv; +extern PFNGLBINDSAMPLERPROC glBindSampler; +extern PFNGLDELETESAMPLERSPROC glDeleteSamplers; +extern PFNGLGENSAMPLERSPROC glGenSamplers; + +extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex; +extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding; +#endif + +namespace GLFunc +{ + void Init(); +} +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h index 6df5aa1524..6057fa99f4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h @@ -21,6 +21,9 @@ #define PREC "highp" #define TEXTYPE "sampler2D" #define TEXFUNC "texture2D" +#ifdef USE_GLES3 +#include "GLFunctions.h" +#endif #else #define TEX2D GL_TEXTURE_RECTANGLE_ARB #define PREC diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp index 2df1f47760..90cf401687 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "ProgramShaderCache.h" +#include "DriverDetails.h" #include "MathUtil.h" #include "StreamBuffer.h" #include "Debugger.h" @@ -532,15 +533,15 @@ void ProgramShaderCache::CreateHeader ( void ) "%s\n" "%s\n" "#define COLOROUT(name) %s\n" - + , v==GLSLES3 ? "300 es" : v==GLSL_120 ? "120" : v==GLSL_130 ? "130" : "140" , v==GLSLES3 ? "precision highp float;" : "" , v==GLSLES3 ? "" : v<=GLSL_130 ? "#extension GL_ARB_texture_rectangle : enable" : "#define texture2DRect texture" , g_ActiveConfig.backend_info.bSupportsGLSLUBO && v