Skip to content

Commit

Permalink
Merge pull request #7729 from stenzek/adreno-sillyness
Browse files Browse the repository at this point in the history
ShaderGen: Fix broken rendering on Adreno Vulkan drivers
  • Loading branch information
stenzek authored Jan 25, 2019
2 parents ddb1fbf + 1d61041 commit 224b23b
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 111 deletions.
48 changes: 22 additions & 26 deletions Source/Core/VideoCommon/GeometryShaderGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ GeometryShaderUid GetGeometryShaderUid(PrimitiveType primitive_type)

static void EmitVertex(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, const char* vertex,
APIType ApiType, bool wireframe, bool pixel_lighting,
bool first_vertex = false);
APIType ApiType, bool wireframe, bool first_vertex = false);
static void EndPrimitive(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, APIType ApiType, bool wireframe,
bool pixel_lighting);
const geometry_shader_uid_data* uid_data, APIType ApiType, bool wireframe);

ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data)
Expand All @@ -52,7 +50,6 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
// Non-uid template parameters will write to the dummy data (=> gets optimized out)

const bool wireframe = host_config.wireframe;
const bool pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
const bool msaa = host_config.msaa;
const bool ssaa = host_config.ssaa;
const bool stereo = host_config.stereo;
Expand Down Expand Up @@ -96,7 +93,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
"};\n");

out.Write("struct VS_OUTPUT {\n");
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, pixel_lighting, "");
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, host_config, "");
out.Write("};\n");

if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
Expand All @@ -105,12 +102,12 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
out.Write("#define InstanceID gl_InvocationID\n");

out.Write("VARYING_LOCATION(0) in VertexData {\n");
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, pixel_lighting,
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, host_config,
GetInterpolationQualifier(msaa, ssaa, true, true));
out.Write("} vs[%d];\n", vertex_in);

out.Write("VARYING_LOCATION(0) out VertexData {\n");
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, pixel_lighting,
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, host_config,
GetInterpolationQualifier(msaa, ssaa, true, false));

if (stereo)
Expand Down Expand Up @@ -152,8 +149,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
{
out.Write("\tVS_OUTPUT start, end;\n");
AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, pixel_lighting);
AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, pixel_lighting);
AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, host_config);
AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, host_config);
}
else
{
Expand Down Expand Up @@ -183,7 +180,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
{
out.Write("\tVS_OUTPUT center;\n");
AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, pixel_lighting);
AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, host_config);
}
else
{
Expand Down Expand Up @@ -214,7 +211,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
{
out.Write("\tVS_OUTPUT f;\n");
AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, pixel_lighting);
AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, host_config);

if (host_config.backend_depth_clamp &&
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLIP_DISTANCE))
Expand Down Expand Up @@ -266,8 +263,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
}
out.Write("\t}\n");

EmitVertex(out, host_config, uid_data, "l", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, host_config, uid_data, "r", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "l", ApiType, wireframe, true);
EmitVertex(out, host_config, uid_data, "r", ApiType, wireframe);
}
else if (primitive_type == PrimitiveType::Points)
{
Expand Down Expand Up @@ -295,19 +292,19 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
}
out.Write("\t}\n");

EmitVertex(out, host_config, uid_data, "ll", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, host_config, uid_data, "lr", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "ul", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "ur", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "ll", ApiType, wireframe, true);
EmitVertex(out, host_config, uid_data, "lr", ApiType, wireframe);
EmitVertex(out, host_config, uid_data, "ul", ApiType, wireframe);
EmitVertex(out, host_config, uid_data, "ur", ApiType, wireframe);
}
else
{
EmitVertex(out, host_config, uid_data, "f", ApiType, wireframe, pixel_lighting, true);
EmitVertex(out, host_config, uid_data, "f", ApiType, wireframe, true);
}

out.Write("\t}\n");

EndPrimitive(out, host_config, uid_data, ApiType, wireframe, pixel_lighting);
EndPrimitive(out, host_config, uid_data, ApiType, wireframe);

if (stereo && !host_config.backend_gs_instancing)
out.Write("\t}\n");
Expand All @@ -319,7 +316,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h

static void EmitVertex(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, const char* vertex,
APIType ApiType, bool wireframe, bool pixel_lighting, bool first_vertex)
APIType ApiType, bool wireframe, bool first_vertex)
{
if (wireframe && first_vertex)
out.Write("\tif (i == 0) first = %s;\n", vertex);
Expand All @@ -332,14 +329,14 @@ static void EmitVertex(ShaderCode& out, const ShaderHostConfig& host_config,
out.Write("\tgl_ClipDistance[0] = %s.clipDist0;\n", vertex);
out.Write("\tgl_ClipDistance[1] = %s.clipDist1;\n", vertex);
}
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, pixel_lighting);
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, host_config);
}
else if (ApiType == APIType::Vulkan)
{
// Vulkan NDC space has Y pointing down (right-handed NDC space).
out.Write("\tgl_Position = %s.pos;\n", vertex);
out.Write("\tgl_Position.y = -gl_Position.y;\n");
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, pixel_lighting);
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, host_config);
}
else
{
Expand All @@ -353,11 +350,10 @@ static void EmitVertex(ShaderCode& out, const ShaderHostConfig& host_config,
}

static void EndPrimitive(ShaderCode& out, const ShaderHostConfig& host_config,
const geometry_shader_uid_data* uid_data, APIType ApiType, bool wireframe,
bool pixel_lighting)
const geometry_shader_uid_data* uid_data, APIType ApiType, bool wireframe)
{
if (wireframe)
EmitVertex(out, host_config, uid_data, "first", ApiType, wireframe, pixel_lighting);
EmitVertex(out, host_config, uid_data, "first", ApiType, wireframe);

if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
out.Write("\tEndPrimitive();\n");
Expand Down
48 changes: 30 additions & 18 deletions Source/Core/VideoCommon/PixelShaderGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ void ClearUnusedPixelShaderUidBits(APIType ApiType, const ShaderHostConfig& host
}

void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, u32 num_texgens,
bool per_pixel_lighting, bool bounding_box)
const ShaderHostConfig& host_config, bool bounding_box)
{
// dot product for integer vectors
out.Write("int idot(int3 x, int3 y)\n"
Expand Down Expand Up @@ -430,7 +430,7 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, u32 num_texg
"#define bpmem_tevorder(i) (bpmem_pack2[(i)].x)\n"
"#define bpmem_tevksel(i) (bpmem_pack2[(i)].y)\n\n");

if (per_pixel_lighting)
if (host_config.per_pixel_lighting)
{
out.Write("%s", s_lighting_struct);

Expand Down Expand Up @@ -458,7 +458,7 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, u32 num_texg
}

out.Write("struct VS_OUTPUT {\n");
GenerateVSOutputMembers(out, ApiType, num_texgens, per_pixel_lighting, "");
GenerateVSOutputMembers(out, ApiType, num_texgens, host_config, "");
out.Write("};\n");
}

Expand Down Expand Up @@ -491,7 +491,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
uid_data->genMode_numindstages);

// Stuff that is shared between ubershaders and pixelgen.
WritePixelShaderCommonHeader(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting,
WritePixelShaderCommonHeader(out, ApiType, uid_data->genMode_numtexgens, host_config,
uid_data->bounding_box);

if (uid_data->forced_early_z && g_ActiveConfig.backend_info.bSupportsEarlyZ)
Expand Down Expand Up @@ -587,11 +587,10 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
if (uid_data->per_pixel_depth)
out.Write("#define depth gl_FragDepth\n");

// We need to always use output blocks for Vulkan, but geometry shaders are also optional.
if (host_config.backend_geometry_shaders || ApiType == APIType::Vulkan)
if (host_config.backend_geometry_shaders)
{
out.Write("VARYING_LOCATION(0) in VertexData {\n");
GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting,
GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, host_config,
GetInterpolationQualifier(msaa, ssaa, true, true));

if (stereo)
Expand All @@ -601,19 +600,26 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
}
else
{
out.Write("%s in float4 colors_0;\n", GetInterpolationQualifier(msaa, ssaa));
out.Write("%s in float4 colors_1;\n", GetInterpolationQualifier(msaa, ssaa));
// compute window position if needed because binding semantic WPOS is not widely supported
// Let's set up attributes
u32 counter = 0;
out.Write("VARYING_LOCATION(%u) %s in float4 colors_0;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
out.Write("VARYING_LOCATION(%u) %s in float4 colors_1;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
{
out.Write("%s in float3 tex%d;\n", GetInterpolationQualifier(msaa, ssaa), i);
out.Write("VARYING_LOCATION(%u) %s in float3 tex%d;\n", counter++,
GetInterpolationQualifier(msaa, ssaa), i);
}
out.Write("%s in float4 clipPos;\n", GetInterpolationQualifier(msaa, ssaa));
if (!host_config.fast_depth_calc)
out.Write("VARYING_LOCATION(%u) %s in float4 clipPos;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
if (per_pixel_lighting)
{
out.Write("%s in float3 Normal;\n", GetInterpolationQualifier(msaa, ssaa));
out.Write("%s in float3 WorldPos;\n", GetInterpolationQualifier(msaa, ssaa));
out.Write("VARYING_LOCATION(%u) %s in float3 Normal;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
out.Write("VARYING_LOCATION(%u) %s in float3 WorldPos;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
}
}

Expand Down Expand Up @@ -646,17 +652,23 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
out.Write(",\n in %s float3 tex%d : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa), i,
i);
out.Write(",\n in %s float4 clipPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
uid_data->genMode_numtexgens);
if (!host_config.fast_depth_calc)
{
out.Write(",\n in %s float4 clipPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
uid_data->genMode_numtexgens);
}
if (per_pixel_lighting)
{
out.Write(",\n in %s float3 Normal : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
uid_data->genMode_numtexgens + 1);
out.Write(",\n in %s float3 WorldPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
uid_data->genMode_numtexgens + 2);
}
out.Write(",\n in float clipDist0 : SV_ClipDistance0\n");
out.Write(",\n in float clipDist1 : SV_ClipDistance1\n");
if (host_config.backend_geometry_shaders)
{
out.Write(",\n in float clipDist0 : SV_ClipDistance0\n");
out.Write(",\n in float clipDist1 : SV_ClipDistance1\n");
}
if (stereo)
out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
out.Write(" ) {\n");
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoCommon/PixelShaderGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ typedef ShaderUid<pixel_shader_uid_data> PixelShaderUid;
ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data);
void WritePixelShaderCommonHeader(ShaderCode& out, APIType ApiType, u32 num_texgens,
bool per_pixel_lighting, bool bounding_box);
const ShaderHostConfig& host_config, bool bounding_box);
void ClearUnusedPixelShaderUidBits(APIType ApiType, const ShaderHostConfig& host_config,
PixelShaderUid* uid);
PixelShaderUid GetPixelShaderUid();
28 changes: 18 additions & 10 deletions Source/Core/VideoCommon/ShaderGenCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ inline void DefineOutputMember(T& object, APIType api_type, const char* qualifie

template <class T>
inline void GenerateVSOutputMembers(T& object, APIType api_type, u32 texgens,
bool per_pixel_lighting, const char* qualifier)
const ShaderHostConfig& host_config, const char* qualifier)
{
DefineOutputMember(object, api_type, qualifier, "float4", "pos", -1, "POSITION");
DefineOutputMember(object, api_type, qualifier, "float4", "colors_", 0, "COLOR", 0);
Expand All @@ -223,23 +223,27 @@ inline void GenerateVSOutputMembers(T& object, APIType api_type, u32 texgens,
for (unsigned int i = 0; i < texgens; ++i)
DefineOutputMember(object, api_type, qualifier, "float3", "tex", i, "TEXCOORD", i);

DefineOutputMember(object, api_type, qualifier, "float4", "clipPos", -1, "TEXCOORD", texgens);
if (!host_config.fast_depth_calc)
DefineOutputMember(object, api_type, qualifier, "float4", "clipPos", -1, "TEXCOORD", texgens);

if (per_pixel_lighting)
if (host_config.per_pixel_lighting)
{
DefineOutputMember(object, api_type, qualifier, "float3", "Normal", -1, "TEXCOORD",
texgens + 1);
DefineOutputMember(object, api_type, qualifier, "float3", "WorldPos", -1, "TEXCOORD",
texgens + 2);
}

DefineOutputMember(object, api_type, qualifier, "float", "clipDist", 0, "SV_ClipDistance", 0);
DefineOutputMember(object, api_type, qualifier, "float", "clipDist", 1, "SV_ClipDistance", 1);
if (host_config.backend_geometry_shaders)
{
DefineOutputMember(object, api_type, qualifier, "float", "clipDist", 0, "SV_ClipDistance", 0);
DefineOutputMember(object, api_type, qualifier, "float", "clipDist", 1, "SV_ClipDistance", 1);
}
}

template <class T>
inline void AssignVSOutputMembers(T& object, const char* a, const char* b, u32 texgens,
bool per_pixel_lighting)
const ShaderHostConfig& host_config)
{
object.Write("\t%s.pos = %s.pos;\n", a, b);
object.Write("\t%s.colors_0 = %s.colors_0;\n", a, b);
Expand All @@ -248,16 +252,20 @@ inline void AssignVSOutputMembers(T& object, const char* a, const char* b, u32 t
for (unsigned int i = 0; i < texgens; ++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 (!host_config.fast_depth_calc)
object.Write("\t%s.clipPos = %s.clipPos;\n", a, b);

if (per_pixel_lighting)
if (host_config.per_pixel_lighting)
{
object.Write("\t%s.Normal = %s.Normal;\n", a, b);
object.Write("\t%s.WorldPos = %s.WorldPos;\n", a, b);
}

object.Write("\t%s.clipDist0 = %s.clipDist0;\n", a, b);
object.Write("\t%s.clipDist1 = %s.clipDist1;\n", a, b);
if (host_config.backend_geometry_shaders)
{
object.Write("\t%s.clipDist0 = %s.clipDist0;\n", a, b);
object.Write("\t%s.clipDist1 = %s.clipDist1;\n", a, b);
}
}

// We use the flag "centroid" to fix some MSAA rendering bugs. With MSAA, the
Expand Down
Loading

0 comments on commit 224b23b

Please sign in to comment.