Merge pull request #1747 from Armada651/intel-workaround

OGL: Work around Intel structures bug.
This commit is contained in:
Markus Wick 2015-01-01 21:41:09 +01:00
commit ec4dfae333
8 changed files with 95 additions and 72 deletions

View file

@ -463,8 +463,7 @@ Renderer::Renderer()
g_Config.backend_info.bSupportsEarlyZ = GLExtensions::Supports("GL_ARB_shader_image_load_store");
g_Config.backend_info.bSupportsBBox = GLExtensions::Supports("GL_ARB_shader_storage_buffer_object");
g_Config.backend_info.bSupportsGSInstancing = GLExtensions::Supports("GL_ARB_gpu_shader5");
g_Config.backend_info.bSupportsGeometryShaders = (GLExtensions::Version() >= 320) &&
!DriverDetails::HasBug(DriverDetails::BUG_INTELBROKENINTERFACEBLOCKS);
g_Config.backend_info.bSupportsGeometryShaders = GLExtensions::Version() >= 320;
// Desktop OpenGL supports the binding layout if it supports 420pack
// OpenGL ES 3.1 supports it implicitly without an extension

View file

@ -59,7 +59,6 @@ namespace DriverDetails
{OS_WINDOWS,VENDOR_NVIDIA, DRIVER_NVIDIA, -1, BUG_BROKENUNSYNCMAPPING, -1.0, -1.0, true},
{OS_LINUX, VENDOR_NVIDIA, DRIVER_NVIDIA, -1, BUG_BROKENUNSYNCMAPPING, -1.0, -1.0, true},
{OS_WINDOWS,VENDOR_INTEL, DRIVER_INTEL, -1, BUG_INTELBROKENBUFFERSTORAGE, 101810.3907, 101810.3960, true},
{OS_WINDOWS,VENDOR_INTEL, DRIVER_INTEL, -1, BUG_INTELBROKENINTERFACEBLOCKS, -1.0, -1.0, true},
};
static std::map<Bug, BugInfo> m_bugs;

View file

@ -200,15 +200,6 @@ namespace DriverDetails
// Broken on Windows Intel
// if (cond == false)
BUG_BROKENNEGATEDBOOLEAN,
// Bug: Intel's Windows driver breaks interface blocks that contain structs.
// Affected devices: Intel (Windows)
// Started Version: -1
// Ended Version: -1
// We need interface blocks to make the geometry shader optional and we need structs to make
// assignment easier in the geometry shader stage. However Intel's Windows drivers don't seem
// to be able handle this combination.
// TODO: Find affected versions.
BUG_INTELBROKENINTERFACEBLOCKS,
};

View file

@ -84,7 +84,9 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A
uid_data->numTexGens = bpmem.genMode.numtexgens;
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
GenerateVSOutputStruct<T>(out, ApiType);
out.Write("struct VS_OUTPUT {\n");
GenerateVSOutputMembers<T>(out, ApiType);
out.Write("};\n");
if (ApiType == API_OPENGL)
{
@ -92,11 +94,11 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A
out.Write("#define InstanceID gl_InvocationID\n");
out.Write("in VertexData {\n");
out.Write("\tcentroid %s VS_OUTPUT o;\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? "" : "in");
GenerateVSOutputMembers<T>(out, ApiType, g_ActiveConfig.backend_info.bSupportsBindingLayout ? "centroid" : "centroid in");
out.Write("} vs[%d];\n", vertex_in);
out.Write("out VertexData {\n");
out.Write("\tcentroid %s VS_OUTPUT o;\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? "" : "out");
GenerateVSOutputMembers<T>(out, ApiType, g_ActiveConfig.backend_info.bSupportsBindingLayout ? "centroid" : "centroid out");
if (g_ActiveConfig.iStereoMode > 0)
out.Write("\tflat int layer;\n");
@ -133,8 +135,9 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A
{
if (ApiType == API_OPENGL)
{
out.Write("\tVS_OUTPUT start = vs[0].o;\n");
out.Write("\tVS_OUTPUT end = vs[1].o;\n");
out.Write("\tVS_OUTPUT start, end;\n");
AssignVSOutputMembers(out, "start", "vs[0]");
AssignVSOutputMembers(out, "end", "vs[1]");
}
else
{
@ -163,9 +166,14 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A
else if (primitive_type == PRIMITIVE_POINTS)
{
if (ApiType == API_OPENGL)
out.Write("\tVS_OUTPUT center = vs[0].o;\n");
{
out.Write("\tVS_OUTPUT center;\n");
AssignVSOutputMembers(out, "center", "vs[0]");
}
else
{
out.Write("\tVS_OUTPUT center = o[0];\n");
}
// Offset from center to upper right vertex
// Lerp PointSize/2 from [0,0..VpWidth,VpHeight] to [-1,1..1,-1]
@ -188,9 +196,14 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A
out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in);
if (ApiType == API_OPENGL)
out.Write("\tVS_OUTPUT f = vs[i].o;\n");
{
out.Write("\tVS_OUTPUT f;\n");
AssignVSOutputMembers(out, "f", "vs[i]");
}
else
{
out.Write("\tVS_OUTPUT f = o[i];\n");
}
if (g_ActiveConfig.iStereoMode > 0)
{
@ -289,9 +302,14 @@ static inline void EmitVertex(T& out, const char* vertex, API_TYPE ApiType, bool
out.Write("\tif (i == 0) first = %s;\n", vertex);
if (ApiType == API_OPENGL)
{
out.Write("\tgl_Position = %s.pos;\n", vertex);
out.Write("\tps.o = %s;\n", vertex);
AssignVSOutputMembers(out, "ps", vertex);
}
else
{
out.Write("\tps.o = %s;\n", vertex);
}
if (ApiType == API_OPENGL)
out.Write("\tEmitVertex();\n");

View file

@ -264,7 +264,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
GenerateLightShader<T>(object, uid_data, i, lit_index, coloralpha);
}
}
object.Write("lacc = clamp(lacc, 0, 255);");
object.Write("lacc = clamp(lacc, 0, 255);\n");
object.Write("%s%d = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n", dest, j);
object.Write("}\n");
}

View file

@ -124,8 +124,8 @@ static const char *tevAInputTable[] =
static const char *tevRasTable[] =
{
"iround(colors_0 * 255.0)",
"iround(colors_1 * 255.0)",
"iround(col0 * 255.0)",
"iround(col1 * 255.0)",
"ERROR13", //2
"ERROR14", //3
"ERROR15", //4
@ -264,7 +264,9 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
}
}
GenerateVSOutputStruct<T>(out, ApiType);
out.Write("struct VS_OUTPUT {\n");
GenerateVSOutputMembers<T>(out, ApiType);
out.Write("};\n");
const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);
@ -320,7 +322,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
{
out.Write("in VertexData {\n");
out.Write("\tcentroid %s VS_OUTPUT o;\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? "" : "in");
GenerateVSOutputMembers<T>(out, ApiType, g_ActiveConfig.backend_info.bSupportsBindingLayout ? "centroid" : "centroid in");
if (g_ActiveConfig.iStereoMode > 0)
out.Write("\tflat int layer;\n");
@ -329,8 +331,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
}
else
{
out.Write("centroid in float4 colors_02;\n");
out.Write("centroid in float4 colors_12;\n");
out.Write("centroid in float4 colors_0;\n");
out.Write("centroid in float4 colors_1;\n");
// compute window position if needed because binding semantic WPOS is not widely supported
// Let's set up attributes
for (unsigned int i = 0; i < numTexgen; ++i)
@ -348,24 +350,10 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
{
// compute window position if needed because binding semantic WPOS is not widely supported
// Let's set up attributes
for (unsigned int i = 0; i < numTexgen; ++i)
{
out.Write("\tfloat3 uv%d = o.tex%d;\n", i, i);
}
out.Write("\tfloat4 clipPos = o.clipPos;\n");
if (g_ActiveConfig.bEnablePixelLighting)
{
out.Write("\tfloat4 Normal = o.Normal;\n");
}
out.Write("\tfloat3 uv%d = tex%d;\n", i, i);
}
// On Mali, global variables must be initialized as constants.
// This is why we initialize these variables locally instead.
out.Write("\tfloat4 colors_0 = %s;\n", g_ActiveConfig.backend_info.bSupportsGeometryShaders ? "o.colors_0" : "colors_02");
out.Write("\tfloat4 colors_1 = %s;\n", g_ActiveConfig.backend_info.bSupportsGeometryShaders ? "o.colors_1" : "colors_12");
out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
}
else // D3D
@ -407,13 +395,22 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
"\tfloat3 ldir, h;\n"
"\tfloat dist, dist2, attn;\n");
// On GLSL, input variables must not be assigned to.
// This is why we declare these variables locally instead.
out.Write("\tfloat4 col0, col1;\n");
// TODO: Our current constant usage code isn't able to handle more than one buffer.
// So we can't mark the VS constant as used here. But keep them here as reference.
//out.SetConstantsUsed(C_PLIGHT_COLORS, C_PLIGHT_COLORS+7); // TODO: Can be optimized further
//out.SetConstantsUsed(C_PLIGHTS, C_PLIGHTS+31); // TODO: Can be optimized further
//out.SetConstantsUsed(C_PMATERIALS, C_PMATERIALS+3);
uid_data->components = components;
GenerateLightingShader<T>(out, uid_data->lighting, components, "colors_", "colors_");
GenerateLightingShader<T>(out, uid_data->lighting, components, "colors_", "col");
}
else
{
out.Write("\tfloat4 col0 = colors_0;\n");
out.Write("\tfloat4 col1 = colors_1;\n");
}
// HACK to handle cases where the tex gen is not enabled

View file

@ -221,9 +221,13 @@ private:
};
template<class T>
static void DefineOutputStructMember(T& object, API_TYPE api_type, const char* type, const char* name, int var_index, const char* semantic = "", int semantic_index = -1)
static void DefineOutputMember(T& object, API_TYPE api_type, const char* qualifier, const char* type, const char* name, int var_index, const char* semantic = "", int semantic_index = -1)
{
object.Write(" %s %s", type, name);
if (qualifier != nullptr)
object.Write("\t%s %s %s", qualifier, type, name);
else
object.Write("\t%s %s", type, name);
if (var_index != -1)
object.Write("%d", var_index);
@ -239,23 +243,35 @@ static void DefineOutputStructMember(T& object, API_TYPE api_type, const char* t
}
template<class T>
static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type)
static inline void GenerateVSOutputMembers(T& object, API_TYPE api_type, const char* qualifier = nullptr)
{
object.Write("struct VS_OUTPUT {\n");
DefineOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
DefineOutputStructMember(object, api_type, "float4", "colors_", 0, "COLOR", 0);
DefineOutputStructMember(object, api_type, "float4", "colors_", 1, "COLOR", 1);
DefineOutputMember(object, api_type, qualifier, "float4", "pos", -1, "POSITION");
DefineOutputMember(object, api_type, qualifier, "float4", "colors_", 0, "COLOR", 0);
DefineOutputMember(object, api_type, qualifier, "float4", "colors_", 1, "COLOR", 1);
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
DefineOutputStructMember(object, api_type, "float3", "tex", i, "TEXCOORD", i);
DefineOutputMember(object, api_type, qualifier, "float3", "tex", i, "TEXCOORD", i);
DefineOutputStructMember(object, api_type, "float4", "clipPos", -1, "TEXCOORD", xfmem.numTexGen.numTexGens);
DefineOutputMember(object, api_type, qualifier, "float4", "clipPos", -1, "TEXCOORD", xfmem.numTexGen.numTexGens);
if (g_ActiveConfig.bEnablePixelLighting)
DefineOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1);
DefineOutputMember(object, api_type, qualifier, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1);
}
object.Write("};\n");
template<class T>
static inline void AssignVSOutputMembers(T& object, const char* a, const char* b)
{
object.Write("\t%s.pos = %s.pos;\n", a, b);
object.Write("\t%s.colors_0 = %s.colors_0;\n", a, b);
object.Write("\t%s.colors_1 = %s.colors_1;\n", a, b);
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
object.Write("\t%s.tex%d = %s.tex%d;\n", a, i, b, i);
object.Write("\t%s.clipPos = %s.clipPos;\n", a, b);
if (g_ActiveConfig.bEnablePixelLighting)
object.Write("\t%s.Normal = %s.Normal;\n", a, b);
}
// Constant variable names

View file

@ -42,7 +42,9 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
out.Write(s_shader_uniforms);
out.Write("};\n");
GenerateVSOutputStruct<T>(out, api_type);
out.Write("struct VS_OUTPUT {\n");
GenerateVSOutputMembers<T>(out, api_type);
out.Write("};\n");
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
uid_data->components = components;
@ -74,9 +76,9 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
{
out.Write("out VertexData {\n"
"\tcentroid %s VS_OUTPUT o;\n"
"};\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? "" : "out");
out.Write("out VertexData {\n");
GenerateVSOutputMembers<T>(out, api_type, g_ActiveConfig.backend_info.bSupportsBindingLayout ? "centroid" : "centroid out");
out.Write("} vs;\n");
}
else
{
@ -91,14 +93,11 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
out.Write("centroid out float4 clipPos;\n");
if (g_ActiveConfig.bEnablePixelLighting)
out.Write("centroid out float4 Normal;\n");
out.Write("centroid out float4 colors_02;\n");
out.Write("centroid out float4 colors_12;\n");
out.Write("centroid out float4 colors_0;\n");
out.Write("centroid out float4 colors_1;\n");
}
out.Write("void main()\n{\n");
if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders)
out.Write("VS_OUTPUT o;\n");
}
else // D3D
{
@ -124,10 +123,10 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
if (components & VB_HAS_POSMTXIDX)
out.Write(" int posmtx : BLENDINDICES,\n");
out.Write(" float4 rawpos : POSITION) {\n");
out.Write("VS_OUTPUT o;\n");
}
out.Write("VS_OUTPUT o;\n");
// transforms
if (components & VB_HAS_POSMTXIDX)
{
@ -384,17 +383,21 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
if (api_type == API_OPENGL)
{
if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders)
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
{
// TODO: Pass structs between shader stages even if geometry shaders
// are not supported, however that will break GL 3.0 and 3.1 support.
AssignVSOutputMembers(out, "vs", "o");
}
else
{
// TODO: Pass interface blocks between shader stages even if geometry shaders
// are not supported, however that will require at least OpenGL 3.2 support.
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
out.Write("uv%d.xyz = o.tex%d;\n", i, i);
out.Write("clipPos = o.clipPos;\n");
if (g_ActiveConfig.bEnablePixelLighting)
out.Write("Normal = o.Normal;\n");
out.Write("colors_02 = o.colors_0;\n");
out.Write("colors_12 = o.colors_1;\n");
out.Write("colors_0 = o.colors_0;\n");
out.Write("colors_1 = o.colors_1;\n");
}
out.Write("gl_Position = o.pos;\n");