ShaderGen: Remove host state from shader uids
This commit is contained in:
parent
c207a1072d
commit
82c27182a8
|
@ -18,10 +18,12 @@ static const char* primitives_ogl[] = {"points", "lines", "triangles"};
|
||||||
|
|
||||||
static const char* primitives_d3d[] = {"point", "line", "triangle"};
|
static const char* primitives_d3d[] = {"point", "line", "triangle"};
|
||||||
|
|
||||||
template <class T>
|
bool geometry_shader_uid_data::IsPassthrough() const
|
||||||
static void EmitVertex(T& out, const char* vertex, APIType ApiType, bool first_vertex = false);
|
{
|
||||||
template <class T>
|
const bool stereo = g_ActiveConfig.iStereoMode > 0;
|
||||||
static void EndPrimitive(T& out, APIType ApiType);
|
const bool wireframe = g_ActiveConfig.bWireFrame;
|
||||||
|
return primitive_type == PRIMITIVE_TRIANGLES && !stereo && !wireframe;
|
||||||
|
}
|
||||||
|
|
||||||
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type)
|
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type)
|
||||||
{
|
{
|
||||||
|
@ -30,30 +32,31 @@ GeometryShaderUid GetGeometryShaderUid(u32 primitive_type)
|
||||||
memset(uid_data, 0, sizeof(geometry_shader_uid_data));
|
memset(uid_data, 0, sizeof(geometry_shader_uid_data));
|
||||||
|
|
||||||
uid_data->primitive_type = primitive_type;
|
uid_data->primitive_type = primitive_type;
|
||||||
uid_data->wireframe = g_ActiveConfig.bWireFrame;
|
|
||||||
uid_data->msaa = g_ActiveConfig.iMultisamples > 1;
|
|
||||||
uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA;
|
|
||||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
|
||||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
||||||
const char* vertex, APIType ApiType, bool first_vertex = false);
|
const char* vertex, APIType ApiType, bool wireframe, bool pixel_lighting,
|
||||||
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
bool first_vertex = false);
|
||||||
APIType ApiType);
|
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType,
|
||||||
|
bool wireframe, bool pixel_lighting);
|
||||||
|
|
||||||
ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid_data* uid_data)
|
ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid_data* uid_data)
|
||||||
{
|
{
|
||||||
ShaderCode out;
|
ShaderCode out;
|
||||||
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
|
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
|
||||||
|
|
||||||
|
const bool wireframe = g_ActiveConfig.bWireFrame;
|
||||||
|
const bool pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||||
|
const bool msaa = g_ActiveConfig.IsMSAAEnabled();
|
||||||
|
const bool ssaa = g_ActiveConfig.IsSSAAEnabled();
|
||||||
|
const bool stereo = g_ActiveConfig.IsStereoEnabled();
|
||||||
const unsigned int vertex_in = uid_data->primitive_type + 1;
|
const unsigned int vertex_in = uid_data->primitive_type + 1;
|
||||||
unsigned int vertex_out = uid_data->primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4;
|
unsigned int vertex_out = uid_data->primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4;
|
||||||
|
|
||||||
if (uid_data->wireframe)
|
if (wireframe)
|
||||||
vertex_out++;
|
vertex_out++;
|
||||||
|
|
||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
|
@ -62,16 +65,15 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||||
{
|
{
|
||||||
out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[uid_data->primitive_type],
|
out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[uid_data->primitive_type],
|
||||||
uid_data->stereo ? 2 : 1);
|
stereo ? 2 : 1);
|
||||||
out.Write("layout(%s_strip, max_vertices = %d) out;\n",
|
out.Write("layout(%s_strip, max_vertices = %d) out;\n", wireframe ? "line" : "triangle",
|
||||||
uid_data->wireframe ? "line" : "triangle", vertex_out);
|
vertex_out);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.Write("layout(%s) in;\n", primitives_ogl[uid_data->primitive_type]);
|
out.Write("layout(%s) in;\n", primitives_ogl[uid_data->primitive_type]);
|
||||||
out.Write("layout(%s_strip, max_vertices = %d) out;\n",
|
out.Write("layout(%s_strip, max_vertices = %d) out;\n", wireframe ? "line" : "triangle",
|
||||||
uid_data->wireframe ? "line" : "triangle",
|
stereo ? vertex_out * 2 : vertex_out);
|
||||||
uid_data->stereo ? vertex_out * 2 : vertex_out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +91,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
"};\n");
|
"};\n");
|
||||||
|
|
||||||
out.Write("struct VS_OUTPUT {\n");
|
out.Write("struct VS_OUTPUT {\n");
|
||||||
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting,
|
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, pixel_lighting, "");
|
||||||
"");
|
|
||||||
out.Write("};\n");
|
out.Write("};\n");
|
||||||
|
|
||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
|
@ -99,17 +100,15 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
out.Write("#define InstanceID gl_InvocationID\n");
|
out.Write("#define InstanceID gl_InvocationID\n");
|
||||||
|
|
||||||
out.Write("VARYING_LOCATION(0) in VertexData {\n");
|
out.Write("VARYING_LOCATION(0) in VertexData {\n");
|
||||||
GenerateVSOutputMembers<ShaderCode>(
|
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, pixel_lighting,
|
||||||
out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting,
|
GetInterpolationQualifier(msaa, ssaa, true, true));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true));
|
|
||||||
out.Write("} vs[%d];\n", vertex_in);
|
out.Write("} vs[%d];\n", vertex_in);
|
||||||
|
|
||||||
out.Write("VARYING_LOCATION(0) out VertexData {\n");
|
out.Write("VARYING_LOCATION(0) out VertexData {\n");
|
||||||
GenerateVSOutputMembers<ShaderCode>(
|
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, pixel_lighting,
|
||||||
out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting,
|
GetInterpolationQualifier(msaa, ssaa, true, false));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, false));
|
|
||||||
|
|
||||||
if (uid_data->stereo)
|
if (stereo)
|
||||||
out.Write("\tflat int layer;\n");
|
out.Write("\tflat int layer;\n");
|
||||||
|
|
||||||
out.Write("} ps;\n");
|
out.Write("} ps;\n");
|
||||||
|
@ -121,25 +120,25 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
out.Write("struct VertexData {\n");
|
out.Write("struct VertexData {\n");
|
||||||
out.Write("\tVS_OUTPUT o;\n");
|
out.Write("\tVS_OUTPUT o;\n");
|
||||||
|
|
||||||
if (uid_data->stereo)
|
if (stereo)
|
||||||
out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n");
|
out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n");
|
||||||
|
|
||||||
out.Write("};\n");
|
out.Write("};\n");
|
||||||
|
|
||||||
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||||
{
|
{
|
||||||
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, uid_data->stereo ? 2 : 1);
|
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, stereo ? 2 : 1);
|
||||||
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output, in uint "
|
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output, in uint "
|
||||||
"InstanceID : SV_GSInstanceID)\n{\n",
|
"InstanceID : SV_GSInstanceID)\n{\n",
|
||||||
primitives_d3d[uid_data->primitive_type], vertex_in,
|
primitives_d3d[uid_data->primitive_type], vertex_in,
|
||||||
uid_data->wireframe ? "Line" : "Triangle");
|
wireframe ? "Line" : "Triangle");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.Write("[maxvertexcount(%d)]\n", uid_data->stereo ? vertex_out * 2 : vertex_out);
|
out.Write("[maxvertexcount(%d)]\n", stereo ? vertex_out * 2 : vertex_out);
|
||||||
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output)\n{\n",
|
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output)\n{\n",
|
||||||
primitives_d3d[uid_data->primitive_type], vertex_in,
|
primitives_d3d[uid_data->primitive_type], vertex_in,
|
||||||
uid_data->wireframe ? "Line" : "Triangle");
|
wireframe ? "Line" : "Triangle");
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("\tVertexData ps;\n");
|
out.Write("\tVertexData ps;\n");
|
||||||
|
@ -150,8 +149,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
out.Write("\tVS_OUTPUT start, end;\n");
|
out.Write("\tVS_OUTPUT start, end;\n");
|
||||||
AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, pixel_lighting);
|
||||||
AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, pixel_lighting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -181,7 +180,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
out.Write("\tVS_OUTPUT center;\n");
|
out.Write("\tVS_OUTPUT center;\n");
|
||||||
AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, pixel_lighting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -194,7 +193,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
".x, -" I_LINEPTPARAMS ".w / " I_LINEPTPARAMS ".y) * center.pos.w;\n");
|
".x, -" I_LINEPTPARAMS ".w / " I_LINEPTPARAMS ".y) * center.pos.w;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid_data->stereo)
|
if (stereo)
|
||||||
{
|
{
|
||||||
// If the GPU supports invocation we don't need a for loop and can simply use the
|
// If the GPU supports invocation we don't need a for loop and can simply use the
|
||||||
// invocation identifier to determine which layer we're rendering.
|
// invocation identifier to determine which layer we're rendering.
|
||||||
|
@ -204,7 +203,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n");
|
out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid_data->wireframe)
|
if (wireframe)
|
||||||
out.Write("\tVS_OUTPUT first;\n");
|
out.Write("\tVS_OUTPUT first;\n");
|
||||||
|
|
||||||
out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in);
|
out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in);
|
||||||
|
@ -212,7 +211,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
out.Write("\tVS_OUTPUT f;\n");
|
out.Write("\tVS_OUTPUT f;\n");
|
||||||
AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, pixel_lighting);
|
||||||
|
|
||||||
if (g_ActiveConfig.backend_info.bSupportsDepthClamp &&
|
if (g_ActiveConfig.backend_info.bSupportsDepthClamp &&
|
||||||
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLIP_DISTANCE))
|
DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLIP_DISTANCE))
|
||||||
|
@ -228,7 +227,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
out.Write("\tVS_OUTPUT f = o[i];\n");
|
out.Write("\tVS_OUTPUT f = o[i];\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid_data->stereo)
|
if (stereo)
|
||||||
{
|
{
|
||||||
// Select the output layer
|
// Select the output layer
|
||||||
out.Write("\tps.layer = eye;\n");
|
out.Write("\tps.layer = eye;\n");
|
||||||
|
@ -264,8 +263,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
}
|
}
|
||||||
out.Write("\t}\n");
|
out.Write("\t}\n");
|
||||||
|
|
||||||
EmitVertex(out, uid_data, "l", ApiType, true);
|
EmitVertex(out, uid_data, "l", ApiType, wireframe, pixel_lighting, true);
|
||||||
EmitVertex(out, uid_data, "r", ApiType);
|
EmitVertex(out, uid_data, "r", ApiType, wireframe, pixel_lighting);
|
||||||
}
|
}
|
||||||
else if (uid_data->primitive_type == PRIMITIVE_POINTS)
|
else if (uid_data->primitive_type == PRIMITIVE_POINTS)
|
||||||
{
|
{
|
||||||
|
@ -293,21 +292,21 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
}
|
}
|
||||||
out.Write("\t}\n");
|
out.Write("\t}\n");
|
||||||
|
|
||||||
EmitVertex(out, uid_data, "ll", ApiType, true);
|
EmitVertex(out, uid_data, "ll", ApiType, wireframe, pixel_lighting, true);
|
||||||
EmitVertex(out, uid_data, "lr", ApiType);
|
EmitVertex(out, uid_data, "lr", ApiType, wireframe, pixel_lighting);
|
||||||
EmitVertex(out, uid_data, "ul", ApiType);
|
EmitVertex(out, uid_data, "ul", ApiType, wireframe, pixel_lighting);
|
||||||
EmitVertex(out, uid_data, "ur", ApiType);
|
EmitVertex(out, uid_data, "ur", ApiType, wireframe, pixel_lighting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVertex(out, uid_data, "f", ApiType, true);
|
EmitVertex(out, uid_data, "f", ApiType, wireframe, pixel_lighting, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("\t}\n");
|
out.Write("\t}\n");
|
||||||
|
|
||||||
EndPrimitive(out, uid_data, ApiType);
|
EndPrimitive(out, uid_data, ApiType, wireframe, pixel_lighting);
|
||||||
|
|
||||||
if (uid_data->stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
if (stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||||
out.Write("\t}\n");
|
out.Write("\t}\n");
|
||||||
|
|
||||||
out.Write("}\n");
|
out.Write("}\n");
|
||||||
|
@ -316,9 +315,10 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
||||||
const char* vertex, APIType ApiType, bool first_vertex)
|
const char* vertex, APIType ApiType, bool wireframe, bool pixel_lighting,
|
||||||
|
bool first_vertex)
|
||||||
{
|
{
|
||||||
if (uid_data->wireframe && first_vertex)
|
if (wireframe && first_vertex)
|
||||||
out.Write("\tif (i == 0) first = %s;\n", vertex);
|
out.Write("\tif (i == 0) first = %s;\n", vertex);
|
||||||
|
|
||||||
if (ApiType == APIType::OpenGL)
|
if (ApiType == APIType::OpenGL)
|
||||||
|
@ -329,14 +329,14 @@ static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data
|
||||||
out.Write("\tgl_ClipDistance[0] = %s.clipDist0;\n", vertex);
|
out.Write("\tgl_ClipDistance[0] = %s.clipDist0;\n", vertex);
|
||||||
out.Write("\tgl_ClipDistance[1] = %s.clipDist1;\n", vertex);
|
out.Write("\tgl_ClipDistance[1] = %s.clipDist1;\n", vertex);
|
||||||
}
|
}
|
||||||
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, pixel_lighting);
|
||||||
}
|
}
|
||||||
else if (ApiType == APIType::Vulkan)
|
else if (ApiType == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
// Vulkan NDC space has Y pointing down (right-handed NDC space).
|
// Vulkan NDC space has Y pointing down (right-handed NDC space).
|
||||||
out.Write("\tgl_Position = %s.pos;\n", vertex);
|
out.Write("\tgl_Position = %s.pos;\n", vertex);
|
||||||
out.Write("\tgl_Position.y = -gl_Position.y;\n");
|
out.Write("\tgl_Position.y = -gl_Position.y;\n");
|
||||||
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, pixel_lighting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -349,10 +349,11 @@ static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data
|
||||||
out.Write("\toutput.Append(ps);\n");
|
out.Write("\toutput.Append(ps);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType)
|
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType,
|
||||||
|
bool wireframe, bool pixel_lighting)
|
||||||
{
|
{
|
||||||
if (uid_data->wireframe)
|
if (wireframe)
|
||||||
EmitVertex(out, uid_data, "first", ApiType);
|
EmitVertex(out, uid_data, "first", ApiType, wireframe, pixel_lighting);
|
||||||
|
|
||||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||||
out.Write("\tEndPrimitive();\n");
|
out.Write("\tEndPrimitive();\n");
|
||||||
|
|
|
@ -15,18 +15,10 @@ enum class APIType;
|
||||||
struct geometry_shader_uid_data
|
struct geometry_shader_uid_data
|
||||||
{
|
{
|
||||||
u32 NumValues() const { return sizeof(geometry_shader_uid_data); }
|
u32 NumValues() const { return sizeof(geometry_shader_uid_data); }
|
||||||
bool IsPassthrough() const
|
bool IsPassthrough() const;
|
||||||
{
|
|
||||||
return primitive_type == PRIMITIVE_TRIANGLES && !stereo && !wireframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 stereo : 1;
|
|
||||||
u32 numTexGens : 4;
|
u32 numTexGens : 4;
|
||||||
u32 pixel_lighting : 1;
|
|
||||||
u32 primitive_type : 2;
|
u32 primitive_type : 2;
|
||||||
u32 wireframe : 1;
|
|
||||||
u32 msaa : 1;
|
|
||||||
u32 ssaa : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
|
@ -170,7 +170,6 @@ PixelShaderUid GetPixelShaderUid()
|
||||||
uid_data->genMode_numindstages = bpmem.genMode.numindstages;
|
uid_data->genMode_numindstages = bpmem.genMode.numindstages;
|
||||||
uid_data->genMode_numtevstages = bpmem.genMode.numtevstages;
|
uid_data->genMode_numtevstages = bpmem.genMode.numtevstages;
|
||||||
uid_data->genMode_numtexgens = bpmem.genMode.numtexgens;
|
uid_data->genMode_numtexgens = bpmem.genMode.numtexgens;
|
||||||
uid_data->per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
|
||||||
uid_data->bounding_box = g_ActiveConfig.BBoxUseFragmentShaderImplementation() &&
|
uid_data->bounding_box = g_ActiveConfig.BBoxUseFragmentShaderImplementation() &&
|
||||||
g_ActiveConfig.bBBoxEnable && BoundingBox::active;
|
g_ActiveConfig.bBBoxEnable && BoundingBox::active;
|
||||||
uid_data->rgba6_format =
|
uid_data->rgba6_format =
|
||||||
|
@ -192,13 +191,9 @@ PixelShaderUid GetPixelShaderUid()
|
||||||
|
|
||||||
uid_data->per_pixel_depth = per_pixel_depth;
|
uid_data->per_pixel_depth = per_pixel_depth;
|
||||||
uid_data->forced_early_z = forced_early_z;
|
uid_data->forced_early_z = forced_early_z;
|
||||||
uid_data->fast_depth_calc = g_ActiveConfig.bFastDepthCalc;
|
|
||||||
uid_data->msaa = g_ActiveConfig.iMultisamples > 1;
|
|
||||||
uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA;
|
|
||||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
|
||||||
|
|
||||||
if (!uid_data->forced_early_z && bpmem.UseEarlyDepthTest() &&
|
if (!uid_data->forced_early_z && bpmem.UseEarlyDepthTest() &&
|
||||||
(!uid_data->fast_depth_calc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED))
|
(!g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED))
|
||||||
{
|
{
|
||||||
static bool warn_once = true;
|
static bool warn_once = true;
|
||||||
if (warn_once)
|
if (warn_once)
|
||||||
|
@ -209,7 +204,7 @@ PixelShaderUid GetPixelShaderUid()
|
||||||
warn_once = false;
|
warn_once = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid_data->per_pixel_lighting)
|
if (g_ActiveConfig.bEnablePixelLighting)
|
||||||
{
|
{
|
||||||
// The lighting shader only needs the two color bits of the 23bit component bit array.
|
// The lighting shader only needs the two color bits of the 23bit component bit array.
|
||||||
uid_data->components =
|
uid_data->components =
|
||||||
|
@ -297,7 +292,7 @@ PixelShaderUid GetPixelShaderUid()
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MY_STRUCT_OFFSET(str, elem) ((u32)((u64) & (str).elem - (u64) & (str)))
|
#define MY_STRUCT_OFFSET(str, elem) ((u32)((u64) & (str).elem - (u64) & (str)))
|
||||||
uid_data->num_values = (uid_data->per_pixel_lighting) ?
|
uid_data->num_values = (g_ActiveConfig.bEnablePixelLighting) ?
|
||||||
sizeof(*uid_data) :
|
sizeof(*uid_data) :
|
||||||
MY_STRUCT_OFFSET(*uid_data, stagehash[numStages]);
|
MY_STRUCT_OFFSET(*uid_data, stagehash[numStages]);
|
||||||
|
|
||||||
|
@ -339,7 +334,7 @@ PixelShaderUid GetPixelShaderUid()
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
|
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
|
||||||
APIType ApiType);
|
APIType ApiType, bool stereo);
|
||||||
static void WriteTevRegular(ShaderCode& out, const char* components, int bias, int op, int clamp,
|
static void WriteTevRegular(ShaderCode& out, const char* components, int bias, int op, int clamp,
|
||||||
int shift, bool alpha);
|
int shift, bool alpha);
|
||||||
static void SampleTexture(ShaderCode& out, const char* texcoords, const char* texswap, int texmap,
|
static void SampleTexture(ShaderCode& out, const char* texcoords, const char* texswap, int texmap,
|
||||||
|
@ -354,7 +349,11 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
{
|
{
|
||||||
ShaderCode out;
|
ShaderCode out;
|
||||||
|
|
||||||
u32 numStages = uid_data->genMode_numtevstages + 1;
|
const bool per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||||
|
const bool msaa = g_ActiveConfig.IsMSAAEnabled();
|
||||||
|
const bool ssaa = g_ActiveConfig.IsSSAAEnabled();
|
||||||
|
const bool stereo = g_ActiveConfig.IsStereoEnabled();
|
||||||
|
const u32 numStages = uid_data->genMode_numtevstages + 1;
|
||||||
|
|
||||||
out.Write("//Pixel Shader for TEV stages\n");
|
out.Write("//Pixel Shader for TEV stages\n");
|
||||||
out.Write("//%i TEV stages, %i texgens, %i IND stages\n", numStages, uid_data->genMode_numtexgens,
|
out.Write("//%i TEV stages, %i texgens, %i IND stages\n", numStages, uid_data->genMode_numtexgens,
|
||||||
|
@ -422,7 +421,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
"\tfloat4 " I_EFBSCALE ";\n"
|
"\tfloat4 " I_EFBSCALE ";\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
|
|
||||||
if (uid_data->per_pixel_lighting)
|
if (per_pixel_lighting)
|
||||||
{
|
{
|
||||||
out.Write("%s", s_lighting_struct);
|
out.Write("%s", s_lighting_struct);
|
||||||
|
|
||||||
|
@ -450,8 +449,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("struct VS_OUTPUT {\n");
|
out.Write("struct VS_OUTPUT {\n");
|
||||||
GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, uid_data->per_pixel_lighting,
|
GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting, "");
|
||||||
"");
|
|
||||||
out.Write("};\n");
|
out.Write("};\n");
|
||||||
|
|
||||||
if (uid_data->forced_early_z)
|
if (uid_data->forced_early_z)
|
||||||
|
@ -534,36 +532,29 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || ApiType == APIType::Vulkan)
|
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || ApiType == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
out.Write("VARYING_LOCATION(0) in VertexData {\n");
|
out.Write("VARYING_LOCATION(0) in VertexData {\n");
|
||||||
GenerateVSOutputMembers(
|
GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting,
|
||||||
out, ApiType, uid_data->genMode_numtexgens, uid_data->per_pixel_lighting,
|
GetInterpolationQualifier(msaa, ssaa, true, true));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true));
|
|
||||||
|
|
||||||
if (uid_data->stereo)
|
if (stereo)
|
||||||
out.Write("\tflat int layer;\n");
|
out.Write("\tflat int layer;\n");
|
||||||
|
|
||||||
out.Write("};\n");
|
out.Write("};\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.Write("%s in float4 colors_0;\n",
|
out.Write("%s in float4 colors_0;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
out.Write("%s in float4 colors_1;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
out.Write("%s in float4 colors_1;\n",
|
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
|
||||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||||
// Let's set up attributes
|
// Let's set up attributes
|
||||||
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
|
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
|
||||||
{
|
{
|
||||||
out.Write("%s in float3 uv%d;\n", GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa),
|
out.Write("%s in float3 uv%d;\n", GetInterpolationQualifier(msaa, ssaa), i);
|
||||||
i);
|
|
||||||
}
|
}
|
||||||
out.Write("%s in float4 clipPos;\n",
|
out.Write("%s in float4 clipPos;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
if (per_pixel_lighting)
|
||||||
if (uid_data->per_pixel_lighting)
|
|
||||||
{
|
{
|
||||||
out.Write("%s in float3 Normal;\n",
|
out.Write("%s in float3 Normal;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
out.Write("%s in float3 WorldPos;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
out.Write("%s in float3 WorldPos;\n",
|
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,30 +576,24 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
" in float4 rawpos : SV_Position,\n",
|
" in float4 rawpos : SV_Position,\n",
|
||||||
uid_data->per_pixel_depth ? " out float depth : SV_Depth,\n" : "");
|
uid_data->per_pixel_depth ? " out float depth : SV_Depth,\n" : "");
|
||||||
|
|
||||||
out.Write(" in %s float4 colors_0 : COLOR0,\n",
|
out.Write(" in %s float4 colors_0 : COLOR0,\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
out.Write(" in %s float4 colors_1 : COLOR1\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
out.Write(" in %s float4 colors_1 : COLOR1\n",
|
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
|
||||||
|
|
||||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||||
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
|
for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i)
|
||||||
out.Write(",\n in %s float3 uv%d : TEXCOORD%d",
|
out.Write(",\n in %s float3 uv%d : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa), i, i);
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), i, i);
|
out.Write(",\n in %s float4 clipPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
|
||||||
out.Write(",\n in %s float4 clipPos : TEXCOORD%d",
|
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa),
|
|
||||||
uid_data->genMode_numtexgens);
|
uid_data->genMode_numtexgens);
|
||||||
if (uid_data->per_pixel_lighting)
|
if (per_pixel_lighting)
|
||||||
{
|
{
|
||||||
out.Write(",\n in %s float3 Normal : TEXCOORD%d",
|
out.Write(",\n in %s float3 Normal : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa),
|
|
||||||
uid_data->genMode_numtexgens + 1);
|
uid_data->genMode_numtexgens + 1);
|
||||||
out.Write(",\n in %s float3 WorldPos : TEXCOORD%d",
|
out.Write(",\n in %s float3 WorldPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa),
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa),
|
|
||||||
uid_data->genMode_numtexgens + 2);
|
uid_data->genMode_numtexgens + 2);
|
||||||
}
|
}
|
||||||
out.Write(",\n in float clipDist0 : SV_ClipDistance0\n");
|
out.Write(",\n in float clipDist0 : SV_ClipDistance0\n");
|
||||||
out.Write(",\n in float clipDist1 : SV_ClipDistance1\n");
|
out.Write(",\n in float clipDist1 : SV_ClipDistance1\n");
|
||||||
if (uid_data->stereo)
|
if (stereo)
|
||||||
out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
|
out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
|
||||||
out.Write(" ) {\n");
|
out.Write(" ) {\n");
|
||||||
}
|
}
|
||||||
|
@ -630,7 +615,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
out.Write("\tfloat4 col0 = colors_0;\n");
|
out.Write("\tfloat4 col0 = colors_0;\n");
|
||||||
out.Write("\tfloat4 col1 = colors_1;\n");
|
out.Write("\tfloat4 col1 = colors_1;\n");
|
||||||
|
|
||||||
if (uid_data->per_pixel_lighting)
|
if (per_pixel_lighting)
|
||||||
{
|
{
|
||||||
out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
|
out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||||
out.Write("\tfloat3 pos = WorldPos;\n");
|
out.Write("\tfloat3 pos = WorldPos;\n");
|
||||||
|
@ -682,12 +667,12 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
out.Write("\ttempcoord = int2(0, 0);\n");
|
out.Write("\ttempcoord = int2(0, 0);\n");
|
||||||
|
|
||||||
out.Write("\tint3 iindtex%d = ", i);
|
out.Write("\tint3 iindtex%d = ", i);
|
||||||
SampleTexture(out, "float2(tempcoord)", "abg", texmap, uid_data->stereo, ApiType);
|
SampleTexture(out, "float2(tempcoord)", "abg", texmap, stereo, ApiType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < numStages; i++)
|
for (unsigned int i = 0; i < numStages; i++)
|
||||||
WriteStage(out, uid_data, i, ApiType); // build the equation for this stage
|
WriteStage(out, uid_data, i, ApiType, stereo); // build the equation for this stage
|
||||||
|
|
||||||
{
|
{
|
||||||
// The results of the last texenv stage are put onto the screen,
|
// The results of the last texenv stage are put onto the screen,
|
||||||
|
@ -728,7 +713,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
out.Write("\tint zCoord = int(" I_ZSLOPE ".z + " I_ZSLOPE ".x * screenpos.x + " I_ZSLOPE
|
out.Write("\tint zCoord = int(" I_ZSLOPE ".z + " I_ZSLOPE ".x * screenpos.x + " I_ZSLOPE
|
||||||
".y * screenpos.y);\n");
|
".y * screenpos.y);\n");
|
||||||
}
|
}
|
||||||
else if (!uid_data->fast_depth_calc)
|
else if (!g_ActiveConfig.bFastDepthCalc)
|
||||||
{
|
{
|
||||||
// FastDepth means to trust the depth generated in perspective division.
|
// FastDepth means to trust the depth generated in perspective division.
|
||||||
// It should be correct, but it seems not to be as accurate as required. TODO: Find out why!
|
// It should be correct, but it seems not to be as accurate as required. TODO: Find out why!
|
||||||
|
@ -814,7 +799,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data*
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
|
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
|
||||||
APIType ApiType)
|
APIType ApiType, bool stereo)
|
||||||
{
|
{
|
||||||
auto& stage = uid_data->stagehash[n];
|
auto& stage = uid_data->stagehash[n];
|
||||||
out.Write("\n\t// TEV stage %d\n", n);
|
out.Write("\n\t// TEV stage %d\n", n);
|
||||||
|
@ -1013,8 +998,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
out.Write("\ttevcoord.xy = int2(0, 0);\n");
|
out.Write("\ttevcoord.xy = int2(0, 0);\n");
|
||||||
}
|
}
|
||||||
out.Write("\ttextemp = ");
|
out.Write("\ttextemp = ");
|
||||||
SampleTexture(out, "float2(tevcoord.xy)", texswap, stage.tevorders_texmap, uid_data->stereo,
|
SampleTexture(out, "float2(tevcoord.xy)", texswap, stage.tevorders_texmap, stereo, ApiType);
|
||||||
ApiType);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,11 +18,10 @@ struct pixel_shader_uid_data
|
||||||
u32 num_values; // TODO: Shouldn't be a u32
|
u32 num_values; // TODO: Shouldn't be a u32
|
||||||
u32 NumValues() const { return num_values; }
|
u32 NumValues() const { return num_values; }
|
||||||
u32 components : 2;
|
u32 components : 2;
|
||||||
u32 pad0 : 1;
|
u32 pad0 : 2;
|
||||||
u32 useDstAlpha : 1;
|
u32 useDstAlpha : 1;
|
||||||
u32 Pretest : 2;
|
u32 Pretest : 2;
|
||||||
u32 nIndirectStagesUsed : 4;
|
u32 nIndirectStagesUsed : 4;
|
||||||
u32 stereo : 1;
|
|
||||||
u32 genMode_numtexgens : 4;
|
u32 genMode_numtexgens : 4;
|
||||||
u32 genMode_numtevstages : 4;
|
u32 genMode_numtevstages : 4;
|
||||||
u32 genMode_numindstages : 3;
|
u32 genMode_numindstages : 3;
|
||||||
|
@ -35,20 +34,16 @@ struct pixel_shader_uid_data
|
||||||
u32 fog_fsel : 3;
|
u32 fog_fsel : 3;
|
||||||
u32 fog_RangeBaseEnabled : 1;
|
u32 fog_RangeBaseEnabled : 1;
|
||||||
u32 ztex_op : 2;
|
u32 ztex_op : 2;
|
||||||
u32 fast_depth_calc : 1;
|
|
||||||
u32 per_pixel_depth : 1;
|
u32 per_pixel_depth : 1;
|
||||||
u32 per_pixel_lighting : 1;
|
|
||||||
u32 forced_early_z : 1;
|
u32 forced_early_z : 1;
|
||||||
u32 early_ztest : 1;
|
u32 early_ztest : 1;
|
||||||
u32 late_ztest : 1;
|
u32 late_ztest : 1;
|
||||||
u32 bounding_box : 1;
|
u32 bounding_box : 1;
|
||||||
u32 zfreeze : 1;
|
u32 zfreeze : 1;
|
||||||
u32 msaa : 1;
|
|
||||||
u32 ssaa : 1;
|
|
||||||
u32 numColorChans : 2;
|
u32 numColorChans : 2;
|
||||||
u32 rgba6_format : 1;
|
u32 rgba6_format : 1;
|
||||||
u32 dither : 1;
|
u32 dither : 1;
|
||||||
u32 pad : 12;
|
u32 pad : 16;
|
||||||
|
|
||||||
u32 texMtxInfo_n_projection : 8; // 8x1 bit
|
u32 texMtxInfo_n_projection : 8; // 8x1 bit
|
||||||
u32 tevindref_bi0 : 3;
|
u32 tevindref_bi0 : 3;
|
||||||
|
|
|
@ -26,11 +26,6 @@ VertexShaderUid GetVertexShaderUid()
|
||||||
|
|
||||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||||
uid_data->components = VertexLoaderManager::g_current_components;
|
uid_data->components = VertexLoaderManager::g_current_components;
|
||||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
|
||||||
uid_data->vertex_rounding =
|
|
||||||
g_ActiveConfig.bVertexRounding && g_ActiveConfig.iEFBScale != SCALE_1X;
|
|
||||||
uid_data->msaa = g_ActiveConfig.iMultisamples > 1;
|
|
||||||
uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA;
|
|
||||||
uid_data->numColorChans = xfmem.numChan.numColorChans;
|
uid_data->numColorChans = xfmem.numChan.numColorChans;
|
||||||
|
|
||||||
GetLightingShaderUid(uid_data->lighting);
|
GetLightingShaderUid(uid_data->lighting);
|
||||||
|
@ -84,6 +79,12 @@ VertexShaderUid GetVertexShaderUid()
|
||||||
ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_data* uid_data)
|
ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_data* uid_data)
|
||||||
{
|
{
|
||||||
ShaderCode out;
|
ShaderCode out;
|
||||||
|
|
||||||
|
const bool per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||||
|
const bool msaa = g_ActiveConfig.IsMSAAEnabled();
|
||||||
|
const bool ssaa = g_ActiveConfig.IsSSAAEnabled();
|
||||||
|
const bool vertex_rounding = g_ActiveConfig.UseVertexRounding();
|
||||||
|
|
||||||
out.Write("%s", s_lighting_struct);
|
out.Write("%s", s_lighting_struct);
|
||||||
|
|
||||||
// uniforms
|
// uniforms
|
||||||
|
@ -96,7 +97,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
out.Write("};\n");
|
out.Write("};\n");
|
||||||
|
|
||||||
out.Write("struct VS_OUTPUT {\n");
|
out.Write("struct VS_OUTPUT {\n");
|
||||||
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, "");
|
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, per_pixel_lighting, "");
|
||||||
out.Write("};\n");
|
out.Write("};\n");
|
||||||
|
|
||||||
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
|
if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
|
||||||
|
@ -130,9 +131,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan)
|
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
out.Write("VARYING_LOCATION(0) out VertexData {\n");
|
out.Write("VARYING_LOCATION(0) out VertexData {\n");
|
||||||
GenerateVSOutputMembers(
|
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, per_pixel_lighting,
|
||||||
out, api_type, uid_data->numTexGens, uid_data->pixel_lighting,
|
GetInterpolationQualifier(msaa, ssaa, true, false));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, false));
|
|
||||||
out.Write("} vs;\n");
|
out.Write("} vs;\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -142,23 +142,17 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
{
|
{
|
||||||
if (i < uid_data->numTexGens)
|
if (i < uid_data->numTexGens)
|
||||||
{
|
{
|
||||||
out.Write("%s out float3 uv%u;\n",
|
out.Write("%s out float3 uv%u;\n", GetInterpolationQualifier(msaa, ssaa), i);
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.Write("%s out float4 clipPos;\n",
|
out.Write("%s out float4 clipPos;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
if (per_pixel_lighting)
|
||||||
if (uid_data->pixel_lighting)
|
|
||||||
{
|
{
|
||||||
out.Write("%s out float3 Normal;\n",
|
out.Write("%s out float3 Normal;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
out.Write("%s out float3 WorldPos;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
out.Write("%s out float3 WorldPos;\n",
|
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
|
||||||
}
|
}
|
||||||
out.Write("%s out float4 colors_0;\n",
|
out.Write("%s out float4 colors_0;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
out.Write("%s out float4 colors_1;\n", GetInterpolationQualifier(msaa, ssaa));
|
||||||
out.Write("%s out float4 colors_1;\n",
|
|
||||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Write("void main()\n{\n");
|
out.Write("void main()\n{\n");
|
||||||
|
@ -406,7 +400,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
// clipPos/w needs to be done in pixel shader, not here
|
// clipPos/w needs to be done in pixel shader, not here
|
||||||
out.Write("o.clipPos = o.pos;\n");
|
out.Write("o.clipPos = o.pos;\n");
|
||||||
|
|
||||||
if (uid_data->pixel_lighting)
|
if (per_pixel_lighting)
|
||||||
{
|
{
|
||||||
out.Write("o.Normal = _norm0;\n");
|
out.Write("o.Normal = _norm0;\n");
|
||||||
out.Write("o.WorldPos = pos.xyz;\n");
|
out.Write("o.WorldPos = pos.xyz;\n");
|
||||||
|
@ -466,7 +460,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
// get rasterized correctly.
|
// get rasterized correctly.
|
||||||
out.Write("o.pos.xy = o.pos.xy - o.pos.w * " I_PIXELCENTERCORRECTION ".xy;\n");
|
out.Write("o.pos.xy = o.pos.xy - o.pos.w * " I_PIXELCENTERCORRECTION ".xy;\n");
|
||||||
|
|
||||||
if (uid_data->vertex_rounding)
|
if (vertex_rounding)
|
||||||
{
|
{
|
||||||
// By now our position is in clip space
|
// By now our position is in clip space
|
||||||
// however, higher resolutions than the Wii outputs
|
// however, higher resolutions than the Wii outputs
|
||||||
|
@ -493,7 +487,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
{
|
{
|
||||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan)
|
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan)
|
||||||
{
|
{
|
||||||
AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, uid_data->pixel_lighting);
|
AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, per_pixel_lighting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -502,7 +496,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
|
||||||
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
||||||
out.Write("uv%d.xyz = o.tex%d;\n", i, i);
|
out.Write("uv%d.xyz = o.tex%d;\n", i, i);
|
||||||
out.Write("clipPos = o.clipPos;\n");
|
out.Write("clipPos = o.clipPos;\n");
|
||||||
if (uid_data->pixel_lighting)
|
if (per_pixel_lighting)
|
||||||
{
|
{
|
||||||
out.Write("Normal = o.Normal;\n");
|
out.Write("Normal = o.Normal;\n");
|
||||||
out.Write("WorldPos = o.WorldPos;\n");
|
out.Write("WorldPos = o.WorldPos;\n");
|
||||||
|
|
|
@ -37,14 +37,10 @@ struct vertex_shader_uid_data
|
||||||
u32 numTexGens : 4;
|
u32 numTexGens : 4;
|
||||||
u32 numColorChans : 2;
|
u32 numColorChans : 2;
|
||||||
u32 dualTexTrans_enabled : 1;
|
u32 dualTexTrans_enabled : 1;
|
||||||
u32 pixel_lighting : 1;
|
|
||||||
u32 msaa : 1;
|
|
||||||
|
|
||||||
u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is
|
u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is
|
||||||
// 8 bits wide
|
// 8 bits wide
|
||||||
u32 ssaa : 1;
|
u32 pad : 18;
|
||||||
u32 vertex_rounding : 1;
|
|
||||||
u32 pad : 14;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,3 +187,19 @@ bool VideoConfig::IsVSync()
|
||||||
{
|
{
|
||||||
return bVSync && !Core::GetIsThrottlerTempDisabled();
|
return bVSync && !Core::GetIsThrottlerTempDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VideoConfig::IsStereoEnabled() const
|
||||||
|
{
|
||||||
|
return iStereoMode > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConfig::IsMSAAEnabled() const
|
||||||
|
{
|
||||||
|
return iMultisamples > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoConfig::IsSSAAEnabled() const
|
||||||
|
{
|
||||||
|
return iMultisamples > 1 && bSSAA && backend_info.bSupportsSSAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,13 @@ struct VideoConfig final
|
||||||
{
|
{
|
||||||
return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding;
|
return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding;
|
||||||
}
|
}
|
||||||
|
bool UseVertexRounding() const { return bVertexRounding && iEFBScale != SCALE_1X; }
|
||||||
|
bool IsStereoEnabled() const;
|
||||||
|
bool IsMSAAEnabled() const;
|
||||||
|
bool IsSSAAEnabled() const;
|
||||||
|
// Host config contains the settings which can influence generated shaders.
|
||||||
|
u32 GetHostConfigBits() const;
|
||||||
|
std::string GetHostConfigFilename() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern VideoConfig g_Config;
|
extern VideoConfig g_Config;
|
||||||
|
|
Loading…
Reference in New Issue