ShaderProcessor.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) 2022, Stephan Unverwerth <s.unverwerth@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/Vector2.h>
  7. #include <LibGfx/Vector4.h>
  8. #include <LibSoftGPU/Shader.h>
  9. #include <LibSoftGPU/ShaderProcessor.h>
  10. namespace SoftGPU {
  11. using AK::SIMD::f32x4;
  12. void ShaderProcessor::execute(PixelQuad& quad, Shader const& shader)
  13. {
  14. auto& instructions = shader.instructions();
  15. for (size_t program_counter = 0; program_counter < instructions.size(); ++program_counter) {
  16. auto instruction = instructions[program_counter];
  17. switch (instruction.operation) {
  18. case Opcode::Input:
  19. op_input(quad, instruction.arguments);
  20. break;
  21. case Opcode::Output:
  22. op_output(quad, instruction.arguments);
  23. break;
  24. case Opcode::Sample2D:
  25. op_sample2d(instruction.arguments);
  26. break;
  27. case Opcode::Swizzle:
  28. op_swizzle(instruction.arguments);
  29. break;
  30. case Opcode::Add:
  31. op_add(instruction.arguments);
  32. break;
  33. case Opcode::Sub:
  34. op_sub(instruction.arguments);
  35. break;
  36. case Opcode::Mul:
  37. op_mul(instruction.arguments);
  38. break;
  39. case Opcode::Div:
  40. op_div(instruction.arguments);
  41. break;
  42. default:
  43. VERIFY_NOT_REACHED();
  44. }
  45. }
  46. }
  47. void ShaderProcessor::op_input(PixelQuad const& quad, Instruction::Arguments arguments)
  48. {
  49. set_register(arguments.input.target_register, quad.get_input_float(arguments.input.input_index));
  50. set_register(arguments.input.target_register + 1, quad.get_input_float(arguments.input.input_index + 1));
  51. set_register(arguments.input.target_register + 2, quad.get_input_float(arguments.input.input_index + 2));
  52. set_register(arguments.input.target_register + 3, quad.get_input_float(arguments.input.input_index + 3));
  53. }
  54. void ShaderProcessor::op_output(PixelQuad& quad, Instruction::Arguments arguments)
  55. {
  56. quad.set_output(arguments.output.output_index, get_register(arguments.output.source_register));
  57. quad.set_output(arguments.output.output_index + 1, get_register(arguments.output.source_register + 1));
  58. quad.set_output(arguments.output.output_index + 2, get_register(arguments.output.source_register + 2));
  59. quad.set_output(arguments.output.output_index + 3, get_register(arguments.output.source_register + 3));
  60. }
  61. void ShaderProcessor::op_sample2d(Instruction::Arguments arguments)
  62. {
  63. Vector2<AK::SIMD::f32x4> coordinates = {
  64. get_register(arguments.sample.coordinates_register),
  65. get_register(arguments.sample.coordinates_register + 1),
  66. };
  67. auto sample = m_samplers[arguments.sample.sampler_index].sample_2d(coordinates);
  68. set_register(arguments.sample.target_register, sample.x());
  69. set_register(arguments.sample.target_register + 1, sample.y());
  70. set_register(arguments.sample.target_register + 2, sample.z());
  71. set_register(arguments.sample.target_register + 3, sample.w());
  72. }
  73. void ShaderProcessor::op_swizzle(Instruction::Arguments arguments)
  74. {
  75. f32x4 inputs[] {
  76. get_register(arguments.swizzle.source_register),
  77. get_register(arguments.swizzle.source_register + 1),
  78. get_register(arguments.swizzle.source_register + 2),
  79. get_register(arguments.swizzle.source_register + 3)
  80. };
  81. set_register(arguments.swizzle.target_register, inputs[swizzle_index(arguments.swizzle.pattern, 0)]);
  82. set_register(arguments.swizzle.target_register + 1, inputs[swizzle_index(arguments.swizzle.pattern, 1)]);
  83. set_register(arguments.swizzle.target_register + 2, inputs[swizzle_index(arguments.swizzle.pattern, 2)]);
  84. set_register(arguments.swizzle.target_register + 3, inputs[swizzle_index(arguments.swizzle.pattern, 3)]);
  85. }
  86. #define SHADER_BINOP(NAME, OP) \
  87. void ShaderProcessor::op_##NAME(Instruction::Arguments arguments) \
  88. { \
  89. auto const target = arguments.binop.target_register; \
  90. auto const source1 = arguments.binop.source_register1; \
  91. auto const source2 = arguments.binop.source_register2; \
  92. set_register(target, get_register(source1) OP get_register(source2)); \
  93. set_register(target + 1, get_register(source1 + 1) OP get_register(source2 + 1)); \
  94. set_register(target + 2, get_register(source1 + 2) OP get_register(source2 + 2)); \
  95. set_register(target + 3, get_register(source1 + 3) OP get_register(source2 + 3)); \
  96. }
  97. SHADER_BINOP(add, +)
  98. SHADER_BINOP(sub, -)
  99. SHADER_BINOP(mul, *)
  100. SHADER_BINOP(div, /)
  101. #undef SHADER_BINOP
  102. }