shader_interpreter.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include <cmath>
  7. #include <numeric>
  8. #include <boost/container/static_vector.hpp>
  9. #include <boost/range/algorithm/fill.hpp>
  10. #include <nihstro/shader_bytecode.h>
  11. #include "common/assert.h"
  12. #include "common/common_types.h"
  13. #include "common/logging/log.h"
  14. #include "common/microprofile.h"
  15. #include "common/vector_math.h"
  16. #include "video_core/pica_state.h"
  17. #include "video_core/pica_types.h"
  18. #include "video_core/shader/shader.h"
  19. #include "video_core/shader/shader_interpreter.h"
  20. using nihstro::OpCode;
  21. using nihstro::Instruction;
  22. using nihstro::RegisterType;
  23. using nihstro::SourceRegister;
  24. using nihstro::SwizzlePattern;
  25. namespace Pica {
  26. namespace Shader {
  27. struct CallStackElement {
  28. u32 final_address; // Address upon which we jump to return_address
  29. u32 return_address; // Where to jump when leaving scope
  30. u8 repeat_counter; // How often to repeat until this call stack element is removed
  31. u8 loop_increment; // Which value to add to the loop counter after an iteration
  32. // TODO: Should this be a signed value? Does it even matter?
  33. u32 loop_address; // The address where we'll return to after each loop iteration
  34. };
  35. template <bool Debug>
  36. static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData<Debug>& debug_data,
  37. unsigned offset) {
  38. // TODO: Is there a maximal size for this?
  39. boost::container::static_vector<CallStackElement, 16> call_stack;
  40. u32 program_counter = offset;
  41. state.conditional_code[0] = false;
  42. state.conditional_code[1] = false;
  43. auto call = [&program_counter, &call_stack](u32 offset, u32 num_instructions, u32 return_offset,
  44. u8 repeat_count, u8 loop_increment) {
  45. // -1 to make sure when incrementing the PC we end up at the correct offset
  46. program_counter = offset - 1;
  47. ASSERT(call_stack.size() < call_stack.capacity());
  48. call_stack.push_back(
  49. {offset + num_instructions, return_offset, repeat_count, loop_increment, offset});
  50. };
  51. auto evaluate_condition = [&state](Instruction::FlowControlType flow_control) {
  52. using Op = Instruction::FlowControlType::Op;
  53. bool result_x = flow_control.refx.Value() == state.conditional_code[0];
  54. bool result_y = flow_control.refy.Value() == state.conditional_code[1];
  55. switch (flow_control.op) {
  56. case Op::Or:
  57. return result_x || result_y;
  58. case Op::And:
  59. return result_x && result_y;
  60. case Op::JustX:
  61. return result_x;
  62. case Op::JustY:
  63. return result_y;
  64. default:
  65. UNREACHABLE();
  66. return false;
  67. }
  68. };
  69. const auto& uniforms = setup.uniforms;
  70. const auto& swizzle_data = setup.swizzle_data;
  71. const auto& program_code = setup.program_code;
  72. // Placeholder for invalid inputs
  73. static float24 dummy_vec4_float24[4];
  74. unsigned iteration = 0;
  75. bool exit_loop = false;
  76. while (!exit_loop) {
  77. if (!call_stack.empty()) {
  78. auto& top = call_stack.back();
  79. if (program_counter == top.final_address) {
  80. state.address_registers[2] += top.loop_increment;
  81. if (top.repeat_counter-- == 0) {
  82. program_counter = top.return_address;
  83. call_stack.pop_back();
  84. } else {
  85. program_counter = top.loop_address;
  86. }
  87. // TODO: Is "trying again" accurate to hardware?
  88. continue;
  89. }
  90. }
  91. const Instruction instr = {program_code[program_counter]};
  92. const SwizzlePattern swizzle = {swizzle_data[instr.common.operand_desc_id]};
  93. Record<DebugDataRecord::CUR_INSTR>(debug_data, iteration, program_counter);
  94. if (iteration > 0)
  95. Record<DebugDataRecord::NEXT_INSTR>(debug_data, iteration - 1, program_counter);
  96. debug_data.max_offset = std::max<u32>(debug_data.max_offset, 1 + program_counter);
  97. auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* {
  98. switch (source_reg.GetRegisterType()) {
  99. case RegisterType::Input:
  100. return &state.registers.input[source_reg.GetIndex()].x;
  101. case RegisterType::Temporary:
  102. return &state.registers.temporary[source_reg.GetIndex()].x;
  103. case RegisterType::FloatUniform:
  104. return &uniforms.f[source_reg.GetIndex()].x;
  105. default:
  106. return dummy_vec4_float24;
  107. }
  108. };
  109. switch (instr.opcode.Value().GetInfo().type) {
  110. case OpCode::Type::Arithmetic: {
  111. const bool is_inverted =
  112. (0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed));
  113. const int address_offset =
  114. (instr.common.address_register_index == 0)
  115. ? 0
  116. : state.address_registers[instr.common.address_register_index - 1];
  117. const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) +
  118. (is_inverted ? 0 : address_offset));
  119. const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted) +
  120. (is_inverted ? address_offset : 0));
  121. const bool negate_src1 = ((bool)swizzle.negate_src1 != false);
  122. const bool negate_src2 = ((bool)swizzle.negate_src2 != false);
  123. float24 src1[4] = {
  124. src1_[(int)swizzle.src1_selector_0.Value()],
  125. src1_[(int)swizzle.src1_selector_1.Value()],
  126. src1_[(int)swizzle.src1_selector_2.Value()],
  127. src1_[(int)swizzle.src1_selector_3.Value()],
  128. };
  129. if (negate_src1) {
  130. src1[0] = -src1[0];
  131. src1[1] = -src1[1];
  132. src1[2] = -src1[2];
  133. src1[3] = -src1[3];
  134. }
  135. float24 src2[4] = {
  136. src2_[(int)swizzle.src2_selector_0.Value()],
  137. src2_[(int)swizzle.src2_selector_1.Value()],
  138. src2_[(int)swizzle.src2_selector_2.Value()],
  139. src2_[(int)swizzle.src2_selector_3.Value()],
  140. };
  141. if (negate_src2) {
  142. src2[0] = -src2[0];
  143. src2[1] = -src2[1];
  144. src2[2] = -src2[2];
  145. src2[3] = -src2[3];
  146. }
  147. float24* dest =
  148. (instr.common.dest.Value() < 0x10)
  149. ? &state.registers.output[instr.common.dest.Value().GetIndex()][0]
  150. : (instr.common.dest.Value() < 0x20)
  151. ? &state.registers.temporary[instr.common.dest.Value().GetIndex()][0]
  152. : dummy_vec4_float24;
  153. debug_data.max_opdesc_id =
  154. std::max<u32>(debug_data.max_opdesc_id, 1 + instr.common.operand_desc_id);
  155. switch (instr.opcode.Value().EffectiveOpCode()) {
  156. case OpCode::Id::ADD: {
  157. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  158. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  159. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  160. for (int i = 0; i < 4; ++i) {
  161. if (!swizzle.DestComponentEnabled(i))
  162. continue;
  163. dest[i] = src1[i] + src2[i];
  164. }
  165. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  166. break;
  167. }
  168. case OpCode::Id::MUL: {
  169. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  170. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  171. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  172. for (int i = 0; i < 4; ++i) {
  173. if (!swizzle.DestComponentEnabled(i))
  174. continue;
  175. dest[i] = src1[i] * src2[i];
  176. }
  177. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  178. break;
  179. }
  180. case OpCode::Id::FLR:
  181. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  182. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  183. for (int i = 0; i < 4; ++i) {
  184. if (!swizzle.DestComponentEnabled(i))
  185. continue;
  186. dest[i] = float24::FromFloat32(std::floor(src1[i].ToFloat32()));
  187. }
  188. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  189. break;
  190. case OpCode::Id::MAX:
  191. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  192. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  193. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  194. for (int i = 0; i < 4; ++i) {
  195. if (!swizzle.DestComponentEnabled(i))
  196. continue;
  197. // NOTE: Exact form required to match NaN semantics to hardware:
  198. // max(0, NaN) -> NaN
  199. // max(NaN, 0) -> 0
  200. dest[i] = (src1[i] > src2[i]) ? src1[i] : src2[i];
  201. }
  202. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  203. break;
  204. case OpCode::Id::MIN:
  205. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  206. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  207. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  208. for (int i = 0; i < 4; ++i) {
  209. if (!swizzle.DestComponentEnabled(i))
  210. continue;
  211. // NOTE: Exact form required to match NaN semantics to hardware:
  212. // min(0, NaN) -> NaN
  213. // min(NaN, 0) -> 0
  214. dest[i] = (src1[i] < src2[i]) ? src1[i] : src2[i];
  215. }
  216. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  217. break;
  218. case OpCode::Id::DP3:
  219. case OpCode::Id::DP4:
  220. case OpCode::Id::DPH:
  221. case OpCode::Id::DPHI: {
  222. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  223. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  224. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  225. OpCode::Id opcode = instr.opcode.Value().EffectiveOpCode();
  226. if (opcode == OpCode::Id::DPH || opcode == OpCode::Id::DPHI)
  227. src1[3] = float24::FromFloat32(1.0f);
  228. int num_components = (opcode == OpCode::Id::DP3) ? 3 : 4;
  229. float24 dot = std::inner_product(src1, src1 + num_components, src2,
  230. float24::FromFloat32(0.f));
  231. for (int i = 0; i < 4; ++i) {
  232. if (!swizzle.DestComponentEnabled(i))
  233. continue;
  234. dest[i] = dot;
  235. }
  236. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  237. break;
  238. }
  239. // Reciprocal
  240. case OpCode::Id::RCP: {
  241. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  242. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  243. float24 rcp_res = float24::FromFloat32(1.0f / src1[0].ToFloat32());
  244. for (int i = 0; i < 4; ++i) {
  245. if (!swizzle.DestComponentEnabled(i))
  246. continue;
  247. dest[i] = rcp_res;
  248. }
  249. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  250. break;
  251. }
  252. // Reciprocal Square Root
  253. case OpCode::Id::RSQ: {
  254. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  255. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  256. float24 rsq_res = float24::FromFloat32(1.0f / std::sqrt(src1[0].ToFloat32()));
  257. for (int i = 0; i < 4; ++i) {
  258. if (!swizzle.DestComponentEnabled(i))
  259. continue;
  260. dest[i] = rsq_res;
  261. }
  262. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  263. break;
  264. }
  265. case OpCode::Id::MOVA: {
  266. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  267. for (int i = 0; i < 2; ++i) {
  268. if (!swizzle.DestComponentEnabled(i))
  269. continue;
  270. // TODO: Figure out how the rounding is done on hardware
  271. state.address_registers[i] = static_cast<s32>(src1[i].ToFloat32());
  272. }
  273. Record<DebugDataRecord::ADDR_REG_OUT>(debug_data, iteration,
  274. state.address_registers);
  275. break;
  276. }
  277. case OpCode::Id::MOV: {
  278. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  279. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  280. for (int i = 0; i < 4; ++i) {
  281. if (!swizzle.DestComponentEnabled(i))
  282. continue;
  283. dest[i] = src1[i];
  284. }
  285. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  286. break;
  287. }
  288. case OpCode::Id::SGE:
  289. case OpCode::Id::SGEI:
  290. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  291. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  292. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  293. for (int i = 0; i < 4; ++i) {
  294. if (!swizzle.DestComponentEnabled(i))
  295. continue;
  296. dest[i] = (src1[i] >= src2[i]) ? float24::FromFloat32(1.0f)
  297. : float24::FromFloat32(0.0f);
  298. }
  299. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  300. break;
  301. case OpCode::Id::SLT:
  302. case OpCode::Id::SLTI:
  303. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  304. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  305. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  306. for (int i = 0; i < 4; ++i) {
  307. if (!swizzle.DestComponentEnabled(i))
  308. continue;
  309. dest[i] = (src1[i] < src2[i]) ? float24::FromFloat32(1.0f)
  310. : float24::FromFloat32(0.0f);
  311. }
  312. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  313. break;
  314. case OpCode::Id::CMP:
  315. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  316. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  317. for (int i = 0; i < 2; ++i) {
  318. // TODO: Can you restrict to one compare via dest masking?
  319. auto compare_op = instr.common.compare_op;
  320. auto op = (i == 0) ? compare_op.x.Value() : compare_op.y.Value();
  321. switch (op) {
  322. case Instruction::Common::CompareOpType::Equal:
  323. state.conditional_code[i] = (src1[i] == src2[i]);
  324. break;
  325. case Instruction::Common::CompareOpType::NotEqual:
  326. state.conditional_code[i] = (src1[i] != src2[i]);
  327. break;
  328. case Instruction::Common::CompareOpType::LessThan:
  329. state.conditional_code[i] = (src1[i] < src2[i]);
  330. break;
  331. case Instruction::Common::CompareOpType::LessEqual:
  332. state.conditional_code[i] = (src1[i] <= src2[i]);
  333. break;
  334. case Instruction::Common::CompareOpType::GreaterThan:
  335. state.conditional_code[i] = (src1[i] > src2[i]);
  336. break;
  337. case Instruction::Common::CompareOpType::GreaterEqual:
  338. state.conditional_code[i] = (src1[i] >= src2[i]);
  339. break;
  340. default:
  341. LOG_ERROR(HW_GPU, "Unknown compare mode %x", static_cast<int>(op));
  342. break;
  343. }
  344. }
  345. Record<DebugDataRecord::CMP_RESULT>(debug_data, iteration, state.conditional_code);
  346. break;
  347. case OpCode::Id::EX2: {
  348. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  349. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  350. // EX2 only takes first component exp2 and writes it to all dest components
  351. float24 ex2_res = float24::FromFloat32(std::exp2(src1[0].ToFloat32()));
  352. for (int i = 0; i < 4; ++i) {
  353. if (!swizzle.DestComponentEnabled(i))
  354. continue;
  355. dest[i] = ex2_res;
  356. }
  357. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  358. break;
  359. }
  360. case OpCode::Id::LG2: {
  361. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  362. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  363. // LG2 only takes the first component log2 and writes it to all dest components
  364. float24 lg2_res = float24::FromFloat32(std::log2(src1[0].ToFloat32()));
  365. for (int i = 0; i < 4; ++i) {
  366. if (!swizzle.DestComponentEnabled(i))
  367. continue;
  368. dest[i] = lg2_res;
  369. }
  370. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  371. break;
  372. }
  373. default:
  374. LOG_ERROR(HW_GPU, "Unhandled arithmetic instruction: 0x%02x (%s): 0x%08x",
  375. (int)instr.opcode.Value().EffectiveOpCode(),
  376. instr.opcode.Value().GetInfo().name, instr.hex);
  377. DEBUG_ASSERT(false);
  378. break;
  379. }
  380. break;
  381. }
  382. case OpCode::Type::MultiplyAdd: {
  383. if ((instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MAD) ||
  384. (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI)) {
  385. const SwizzlePattern& swizzle = *reinterpret_cast<const SwizzlePattern*>(
  386. &swizzle_data[instr.mad.operand_desc_id]);
  387. bool is_inverted = (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI);
  388. const int address_offset =
  389. (instr.mad.address_register_index == 0)
  390. ? 0
  391. : state.address_registers[instr.mad.address_register_index - 1];
  392. const float24* src1_ = LookupSourceRegister(instr.mad.GetSrc1(is_inverted));
  393. const float24* src2_ = LookupSourceRegister(instr.mad.GetSrc2(is_inverted) +
  394. (!is_inverted * address_offset));
  395. const float24* src3_ = LookupSourceRegister(instr.mad.GetSrc3(is_inverted) +
  396. (is_inverted * address_offset));
  397. const bool negate_src1 = ((bool)swizzle.negate_src1 != false);
  398. const bool negate_src2 = ((bool)swizzle.negate_src2 != false);
  399. const bool negate_src3 = ((bool)swizzle.negate_src3 != false);
  400. float24 src1[4] = {
  401. src1_[(int)swizzle.src1_selector_0.Value()],
  402. src1_[(int)swizzle.src1_selector_1.Value()],
  403. src1_[(int)swizzle.src1_selector_2.Value()],
  404. src1_[(int)swizzle.src1_selector_3.Value()],
  405. };
  406. if (negate_src1) {
  407. src1[0] = -src1[0];
  408. src1[1] = -src1[1];
  409. src1[2] = -src1[2];
  410. src1[3] = -src1[3];
  411. }
  412. float24 src2[4] = {
  413. src2_[(int)swizzle.src2_selector_0.Value()],
  414. src2_[(int)swizzle.src2_selector_1.Value()],
  415. src2_[(int)swizzle.src2_selector_2.Value()],
  416. src2_[(int)swizzle.src2_selector_3.Value()],
  417. };
  418. if (negate_src2) {
  419. src2[0] = -src2[0];
  420. src2[1] = -src2[1];
  421. src2[2] = -src2[2];
  422. src2[3] = -src2[3];
  423. }
  424. float24 src3[4] = {
  425. src3_[(int)swizzle.src3_selector_0.Value()],
  426. src3_[(int)swizzle.src3_selector_1.Value()],
  427. src3_[(int)swizzle.src3_selector_2.Value()],
  428. src3_[(int)swizzle.src3_selector_3.Value()],
  429. };
  430. if (negate_src3) {
  431. src3[0] = -src3[0];
  432. src3[1] = -src3[1];
  433. src3[2] = -src3[2];
  434. src3[3] = -src3[3];
  435. }
  436. float24* dest =
  437. (instr.mad.dest.Value() < 0x10)
  438. ? &state.registers.output[instr.mad.dest.Value().GetIndex()][0]
  439. : (instr.mad.dest.Value() < 0x20)
  440. ? &state.registers.temporary[instr.mad.dest.Value().GetIndex()][0]
  441. : dummy_vec4_float24;
  442. Record<DebugDataRecord::SRC1>(debug_data, iteration, src1);
  443. Record<DebugDataRecord::SRC2>(debug_data, iteration, src2);
  444. Record<DebugDataRecord::SRC3>(debug_data, iteration, src3);
  445. Record<DebugDataRecord::DEST_IN>(debug_data, iteration, dest);
  446. for (int i = 0; i < 4; ++i) {
  447. if (!swizzle.DestComponentEnabled(i))
  448. continue;
  449. dest[i] = src1[i] * src2[i] + src3[i];
  450. }
  451. Record<DebugDataRecord::DEST_OUT>(debug_data, iteration, dest);
  452. } else {
  453. LOG_ERROR(HW_GPU, "Unhandled multiply-add instruction: 0x%02x (%s): 0x%08x",
  454. (int)instr.opcode.Value().EffectiveOpCode(),
  455. instr.opcode.Value().GetInfo().name, instr.hex);
  456. }
  457. break;
  458. }
  459. default: {
  460. // Handle each instruction on its own
  461. switch (instr.opcode.Value()) {
  462. case OpCode::Id::END:
  463. exit_loop = true;
  464. break;
  465. case OpCode::Id::JMPC:
  466. Record<DebugDataRecord::COND_CMP_IN>(debug_data, iteration, state.conditional_code);
  467. if (evaluate_condition(instr.flow_control)) {
  468. program_counter = instr.flow_control.dest_offset - 1;
  469. }
  470. break;
  471. case OpCode::Id::JMPU:
  472. Record<DebugDataRecord::COND_BOOL_IN>(
  473. debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
  474. if (uniforms.b[instr.flow_control.bool_uniform_id] ==
  475. !(instr.flow_control.num_instructions & 1)) {
  476. program_counter = instr.flow_control.dest_offset - 1;
  477. }
  478. break;
  479. case OpCode::Id::CALL:
  480. call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
  481. program_counter + 1, 0, 0);
  482. break;
  483. case OpCode::Id::CALLU:
  484. Record<DebugDataRecord::COND_BOOL_IN>(
  485. debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
  486. if (uniforms.b[instr.flow_control.bool_uniform_id]) {
  487. call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
  488. program_counter + 1, 0, 0);
  489. }
  490. break;
  491. case OpCode::Id::CALLC:
  492. Record<DebugDataRecord::COND_CMP_IN>(debug_data, iteration, state.conditional_code);
  493. if (evaluate_condition(instr.flow_control)) {
  494. call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
  495. program_counter + 1, 0, 0);
  496. }
  497. break;
  498. case OpCode::Id::NOP:
  499. break;
  500. case OpCode::Id::IFU:
  501. Record<DebugDataRecord::COND_BOOL_IN>(
  502. debug_data, iteration, uniforms.b[instr.flow_control.bool_uniform_id]);
  503. if (uniforms.b[instr.flow_control.bool_uniform_id]) {
  504. call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1,
  505. instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0,
  506. 0);
  507. } else {
  508. call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
  509. instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0,
  510. 0);
  511. }
  512. break;
  513. case OpCode::Id::IFC: {
  514. // TODO: Do we need to consider swizzlers here?
  515. Record<DebugDataRecord::COND_CMP_IN>(debug_data, iteration, state.conditional_code);
  516. if (evaluate_condition(instr.flow_control)) {
  517. call(program_counter + 1, instr.flow_control.dest_offset - program_counter - 1,
  518. instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0,
  519. 0);
  520. } else {
  521. call(instr.flow_control.dest_offset, instr.flow_control.num_instructions,
  522. instr.flow_control.dest_offset + instr.flow_control.num_instructions, 0,
  523. 0);
  524. }
  525. break;
  526. }
  527. case OpCode::Id::LOOP: {
  528. Math::Vec4<u8> loop_param(uniforms.i[instr.flow_control.int_uniform_id].x,
  529. uniforms.i[instr.flow_control.int_uniform_id].y,
  530. uniforms.i[instr.flow_control.int_uniform_id].z,
  531. uniforms.i[instr.flow_control.int_uniform_id].w);
  532. state.address_registers[2] = loop_param.y;
  533. Record<DebugDataRecord::LOOP_INT_IN>(debug_data, iteration, loop_param);
  534. call(program_counter + 1, instr.flow_control.dest_offset - program_counter,
  535. instr.flow_control.dest_offset + 1, loop_param.x, loop_param.z);
  536. break;
  537. }
  538. case OpCode::Id::EMIT: {
  539. GSEmitter* emitter = state.emitter_ptr;
  540. ASSERT_MSG(emitter, "Execute EMIT on VS");
  541. emitter->Emit(state.registers.output);
  542. break;
  543. }
  544. case OpCode::Id::SETEMIT: {
  545. GSEmitter* emitter = state.emitter_ptr;
  546. ASSERT_MSG(emitter, "Execute SETEMIT on VS");
  547. emitter->vertex_id = instr.setemit.vertex_id;
  548. emitter->prim_emit = instr.setemit.prim_emit != 0;
  549. emitter->winding = instr.setemit.winding != 0;
  550. break;
  551. }
  552. default:
  553. LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
  554. (int)instr.opcode.Value().EffectiveOpCode(),
  555. instr.opcode.Value().GetInfo().name, instr.hex);
  556. break;
  557. }
  558. break;
  559. }
  560. }
  561. ++program_counter;
  562. ++iteration;
  563. }
  564. }
  565. void InterpreterEngine::SetupBatch(ShaderSetup& setup, unsigned int entry_point) {
  566. ASSERT(entry_point < MAX_PROGRAM_CODE_LENGTH);
  567. setup.engine_data.entry_point = entry_point;
  568. }
  569. MICROPROFILE_DECLARE(GPU_Shader);
  570. void InterpreterEngine::Run(const ShaderSetup& setup, UnitState& state) const {
  571. MICROPROFILE_SCOPE(GPU_Shader);
  572. DebugData<false> dummy_debug_data;
  573. RunInterpreter(setup, state, dummy_debug_data, setup.engine_data.entry_point);
  574. }
  575. DebugData<true> InterpreterEngine::ProduceDebugInfo(const ShaderSetup& setup,
  576. const AttributeBuffer& input,
  577. const ShaderRegs& config) const {
  578. UnitState state;
  579. DebugData<true> debug_data;
  580. // Setup input register table
  581. boost::fill(state.registers.input, Math::Vec4<float24>::AssignToAll(float24::Zero()));
  582. state.LoadInput(config, input);
  583. RunInterpreter(setup, state, debug_data, setup.engine_data.entry_point);
  584. return debug_data;
  585. }
  586. } // namespace
  587. } // namespace