summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/shader.cpp38
-rw-r--r--src/video_core/shader/shader.h46
2 files changed, 84 insertions, 0 deletions
diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp
index 67ed19ba8..b12468d3a 100644
--- a/src/video_core/shader/shader.cpp
+++ b/src/video_core/shader/shader.cpp
@@ -82,6 +82,44 @@ void UnitState::WriteOutput(const ShaderRegs& config, AttributeBuffer& output) {
82 } 82 }
83} 83}
84 84
85UnitState::UnitState(GSEmitter* emitter) : emitter_ptr(emitter) {}
86
87GSEmitter::GSEmitter() {
88 handlers = new Handlers;
89}
90
91GSEmitter::~GSEmitter() {
92 delete handlers;
93}
94
95void GSEmitter::Emit(Math::Vec4<float24> (&vertex)[16]) {
96 ASSERT(vertex_id < 3);
97 std::copy(std::begin(vertex), std::end(vertex), buffer[vertex_id].begin());
98 if (prim_emit) {
99 if (winding)
100 handlers->winding_setter();
101 for (size_t i = 0; i < buffer.size(); ++i) {
102 AttributeBuffer output;
103 unsigned int output_i = 0;
104 for (unsigned int reg : Common::BitSet<u32>(output_mask)) {
105 output.attr[output_i++] = buffer[i][reg];
106 }
107 handlers->vertex_handler(output);
108 }
109 }
110}
111
112GSUnitState::GSUnitState() : UnitState(&emitter) {}
113
114void GSUnitState::SetVertexHandler(VertexHandler vertex_handler, WindingSetter winding_setter) {
115 emitter.handlers->vertex_handler = std::move(vertex_handler);
116 emitter.handlers->winding_setter = std::move(winding_setter);
117}
118
119void GSUnitState::ConfigOutput(const ShaderRegs& config) {
120 emitter.output_mask = config.output_mask;
121}
122
85MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240)); 123MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240));
86 124
87#ifdef ARCHITECTURE_x86_64 125#ifdef ARCHITECTURE_x86_64
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h
index e156f6aef..caec96043 100644
--- a/src/video_core/shader/shader.h
+++ b/src/video_core/shader/shader.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <functional>
9#include <type_traits> 10#include <type_traits>
10#include <nihstro/shader_bytecode.h> 11#include <nihstro/shader_bytecode.h>
11#include "common/assert.h" 12#include "common/assert.h"
@@ -31,6 +32,12 @@ struct AttributeBuffer {
31 alignas(16) Math::Vec4<float24> attr[16]; 32 alignas(16) Math::Vec4<float24> attr[16];
32}; 33};
33 34
35/// Handler type for receiving vertex outputs from vertex shader or geometry shader
36using VertexHandler = std::function<void(const AttributeBuffer&)>;
37
38/// Handler type for signaling to invert the vertex order of the next triangle
39using WindingSetter = std::function<void()>;
40
34struct OutputVertex { 41struct OutputVertex {
35 Math::Vec4<float24> pos; 42 Math::Vec4<float24> pos;
36 Math::Vec4<float24> quat; 43 Math::Vec4<float24> quat;
@@ -61,12 +68,36 @@ static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD");
61static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size"); 68static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size");
62 69
63/** 70/**
71 * This structure contains state information for primitive emitting in geometry shader.
72 */
73struct GSEmitter {
74 std::array<std::array<Math::Vec4<float24>, 16>, 3> buffer;
75 u8 vertex_id;
76 bool prim_emit;
77 bool winding;
78 u32 output_mask;
79
80 // Function objects are hidden behind a raw pointer to make the structure standard layout type,
81 // for JIT to use offsetof to access other members.
82 struct Handlers {
83 VertexHandler vertex_handler;
84 WindingSetter winding_setter;
85 } * handlers;
86
87 GSEmitter();
88 ~GSEmitter();
89 void Emit(Math::Vec4<float24> (&vertex)[16]);
90};
91static_assert(std::is_standard_layout<GSEmitter>::value, "GSEmitter is not standard layout type");
92
93/**
64 * This structure contains the state information that needs to be unique for a shader unit. The 3DS 94 * This structure contains the state information that needs to be unique for a shader unit. The 3DS
65 * has four shader units that process shaders in parallel. At the present, Citra only implements a 95 * has four shader units that process shaders in parallel. At the present, Citra only implements a
66 * single shader unit that processes all shaders serially. Putting the state information in a struct 96 * single shader unit that processes all shaders serially. Putting the state information in a struct
67 * here will make it easier for us to parallelize the shader processing later. 97 * here will make it easier for us to parallelize the shader processing later.
68 */ 98 */
69struct UnitState { 99struct UnitState {
100 explicit UnitState(GSEmitter* emitter = nullptr);
70 struct Registers { 101 struct Registers {
71 // The registers are accessed by the shader JIT using SSE instructions, and are therefore 102 // The registers are accessed by the shader JIT using SSE instructions, and are therefore
72 // required to be 16-byte aligned. 103 // required to be 16-byte aligned.
@@ -82,6 +113,8 @@ struct UnitState {
82 // TODO: How many bits do these actually have? 113 // TODO: How many bits do these actually have?
83 s32 address_registers[3]; 114 s32 address_registers[3];
84 115
116 GSEmitter* emitter_ptr;
117
85 static size_t InputOffset(const SourceRegister& reg) { 118 static size_t InputOffset(const SourceRegister& reg) {
86 switch (reg.GetRegisterType()) { 119 switch (reg.GetRegisterType()) {
87 case RegisterType::Input: 120 case RegisterType::Input:
@@ -125,6 +158,19 @@ struct UnitState {
125 void WriteOutput(const ShaderRegs& config, AttributeBuffer& output); 158 void WriteOutput(const ShaderRegs& config, AttributeBuffer& output);
126}; 159};
127 160
161/**
162 * This is an extended shader unit state that represents the special unit that can run both vertex
163 * shader and geometry shader. It contains an additional primitive emitter and utilities for
164 * geometry shader.
165 */
166struct GSUnitState : public UnitState {
167 GSUnitState();
168 void SetVertexHandler(VertexHandler vertex_handler, WindingSetter winding_setter);
169 void ConfigOutput(const ShaderRegs& config);
170
171 GSEmitter emitter;
172};
173
128struct ShaderSetup { 174struct ShaderSetup {
129 struct { 175 struct {
130 // The float uniforms are accessed by the shader JIT using SSE instructions, and are 176 // The float uniforms are accessed by the shader JIT using SSE instructions, and are