MTLVertexManager.mm 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright 2022 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "VideoBackends/Metal/MTLVertexManager.h"
  4. #include "Core/System.h"
  5. #include "VideoBackends/Metal/MTLStateTracker.h"
  6. #include "VideoCommon/GeometryShaderManager.h"
  7. #include "VideoCommon/PixelShaderManager.h"
  8. #include "VideoCommon/Statistics.h"
  9. #include "VideoCommon/VertexShaderManager.h"
  10. Metal::VertexManager::VertexManager()
  11. {
  12. }
  13. Metal::VertexManager::~VertexManager() = default;
  14. void Metal::VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
  15. {
  16. g_state_tracker->SetUtilityUniform(uniforms, uniforms_size);
  17. }
  18. bool Metal::VertexManager::UploadTexelBuffer(const void* data, u32 data_size,
  19. TexelBufferFormat format, u32* out_offset)
  20. {
  21. *out_offset = 0;
  22. StateTracker::Map map = g_state_tracker->Allocate(StateTracker::UploadBuffer::Texels, data_size,
  23. StateTracker::AlignMask::Other);
  24. memcpy(map.cpu_buffer, data, data_size);
  25. g_state_tracker->SetTexelBuffer(map.gpu_buffer, map.gpu_offset, 0);
  26. return true;
  27. }
  28. bool Metal::VertexManager::UploadTexelBuffer(const void* data, u32 data_size,
  29. TexelBufferFormat format, u32* out_offset,
  30. const void* palette_data, u32 palette_size,
  31. TexelBufferFormat palette_format,
  32. u32* out_palette_offset)
  33. {
  34. *out_offset = 0;
  35. *out_palette_offset = 0;
  36. const u32 aligned_data_size = g_state_tracker->Align(data_size, StateTracker::AlignMask::Other);
  37. const u32 total_size = aligned_data_size + palette_size;
  38. StateTracker::Map map = g_state_tracker->Allocate(StateTracker::UploadBuffer::Texels, total_size,
  39. StateTracker::AlignMask::Other);
  40. memcpy(map.cpu_buffer, data, data_size);
  41. memcpy(static_cast<char*>(map.cpu_buffer) + aligned_data_size, palette_data, palette_size);
  42. g_state_tracker->SetTexelBuffer(map.gpu_buffer, map.gpu_offset,
  43. map.gpu_offset + aligned_data_size);
  44. return true;
  45. }
  46. void Metal::VertexManager::ResetBuffer(u32 vertex_stride)
  47. {
  48. const u32 max_vertex_size = 65535 * vertex_stride;
  49. const u32 vertex_alloc = max_vertex_size + vertex_stride - 1; // for alignment
  50. auto vertex = g_state_tracker->Preallocate(StateTracker::UploadBuffer::Vertex, vertex_alloc);
  51. auto index =
  52. g_state_tracker->Preallocate(StateTracker::UploadBuffer::Index, MAXIBUFFERSIZE * sizeof(u16));
  53. // Align the base vertex
  54. m_base_vertex = (vertex.second + vertex_stride - 1) / vertex_stride;
  55. m_vertex_offset = m_base_vertex * vertex_stride - vertex.second;
  56. m_cur_buffer_pointer = m_base_buffer_pointer = static_cast<u8*>(vertex.first) + m_vertex_offset;
  57. m_end_buffer_pointer = m_base_buffer_pointer + max_vertex_size;
  58. m_index_generator.Start(static_cast<u16*>(index.first));
  59. }
  60. void Metal::VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
  61. u32* out_base_vertex, u32* out_base_index)
  62. {
  63. const u32 vsize = num_vertices * vertex_stride + m_vertex_offset;
  64. const u32 isize = num_indices * sizeof(u16);
  65. StateTracker::Map vmap = g_state_tracker->CommitPreallocation(
  66. StateTracker::UploadBuffer::Vertex, vsize, StateTracker::AlignMask::None);
  67. StateTracker::Map imap = g_state_tracker->CommitPreallocation(
  68. StateTracker::UploadBuffer::Index, isize, StateTracker::AlignMask::None);
  69. ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, vsize);
  70. ADDSTAT(g_stats.this_frame.bytes_index_streamed, isize);
  71. DEBUG_ASSERT(vmap.gpu_offset + m_vertex_offset == m_base_vertex * vertex_stride);
  72. g_state_tracker->SetVerticesAndIndices(vmap.gpu_buffer, imap.gpu_buffer);
  73. *out_base_vertex = m_base_vertex;
  74. *out_base_index = imap.gpu_offset / sizeof(u16);
  75. }
  76. void Metal::VertexManager::UploadUniforms()
  77. {
  78. auto& system = Core::System::GetInstance();
  79. auto& vertex_shader_manager = system.GetVertexShaderManager();
  80. auto& geometry_shader_manager = system.GetGeometryShaderManager();
  81. auto& pixel_shader_manager = system.GetPixelShaderManager();
  82. g_state_tracker->InvalidateUniforms(vertex_shader_manager.dirty, geometry_shader_manager.dirty,
  83. pixel_shader_manager.dirty);
  84. vertex_shader_manager.dirty = false;
  85. geometry_shader_manager.dirty = false;
  86. pixel_shader_manager.dirty = false;
  87. }