BCnEncoder.cs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. using Ryujinx.Common;
  2. using Ryujinx.Graphics.Texture.Encoders;
  3. using System;
  4. namespace Ryujinx.Graphics.Texture
  5. {
  6. public static class BCnEncoder
  7. {
  8. private const int BlockWidth = 4;
  9. private const int BlockHeight = 4;
  10. public static byte[] EncodeBC7(byte[] data, int width, int height, int depth, int levels, int layers)
  11. {
  12. int size = 0;
  13. for (int l = 0; l < levels; l++)
  14. {
  15. int w = BitUtils.DivRoundUp(Math.Max(1, width >> l), BlockWidth);
  16. int h = BitUtils.DivRoundUp(Math.Max(1, height >> l), BlockHeight);
  17. size += w * h * 16 * Math.Max(1, depth >> l) * layers;
  18. }
  19. byte[] output = new byte[size];
  20. int imageBaseIOffs = 0;
  21. int imageBaseOOffs = 0;
  22. for (int l = 0; l < levels; l++)
  23. {
  24. int rgba8Size = width * height * depth * layers * 4;
  25. int w = BitUtils.DivRoundUp(width, BlockWidth);
  26. int h = BitUtils.DivRoundUp(height, BlockHeight);
  27. for (int l2 = 0; l2 < layers; l2++)
  28. {
  29. for (int z = 0; z < depth; z++)
  30. {
  31. BC7Encoder.Encode(
  32. output.AsMemory().Slice(imageBaseOOffs),
  33. data.AsMemory().Slice(imageBaseIOffs),
  34. width,
  35. height,
  36. EncodeMode.Fast | EncodeMode.Multithreaded);
  37. imageBaseIOffs += width * height * 4;
  38. imageBaseOOffs += w * h * 16;
  39. }
  40. }
  41. width = Math.Max(1, width >> 1);
  42. height = Math.Max(1, height >> 1);
  43. depth = Math.Max(1, depth >> 1);
  44. }
  45. return output;
  46. }
  47. }
  48. }