From 2f1c129f6407fe2d5c8c3e57c6717d5668570de5 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 17 Aug 2014 17:44:55 +0200 Subject: Pica: Consolidate the primitive assembly code in PrimitiveAssembly and GeometryDumper. --- src/video_core/command_processor.cpp | 20 ++++++++++++---- src/video_core/debug_utils/debug_utils.cpp | 22 +++++------------ src/video_core/debug_utils/debug_utils.h | 12 ++++------ src/video_core/primitive_assembly.cpp | 28 +++++++++++++--------- src/video_core/primitive_assembly.h | 38 +++++++++++++++++++++++------- 5 files changed, 74 insertions(+), 46 deletions(-) diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 8da03060..9567a984 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include "clipper.h" #include "command_processor.h" #include "math.h" #include "pica.h" @@ -79,6 +80,8 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { bool index_u16 = (bool)index_info.format; DebugUtils::GeometryDumper geometry_dumper; + PrimitiveAssembler clipper_primitive_assembler(registers.triangle_topology.Value()); + PrimitiveAssembler dumping_primitive_assembler(registers.triangle_topology.Value()); for (int index = 0; index < registers.num_vertices; ++index) { @@ -108,16 +111,25 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { } } - // NOTE: For now, we simply assume that the first input attribute corresponds to the position. - geometry_dumper.AddVertex({input.attr[0][0].ToFloat32(), input.attr[0][1].ToFloat32(), input.attr[0][2].ToFloat32()}, registers.triangle_topology); - + // NOTE: When dumping geometry, we simply assume that the first input attribute + // corresponds to the position for now. + DebugUtils::GeometryDumper::Vertex dumped_vertex = { + input.attr[0][0].ToFloat32(), input.attr[0][1].ToFloat32(), input.attr[0][2].ToFloat32() + }; + using namespace std::placeholders; + dumping_primitive_assembler.SubmitVertex(dumped_vertex, + std::bind(&DebugUtils::GeometryDumper::AddTriangle, + &geometry_dumper, _1, _2, _3)); + + // Send to vertex shader VertexShader::OutputVertex output = VertexShader::RunShader(input, attribute_config.GetNumTotalAttributes()); if (is_indexed) { // TODO: Add processed vertex to vertex cache! } - PrimitiveAssembly::SubmitVertex(output); + // Send to triangle clipper + clipper_primitive_assembler.SubmitVertex(output, Clipper::ProcessTriangle); } geometry_dumper.Dump(); break; diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index f7d9455b..48e6dd18 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -22,27 +22,17 @@ namespace Pica { namespace DebugUtils { -void GeometryDumper::AddVertex(std::array pos, TriangleTopology topology) { - vertices.push_back({pos[0], pos[1], pos[2]}); +void GeometryDumper::AddTriangle(Vertex& v0, Vertex& v1, Vertex& v2) { + vertices.push_back(v0); + vertices.push_back(v1); + vertices.push_back(v2); int num_vertices = vertices.size(); - - switch (topology) { - case TriangleTopology::List: - case TriangleTopology::ListIndexed: - if (0 == (num_vertices % 3)) - faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); - break; - - default: - ERROR_LOG(GPU, "Unknown triangle topology %x", (int)topology); - exit(0); - break; - } + faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); } void GeometryDumper::Dump() { - // NOTE: Permanently enabling this just trashes hard disks for no reason. + // NOTE: Permanently enabling this just trashes the hard disk for no reason. // Hence, this is currently disabled. return; diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index 53c33c96..8b1499bf 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h @@ -14,20 +14,18 @@ namespace Pica { namespace DebugUtils { -using TriangleTopology = Regs::TriangleTopology; - // Simple utility class for dumping geometry data to an OBJ file class GeometryDumper { public: - void AddVertex(std::array pos, TriangleTopology topology); - - void Dump(); - -private: struct Vertex { std::array pos; }; + void AddTriangle(Vertex& v0, Vertex& v1, Vertex& v2); + + void Dump(); + +private: struct Face { int index[3]; }; diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp index 2354ffb9..dabf2d1a 100644 --- a/src/video_core/primitive_assembly.cpp +++ b/src/video_core/primitive_assembly.cpp @@ -2,21 +2,23 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include "clipper.h" #include "pica.h" #include "primitive_assembly.h" #include "vertex_shader.h" -namespace Pica { +#include "video_core/debug_utils/debug_utils.h" -namespace PrimitiveAssembly { +namespace Pica { -static OutputVertex buffer[2]; -static int buffer_index = 0; // TODO: reset this on emulation restart +template +PrimitiveAssembler::PrimitiveAssembler(Regs::TriangleTopology topology) + : topology(topology), buffer_index(0) { +} -void SubmitVertex(OutputVertex& vtx) +template +void PrimitiveAssembler::SubmitVertex(VertexType& vtx, TriangleHandler triangle_handler) { - switch (registers.triangle_topology) { + switch (topology) { case Regs::TriangleTopology::List: case Regs::TriangleTopology::ListIndexed: if (buffer_index < 2) { @@ -24,7 +26,7 @@ void SubmitVertex(OutputVertex& vtx) } else { buffer_index = 0; - Clipper::ProcessTriangle(buffer[0], buffer[1], vtx); + triangle_handler(buffer[0], buffer[1], vtx); } break; @@ -32,7 +34,7 @@ void SubmitVertex(OutputVertex& vtx) if (buffer_index == 2) { buffer_index = 0; - Clipper::ProcessTriangle(buffer[0], buffer[1], vtx); + triangle_handler(buffer[0], buffer[1], vtx); buffer[1] = vtx; } else { @@ -41,11 +43,15 @@ void SubmitVertex(OutputVertex& vtx) break; default: - ERROR_LOG(GPU, "Unknown triangle mode %x:", (int)registers.triangle_topology.Value()); + ERROR_LOG(GPU, "Unknown triangle topology %x:", (int)topology); break; } } -} // namespace +// explicitly instantiate use cases +template +struct PrimitiveAssembler; +template +struct PrimitiveAssembler; } // namespace diff --git a/src/video_core/primitive_assembly.h b/src/video_core/primitive_assembly.h index 2a2b0c17..ea2e2f61 100644 --- a/src/video_core/primitive_assembly.h +++ b/src/video_core/primitive_assembly.h @@ -4,18 +4,40 @@ #pragma once -namespace Pica { +#include -namespace VertexShader { - struct OutputVertex; -} +#include "video_core/pica.h" -namespace PrimitiveAssembly { +#include "video_core/vertex_shader.h" -using VertexShader::OutputVertex; +namespace Pica { -void SubmitVertex(OutputVertex& vtx); +/* + * Utility class to build triangles from a series of vertices, + * according to a given triangle topology. + */ +template +struct PrimitiveAssembler { + using TriangleHandler = std::function; + + PrimitiveAssembler(Regs::TriangleTopology topology); + + /* + * Queues a vertex, builds primitives from the vertex queue according to the given + * triangle topology, and calls triangle_handler for each generated primitive. + * NOTE: We could specify the triangle handler in the constructor, but this way we can + * keep event and handler code next to each other. + */ + void SubmitVertex(VertexType& vtx, TriangleHandler triangle_handler); + +private: + Regs::TriangleTopology topology; + + int buffer_index; + VertexType buffer[2]; +}; -} // namespace } // namespace -- cgit v1.2.3