metal-samplerstate.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /******************************************************************************
  2. Copyright (C) 2024 by Patrick Heyer <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. import Foundation
  15. import Metal
  16. /// Creates a new ``MTLSamplerDescriptor`` to share as an opaque pointer with `libobs`
  17. /// - Parameters:
  18. /// - device: Opaque pointer to ``MetalDevice`` instance shared with `libobs`
  19. /// - info: Sampler information encoded as a `gs_sampler_info` struct
  20. /// - Returns: Opaque pointer to a new ``MTLSamplerDescriptor`` instance on success, `nil` otherwise
  21. @_cdecl("device_samplerstate_create")
  22. public func device_samplerstate_create(device: UnsafeRawPointer, info: gs_sampler_info) -> OpaquePointer? {
  23. let device: MetalDevice = unretained(device)
  24. guard let sAddressMode = info.address_u.mtlMode,
  25. let tAddressMode = info.address_v.mtlMode,
  26. let rAddressMode = info.address_w.mtlMode
  27. else {
  28. assertionFailure("device_samplerstate_create: Invalid address modes provided")
  29. return nil
  30. }
  31. guard let minFilter = info.filter.minMagFilter, let magFilter = info.filter.minMagFilter,
  32. let mipFilter = info.filter.mipFilter
  33. else {
  34. assertionFailure("device_samplerstate_create: Invalid filter modes provided")
  35. return nil
  36. }
  37. let descriptor = MTLSamplerDescriptor()
  38. descriptor.sAddressMode = sAddressMode
  39. descriptor.tAddressMode = tAddressMode
  40. descriptor.rAddressMode = rAddressMode
  41. descriptor.minFilter = minFilter
  42. descriptor.magFilter = magFilter
  43. descriptor.mipFilter = mipFilter
  44. descriptor.maxAnisotropy = max(16, min(1, Int(info.max_anisotropy)))
  45. descriptor.compareFunction = .always
  46. descriptor.borderColor =
  47. if (info.border_color & 0x00_00_00_FF) == 0 {
  48. .transparentBlack
  49. } else if info.border_color == 0xFF_FF_FF_FF {
  50. .opaqueWhite
  51. } else {
  52. .opaqueBlack
  53. }
  54. guard let samplerState = device.device.makeSamplerState(descriptor: descriptor) else {
  55. assertionFailure("device_samplerstate_create: Unable to create sampler state")
  56. return nil
  57. }
  58. let retained = Unmanaged.passRetained(samplerState).toOpaque()
  59. return OpaquePointer(retained)
  60. }
  61. /// Requests the deinitialization of the ``MTLSamplerState`` instance shared with `libobs`
  62. /// - Parameter samplerstate: Opaque pointer to ``MTLSamplerState`` instance shared with `libobs`
  63. ///
  64. /// Ownership of the ``MTLSamplerState`` instance will be transferred into the function and if this was the last
  65. /// strong reference to it, the object will be automatically deinitialized and deallocated by Swift.
  66. @_cdecl("gs_samplerstate_destroy")
  67. public func gs_samplerstate_destroy(samplerstate: UnsafeRawPointer) {
  68. let _ = retained(samplerstate) as MTLSamplerState
  69. }
  70. /// Loads the provided ``MTLSamplerState`` into the current pipeline's sampler array at the requested texture unit
  71. /// number
  72. /// - Parameters:
  73. /// - device: Opaque pointer to ``MetalDevice`` instance shared with `libobs`
  74. /// - samplerstate: Opaque pointer to ``MTLSamplerState`` instance shared with `libobs`
  75. /// - unit: Number identifying the "texture slot" used by OBS Studio's renderer.
  76. ///
  77. /// Texture slot numbers are equivalent to array index and represent a direct mapping between samplers and textures.
  78. @_cdecl("device_load_samplerstate")
  79. public func device_load_samplerstate(device: UnsafeRawPointer, samplerstate: UnsafeRawPointer, unit: UInt32) {
  80. let device: MetalDevice = unretained(device)
  81. let samplerState: MTLSamplerState = unretained(samplerstate)
  82. device.renderState.samplers[Int(unit)] = samplerState
  83. }