diff options
| author | 2014-07-27 18:02:35 +0200 | |
|---|---|---|
| committer | 2014-08-12 13:50:07 +0200 | |
| commit | 94d742fe172ba933af321bfb0e02889b40d0c179 (patch) | |
| tree | 241e6d8b36e6ab9921ef7afb71e7350e52862e2a | |
| parent | Pica: Add triangle clipper. (diff) | |
| download | yuzu-94d742fe172ba933af321bfb0e02889b40d0c179.tar.gz yuzu-94d742fe172ba933af321bfb0e02889b40d0c179.tar.xz yuzu-94d742fe172ba933af321bfb0e02889b40d0c179.zip | |
Pica: Add basic rasterizer.
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/clipper.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/pica.h | 52 | ||||
| -rw-r--r-- | src/video_core/rasterizer.cpp | 180 | ||||
| -rw-r--r-- | src/video_core/rasterizer.h | 21 | ||||
| -rw-r--r-- | src/video_core/video_core.vcxproj | 2 | ||||
| -rw-r--r-- | src/video_core/video_core.vcxproj.filters | 2 |
7 files changed, 260 insertions, 2 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 828bf30fc..8e7b93acb 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | set(SRCS clipper.cpp | 1 | set(SRCS clipper.cpp |
| 2 | command_processor.cpp | 2 | command_processor.cpp |
| 3 | primitive_assembly.cpp | 3 | primitive_assembly.cpp |
| 4 | rasterizer.cpp | ||
| 4 | utils.cpp | 5 | utils.cpp |
| 5 | vertex_shader.cpp | 6 | vertex_shader.cpp |
| 6 | video_core.cpp | 7 | video_core.cpp |
| @@ -10,6 +11,7 @@ set(HEADERS clipper.h | |||
| 10 | command_processor.h | 11 | command_processor.h |
| 11 | math.h | 12 | math.h |
| 12 | primitive_assembly.h | 13 | primitive_assembly.h |
| 14 | rasterizer.h | ||
| 13 | utils.h | 15 | utils.h |
| 14 | video_core.h | 16 | video_core.h |
| 15 | renderer_base.h | 17 | renderer_base.h |
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp index e9ab6242c..b7180328c 100644 --- a/src/video_core/clipper.cpp +++ b/src/video_core/clipper.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "clipper.h" | 7 | #include "clipper.h" |
| 8 | #include "pica.h" | 8 | #include "pica.h" |
| 9 | #include "rasterizer.h" | ||
| 9 | #include "vertex_shader.h" | 10 | #include "vertex_shader.h" |
| 10 | 11 | ||
| 11 | namespace Pica { | 12 | namespace Pica { |
| @@ -168,7 +169,7 @@ void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) { | |||
| 168 | vtx1.screenpos.x.ToFloat32(), vtx1.screenpos.y.ToFloat32(), vtx1.screenpos.z.ToFloat32(), | 169 | vtx1.screenpos.x.ToFloat32(), vtx1.screenpos.y.ToFloat32(), vtx1.screenpos.z.ToFloat32(), |
| 169 | vtx2.screenpos.x.ToFloat32(), vtx2.screenpos.y.ToFloat32(), vtx2.screenpos.z.ToFloat32()); | 170 | vtx2.screenpos.x.ToFloat32(), vtx2.screenpos.y.ToFloat32(), vtx2.screenpos.z.ToFloat32()); |
| 170 | 171 | ||
| 171 | // TODO: Send triangle to rasterizer | 172 | Rasterizer::ProcessTriangle(vtx0, vtx1, vtx2); |
| 172 | } | 173 | } |
| 173 | } | 174 | } |
| 174 | 175 | ||
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 1ced0d323..81af57336 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -94,7 +94,55 @@ struct Regs { | |||
| 94 | BitField<16, 16, u32> y; | 94 | BitField<16, 16, u32> y; |
| 95 | } viewport_corner; | 95 | } viewport_corner; |
| 96 | 96 | ||
| 97 | INSERT_PADDING_WORDS(0x197); | 97 | INSERT_PADDING_WORDS(0xa7); |
| 98 | |||
| 99 | struct { | ||
| 100 | enum ColorFormat : u32 { | ||
| 101 | RGBA8 = 0, | ||
| 102 | RGB8 = 1, | ||
| 103 | RGBA5551 = 2, | ||
| 104 | RGB565 = 3, | ||
| 105 | RGBA4 = 4, | ||
| 106 | }; | ||
| 107 | |||
| 108 | INSERT_PADDING_WORDS(0x6); | ||
| 109 | |||
| 110 | u32 depth_format; | ||
| 111 | u32 color_format; | ||
| 112 | |||
| 113 | INSERT_PADDING_WORDS(0x4); | ||
| 114 | |||
| 115 | u32 depth_buffer_address; | ||
| 116 | u32 color_buffer_address; | ||
| 117 | |||
| 118 | union { | ||
| 119 | // Apparently, the framebuffer width is stored as expected, | ||
| 120 | // while the height is stored as the actual height minus one. | ||
| 121 | // Hence, don't access these fields directly but use the accessors | ||
| 122 | // GetWidth() and GetHeight() instead. | ||
| 123 | BitField< 0, 11, u32> width; | ||
| 124 | BitField<12, 10, u32> height; | ||
| 125 | }; | ||
| 126 | |||
| 127 | INSERT_PADDING_WORDS(0x1); | ||
| 128 | |||
| 129 | inline u32 GetColorBufferAddress() const { | ||
| 130 | return Memory::PhysicalToVirtualAddress(DecodeAddressRegister(color_buffer_address)); | ||
| 131 | } | ||
| 132 | inline u32 GetDepthBufferAddress() const { | ||
| 133 | return Memory::PhysicalToVirtualAddress(DecodeAddressRegister(depth_buffer_address)); | ||
| 134 | } | ||
| 135 | |||
| 136 | inline u32 GetWidth() const { | ||
| 137 | return width; | ||
| 138 | } | ||
| 139 | |||
| 140 | inline u32 GetHeight() const { | ||
| 141 | return height + 1; | ||
| 142 | } | ||
| 143 | } framebuffer; | ||
| 144 | |||
| 145 | INSERT_PADDING_WORDS(0xe0); | ||
| 98 | 146 | ||
| 99 | struct { | 147 | struct { |
| 100 | enum class Format : u64 { | 148 | enum class Format : u64 { |
| @@ -355,6 +403,7 @@ struct Regs { | |||
| 355 | ADD_FIELD(viewport_depth_range); | 403 | ADD_FIELD(viewport_depth_range); |
| 356 | ADD_FIELD(viewport_depth_far_plane); | 404 | ADD_FIELD(viewport_depth_far_plane); |
| 357 | ADD_FIELD(viewport_corner); | 405 | ADD_FIELD(viewport_corner); |
| 406 | ADD_FIELD(framebuffer); | ||
| 358 | ADD_FIELD(vertex_attributes); | 407 | ADD_FIELD(vertex_attributes); |
| 359 | ADD_FIELD(index_array); | 408 | ADD_FIELD(index_array); |
| 360 | ADD_FIELD(num_vertices); | 409 | ADD_FIELD(num_vertices); |
| @@ -411,6 +460,7 @@ ASSERT_REG_POSITION(viewport_depth_far_plane, 0x4e); | |||
| 411 | ASSERT_REG_POSITION(vs_output_attributes[0], 0x50); | 460 | ASSERT_REG_POSITION(vs_output_attributes[0], 0x50); |
| 412 | ASSERT_REG_POSITION(vs_output_attributes[1], 0x51); | 461 | ASSERT_REG_POSITION(vs_output_attributes[1], 0x51); |
| 413 | ASSERT_REG_POSITION(viewport_corner, 0x68); | 462 | ASSERT_REG_POSITION(viewport_corner, 0x68); |
| 463 | ASSERT_REG_POSITION(framebuffer, 0x110); | ||
| 414 | ASSERT_REG_POSITION(vertex_attributes, 0x200); | 464 | ASSERT_REG_POSITION(vertex_attributes, 0x200); |
| 415 | ASSERT_REG_POSITION(index_array, 0x227); | 465 | ASSERT_REG_POSITION(index_array, 0x227); |
| 416 | ASSERT_REG_POSITION(num_vertices, 0x228); | 466 | ASSERT_REG_POSITION(num_vertices, 0x228); |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp new file mode 100644 index 000000000..a7c1bab3e --- /dev/null +++ b/src/video_core/rasterizer.cpp | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "math.h" | ||
| 10 | #include "pica.h" | ||
| 11 | #include "rasterizer.h" | ||
| 12 | #include "vertex_shader.h" | ||
| 13 | |||
| 14 | namespace Pica { | ||
| 15 | |||
| 16 | namespace Rasterizer { | ||
| 17 | |||
| 18 | static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { | ||
| 19 | u32* color_buffer = (u32*)Memory::GetPointer(registers.framebuffer.GetColorBufferAddress()); | ||
| 20 | u32 value = (color.a() << 24) | (color.r() << 16) | (color.g() << 8) | color.b(); | ||
| 21 | |||
| 22 | // Assuming RGBA8 format until actual framebuffer format handling is implemented | ||
| 23 | *(color_buffer + x + y * registers.framebuffer.GetWidth() / 2) = value; | ||
| 24 | } | ||
| 25 | |||
| 26 | static u32 GetDepth(int x, int y) { | ||
| 27 | u16* depth_buffer = (u16*)Memory::GetPointer(registers.framebuffer.GetDepthBufferAddress()); | ||
| 28 | |||
| 29 | // Assuming 16-bit depth buffer format until actual format handling is implemented | ||
| 30 | return *(depth_buffer + x + y * registers.framebuffer.GetWidth() / 2); | ||
| 31 | } | ||
| 32 | |||
| 33 | static void SetDepth(int x, int y, u16 value) { | ||
| 34 | u16* depth_buffer = (u16*)Memory::GetPointer(registers.framebuffer.GetDepthBufferAddress()); | ||
| 35 | |||
| 36 | // Assuming 16-bit depth buffer format until actual format handling is implemented | ||
| 37 | *(depth_buffer + x + y * registers.framebuffer.GetWidth() / 2) = value; | ||
| 38 | } | ||
| 39 | |||
| 40 | void ProcessTriangle(const VertexShader::OutputVertex& v0, | ||
| 41 | const VertexShader::OutputVertex& v1, | ||
| 42 | const VertexShader::OutputVertex& v2) | ||
| 43 | { | ||
| 44 | // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values | ||
| 45 | struct Fix12P4 { | ||
| 46 | Fix12P4() {} | ||
| 47 | Fix12P4(u16 val) : val(val) {} | ||
| 48 | |||
| 49 | static u16 FracMask() { return 0xF; } | ||
| 50 | static u16 IntMask() { return (u16)~0xF; } | ||
| 51 | |||
| 52 | operator u16() const { | ||
| 53 | return val; | ||
| 54 | } | ||
| 55 | |||
| 56 | bool operator < (const Fix12P4& oth) const { | ||
| 57 | return (u16)*this < (u16)oth; | ||
| 58 | } | ||
| 59 | |||
| 60 | private: | ||
| 61 | u16 val; | ||
| 62 | }; | ||
| 63 | |||
| 64 | // vertex positions in rasterizer coordinates | ||
| 65 | auto FloatToFix = [](float24 flt) { | ||
| 66 | return Fix12P4(flt.ToFloat32() * 16.0f); | ||
| 67 | }; | ||
| 68 | auto ScreenToRasterizerCoordinates = [FloatToFix](const Math::Vec3<float24> vec) { | ||
| 69 | return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)}; | ||
| 70 | }; | ||
| 71 | Math::Vec3<Fix12P4> vtxpos[3]{ ScreenToRasterizerCoordinates(v0.screenpos), | ||
| 72 | ScreenToRasterizerCoordinates(v1.screenpos), | ||
| 73 | ScreenToRasterizerCoordinates(v2.screenpos) }; | ||
| 74 | |||
| 75 | // TODO: Proper scissor rect test! | ||
| 76 | u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); | ||
| 77 | u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); | ||
| 78 | u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); | ||
| 79 | u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); | ||
| 80 | |||
| 81 | min_x = min_x & Fix12P4::IntMask(); | ||
| 82 | min_y = min_y & Fix12P4::IntMask(); | ||
| 83 | max_x = (max_x + Fix12P4::FracMask()) & Fix12P4::IntMask(); | ||
| 84 | max_y = (max_y + Fix12P4::FracMask()) & Fix12P4::IntMask(); | ||
| 85 | |||
| 86 | // Triangle filling rules: Pixels on the right-sided edge or on flat bottom edges are not | ||
| 87 | // drawn. Pixels on any other triangle border are drawn. This is implemented with three bias | ||
| 88 | // values which are added to the barycentric coordinates w0, w1 and w2, respectively. | ||
| 89 | // NOTE: These are the PSP filling rules. Not sure if the 3DS uses the same ones... | ||
| 90 | auto IsRightSideOrFlatBottomEdge = [](const Math::Vec2<Fix12P4>& vtx, | ||
| 91 | const Math::Vec2<Fix12P4>& line1, | ||
| 92 | const Math::Vec2<Fix12P4>& line2) | ||
| 93 | { | ||
| 94 | if (line1.y == line2.y) { | ||
| 95 | // just check if vertex is above us => bottom line parallel to x-axis | ||
| 96 | return vtx.y < line1.y; | ||
| 97 | } else { | ||
| 98 | // check if vertex is on our left => right side | ||
| 99 | // TODO: Not sure how likely this is to overflow | ||
| 100 | return (int)vtx.x < (int)line1.x + ((int)line2.x - (int)line1.x) * ((int)vtx.y - (int)line1.y) / ((int)line2.y - (int)line1.y); | ||
| 101 | } | ||
| 102 | }; | ||
| 103 | int bias0 = IsRightSideOrFlatBottomEdge(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) ? -1 : 0; | ||
| 104 | int bias1 = IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0; | ||
| 105 | int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; | ||
| 106 | |||
| 107 | // TODO: Not sure if looping through x first might be faster | ||
| 108 | for (u16 y = min_y; y < max_y; y += 0x10) { | ||
| 109 | for (u16 x = min_x; x < max_x; x += 0x10) { | ||
| 110 | |||
| 111 | // Calculate the barycentric coordinates w0, w1 and w2 | ||
| 112 | auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1, | ||
| 113 | const Math::Vec2<Fix12P4>& vtx2, | ||
| 114 | const Math::Vec2<Fix12P4>& vtx3) { | ||
| 115 | const auto vec1 = (vtx2.Cast<int>() - vtx1.Cast<int>()).Append(0); | ||
| 116 | const auto vec2 = (vtx3.Cast<int>() - vtx1.Cast<int>()).Append(0); | ||
| 117 | // TODO: There is a very small chance this will overflow for sizeof(int) == 4 | ||
| 118 | return Cross(vec1, vec2).z; | ||
| 119 | }; | ||
| 120 | |||
| 121 | int w0 = bias0 + orient2d(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); | ||
| 122 | int w1 = bias1 + orient2d(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); | ||
| 123 | int w2 = bias2 + orient2d(vtxpos[0].xy(), vtxpos[1].xy(), {x, y}); | ||
| 124 | int wsum = w0 + w1 + w2; | ||
| 125 | |||
| 126 | // If current pixel is not covered by the current primitive | ||
| 127 | if (w0 < 0 || w1 < 0 || w2 < 0) | ||
| 128 | continue; | ||
| 129 | |||
| 130 | // Perspective correct attribute interpolation: | ||
| 131 | // Attribute values cannot be calculated by simple linear interpolation since | ||
| 132 | // they are not linear in screen space. For example, when interpolating a | ||
| 133 | // texture coordinate across two vertices, something simple like | ||
| 134 | // u = (u0*w0 + u1*w1)/(w0+w1) | ||
| 135 | // will not work. However, the attribute value divided by the | ||
| 136 | // clipspace w-coordinate (u/w) and and the inverse w-coordinate (1/w) are linear | ||
| 137 | // in screenspace. Hence, we can linearly interpolate these two independently and | ||
| 138 | // calculate the interpolated attribute by dividing the results. | ||
| 139 | // I.e. | ||
| 140 | // u_over_w = ((u0/v0.pos.w)*w0 + (u1/v1.pos.w)*w1)/(w0+w1) | ||
| 141 | // one_over_w = (( 1/v0.pos.w)*w0 + ( 1/v1.pos.w)*w1)/(w0+w1) | ||
| 142 | // u = u_over_w / one_over_w | ||
| 143 | // | ||
| 144 | // The generalization to three vertices is straightforward in baricentric coordinates. | ||
| 145 | auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { | ||
| 146 | auto attr_over_w = Math::MakeVec3(attr0 / v0.pos.w, | ||
| 147 | attr1 / v1.pos.w, | ||
| 148 | attr2 / v2.pos.w); | ||
| 149 | auto w_inverse = Math::MakeVec3(float24::FromFloat32(1.f) / v0.pos.w, | ||
| 150 | float24::FromFloat32(1.f) / v1.pos.w, | ||
| 151 | float24::FromFloat32(1.f) / v2.pos.w); | ||
| 152 | auto baricentric_coordinates = Math::MakeVec3(float24::FromFloat32(w0), | ||
| 153 | float24::FromFloat32(w1), | ||
| 154 | float24::FromFloat32(w2)); | ||
| 155 | |||
| 156 | float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); | ||
| 157 | float24 interpolated_w_inverse = Math::Dot(w_inverse, baricentric_coordinates); | ||
| 158 | return interpolated_attr_over_w / interpolated_w_inverse; | ||
| 159 | }; | ||
| 160 | |||
| 161 | Math::Vec4<u8> primary_color{ | ||
| 162 | (u8)(GetInterpolatedAttribute(v0.color.r(), v1.color.r(), v2.color.r()).ToFloat32() * 255), | ||
| 163 | (u8)(GetInterpolatedAttribute(v0.color.g(), v1.color.g(), v2.color.g()).ToFloat32() * 255), | ||
| 164 | (u8)(GetInterpolatedAttribute(v0.color.b(), v1.color.b(), v2.color.b()).ToFloat32() * 255), | ||
| 165 | (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255) | ||
| 166 | }; | ||
| 167 | |||
| 168 | u16 z = (u16)(((float)v0.screenpos[2].ToFloat32() * w0 + | ||
| 169 | (float)v1.screenpos[2].ToFloat32() * w1 + | ||
| 170 | (float)v2.screenpos[2].ToFloat32() * w2) * 65535.f / wsum); // TODO: Shouldn't need to multiply by 65536? | ||
| 171 | SetDepth(x >> 4, y >> 4, z); | ||
| 172 | |||
| 173 | DrawPixel(x >> 4, y >> 4, primary_color); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | } // namespace Rasterizer | ||
| 179 | |||
| 180 | } // namespace Pica | ||
diff --git a/src/video_core/rasterizer.h b/src/video_core/rasterizer.h new file mode 100644 index 000000000..500be9462 --- /dev/null +++ b/src/video_core/rasterizer.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Pica { | ||
| 8 | |||
| 9 | namespace VertexShader { | ||
| 10 | struct OutputVertex; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Rasterizer { | ||
| 14 | |||
| 15 | void ProcessTriangle(const VertexShader::OutputVertex& v0, | ||
| 16 | const VertexShader::OutputVertex& v1, | ||
| 17 | const VertexShader::OutputVertex& v2); | ||
| 18 | |||
| 19 | } // namespace Rasterizer | ||
| 20 | |||
| 21 | } // namespace Pica | ||
diff --git a/src/video_core/video_core.vcxproj b/src/video_core/video_core.vcxproj index 99ab63dce..48d77cdc4 100644 --- a/src/video_core/video_core.vcxproj +++ b/src/video_core/video_core.vcxproj | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | <ClCompile Include="clipper.cpp" /> | 23 | <ClCompile Include="clipper.cpp" /> |
| 24 | <ClCompile Include="command_processor.cpp" /> | 24 | <ClCompile Include="command_processor.cpp" /> |
| 25 | <ClCompile Include="primitive_assembly.cpp" /> | 25 | <ClCompile Include="primitive_assembly.cpp" /> |
| 26 | <ClCompile Include="rasterizer.cpp" /> | ||
| 26 | <ClCompile Include="utils.cpp" /> | 27 | <ClCompile Include="utils.cpp" /> |
| 27 | <ClCompile Include="vertex_shader.cpp" /> | 28 | <ClCompile Include="vertex_shader.cpp" /> |
| 28 | <ClCompile Include="video_core.cpp" /> | 29 | <ClCompile Include="video_core.cpp" /> |
| @@ -34,6 +35,7 @@ | |||
| 34 | <ClInclude Include="math.h" /> | 35 | <ClInclude Include="math.h" /> |
| 35 | <ClInclude Include="pica.h" /> | 36 | <ClInclude Include="pica.h" /> |
| 36 | <ClInclude Include="primitive_assembly.h" /> | 37 | <ClInclude Include="primitive_assembly.h" /> |
| 38 | <ClInclude Include="rasterizer.h" /> | ||
| 37 | <ClInclude Include="renderer_base.h" /> | 39 | <ClInclude Include="renderer_base.h" /> |
| 38 | <ClInclude Include="utils.h" /> | 40 | <ClInclude Include="utils.h" /> |
| 39 | <ClInclude Include="vertex_shader.h" /> | 41 | <ClInclude Include="vertex_shader.h" /> |
diff --git a/src/video_core/video_core.vcxproj.filters b/src/video_core/video_core.vcxproj.filters index 5222f2fa0..31af4f1df 100644 --- a/src/video_core/video_core.vcxproj.filters +++ b/src/video_core/video_core.vcxproj.filters | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | <ClCompile Include="clipper.cpp" /> | 12 | <ClCompile Include="clipper.cpp" /> |
| 13 | <ClCompile Include="command_processor.cpp" /> | 13 | <ClCompile Include="command_processor.cpp" /> |
| 14 | <ClCompile Include="primitive_assembly.cpp" /> | 14 | <ClCompile Include="primitive_assembly.cpp" /> |
| 15 | <ClCompile Include="rasterizer.cpp" /> | ||
| 15 | <ClCompile Include="utils.cpp" /> | 16 | <ClCompile Include="utils.cpp" /> |
| 16 | <ClCompile Include="vertex_shader.cpp" /> | 17 | <ClCompile Include="vertex_shader.cpp" /> |
| 17 | <ClCompile Include="video_core.cpp" /> | 18 | <ClCompile Include="video_core.cpp" /> |
| @@ -26,6 +27,7 @@ | |||
| 26 | <ClInclude Include="math.h" /> | 27 | <ClInclude Include="math.h" /> |
| 27 | <ClInclude Include="pica.h" /> | 28 | <ClInclude Include="pica.h" /> |
| 28 | <ClInclude Include="primitive_assembly.h" /> | 29 | <ClInclude Include="primitive_assembly.h" /> |
| 30 | <ClInclude Include="rasterizer.h" /> | ||
| 29 | <ClInclude Include="renderer_base.h" /> | 31 | <ClInclude Include="renderer_base.h" /> |
| 30 | <ClInclude Include="utils.h" /> | 32 | <ClInclude Include="utils.h" /> |
| 31 | <ClInclude Include="vertex_shader.h" /> | 33 | <ClInclude Include="vertex_shader.h" /> |