summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VertexShaderGen.cpp
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2022-10-23 01:49:26 -0400
committerGitHub <noreply@github.com>2022-10-23 01:49:26 -0400
commitcdcbe51b2a0c4dd78ab8d1d3ad38d8ab2947405b (patch)
tree5d29d92713f591f003b7d83da63b427b3c847ea1 /Source/Core/VideoCommon/VertexShaderGen.cpp
parent06bd0a908692f61702a483c51c93fadb2ed7eefc (diff)
parent1e9b6f88e4c13722a2a47aeb0d54df95c3a07c69 (diff)
Merge pull request #10890 from tellowkrinkle/VertexLineExpand
VideoCommon: Add vertex shader point/line expansion
Diffstat (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp')
-rw-r--r--Source/Core/VideoCommon/VertexShaderGen.cpp192
1 files changed, 172 insertions, 20 deletions
diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp
index 2eb5a53a97..5570e52cc0 100644
--- a/Source/Core/VideoCommon/VertexShaderGen.cpp
+++ b/Source/Core/VideoCommon/VertexShaderGen.cpp
@@ -6,6 +6,7 @@
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "VideoCommon/BPMemory.h"
+#include "VideoCommon/ConstantManager.h"
#include "VideoCommon/LightingShaderGen.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/VertexLoaderManager.h"
@@ -83,6 +84,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
const bool ssaa = host_config.ssaa;
const bool vertex_rounding = host_config.vertex_rounding;
+ ShaderCode input_extract;
+
out.Write("{}", s_lighting_struct);
// uniforms
@@ -91,6 +94,21 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
out.Write("{}", s_shader_uniforms);
out.Write("}};\n");
+ if (uid_data->vs_expand != VSExpand::None)
+ {
+ out.Write("UBO_BINDING(std140, 3) uniform GSBlock {{\n");
+ out.Write("{}", s_geometry_shader_uniforms);
+ out.Write("}};\n");
+
+ if (api_type == APIType::D3D)
+ {
+ // D3D doesn't include the base vertex in SV_VertexID
+ out.Write("UBO_BINDING(std140, 4) uniform DX_Constants {{\n"
+ " uint base_vertex;\n"
+ "}};\n\n");
+ }
+ }
+
out.Write("struct VS_OUTPUT {{\n");
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, host_config, "",
ShaderStage::Vertex);
@@ -98,30 +116,113 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
WriteIsNanHeader(out, api_type);
- out.Write("ATTRIBUTE_LOCATION({}) in float4 rawpos;\n", SHADER_POSITION_ATTRIB);
- if ((uid_data->components & VB_HAS_POSMTXIDX) != 0)
- out.Write("ATTRIBUTE_LOCATION({}) in uint4 posmtx;\n", SHADER_POSMTX_ATTRIB);
- if ((uid_data->components & VB_HAS_NORMAL) != 0)
- out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnormal;\n", SHADER_NORMAL_ATTRIB);
- if ((uid_data->components & VB_HAS_TANGENT) != 0)
- out.Write("ATTRIBUTE_LOCATION({}) in float3 rawtangent;\n", SHADER_TANGENT_ATTRIB);
- if ((uid_data->components & VB_HAS_BINORMAL) != 0)
- out.Write("ATTRIBUTE_LOCATION({}) in float3 rawbinormal;\n", SHADER_BINORMAL_ATTRIB);
-
- if ((uid_data->components & VB_HAS_COL0) != 0)
- out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor0;\n", SHADER_COLOR0_ATTRIB);
- if ((uid_data->components & VB_HAS_COL1) != 0)
- out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor1;\n", SHADER_COLOR1_ATTRIB);
-
- for (u32 i = 0; i < 8; ++i)
+ if (uid_data->vs_expand == VSExpand::None)
{
- const u32 has_texmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i));
+ out.Write("ATTRIBUTE_LOCATION({}) in float4 rawpos;\n", SHADER_POSITION_ATTRIB);
+ if ((uid_data->components & VB_HAS_POSMTXIDX) != 0)
+ out.Write("ATTRIBUTE_LOCATION({}) in uint4 posmtx;\n", SHADER_POSMTX_ATTRIB);
+ if ((uid_data->components & VB_HAS_NORMAL) != 0)
+ out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnormal;\n", SHADER_NORMAL_ATTRIB);
+ if ((uid_data->components & VB_HAS_TANGENT) != 0)
+ out.Write("ATTRIBUTE_LOCATION({}) in float3 rawtangent;\n", SHADER_TANGENT_ATTRIB);
+ if ((uid_data->components & VB_HAS_BINORMAL) != 0)
+ out.Write("ATTRIBUTE_LOCATION({}) in float3 rawbinormal;\n", SHADER_BINORMAL_ATTRIB);
+
+ if ((uid_data->components & VB_HAS_COL0) != 0)
+ out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor0;\n", SHADER_COLOR0_ATTRIB);
+ if ((uid_data->components & VB_HAS_COL1) != 0)
+ out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor1;\n", SHADER_COLOR1_ATTRIB);
+
+ for (u32 i = 0; i < 8; ++i)
+ {
+ const u32 has_texmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i));
- if ((uid_data->components & (VB_HAS_UV0 << i)) != 0 || has_texmtx != 0)
+ if ((uid_data->components & (VB_HAS_UV0 << i)) != 0 || has_texmtx != 0)
+ {
+ out.Write("ATTRIBUTE_LOCATION({}) in float{} rawtex{};\n", SHADER_TEXTURE0_ATTRIB + i,
+ has_texmtx != 0 ? 3 : 2, i);
+ }
+ }
+ }
+ else
+ {
+ // Can't use float3, etc because we want 4-byte alignment
+ out.Write(
+ "uint4 unpack_ubyte4(uint value) {{\n"
+ " return uint4(value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, value >> 24);\n"
+ "}}\n\n"
+ "struct InputData {{\n");
+ if (uid_data->components & VB_HAS_POSMTXIDX)
+ {
+ out.Write(" uint posmtx;\n");
+ input_extract.Write("uint4 posmtx = unpack_ubyte4(i.posmtx);\n");
+ }
+ if (uid_data->position_has_3_elems)
+ {
+ out.Write(" float pos0;\n"
+ " float pos1;\n"
+ " float pos2;\n");
+ input_extract.Write("float4 rawpos = float4(i.pos0, i.pos1, i.pos2, 1.0f);\n");
+ }
+ else
+ {
+ out.Write(" float pos0;\n"
+ " float pos1;\n");
+ input_extract.Write("float4 rawpos = float4(i.pos0, i.pos1, 0.0f, 1.0f);\n");
+ }
+ std::array<std::string_view, 3> names = {"normal", "binormal", "tangent"};
+ for (int i = 0; i < 3; i++)
+ {
+ if (uid_data->components & (VB_HAS_NORMAL << i))
+ {
+ out.Write(" float {0}0;\n"
+ " float {0}1;\n"
+ " float {0}2;\n",
+ names[i]);
+ input_extract.Write("float3 raw{0} = float3(i.{0}0, i.{0}1, i.{0}2);\n", names[i]);
+ }
+ }
+ for (int i = 0; i < 2; i++)
+ {
+ if (uid_data->components & (VB_HAS_COL0 << i))
+ {
+ out.Write(" uint color{};\n", i);
+ input_extract.Write("float4 rawcolor{0} = float4(unpack_ubyte4(i.color{0})) / 255.0f;\n",
+ i);
+ }
+ }
+ for (int i = 0; i < 8; i++)
{
- out.Write("ATTRIBUTE_LOCATION({}) in float{} rawtex{};\n", SHADER_TEXTURE0_ATTRIB + i,
- has_texmtx != 0 ? 3 : 2, i);
+ if (uid_data->components & (VB_HAS_UV0 << i))
+ {
+ u32 ncomponents = (uid_data->texcoord_elem_count >> (2 * i)) & 3;
+ if (ncomponents < 2)
+ {
+ out.Write(" float tex{};\n", i);
+ input_extract.Write("float3 rawtex{0} = float3(i.tex{0}, 0.0f, 0.0f);\n", i);
+ }
+ else if (ncomponents == 2)
+ {
+ out.Write(" float tex{0}_0;\n"
+ " float tex{0}_1;\n",
+ i);
+ input_extract.Write("float3 rawtex{0} = float3(i.tex{0}_0, i.tex{0}_1, 0.0f);\n", i);
+ }
+ else
+ {
+ out.Write(" float tex{0}_0;\n"
+ " float tex{0}_1;\n"
+ " float tex{0}_2;\n",
+ i);
+ input_extract.Write("float3 rawtex{0} = float3(i.tex{0}_0, i.tex{0}_1, i.tex{0}_2);\n",
+ i);
+ }
+ }
}
+ out.Write("}};\n\n"
+ "SSBO_BINDING(1) readonly restrict buffer InputBuffer {{\n"
+ " InputData input_buffer[];\n"
+ "}};\n\n");
}
if (host_config.backend_geometry_shaders)
@@ -161,6 +262,21 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
out.Write("void main()\n{{\n");
+ if (uid_data->vs_expand != VSExpand::None)
+ {
+ out.Write("bool is_bottom = (gl_VertexID & 2) != 0;\n"
+ "bool is_right = (gl_VertexID & 1) != 0;\n");
+ // D3D doesn't include the base vertex in SV_VertexID
+ // See comment in UberShaderVertex for details
+ if (api_type == APIType::D3D)
+ out.Write("uint vertex_id = (gl_VertexID >> 2) + base_vertex;\n");
+ else
+ out.Write("uint vertex_id = gl_VertexID >> 2;\n");
+ out.Write("InputData i = input_buffer[vertex_id];\n"
+ "{}",
+ input_extract.GetBuffer());
+ }
+
out.Write("VS_OUTPUT o;\n");
// xfmem.numColorChans controls the number of color channels available to TEV, but we still need
@@ -403,6 +519,42 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
out.Write("}}\n");
}
+ if (uid_data->vs_expand == VSExpand::Line)
+ {
+ out.Write("// Line expansion\n"
+ "uint other_id = vertex_id;\n"
+ "if (is_bottom) {{\n"
+ " other_id -= 1;\n"
+ "}} else {{\n"
+ " other_id += 1;\n"
+ "}}\n"
+ "InputData other = input_buffer[other_id];\n");
+ if (uid_data->position_has_3_elems)
+ out.Write("float4 other_pos = float4(other.pos0, other.pos1, other.pos2, 1.0f);\n");
+ else
+ out.Write("float4 other_pos = float4(other.pos0, other.pos1, 0.0f, 1.0f);\n");
+ if (uid_data->components & VB_HAS_POSMTXIDX)
+ {
+ out.Write("uint other_posidx = other.posmtx & 0xff;\n"
+ "float4 other_p0 = " I_TRANSFORMMATRICES "[other_posidx];\n"
+ "float4 other_p1 = " I_TRANSFORMMATRICES "[other_posidx + 1];\n"
+ "float4 other_p2 = " I_TRANSFORMMATRICES "[other_posidx + 2];\n"
+ "other_pos = float4(dot(other_p0, other_pos), dot(other_p1, other_pos), "
+ "dot(other_p2, other_pos), 1.0f);\n");
+ }
+ else
+ {
+ out.Write("other_pos = float4(dot(P0, other_pos), dot(P1, other_pos), dot(P2, other_pos), "
+ "1.0f);\n");
+ }
+ GenerateVSLineExpansion(out, "", uid_data->numTexGens);
+ }
+ else if (uid_data->vs_expand == VSExpand::Point)
+ {
+ out.Write("// Point expansion\n");
+ GenerateVSPointExpansion(out, "", uid_data->numTexGens);
+ }
+
if (per_pixel_lighting)
{
// When per-pixel lighting is enabled, the vertex colors are passed through