summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-09-16 10:23:00 +0200
committerGravatar GitHub2017-09-16 10:23:00 +0200
commit699c92099140f6017c66433805d2e9a592f91169 (patch)
tree8ff5b734c055dc47c4231d817863f9bd3dcde111 /src
parentMerge pull request #2842 from Subv/switchable_page_table (diff)
parentSwRasterizer/Clipper: flip the sign convention to match PICA and OpenGL (diff)
downloadyuzu-699c92099140f6017c66433805d2e9a592f91169.tar.gz
yuzu-699c92099140f6017c66433805d2e9a592f91169.tar.xz
yuzu-699c92099140f6017c66433805d2e9a592f91169.zip
Merge pull request #2900 from wwylele/clip-2
PICA: implement custom clip plane
Diffstat (limited to '')
-rw-r--r--src/video_core/regs_rasterizer.h14
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp28
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp80
-rw-r--r--src/video_core/swrasterizer/clipper.cpp31
5 files changed, 116 insertions, 46 deletions
diff --git a/src/video_core/regs_rasterizer.h b/src/video_core/regs_rasterizer.h
index 2874fd127..4fef00d76 100644
--- a/src/video_core/regs_rasterizer.h
+++ b/src/video_core/regs_rasterizer.h
@@ -5,10 +5,10 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8
9#include "common/bit_field.h" 8#include "common/bit_field.h"
10#include "common/common_funcs.h" 9#include "common/common_funcs.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/pica_types.h"
12 12
13namespace Pica { 13namespace Pica {
14 14
@@ -31,7 +31,17 @@ struct RasterizerRegs {
31 31
32 BitField<0, 24, u32> viewport_size_y; 32 BitField<0, 24, u32> viewport_size_y;
33 33
34 INSERT_PADDING_WORDS(0x9); 34 INSERT_PADDING_WORDS(0x3);
35
36 BitField<0, 1, u32> clip_enable;
37 BitField<0, 24, u32> clip_coef[4]; // float24
38
39 Math::Vec4<float24> GetClipCoef() const {
40 return {float24::FromRaw(clip_coef[0]), float24::FromRaw(clip_coef[1]),
41 float24::FromRaw(clip_coef[2]), float24::FromRaw(clip_coef[3])};
42 }
43
44 INSERT_PADDING_WORDS(0x1);
35 45
36 BitField<0, 24, u32> viewport_depth_range; // float24 46 BitField<0, 24, u32> viewport_depth_range; // float24
37 BitField<0, 24, u32> viewport_depth_near_plane; // float24 47 BitField<0, 24, u32> viewport_depth_near_plane; // float24
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index aa95ef21d..7b0cd1b66 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -169,6 +169,8 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
169 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, proctex_diff_lut_buffer.handle); 169 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, proctex_diff_lut_buffer.handle);
170 170
171 // Sync fixed function OpenGL state 171 // Sync fixed function OpenGL state
172 SyncClipEnabled();
173 SyncClipCoef();
172 SyncCullMode(); 174 SyncCullMode();
173 SyncBlendEnabled(); 175 SyncBlendEnabled();
174 SyncBlendFuncs(); 176 SyncBlendFuncs();
@@ -401,6 +403,18 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
401 SyncCullMode(); 403 SyncCullMode();
402 break; 404 break;
403 405
406 // Clipping plane
407 case PICA_REG_INDEX(rasterizer.clip_enable):
408 SyncClipEnabled();
409 break;
410
411 case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[0], 0x48):
412 case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[1], 0x49):
413 case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[2], 0x4a):
414 case PICA_REG_INDEX_WORKAROUND(rasterizer.clip_coef[3], 0x4b):
415 SyncClipCoef();
416 break;
417
404 // Depth modifiers 418 // Depth modifiers
405 case PICA_REG_INDEX(rasterizer.viewport_depth_range): 419 case PICA_REG_INDEX(rasterizer.viewport_depth_range):
406 SyncDepthScale(); 420 SyncDepthScale();
@@ -1280,6 +1294,20 @@ void RasterizerOpenGL::SetShader() {
1280 } 1294 }
1281} 1295}
1282 1296
1297void RasterizerOpenGL::SyncClipEnabled() {
1298 state.clip_distance[1] = Pica::g_state.regs.rasterizer.clip_enable != 0;
1299}
1300
1301void RasterizerOpenGL::SyncClipCoef() {
1302 const auto raw_clip_coef = Pica::g_state.regs.rasterizer.GetClipCoef();
1303 const GLvec4 new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(),
1304 raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()};
1305 if (new_clip_coef != uniform_block_data.data.clip_coef) {
1306 uniform_block_data.data.clip_coef = new_clip_coef;
1307 uniform_block_data.dirty = true;
1308 }
1309}
1310
1283void RasterizerOpenGL::SyncCullMode() { 1311void RasterizerOpenGL::SyncCullMode() {
1284 const auto& regs = Pica::g_state.regs; 1312 const auto& regs = Pica::g_state.regs;
1285 1313
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 78e218efe..46c62961c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -151,14 +151,21 @@ private:
151 LightSrc light_src[8]; 151 LightSrc light_src[8];
152 alignas(16) GLvec4 const_color[6]; // A vec4 color for each of the six tev stages 152 alignas(16) GLvec4 const_color[6]; // A vec4 color for each of the six tev stages
153 alignas(16) GLvec4 tev_combiner_buffer_color; 153 alignas(16) GLvec4 tev_combiner_buffer_color;
154 alignas(16) GLvec4 clip_coef;
154 }; 155 };
155 156
156 static_assert( 157 static_assert(
157 sizeof(UniformData) == 0x460, 158 sizeof(UniformData) == 0x470,
158 "The size of the UniformData structure has changed, update the structure in the shader"); 159 "The size of the UniformData structure has changed, update the structure in the shader");
159 static_assert(sizeof(UniformData) < 16384, 160 static_assert(sizeof(UniformData) < 16384,
160 "UniformData structure must be less than 16kb as per the OpenGL spec"); 161 "UniformData structure must be less than 16kb as per the OpenGL spec");
161 162
163 /// Syncs the clip enabled status to match the PICA register
164 void SyncClipEnabled();
165
166 /// Syncs the clip coefficients to match the PICA register
167 void SyncClipCoef();
168
162 /// Sets the OpenGL shader in accordance with the current PICA register state 169 /// Sets the OpenGL shader in accordance with the current PICA register state
163 void SetShader(); 170 void SetShader();
164 171
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index c536e61e1..9fe183944 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -25,6 +25,42 @@ using TevStageConfig = TexturingRegs::TevStageConfig;
25 25
26namespace GLShader { 26namespace GLShader {
27 27
28static const std::string UniformBlockDef = R"(
29#define NUM_TEV_STAGES 6
30#define NUM_LIGHTS 8
31
32struct LightSrc {
33 vec3 specular_0;
34 vec3 specular_1;
35 vec3 diffuse;
36 vec3 ambient;
37 vec3 position;
38 vec3 spot_direction;
39 float dist_atten_bias;
40 float dist_atten_scale;
41};
42
43layout (std140) uniform shader_data {
44 vec2 framebuffer_scale;
45 int alphatest_ref;
46 float depth_scale;
47 float depth_offset;
48 int scissor_x1;
49 int scissor_y1;
50 int scissor_x2;
51 int scissor_y2;
52 vec3 fog_color;
53 vec2 proctex_noise_f;
54 vec2 proctex_noise_a;
55 vec2 proctex_noise_p;
56 vec3 lighting_global_ambient;
57 LightSrc light_src[NUM_LIGHTS];
58 vec4 const_color[NUM_TEV_STAGES];
59 vec4 tev_combiner_buffer_color;
60 vec4 clip_coef;
61};
62)";
63
28PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) { 64PicaShaderConfig PicaShaderConfig::BuildFromRegs(const Pica::Regs& regs) {
29 PicaShaderConfig res; 65 PicaShaderConfig res;
30 66
@@ -1010,8 +1046,6 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) {
1010 1046
1011 std::string out = R"( 1047 std::string out = R"(
1012#version 330 core 1048#version 330 core
1013#define NUM_TEV_STAGES 6
1014#define NUM_LIGHTS 8
1015 1049
1016in vec4 primary_color; 1050in vec4 primary_color;
1017in vec2 texcoord[3]; 1051in vec2 texcoord[3];
@@ -1023,36 +1057,6 @@ in vec4 gl_FragCoord;
1023 1057
1024out vec4 color; 1058out vec4 color;
1025 1059
1026struct LightSrc {
1027 vec3 specular_0;
1028 vec3 specular_1;
1029 vec3 diffuse;
1030 vec3 ambient;
1031 vec3 position;
1032 vec3 spot_direction;
1033 float dist_atten_bias;
1034 float dist_atten_scale;
1035};
1036
1037layout (std140) uniform shader_data {
1038 vec2 framebuffer_scale;
1039 int alphatest_ref;
1040 float depth_scale;
1041 float depth_offset;
1042 int scissor_x1;
1043 int scissor_y1;
1044 int scissor_x2;
1045 int scissor_y2;
1046 vec3 fog_color;
1047 vec2 proctex_noise_f;
1048 vec2 proctex_noise_a;
1049 vec2 proctex_noise_p;
1050 vec3 lighting_global_ambient;
1051 LightSrc light_src[NUM_LIGHTS];
1052 vec4 const_color[NUM_TEV_STAGES];
1053 vec4 tev_combiner_buffer_color;
1054};
1055
1056uniform sampler2D tex[3]; 1060uniform sampler2D tex[3];
1057uniform samplerBuffer lighting_lut; 1061uniform samplerBuffer lighting_lut;
1058uniform samplerBuffer fog_lut; 1062uniform samplerBuffer fog_lut;
@@ -1061,7 +1065,11 @@ uniform samplerBuffer proctex_color_map;
1061uniform samplerBuffer proctex_alpha_map; 1065uniform samplerBuffer proctex_alpha_map;
1062uniform samplerBuffer proctex_lut; 1066uniform samplerBuffer proctex_lut;
1063uniform samplerBuffer proctex_diff_lut; 1067uniform samplerBuffer proctex_diff_lut;
1068)";
1069
1070 out += UniformBlockDef;
1064 1071
1072 out += R"(
1065// Rotate the vector v by the quaternion q 1073// Rotate the vector v by the quaternion q
1066vec3 quaternion_rotate(vec4 q, vec3 v) { 1074vec3 quaternion_rotate(vec4 q, vec3 v) {
1067 return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); 1075 return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
@@ -1197,6 +1205,12 @@ out float texcoord0_w;
1197out vec4 normquat; 1205out vec4 normquat;
1198out vec3 view; 1206out vec3 view;
1199 1207
1208)";
1209
1210 out += UniformBlockDef;
1211
1212 out += R"(
1213
1200void main() { 1214void main() {
1201 primary_color = vert_color; 1215 primary_color = vert_color;
1202 texcoord[0] = vert_texcoord0; 1216 texcoord[0] = vert_texcoord0;
@@ -1207,7 +1221,7 @@ void main() {
1207 view = vert_view; 1221 view = vert_view;
1208 gl_Position = vert_position; 1222 gl_Position = vert_position;
1209 gl_ClipDistance[0] = -vert_position.z; // fixed PICA clipping plane z <= 0 1223 gl_ClipDistance[0] = -vert_position.z; // fixed PICA clipping plane z <= 0
1210 // TODO (wwylele): calculate gl_ClipDistance[1] from user-defined clipping plane 1224 gl_ClipDistance[1] = dot(clip_coef, vert_position);
1211} 1225}
1212)"; 1226)";
1213 1227
diff --git a/src/video_core/swrasterizer/clipper.cpp b/src/video_core/swrasterizer/clipper.cpp
index cdbc71502..a52129eb7 100644
--- a/src/video_core/swrasterizer/clipper.cpp
+++ b/src/video_core/swrasterizer/clipper.cpp
@@ -31,7 +31,7 @@ public:
31 : coeffs(coeffs), bias(bias) {} 31 : coeffs(coeffs), bias(bias) {}
32 32
33 bool IsInside(const Vertex& vertex) const { 33 bool IsInside(const Vertex& vertex) const {
34 return Math::Dot(vertex.pos + bias, coeffs) <= float24::FromFloat32(0); 34 return Math::Dot(vertex.pos + bias, coeffs) >= float24::FromFloat32(0);
35 } 35 }
36 36
37 bool IsOutSide(const Vertex& vertex) const { 37 bool IsOutSide(const Vertex& vertex) const {
@@ -116,19 +116,18 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu
116 static const float24 f0 = float24::FromFloat32(0.0); 116 static const float24 f0 = float24::FromFloat32(0.0);
117 static const float24 f1 = float24::FromFloat32(1.0); 117 static const float24 f1 = float24::FromFloat32(1.0);
118 static const std::array<ClippingEdge, 7> clipping_edges = {{ 118 static const std::array<ClippingEdge, 7> clipping_edges = {{
119 {Math::MakeVec(f1, f0, f0, -f1)}, // x = +w 119 {Math::MakeVec(-f1, f0, f0, f1)}, // x = +w
120 {Math::MakeVec(-f1, f0, f0, -f1)}, // x = -w 120 {Math::MakeVec(f1, f0, f0, f1)}, // x = -w
121 {Math::MakeVec(f0, f1, f0, -f1)}, // y = +w 121 {Math::MakeVec(f0, -f1, f0, f1)}, // y = +w
122 {Math::MakeVec(f0, -f1, f0, -f1)}, // y = -w 122 {Math::MakeVec(f0, f1, f0, f1)}, // y = -w
123 {Math::MakeVec(f0, f0, f1, f0)}, // z = 0 123 {Math::MakeVec(f0, f0, -f1, f0)}, // z = 0
124 {Math::MakeVec(f0, f0, -f1, -f1)}, // z = -w 124 {Math::MakeVec(f0, f0, f1, f1)}, // z = -w
125 {Math::MakeVec(f0, f0, f0, -f1), Math::Vec4<float24>(f0, f0, f0, EPSILON)}, // w = EPSILON 125 {Math::MakeVec(f0, f0, f0, f1), Math::Vec4<float24>(f0, f0, f0, EPSILON)}, // w = EPSILON
126 }}; 126 }};
127 127
128 // Simple implementation of the Sutherland-Hodgman clipping algorithm. 128 // Simple implementation of the Sutherland-Hodgman clipping algorithm.
129 // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here) 129 // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)
130 for (auto edge : clipping_edges) { 130 auto Clip = [&](const ClippingEdge& edge) {
131
132 std::swap(input_list, output_list); 131 std::swap(input_list, output_list);
133 output_list->clear(); 132 output_list->clear();
134 133
@@ -147,12 +146,24 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu
147 } 146 }
148 reference_vertex = &vertex; 147 reference_vertex = &vertex;
149 } 148 }
149 };
150
151 for (auto edge : clipping_edges) {
152 Clip(edge);
150 153
151 // Need to have at least a full triangle to continue... 154 // Need to have at least a full triangle to continue...
152 if (output_list->size() < 3) 155 if (output_list->size() < 3)
153 return; 156 return;
154 } 157 }
155 158
159 if (g_state.regs.rasterizer.clip_enable) {
160 ClippingEdge custom_edge{g_state.regs.rasterizer.GetClipCoef()};
161 Clip(custom_edge);
162
163 if (output_list->size() < 3)
164 return;
165 }
166
156 InitScreenCoordinates((*output_list)[0]); 167 InitScreenCoordinates((*output_list)[0]);
157 InitScreenCoordinates((*output_list)[1]); 168 InitScreenCoordinates((*output_list)[1]);
158 169