summaryrefslogtreecommitdiffstats
path: root/src/video_core/geometry_pipeline.cpp
diff options
context:
space:
mode:
authorJames Rowe <jroweboy@gmail.com>2018-01-12 04:07:44 +0100
committerJames Rowe <jroweboy@gmail.com>2018-01-13 03:11:03 +0100
commit1d28b2e142f845773e2b90e267d9632e196a99b9 (patch)
tree027a3586a0fc927731afb3711c328c6dafc8551f /src/video_core/geometry_pipeline.cpp
parentMassive removal of unused modules (diff)
downloadyuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.tar
yuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.tar.gz
yuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.tar.bz2
yuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.tar.lz
yuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.tar.xz
yuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.tar.zst
yuzu-1d28b2e142f845773e2b90e267d9632e196a99b9.zip
Diffstat (limited to 'src/video_core/geometry_pipeline.cpp')
-rw-r--r--src/video_core/geometry_pipeline.cpp274
1 files changed, 0 insertions, 274 deletions
diff --git a/src/video_core/geometry_pipeline.cpp b/src/video_core/geometry_pipeline.cpp
deleted file mode 100644
index 98ff2ccd3..000000000
--- a/src/video_core/geometry_pipeline.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "video_core/geometry_pipeline.h"
-#include "video_core/pica_state.h"
-#include "video_core/regs.h"
-#include "video_core/renderer_base.h"
-#include "video_core/video_core.h"
-
-namespace Pica {
-
-/// An attribute buffering interface for different pipeline modes
-class GeometryPipelineBackend {
-public:
- virtual ~GeometryPipelineBackend() = default;
-
- /// Checks if there is no incomplete data transfer
- virtual bool IsEmpty() const = 0;
-
- /// Checks if the pipeline needs a direct input from index buffer
- virtual bool NeedIndexInput() const = 0;
-
- /// Submits an index from index buffer
- virtual void SubmitIndex(unsigned int val) = 0;
-
- /**
- * Submits vertex attributes
- * @param input attributes of a vertex output from vertex shader
- * @return if the buffer is full and the geometry shader should be invoked
- */
- virtual bool SubmitVertex(const Shader::AttributeBuffer& input) = 0;
-};
-
-// In the Point mode, vertex attributes are sent to the input registers in the geometry shader unit.
-// The size of vertex shader outputs and geometry shader inputs are constants. Geometry shader is
-// invoked upon inputs buffer filled up by vertex shader outputs. For example, if we have a geometry
-// shader that takes 6 inputs, and the vertex shader outputs 2 attributes, it would take 3 vertices
-// for one geometry shader invocation.
-// TODO: what happens when the input size is not divisible by the output size?
-class GeometryPipeline_Point : public GeometryPipelineBackend {
-public:
- GeometryPipeline_Point(const Regs& regs, Shader::GSUnitState& unit) : regs(regs), unit(unit) {
- ASSERT(regs.pipeline.variable_primitive == 0);
- ASSERT(regs.gs.input_to_uniform == 0);
- vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1;
- size_t gs_input_num = regs.gs.max_input_attribute_index + 1;
- ASSERT(gs_input_num % vs_output_num == 0);
- buffer_cur = attribute_buffer.attr;
- buffer_end = attribute_buffer.attr + gs_input_num;
- }
-
- bool IsEmpty() const override {
- return buffer_cur == attribute_buffer.attr;
- }
-
- bool NeedIndexInput() const override {
- return false;
- }
-
- void SubmitIndex(unsigned int val) override {
- UNREACHABLE();
- }
-
- bool SubmitVertex(const Shader::AttributeBuffer& input) override {
- buffer_cur = std::copy(input.attr, input.attr + vs_output_num, buffer_cur);
- if (buffer_cur == buffer_end) {
- buffer_cur = attribute_buffer.attr;
- unit.LoadInput(regs.gs, attribute_buffer);
- return true;
- }
- return false;
- }
-
-private:
- const Regs& regs;
- Shader::GSUnitState& unit;
- Shader::AttributeBuffer attribute_buffer;
- Math::Vec4<float24>* buffer_cur;
- Math::Vec4<float24>* buffer_end;
- unsigned int vs_output_num;
-};
-
-// In VariablePrimitive mode, vertex attributes are buffered into the uniform registers in the
-// geometry shader unit. The number of vertex is variable, which is specified by the first index
-// value in the batch. This mode is usually used for subdivision.
-class GeometryPipeline_VariablePrimitive : public GeometryPipelineBackend {
-public:
- GeometryPipeline_VariablePrimitive(const Regs& regs, Shader::ShaderSetup& setup)
- : regs(regs), setup(setup) {
- ASSERT(regs.pipeline.variable_primitive == 1);
- ASSERT(regs.gs.input_to_uniform == 1);
- vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1;
- }
-
- bool IsEmpty() const override {
- return need_index;
- }
-
- bool NeedIndexInput() const override {
- return need_index;
- }
-
- void SubmitIndex(unsigned int val) override {
- DEBUG_ASSERT(need_index);
-
- // The number of vertex input is put to the uniform register
- float24 vertex_num = float24::FromFloat32(static_cast<float>(val));
- setup.uniforms.f[0] = Math::MakeVec(vertex_num, vertex_num, vertex_num, vertex_num);
-
- // The second uniform register and so on are used for receiving input vertices
- buffer_cur = setup.uniforms.f + 1;
-
- main_vertex_num = regs.pipeline.variable_vertex_main_num_minus_1 + 1;
- total_vertex_num = val;
- need_index = false;
- }
-
- bool SubmitVertex(const Shader::AttributeBuffer& input) override {
- DEBUG_ASSERT(!need_index);
- if (main_vertex_num != 0) {
- // For main vertices, receive all attributes
- buffer_cur = std::copy(input.attr, input.attr + vs_output_num, buffer_cur);
- --main_vertex_num;
- } else {
- // For other vertices, only receive the first attribute (usually the position)
- *(buffer_cur++) = input.attr[0];
- }
- --total_vertex_num;
-
- if (total_vertex_num == 0) {
- need_index = true;
- return true;
- }
-
- return false;
- }
-
-private:
- bool need_index = true;
- const Regs& regs;
- Shader::ShaderSetup& setup;
- unsigned int main_vertex_num;
- unsigned int total_vertex_num;
- Math::Vec4<float24>* buffer_cur;
- unsigned int vs_output_num;
-};
-
-// In FixedPrimitive mode, vertex attributes are buffered into the uniform registers in the geometry
-// shader unit. The number of vertex per shader invocation is constant. This is usually used for
-// particle system.
-class GeometryPipeline_FixedPrimitive : public GeometryPipelineBackend {
-public:
- GeometryPipeline_FixedPrimitive(const Regs& regs, Shader::ShaderSetup& setup)
- : regs(regs), setup(setup) {
- ASSERT(regs.pipeline.variable_primitive == 0);
- ASSERT(regs.gs.input_to_uniform == 1);
- vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1;
- ASSERT(vs_output_num == regs.pipeline.gs_config.stride_minus_1 + 1);
- size_t vertex_num = regs.pipeline.gs_config.fixed_vertex_num_minus_1 + 1;
- buffer_cur = buffer_begin = setup.uniforms.f + regs.pipeline.gs_config.start_index;
- buffer_end = buffer_begin + vs_output_num * vertex_num;
- }
-
- bool IsEmpty() const override {
- return buffer_cur == buffer_begin;
- }
-
- bool NeedIndexInput() const override {
- return false;
- }
-
- void SubmitIndex(unsigned int val) override {
- UNREACHABLE();
- }
-
- bool SubmitVertex(const Shader::AttributeBuffer& input) override {
- buffer_cur = std::copy(input.attr, input.attr + vs_output_num, buffer_cur);
- if (buffer_cur == buffer_end) {
- buffer_cur = buffer_begin;
- return true;
- }
- return false;
- }
-
-private:
- const Regs& regs;
- Shader::ShaderSetup& setup;
- Math::Vec4<float24>* buffer_begin;
- Math::Vec4<float24>* buffer_cur;
- Math::Vec4<float24>* buffer_end;
- unsigned int vs_output_num;
-};
-
-GeometryPipeline::GeometryPipeline(State& state) : state(state) {}
-
-GeometryPipeline::~GeometryPipeline() = default;
-
-void GeometryPipeline::SetVertexHandler(Shader::VertexHandler vertex_handler) {
- this->vertex_handler = vertex_handler;
-}
-
-void GeometryPipeline::Setup(Shader::ShaderEngine* shader_engine) {
- if (!backend)
- return;
-
- this->shader_engine = shader_engine;
- shader_engine->SetupBatch(state.gs, state.regs.gs.main_offset);
-}
-
-void GeometryPipeline::Reconfigure() {
- ASSERT(!backend || backend->IsEmpty());
-
- if (state.regs.pipeline.use_gs == PipelineRegs::UseGS::No) {
- backend = nullptr;
- return;
- }
-
- ASSERT(state.regs.pipeline.use_gs == PipelineRegs::UseGS::Yes);
-
- // The following assumes that when geometry shader is in use, the shader unit 3 is configured as
- // a geometry shader unit.
- // TODO: what happens if this is not true?
- ASSERT(state.regs.pipeline.gs_unit_exclusive_configuration == 1);
- ASSERT(state.regs.gs.shader_mode == ShaderRegs::ShaderMode::GS);
-
- state.gs_unit.ConfigOutput(state.regs.gs);
-
- ASSERT(state.regs.pipeline.vs_outmap_total_minus_1_a ==
- state.regs.pipeline.vs_outmap_total_minus_1_b);
-
- switch (state.regs.pipeline.gs_config.mode) {
- case PipelineRegs::GSMode::Point:
- backend = std::make_unique<GeometryPipeline_Point>(state.regs, state.gs_unit);
- break;
- case PipelineRegs::GSMode::VariablePrimitive:
- backend = std::make_unique<GeometryPipeline_VariablePrimitive>(state.regs, state.gs);
- break;
- case PipelineRegs::GSMode::FixedPrimitive:
- backend = std::make_unique<GeometryPipeline_FixedPrimitive>(state.regs, state.gs);
- break;
- default:
- UNREACHABLE();
- }
-}
-
-bool GeometryPipeline::NeedIndexInput() const {
- if (!backend)
- return false;
- return backend->NeedIndexInput();
-}
-
-void GeometryPipeline::SubmitIndex(unsigned int val) {
- backend->SubmitIndex(val);
-}
-
-void GeometryPipeline::SubmitVertex(const Shader::AttributeBuffer& input) {
- if (!backend) {
- // No backend means the geometry shader is disabled, so we send the vertex shader output
- // directly to the primitive assembler.
- vertex_handler(input);
- } else {
- if (backend->SubmitVertex(input)) {
- shader_engine->Run(state.gs, state.gs_unit);
-
- // The uniform b15 is set to true after every geometry shader invocation. This is useful
- // for the shader to know if this is the first invocation in a batch, if the program set
- // b15 to false first.
- state.gs.uniforms.b[15] = true;
- }
- }
-}
-
-} // namespace Pica