diff options
| author | 2014-12-20 12:40:06 -0500 | |
|---|---|---|
| committer | 2014-12-20 12:40:06 -0500 | |
| commit | acabd7be82b4174a3adab0771df6320bdbc5a85b (patch) | |
| tree | c47c2f68f50005bfb5c4003831f3977aec0be3ca /src/video_core/vertex_shader.h | |
| parent | Merge pull request #315 from chinhodado/master (diff) | |
| parent | Pica/VertexShader: Promote a log message to critical status. (diff) | |
| download | yuzu-acabd7be82b4174a3adab0771df6320bdbc5a85b.tar.gz yuzu-acabd7be82b4174a3adab0771df6320bdbc5a85b.tar.xz yuzu-acabd7be82b4174a3adab0771df6320bdbc5a85b.zip | |
Merge pull request #284 from neobrain/pica_progress
Pica progress: Texturing, shaders, cleanups & more
Diffstat (limited to 'src/video_core/vertex_shader.h')
| -rw-r--r-- | src/video_core/vertex_shader.h | 223 |
1 files changed, 11 insertions, 212 deletions
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h index bfb6fb6e3..047dde046 100644 --- a/src/video_core/vertex_shader.h +++ b/src/video_core/vertex_shader.h | |||
| @@ -27,15 +27,18 @@ struct OutputVertex { | |||
| 27 | Math::Vec4<float24> dummy; // quaternions (not implemented, yet) | 27 | Math::Vec4<float24> dummy; // quaternions (not implemented, yet) |
| 28 | Math::Vec4<float24> color; | 28 | Math::Vec4<float24> color; |
| 29 | Math::Vec2<float24> tc0; | 29 | Math::Vec2<float24> tc0; |
| 30 | Math::Vec2<float24> tc1; | ||
| 31 | float24 pad[6]; | ||
| 32 | Math::Vec2<float24> tc2; | ||
| 30 | 33 | ||
| 31 | // Padding for optimal alignment | 34 | // Padding for optimal alignment |
| 32 | float24 pad[14]; | 35 | float24 pad2[4]; |
| 33 | 36 | ||
| 34 | // Attributes used to store intermediate results | 37 | // Attributes used to store intermediate results |
| 35 | 38 | ||
| 36 | // position after perspective divide | 39 | // position after perspective divide |
| 37 | Math::Vec3<float24> screenpos; | 40 | Math::Vec3<float24> screenpos; |
| 38 | float24 pad2; | 41 | float24 pad3; |
| 39 | 42 | ||
| 40 | // Linear interpolation | 43 | // Linear interpolation |
| 41 | // factor: 0=this, 1=vtx | 44 | // factor: 0=this, 1=vtx |
| @@ -44,6 +47,8 @@ struct OutputVertex { | |||
| 44 | 47 | ||
| 45 | // TODO: Should perform perspective correct interpolation here... | 48 | // TODO: Should perform perspective correct interpolation here... |
| 46 | tc0 = tc0 * factor + vtx.tc0 * (float24::FromFloat32(1) - factor); | 49 | tc0 = tc0 * factor + vtx.tc0 * (float24::FromFloat32(1) - factor); |
| 50 | tc1 = tc1 * factor + vtx.tc1 * (float24::FromFloat32(1) - factor); | ||
| 51 | tc2 = tc2 * factor + vtx.tc2 * (float24::FromFloat32(1) - factor); | ||
| 47 | 52 | ||
| 48 | screenpos = screenpos * factor + vtx.screenpos * (float24::FromFloat32(1) - factor); | 53 | screenpos = screenpos * factor + vtx.screenpos * (float24::FromFloat32(1) - factor); |
| 49 | 54 | ||
| @@ -61,222 +66,16 @@ struct OutputVertex { | |||
| 61 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); | 66 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); |
| 62 | static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size"); | 67 | static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size"); |
| 63 | 68 | ||
| 64 | union Instruction { | ||
| 65 | enum class OpCode : u32 { | ||
| 66 | ADD = 0x0, | ||
| 67 | DP3 = 0x1, | ||
| 68 | DP4 = 0x2, | ||
| 69 | |||
| 70 | MUL = 0x8, | ||
| 71 | |||
| 72 | MAX = 0xC, | ||
| 73 | MIN = 0xD, | ||
| 74 | RCP = 0xE, | ||
| 75 | RSQ = 0xF, | ||
| 76 | |||
| 77 | MOV = 0x13, | ||
| 78 | |||
| 79 | RET = 0x21, | ||
| 80 | FLS = 0x22, // Flush | ||
| 81 | CALL = 0x24, | ||
| 82 | }; | ||
| 83 | |||
| 84 | std::string GetOpCodeName() const { | ||
| 85 | std::map<OpCode, std::string> map = { | ||
| 86 | { OpCode::ADD, "ADD" }, | ||
| 87 | { OpCode::DP3, "DP3" }, | ||
| 88 | { OpCode::DP4, "DP4" }, | ||
| 89 | { OpCode::MUL, "MUL" }, | ||
| 90 | { OpCode::MAX, "MAX" }, | ||
| 91 | { OpCode::MIN, "MIN" }, | ||
| 92 | { OpCode::RCP, "RCP" }, | ||
| 93 | { OpCode::RSQ, "RSQ" }, | ||
| 94 | { OpCode::MOV, "MOV" }, | ||
| 95 | { OpCode::RET, "RET" }, | ||
| 96 | { OpCode::FLS, "FLS" }, | ||
| 97 | }; | ||
| 98 | auto it = map.find(opcode); | ||
| 99 | if (it == map.end()) | ||
| 100 | return "UNK"; | ||
| 101 | else | ||
| 102 | return it->second; | ||
| 103 | } | ||
| 104 | |||
| 105 | u32 hex; | ||
| 106 | |||
| 107 | BitField<0x1a, 0x6, OpCode> opcode; | ||
| 108 | |||
| 109 | // General notes: | ||
| 110 | // | ||
| 111 | // When two input registers are used, one of them uses a 5-bit index while the other | ||
| 112 | // one uses a 7-bit index. This is because at most one floating point uniform may be used | ||
| 113 | // as an input. | ||
| 114 | |||
| 115 | |||
| 116 | // Format used e.g. by arithmetic instructions and comparisons | ||
| 117 | // "src1" and "src2" specify register indices (i.e. indices referring to groups of 4 floats), | ||
| 118 | // while "dest" addresses individual floats. | ||
| 119 | union { | ||
| 120 | BitField<0x00, 0x5, u32> operand_desc_id; | ||
| 121 | |||
| 122 | template<class BitFieldType> | ||
| 123 | struct SourceRegister : BitFieldType { | ||
| 124 | enum RegisterType { | ||
| 125 | Input, | ||
| 126 | Temporary, | ||
| 127 | FloatUniform | ||
| 128 | }; | ||
| 129 | |||
| 130 | RegisterType GetRegisterType() const { | ||
| 131 | if (BitFieldType::Value() < 0x10) | ||
| 132 | return Input; | ||
| 133 | else if (BitFieldType::Value() < 0x20) | ||
| 134 | return Temporary; | ||
| 135 | else | ||
| 136 | return FloatUniform; | ||
| 137 | } | ||
| 138 | |||
| 139 | int GetIndex() const { | ||
| 140 | if (GetRegisterType() == Input) | ||
| 141 | return BitFieldType::Value(); | ||
| 142 | else if (GetRegisterType() == Temporary) | ||
| 143 | return BitFieldType::Value() - 0x10; | ||
| 144 | else // if (GetRegisterType() == FloatUniform) | ||
| 145 | return BitFieldType::Value() - 0x20; | ||
| 146 | } | ||
| 147 | |||
| 148 | std::string GetRegisterName() const { | ||
| 149 | std::map<RegisterType, std::string> type = { | ||
| 150 | { Input, "i" }, | ||
| 151 | { Temporary, "t" }, | ||
| 152 | { FloatUniform, "f" }, | ||
| 153 | }; | ||
| 154 | return type[GetRegisterType()] + std::to_string(GetIndex()); | ||
| 155 | } | ||
| 156 | }; | ||
| 157 | |||
| 158 | SourceRegister<BitField<0x07, 0x5, u32>> src2; | ||
| 159 | SourceRegister<BitField<0x0c, 0x7, u32>> src1; | ||
| 160 | |||
| 161 | struct : BitField<0x15, 0x5, u32> | ||
| 162 | { | ||
| 163 | enum RegisterType { | ||
| 164 | Output, | ||
| 165 | Temporary, | ||
| 166 | Unknown | ||
| 167 | }; | ||
| 168 | RegisterType GetRegisterType() const { | ||
| 169 | if (Value() < 0x8) | ||
| 170 | return Output; | ||
| 171 | else if (Value() < 0x10) | ||
| 172 | return Unknown; | ||
| 173 | else | ||
| 174 | return Temporary; | ||
| 175 | } | ||
| 176 | int GetIndex() const { | ||
| 177 | if (GetRegisterType() == Output) | ||
| 178 | return Value(); | ||
| 179 | else if (GetRegisterType() == Temporary) | ||
| 180 | return Value() - 0x10; | ||
| 181 | else | ||
| 182 | return Value(); | ||
| 183 | } | ||
| 184 | std::string GetRegisterName() const { | ||
| 185 | std::map<RegisterType, std::string> type = { | ||
| 186 | { Output, "o" }, | ||
| 187 | { Temporary, "t" }, | ||
| 188 | { Unknown, "u" } | ||
| 189 | }; | ||
| 190 | return type[GetRegisterType()] + std::to_string(GetIndex()); | ||
| 191 | } | ||
| 192 | } dest; | ||
| 193 | } common; | ||
| 194 | |||
| 195 | // Format used for flow control instructions ("if") | ||
| 196 | union { | ||
| 197 | BitField<0x00, 0x8, u32> num_instructions; | ||
| 198 | BitField<0x0a, 0xc, u32> offset_words; | ||
| 199 | } flow_control; | ||
| 200 | }; | ||
| 201 | static_assert(std::is_standard_layout<Instruction>::value, "Structure is not using standard layout!"); | ||
| 202 | |||
| 203 | union SwizzlePattern { | ||
| 204 | u32 hex; | ||
| 205 | |||
| 206 | enum class Selector : u32 { | ||
| 207 | x = 0, | ||
| 208 | y = 1, | ||
| 209 | z = 2, | ||
| 210 | w = 3 | ||
| 211 | }; | ||
| 212 | |||
| 213 | Selector GetSelectorSrc1(int comp) const { | ||
| 214 | Selector selectors[] = { | ||
| 215 | src1_selector_0, src1_selector_1, src1_selector_2, src1_selector_3 | ||
| 216 | }; | ||
| 217 | return selectors[comp]; | ||
| 218 | } | ||
| 219 | |||
| 220 | Selector GetSelectorSrc2(int comp) const { | ||
| 221 | Selector selectors[] = { | ||
| 222 | src2_selector_0, src2_selector_1, src2_selector_2, src2_selector_3 | ||
| 223 | }; | ||
| 224 | return selectors[comp]; | ||
| 225 | } | ||
| 226 | |||
| 227 | bool DestComponentEnabled(int i) const { | ||
| 228 | return (dest_mask & (0x8 >> i)) != 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | std::string SelectorToString(bool src2) const { | ||
| 232 | std::map<Selector, std::string> map = { | ||
| 233 | { Selector::x, "x" }, | ||
| 234 | { Selector::y, "y" }, | ||
| 235 | { Selector::z, "z" }, | ||
| 236 | { Selector::w, "w" } | ||
| 237 | }; | ||
| 238 | std::string ret; | ||
| 239 | for (int i = 0; i < 4; ++i) { | ||
| 240 | ret += map.at(src2 ? GetSelectorSrc2(i) : GetSelectorSrc1(i)); | ||
| 241 | } | ||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | |||
| 245 | std::string DestMaskToString() const { | ||
| 246 | std::string ret; | ||
| 247 | for (int i = 0; i < 4; ++i) { | ||
| 248 | if (!DestComponentEnabled(i)) | ||
| 249 | ret += "_"; | ||
| 250 | else | ||
| 251 | ret += "xyzw"[i]; | ||
| 252 | } | ||
| 253 | return ret; | ||
| 254 | } | ||
| 255 | |||
| 256 | // Components of "dest" that should be written to: LSB=dest.w, MSB=dest.x | ||
| 257 | BitField< 0, 4, u32> dest_mask; | ||
| 258 | |||
| 259 | BitField< 4, 1, u32> negate; // negates src1 | ||
| 260 | |||
| 261 | BitField< 5, 2, Selector> src1_selector_3; | ||
| 262 | BitField< 7, 2, Selector> src1_selector_2; | ||
| 263 | BitField< 9, 2, Selector> src1_selector_1; | ||
| 264 | BitField<11, 2, Selector> src1_selector_0; | ||
| 265 | |||
| 266 | BitField<14, 2, Selector> src2_selector_3; | ||
| 267 | BitField<16, 2, Selector> src2_selector_2; | ||
| 268 | BitField<18, 2, Selector> src2_selector_1; | ||
| 269 | BitField<20, 2, Selector> src2_selector_0; | ||
| 270 | |||
| 271 | BitField<31, 1, u32> flag; // not sure what this means, maybe it's the sign? | ||
| 272 | }; | ||
| 273 | |||
| 274 | void SubmitShaderMemoryChange(u32 addr, u32 value); | 69 | void SubmitShaderMemoryChange(u32 addr, u32 value); |
| 275 | void SubmitSwizzleDataChange(u32 addr, u32 value); | 70 | void SubmitSwizzleDataChange(u32 addr, u32 value); |
| 276 | 71 | ||
| 277 | OutputVertex RunShader(const InputVertex& input, int num_attributes); | 72 | OutputVertex RunShader(const InputVertex& input, int num_attributes); |
| 278 | 73 | ||
| 279 | Math::Vec4<float24>& GetFloatUniform(u32 index); | 74 | Math::Vec4<float24>& GetFloatUniform(u32 index); |
| 75 | bool& GetBoolUniform(u32 index); | ||
| 76 | |||
| 77 | const std::array<u32, 1024>& GetShaderBinary(); | ||
| 78 | const std::array<u32, 1024>& GetSwizzlePatterns(); | ||
| 280 | 79 | ||
| 281 | } // namespace | 80 | } // namespace |
| 282 | 81 | ||