diff options
| author | TellowKrinkle <tellowkrinkle@gmail.com> | 2022-07-23 00:47:04 -0500 |
|---|---|---|
| committer | TellowKrinkle <tellowkrinkle@gmail.com> | 2022-10-22 20:13:24 -0500 |
| commit | 68f49df0f8a845eecd1e65c4d75dfbee3bdc989e (patch) | |
| tree | 95fd1e84279cba083fa8e776ba439b59ad7503a7 /Source/Core/VideoCommon/UberShaderVertex.cpp | |
| parent | 804e42150e03532e63ecc5a7f6f6eed751a132af (diff) | |
VideoCommon: Add vertex shader point and line expansion
Diffstat (limited to 'Source/Core/VideoCommon/UberShaderVertex.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/UberShaderVertex.cpp | 120 |
1 files changed, 110 insertions, 10 deletions
diff --git a/Source/Core/VideoCommon/UberShaderVertex.cpp b/Source/Core/VideoCommon/UberShaderVertex.cpp index 04f2b27a14..0bfacf88ee 100644 --- a/Source/Core/VideoCommon/UberShaderVertex.cpp +++ b/Source/Core/VideoCommon/UberShaderVertex.cpp @@ -3,6 +3,7 @@ #include "VideoCommon/UberShaderVertex.h" +#include "VideoCommon/ConstantManager.h" #include "VideoCommon/DriverDetails.h" #include "VideoCommon/NativeVertexFormat.h" #include "VideoCommon/UberShaderCommon.h" @@ -35,6 +36,8 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config const bool ssaa = host_config.ssaa; const bool per_pixel_lighting = host_config.per_pixel_lighting; const bool vertex_rounding = host_config.vertex_rounding; + const bool vertex_loader = + host_config.backend_dynamic_vertex_loader || host_config.backend_vs_point_line_expand; const u32 num_texgen = uid_data->num_texgens; ShaderCode out; @@ -46,6 +49,13 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config out.Write("{}", s_shader_uniforms); out.Write("}};\n"); + if (vertex_loader) + { + out.Write("UBO_BINDING(std140, 3) uniform GSBlock {{\n"); + out.Write("{}", s_geometry_shader_uniforms); + out.Write("}};\n"); + } + out.Write("struct VS_OUTPUT {{\n"); GenerateVSOutputMembers(out, api_type, num_texgen, host_config, "", ShaderStage::Vertex); out.Write("}};\n\n"); @@ -54,7 +64,7 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config WriteBitfieldExtractHeader(out, api_type, host_config); WriteLightingFunction(out); - if (host_config.backend_dynamic_vertex_loader) + if (vertex_loader) { out.Write(R"( SSBO_BINDING(1) readonly restrict buffer Vertices {{ @@ -73,17 +83,17 @@ SSBO_BINDING(1) readonly restrict buffer Vertices {{ // D3D12 uses a root constant for this uniform, since it changes with every draw. // D3D11 doesn't currently support dynamic vertex loader, and we'll have to figure something // out for it if we want to support it in the future. - out.Write("UBO_BINDING(std140, 3) uniform DX_Constants {{\n" + out.Write("UBO_BINDING(std140, 4) uniform DX_Constants {{\n" " uint base_vertex;\n" "}};\n\n" - "uint GetVertexBaseOffset() {{\n" - " return (gl_VertexID + base_vertex) * vertex_stride;\n" + "uint GetVertexBaseOffset(uint vertex_id) {{\n" + " return (vertex_id + base_vertex) * vertex_stride;\n" "}}\n"); } else { - out.Write("uint GetVertexBaseOffset() {{\n" - " return gl_VertexID * vertex_stride;\n" + out.Write("uint GetVertexBaseOffset(uint vertex_id) {{\n" + " return vertex_id * vertex_stride;\n" "}}\n"); } @@ -187,9 +197,17 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{ out.Write("VS_OUTPUT o;\n" "\n"); - if (host_config.backend_dynamic_vertex_loader) + if (host_config.backend_vs_point_line_expand) { - out.Write("uint vertex_base_offset = GetVertexBaseOffset();\n"); + out.Write("uint vertex_id = gl_VertexID;\n" + "if (vs_expand != 0u) {{\n" + " vertex_id = vertex_id >> 2;\n" + "}}\n" + "uint vertex_base_offset = GetVertexBaseOffset(vertex_id);\n"); + } + else if (host_config.backend_dynamic_vertex_loader) + { + out.Write("uint vertex_base_offset = GetVertexBaseOffset(gl_VertexID);\n"); } // rawpos is always needed LoadVertexAttribute(out, host_config, 0, "rawpos", "float4", "rawpos"); @@ -320,6 +338,88 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{ if (num_texgen > 0) GenVertexShaderTexGens(api_type, host_config, num_texgen, out); + if (host_config.backend_vs_point_line_expand) + { + out.Write("if (vs_expand == {}u) {{ // Line\n", static_cast<u32>(VSExpand::Line)); + out.Write(" bool is_bottom = (gl_VertexID & 2) != 0;\n" + " bool is_right = (gl_VertexID & 1) != 0;\n" + " uint other_base_offset = vertex_base_offset;\n" + " if (is_bottom) {{\n" + " other_base_offset -= vertex_stride;\n" + " }} else {{\n" + " other_base_offset += vertex_stride;\n" + " }}\n" + " float4 other_rawpos = load_input_float4_rawpos(other_base_offset, " + "vertex_offset_rawpos);\n" + " float4 other_p0 = P0;\n" + " float4 other_p1 = P1;\n" + " float4 other_p2 = P2;\n" + " if ((components & {}u) != 0u) {{ // VB_HAS_POSMTXIDX\n", + VB_HAS_POSMTXIDX); + out.Write(" uint other_posidx = int(load_input_uint4_ubyte4(other_base_offset, " + "vertex_offset_posmtx).r);\n" + " other_p0 = " I_TRANSFORMMATRICES "[other_posidx];\n" + " other_p1 = " I_TRANSFORMMATRICES "[other_posidx+1];\n" + " other_p2 = " I_TRANSFORMMATRICES "[other_posidx+2];\n" + " }}\n" + " float4 other_pos = float4(dot(other_p0, other_rawpos), " + "dot(other_p1, other_rawpos), dot(other_p2, other_rawpos), 1.0);\n" + " other_pos = float4(dot(" I_PROJECTION "[0], other_pos), dot(" I_PROJECTION + "[1], other_pos), dot(" I_PROJECTION "[2], other_pos), dot(" I_PROJECTION + "[3], other_pos));\n" + "\n" + " float sign = is_right ? 1.0f : -1.0f;\n" + // GameCube/Wii's line drawing algorithm is a little quirky. It does not + // use the correct line caps. Instead, the line caps are vertical or + // horizontal depending the slope of the line. + " float2 offset;\n" + " float2 to = abs(o.pos.xy / o.pos.w - other_pos.xy / other_pos.w);\n" + // FIXME: What does real hardware do when line is at a 45-degree angle? + // FIXME: Lines aren't drawn at the correct width. See Twilight Princess map. + " if (" I_LINEPTPARAMS ".y * to.y > " I_LINEPTPARAMS ".x * to.x) {{\n" + // Line is more tall. Extend geometry left and right. + // Lerp LineWidth/2 from [0..VpWidth] to [-1..1] + " offset = float2(sign * " I_LINEPTPARAMS ".z / " I_LINEPTPARAMS ".x, 0);\n" + " }} else {{\n" + // Line is more wide. Extend geometry up and down. + // Lerp LineWidth/2 from [0..VpHeight] to [1..-1] + " offset = float2(0, sign * " I_LINEPTPARAMS ".z / " I_LINEPTPARAMS ".y);\n" + " }}\n" + "\n" + " o.pos.xy += offset * o.pos.w;\n"); + if (num_texgen > 0) + { + out.Write(" if ((" I_TEXOFFSET "[2] != 0) && is_right) {{\n" + " float texOffset = 1.0 / float(" I_TEXOFFSET "[2]);\n"); + for (u32 i = 0; i < num_texgen; i++) + { + out.Write(" if (((" I_TEXOFFSET "[0] >> {}) & 0x1) != 0)\n", i); + out.Write(" o.tex{}.x += texOffset;\n", i); + } + out.Write(" }}\n"); + } + out.Write("}} else if (vs_expand == {}u) {{ // Point\n", static_cast<u32>(VSExpand::Point)); + out.Write(" bool is_bottom = (gl_VertexID & 2) != 0;\n" + " bool is_right = (gl_VertexID & 1) != 0;\n" + " float2 sign = float2(is_right ? 1.0f : -1.0f, is_bottom ? 1.0f : -1.0f);\n" + " float2 offset = sign * " I_LINEPTPARAMS ".ww / " I_LINEPTPARAMS ".xy;\n" + " o.pos.xy += offset * o.pos.w;\n"); + if (num_texgen > 0) + { + out.Write(" if (" I_TEXOFFSET "[3] != 0) {{\n" + " float texOffsetMagnitude = 1.0f / float(" I_TEXOFFSET "[3]);\n" + " float2 texOffset = float2(is_right ? texOffsetMagnitude : 0.0f, " + "is_bottom ? texOffsetMagnitude : 0.0f);"); + for (u32 i = 0; i < num_texgen; i++) + { + out.Write(" if (((" I_TEXOFFSET "[1] >> {}) & 0x1) != 0)\n", i); + out.Write(" o.tex{}.xy += texOffset;\n", i); + } + out.Write(" }}\n"); + } + out.Write("}}\n"); + } + if (per_pixel_lighting) { out.Write("// When per-pixel lighting is enabled, the vertex colors are passed through\n" @@ -574,7 +674,7 @@ static void GenVertexShaderTexGens(APIType api_type, const ShaderHostConfig& hos " {{\n"); out.Write(" if ((components & ({}u /* VB_HAS_TEXMTXIDX0 */ << texgen)) != 0u) {{\n", VB_HAS_TEXMTXIDX0); - if (host_config.backend_dynamic_vertex_loader) + if (host_config.backend_dynamic_vertex_loader || host_config.backend_vs_point_line_expand) { out.Write(" int tmp = int(load_input_float3_rawtex(vertex_base_offset, " "vertex_offset_rawtex[texgen / 4][texgen % 4]).z);\n" @@ -655,7 +755,7 @@ static void LoadVertexAttribute(ShaderCode& code, const ShaderHostConfig& host_c std::string_view name, std::string_view shader_type, std::string_view stored_type, std::string_view offset_name) { - if (host_config.backend_dynamic_vertex_loader) + if (host_config.backend_dynamic_vertex_loader || host_config.backend_vs_point_line_expand) { code.Write("{:{}}{} {} = load_input_{}_{}(vertex_base_offset, vertex_offset_{});\n", "", indent, shader_type, name, shader_type, stored_type, |
