diff options
Diffstat (limited to 'src/video_core/shader/shader.h')
| -rw-r--r-- | src/video_core/shader/shader.h | 233 |
1 files changed, 0 insertions, 233 deletions
diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h deleted file mode 100644 index a3789da01..000000000 --- a/src/video_core/shader/shader.h +++ /dev/null | |||
| @@ -1,233 +0,0 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | ||
| 9 | #include <functional> | ||
| 10 | #include <type_traits> | ||
| 11 | #include <nihstro/shader_bytecode.h> | ||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/common_funcs.h" | ||
| 14 | #include "common/common_types.h" | ||
| 15 | #include "common/vector_math.h" | ||
| 16 | #include "video_core/pica_types.h" | ||
| 17 | #include "video_core/regs_rasterizer.h" | ||
| 18 | #include "video_core/regs_shader.h" | ||
| 19 | |||
| 20 | using nihstro::RegisterType; | ||
| 21 | using nihstro::SourceRegister; | ||
| 22 | using nihstro::DestRegister; | ||
| 23 | |||
| 24 | namespace Pica { | ||
| 25 | |||
| 26 | namespace Shader { | ||
| 27 | |||
| 28 | constexpr unsigned MAX_PROGRAM_CODE_LENGTH = 4096; | ||
| 29 | constexpr unsigned MAX_SWIZZLE_DATA_LENGTH = 4096; | ||
| 30 | |||
| 31 | struct AttributeBuffer { | ||
| 32 | alignas(16) Math::Vec4<float24> attr[16]; | ||
| 33 | }; | ||
| 34 | |||
| 35 | /// Handler type for receiving vertex outputs from vertex shader or geometry shader | ||
| 36 | using VertexHandler = std::function<void(const AttributeBuffer&)>; | ||
| 37 | |||
| 38 | /// Handler type for signaling to invert the vertex order of the next triangle | ||
| 39 | using WindingSetter = std::function<void()>; | ||
| 40 | |||
| 41 | struct OutputVertex { | ||
| 42 | Math::Vec4<float24> pos; | ||
| 43 | Math::Vec4<float24> quat; | ||
| 44 | Math::Vec4<float24> color; | ||
| 45 | Math::Vec2<float24> tc0; | ||
| 46 | Math::Vec2<float24> tc1; | ||
| 47 | float24 tc0_w; | ||
| 48 | INSERT_PADDING_WORDS(1); | ||
| 49 | Math::Vec3<float24> view; | ||
| 50 | INSERT_PADDING_WORDS(1); | ||
| 51 | Math::Vec2<float24> tc2; | ||
| 52 | |||
| 53 | static OutputVertex FromAttributeBuffer(const RasterizerRegs& regs, | ||
| 54 | const AttributeBuffer& output); | ||
| 55 | }; | ||
| 56 | #define ASSERT_POS(var, pos) \ | ||
| 57 | static_assert(offsetof(OutputVertex, var) == pos * sizeof(float24), "Semantic at wrong " \ | ||
| 58 | "offset.") | ||
| 59 | ASSERT_POS(pos, RasterizerRegs::VSOutputAttributes::POSITION_X); | ||
| 60 | ASSERT_POS(quat, RasterizerRegs::VSOutputAttributes::QUATERNION_X); | ||
| 61 | ASSERT_POS(color, RasterizerRegs::VSOutputAttributes::COLOR_R); | ||
| 62 | ASSERT_POS(tc0, RasterizerRegs::VSOutputAttributes::TEXCOORD0_U); | ||
| 63 | ASSERT_POS(tc1, RasterizerRegs::VSOutputAttributes::TEXCOORD1_U); | ||
| 64 | ASSERT_POS(tc0_w, RasterizerRegs::VSOutputAttributes::TEXCOORD0_W); | ||
| 65 | ASSERT_POS(view, RasterizerRegs::VSOutputAttributes::VIEW_X); | ||
| 66 | ASSERT_POS(tc2, RasterizerRegs::VSOutputAttributes::TEXCOORD2_U); | ||
| 67 | #undef ASSERT_POS | ||
| 68 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); | ||
| 69 | static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size"); | ||
| 70 | |||
| 71 | /** | ||
| 72 | * This structure contains state information for primitive emitting in geometry shader. | ||
| 73 | */ | ||
| 74 | struct GSEmitter { | ||
| 75 | std::array<std::array<Math::Vec4<float24>, 16>, 3> buffer; | ||
| 76 | u8 vertex_id; | ||
| 77 | bool prim_emit; | ||
| 78 | bool winding; | ||
| 79 | u32 output_mask; | ||
| 80 | |||
| 81 | // Function objects are hidden behind a raw pointer to make the structure standard layout type, | ||
| 82 | // for JIT to use offsetof to access other members. | ||
| 83 | struct Handlers { | ||
| 84 | VertexHandler vertex_handler; | ||
| 85 | WindingSetter winding_setter; | ||
| 86 | } * handlers; | ||
| 87 | |||
| 88 | GSEmitter(); | ||
| 89 | ~GSEmitter(); | ||
| 90 | void Emit(Math::Vec4<float24> (&vertex)[16]); | ||
| 91 | }; | ||
| 92 | static_assert(std::is_standard_layout<GSEmitter>::value, "GSEmitter is not standard layout type"); | ||
| 93 | |||
| 94 | /** | ||
| 95 | * This structure contains the state information that needs to be unique for a shader unit. The 3DS | ||
| 96 | * has four shader units that process shaders in parallel. At the present, Citra only implements a | ||
| 97 | * single shader unit that processes all shaders serially. Putting the state information in a struct | ||
| 98 | * here will make it easier for us to parallelize the shader processing later. | ||
| 99 | */ | ||
| 100 | struct UnitState { | ||
| 101 | explicit UnitState(GSEmitter* emitter = nullptr); | ||
| 102 | struct Registers { | ||
| 103 | // The registers are accessed by the shader JIT using SSE instructions, and are therefore | ||
| 104 | // required to be 16-byte aligned. | ||
| 105 | alignas(16) Math::Vec4<float24> input[16]; | ||
| 106 | alignas(16) Math::Vec4<float24> temporary[16]; | ||
| 107 | alignas(16) Math::Vec4<float24> output[16]; | ||
| 108 | } registers; | ||
| 109 | static_assert(std::is_pod<Registers>::value, "Structure is not POD"); | ||
| 110 | |||
| 111 | bool conditional_code[2]; | ||
| 112 | |||
| 113 | // Two Address registers and one loop counter | ||
| 114 | // TODO: How many bits do these actually have? | ||
| 115 | s32 address_registers[3]; | ||
| 116 | |||
| 117 | GSEmitter* emitter_ptr; | ||
| 118 | |||
| 119 | static size_t InputOffset(const SourceRegister& reg) { | ||
| 120 | switch (reg.GetRegisterType()) { | ||
| 121 | case RegisterType::Input: | ||
| 122 | return offsetof(UnitState, registers.input) + | ||
| 123 | reg.GetIndex() * sizeof(Math::Vec4<float24>); | ||
| 124 | |||
| 125 | case RegisterType::Temporary: | ||
| 126 | return offsetof(UnitState, registers.temporary) + | ||
| 127 | reg.GetIndex() * sizeof(Math::Vec4<float24>); | ||
| 128 | |||
| 129 | default: | ||
| 130 | UNREACHABLE(); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | static size_t OutputOffset(const DestRegister& reg) { | ||
| 136 | switch (reg.GetRegisterType()) { | ||
| 137 | case RegisterType::Output: | ||
| 138 | return offsetof(UnitState, registers.output) + | ||
| 139 | reg.GetIndex() * sizeof(Math::Vec4<float24>); | ||
| 140 | |||
| 141 | case RegisterType::Temporary: | ||
| 142 | return offsetof(UnitState, registers.temporary) + | ||
| 143 | reg.GetIndex() * sizeof(Math::Vec4<float24>); | ||
| 144 | |||
| 145 | default: | ||
| 146 | UNREACHABLE(); | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | /** | ||
| 152 | * Loads the unit state with an input vertex. | ||
| 153 | * | ||
| 154 | * @param config Shader configuration registers corresponding to the unit. | ||
| 155 | * @param input Attribute buffer to load into the input registers. | ||
| 156 | */ | ||
| 157 | void LoadInput(const ShaderRegs& config, const AttributeBuffer& input); | ||
| 158 | |||
| 159 | void WriteOutput(const ShaderRegs& config, AttributeBuffer& output); | ||
| 160 | }; | ||
| 161 | |||
| 162 | /** | ||
| 163 | * This is an extended shader unit state that represents the special unit that can run both vertex | ||
| 164 | * shader and geometry shader. It contains an additional primitive emitter and utilities for | ||
| 165 | * geometry shader. | ||
| 166 | */ | ||
| 167 | struct GSUnitState : public UnitState { | ||
| 168 | GSUnitState(); | ||
| 169 | void SetVertexHandler(VertexHandler vertex_handler, WindingSetter winding_setter); | ||
| 170 | void ConfigOutput(const ShaderRegs& config); | ||
| 171 | |||
| 172 | GSEmitter emitter; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct ShaderSetup { | ||
| 176 | struct { | ||
| 177 | // The float uniforms are accessed by the shader JIT using SSE instructions, and are | ||
| 178 | // therefore required to be 16-byte aligned. | ||
| 179 | alignas(16) Math::Vec4<float24> f[96]; | ||
| 180 | |||
| 181 | std::array<bool, 16> b; | ||
| 182 | std::array<Math::Vec4<u8>, 4> i; | ||
| 183 | } uniforms; | ||
| 184 | |||
| 185 | static size_t GetFloatUniformOffset(unsigned index) { | ||
| 186 | return offsetof(ShaderSetup, uniforms.f) + index * sizeof(Math::Vec4<float24>); | ||
| 187 | } | ||
| 188 | |||
| 189 | static size_t GetBoolUniformOffset(unsigned index) { | ||
| 190 | return offsetof(ShaderSetup, uniforms.b) + index * sizeof(bool); | ||
| 191 | } | ||
| 192 | |||
| 193 | static size_t GetIntUniformOffset(unsigned index) { | ||
| 194 | return offsetof(ShaderSetup, uniforms.i) + index * sizeof(Math::Vec4<u8>); | ||
| 195 | } | ||
| 196 | |||
| 197 | std::array<u32, MAX_PROGRAM_CODE_LENGTH> program_code; | ||
| 198 | std::array<u32, MAX_SWIZZLE_DATA_LENGTH> swizzle_data; | ||
| 199 | |||
| 200 | /// Data private to ShaderEngines | ||
| 201 | struct EngineData { | ||
| 202 | unsigned int entry_point; | ||
| 203 | /// Used by the JIT, points to a compiled shader object. | ||
| 204 | const void* cached_shader = nullptr; | ||
| 205 | } engine_data; | ||
| 206 | }; | ||
| 207 | |||
| 208 | class ShaderEngine { | ||
| 209 | public: | ||
| 210 | virtual ~ShaderEngine() = default; | ||
| 211 | |||
| 212 | /** | ||
| 213 | * Performs any shader unit setup that only needs to happen once per shader (as opposed to once | ||
| 214 | * per vertex, which would happen within the `Run` function). | ||
| 215 | */ | ||
| 216 | virtual void SetupBatch(ShaderSetup& setup, unsigned int entry_point) = 0; | ||
| 217 | |||
| 218 | /** | ||
| 219 | * Runs the currently setup shader. | ||
| 220 | * | ||
| 221 | * @param setup Shader engine state, must be setup with SetupBatch on each shader change. | ||
| 222 | * @param state Shader unit state, must be setup with input data before each shader invocation. | ||
| 223 | */ | ||
| 224 | virtual void Run(const ShaderSetup& setup, UnitState& state) const = 0; | ||
| 225 | }; | ||
| 226 | |||
| 227 | // TODO(yuriks): Remove and make it non-global state somewhere | ||
| 228 | ShaderEngine* GetEngine(); | ||
| 229 | void Shutdown(); | ||
| 230 | |||
| 231 | } // namespace Shader | ||
| 232 | |||
| 233 | } // namespace Pica | ||