adapter.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //go:build !js
  2. package wgpu
  3. /*
  4. #include <stdlib.h>
  5. #include "./lib/wgpu.h"
  6. extern void gowebgpu_request_device_callback_c(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, void *userdata);
  7. extern void gowebgpu_device_lost_callback_c(WGPUDeviceLostReason reason, char const * message, void * userdata);
  8. */
  9. import "C"
  10. import (
  11. "errors"
  12. "runtime/cgo"
  13. "unsafe"
  14. )
  15. type Adapter struct {
  16. ref C.WGPUAdapter
  17. }
  18. func (p *Adapter) EnumerateFeatures() []FeatureName {
  19. size := C.wgpuAdapterEnumerateFeatures(p.ref, nil)
  20. if size == 0 {
  21. return nil
  22. }
  23. features := make([]FeatureName, size)
  24. C.wgpuAdapterEnumerateFeatures(p.ref, (*C.WGPUFeatureName)(unsafe.Pointer(&features[0])))
  25. return features
  26. }
  27. func (p *Adapter) GetLimits() SupportedLimits {
  28. var supportedLimits C.WGPUSupportedLimits
  29. extras := (*C.WGPUSupportedLimitsExtras)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUSupportedLimitsExtras{}))))
  30. defer C.free(unsafe.Pointer(extras))
  31. supportedLimits.nextInChain = (*C.WGPUChainedStructOut)(unsafe.Pointer(extras))
  32. C.wgpuAdapterGetLimits(p.ref, &supportedLimits)
  33. limits := supportedLimits.limits
  34. return SupportedLimits{
  35. Limits{
  36. MaxTextureDimension1D: uint32(limits.maxTextureDimension1D),
  37. MaxTextureDimension2D: uint32(limits.maxTextureDimension2D),
  38. MaxTextureDimension3D: uint32(limits.maxTextureDimension3D),
  39. MaxTextureArrayLayers: uint32(limits.maxTextureArrayLayers),
  40. MaxBindGroups: uint32(limits.maxBindGroups),
  41. MaxBindingsPerBindGroup: uint32(limits.maxBindingsPerBindGroup),
  42. MaxDynamicUniformBuffersPerPipelineLayout: uint32(limits.maxDynamicUniformBuffersPerPipelineLayout),
  43. MaxDynamicStorageBuffersPerPipelineLayout: uint32(limits.maxDynamicStorageBuffersPerPipelineLayout),
  44. MaxSampledTexturesPerShaderStage: uint32(limits.maxSampledTexturesPerShaderStage),
  45. MaxSamplersPerShaderStage: uint32(limits.maxSamplersPerShaderStage),
  46. MaxStorageBuffersPerShaderStage: uint32(limits.maxStorageBuffersPerShaderStage),
  47. MaxStorageTexturesPerShaderStage: uint32(limits.maxStorageTexturesPerShaderStage),
  48. MaxUniformBuffersPerShaderStage: uint32(limits.maxUniformBuffersPerShaderStage),
  49. MaxUniformBufferBindingSize: uint64(limits.maxUniformBufferBindingSize),
  50. MaxStorageBufferBindingSize: uint64(limits.maxStorageBufferBindingSize),
  51. MinUniformBufferOffsetAlignment: uint32(limits.minUniformBufferOffsetAlignment),
  52. MinStorageBufferOffsetAlignment: uint32(limits.minStorageBufferOffsetAlignment),
  53. MaxVertexBuffers: uint32(limits.maxVertexBuffers),
  54. MaxBufferSize: uint64(limits.maxBufferSize),
  55. MaxVertexAttributes: uint32(limits.maxVertexAttributes),
  56. MaxVertexBufferArrayStride: uint32(limits.maxVertexBufferArrayStride),
  57. MaxInterStageShaderComponents: uint32(limits.maxInterStageShaderComponents),
  58. MaxInterStageShaderVariables: uint32(limits.maxInterStageShaderVariables),
  59. MaxColorAttachments: uint32(limits.maxColorAttachments),
  60. MaxColorAttachmentBytesPerSample: uint32(limits.maxColorAttachmentBytesPerSample),
  61. MaxComputeWorkgroupStorageSize: uint32(limits.maxComputeWorkgroupStorageSize),
  62. MaxComputeInvocationsPerWorkgroup: uint32(limits.maxComputeInvocationsPerWorkgroup),
  63. MaxComputeWorkgroupSizeX: uint32(limits.maxComputeWorkgroupSizeX),
  64. MaxComputeWorkgroupSizeY: uint32(limits.maxComputeWorkgroupSizeY),
  65. MaxComputeWorkgroupSizeZ: uint32(limits.maxComputeWorkgroupSizeZ),
  66. MaxComputeWorkgroupsPerDimension: uint32(limits.maxComputeWorkgroupsPerDimension),
  67. MaxPushConstantSize: uint32(extras.limits.maxPushConstantSize),
  68. },
  69. }
  70. }
  71. func (p *Adapter) GetInfo() AdapterInfo {
  72. var info C.WGPUAdapterInfo
  73. C.wgpuAdapterGetInfo(p.ref, &info)
  74. return AdapterInfo{
  75. VendorId: uint32(info.vendorID),
  76. VendorName: C.GoString(info.vendor),
  77. Architecture: C.GoString(info.architecture),
  78. DeviceId: uint32(info.deviceID),
  79. Name: C.GoString(info.device),
  80. DriverDescription: C.GoString(info.description),
  81. AdapterType: AdapterType(info.adapterType),
  82. BackendType: BackendType(info.backendType),
  83. }
  84. }
  85. func (p *Adapter) HasFeature(feature FeatureName) bool {
  86. hasFeature := C.wgpuAdapterHasFeature(p.ref, C.WGPUFeatureName(feature))
  87. return goBool(hasFeature)
  88. }
  89. type requestDeviceCb func(status RequestDeviceStatus, device *Device, message string)
  90. //export gowebgpu_request_device_callback_go
  91. func gowebgpu_request_device_callback_go(status C.WGPURequestDeviceStatus, device C.WGPUDevice, message *C.char, userdata unsafe.Pointer) {
  92. handle := *(*cgo.Handle)(userdata)
  93. defer handle.Delete()
  94. cb, ok := handle.Value().(requestDeviceCb)
  95. if ok {
  96. cb(RequestDeviceStatus(status), &Device{ref: device}, C.GoString(message))
  97. }
  98. }
  99. //export gowebgpu_device_lost_callback_go
  100. func gowebgpu_device_lost_callback_go(reason C.WGPUDeviceLostReason, message *C.char, userdata unsafe.Pointer) {
  101. handle := *(*cgo.Handle)(userdata)
  102. defer handle.Delete()
  103. cb, ok := handle.Value().(DeviceLostCallback)
  104. if ok {
  105. cb(DeviceLostReason(reason), C.GoString(message))
  106. }
  107. }
  108. func (p *Adapter) RequestDevice(descriptor *DeviceDescriptor) (*Device, error) {
  109. var desc *C.WGPUDeviceDescriptor = nil
  110. if descriptor != nil {
  111. desc = &C.WGPUDeviceDescriptor{}
  112. if descriptor.Label != "" {
  113. label := C.CString(descriptor.Label)
  114. defer C.free(unsafe.Pointer(label))
  115. desc.label = label
  116. }
  117. requiredFeatureCount := len(descriptor.RequiredFeatures)
  118. if requiredFeatureCount != 0 {
  119. requiredFeatures := C.malloc(C.size_t(requiredFeatureCount) * C.size_t(unsafe.Sizeof(C.WGPUFeatureName(0))))
  120. defer C.free(requiredFeatures)
  121. requiredFeaturesSlice := unsafe.Slice((*FeatureName)(requiredFeatures), requiredFeatureCount)
  122. copy(requiredFeaturesSlice, descriptor.RequiredFeatures)
  123. desc.requiredFeatures = (*C.WGPUFeatureName)(requiredFeatures)
  124. desc.requiredFeatureCount = C.size_t(requiredFeatureCount)
  125. }
  126. if descriptor.RequiredLimits != nil {
  127. requiredLimits := (*C.WGPURequiredLimits)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPURequiredLimits{}))))
  128. defer C.free(unsafe.Pointer(requiredLimits))
  129. l := descriptor.RequiredLimits.Limits
  130. requiredLimits.limits = C.WGPULimits{
  131. maxTextureDimension1D: C.uint32_t(l.MaxTextureDimension1D),
  132. maxTextureDimension2D: C.uint32_t(l.MaxTextureDimension2D),
  133. maxTextureDimension3D: C.uint32_t(l.MaxTextureDimension3D),
  134. maxTextureArrayLayers: C.uint32_t(l.MaxTextureArrayLayers),
  135. maxBindGroups: C.uint32_t(l.MaxBindGroups),
  136. maxBindingsPerBindGroup: C.uint32_t(l.MaxBindingsPerBindGroup),
  137. maxDynamicUniformBuffersPerPipelineLayout: C.uint32_t(l.MaxDynamicUniformBuffersPerPipelineLayout),
  138. maxDynamicStorageBuffersPerPipelineLayout: C.uint32_t(l.MaxDynamicStorageBuffersPerPipelineLayout),
  139. maxSampledTexturesPerShaderStage: C.uint32_t(l.MaxSampledTexturesPerShaderStage),
  140. maxSamplersPerShaderStage: C.uint32_t(l.MaxSamplersPerShaderStage),
  141. maxStorageBuffersPerShaderStage: C.uint32_t(l.MaxStorageBuffersPerShaderStage),
  142. maxStorageTexturesPerShaderStage: C.uint32_t(l.MaxStorageTexturesPerShaderStage),
  143. maxUniformBuffersPerShaderStage: C.uint32_t(l.MaxUniformBuffersPerShaderStage),
  144. maxUniformBufferBindingSize: C.uint64_t(l.MaxUniformBufferBindingSize),
  145. maxStorageBufferBindingSize: C.uint64_t(l.MaxStorageBufferBindingSize),
  146. minUniformBufferOffsetAlignment: C.uint32_t(l.MinUniformBufferOffsetAlignment),
  147. minStorageBufferOffsetAlignment: C.uint32_t(l.MinStorageBufferOffsetAlignment),
  148. maxVertexBuffers: C.uint32_t(l.MaxVertexBuffers),
  149. maxBufferSize: C.uint64_t(l.MaxBufferSize),
  150. maxVertexAttributes: C.uint32_t(l.MaxVertexAttributes),
  151. maxVertexBufferArrayStride: C.uint32_t(l.MaxVertexBufferArrayStride),
  152. maxInterStageShaderComponents: C.uint32_t(l.MaxInterStageShaderComponents),
  153. maxInterStageShaderVariables: C.uint32_t(l.MaxInterStageShaderVariables),
  154. maxColorAttachments: C.uint32_t(l.MaxColorAttachments),
  155. maxComputeWorkgroupStorageSize: C.uint32_t(l.MaxComputeWorkgroupStorageSize),
  156. maxComputeInvocationsPerWorkgroup: C.uint32_t(l.MaxComputeInvocationsPerWorkgroup),
  157. maxComputeWorkgroupSizeX: C.uint32_t(l.MaxComputeWorkgroupSizeX),
  158. maxComputeWorkgroupSizeY: C.uint32_t(l.MaxComputeWorkgroupSizeY),
  159. maxComputeWorkgroupSizeZ: C.uint32_t(l.MaxComputeWorkgroupSizeZ),
  160. maxComputeWorkgroupsPerDimension: C.uint32_t(l.MaxComputeWorkgroupsPerDimension),
  161. }
  162. desc.requiredLimits = requiredLimits
  163. requiredLimitsExtras := (*C.WGPURequiredLimitsExtras)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPURequiredLimitsExtras{}))))
  164. defer C.free(unsafe.Pointer(requiredLimitsExtras))
  165. requiredLimitsExtras.chain.next = nil
  166. requiredLimitsExtras.chain.sType = C.WGPUSType_RequiredLimitsExtras
  167. requiredLimitsExtras.limits.maxPushConstantSize = C.uint32_t(l.MaxPushConstantSize)
  168. desc.requiredLimits.nextInChain = (*C.WGPUChainedStruct)(unsafe.Pointer(requiredLimitsExtras))
  169. }
  170. if descriptor.DeviceLostCallback != nil {
  171. handle := cgo.NewHandle(descriptor.DeviceLostCallback)
  172. desc.deviceLostCallback = C.WGPUDeviceLostCallback(C.gowebgpu_device_lost_callback_c)
  173. desc.deviceLostUserdata = unsafe.Pointer(&handle)
  174. }
  175. if descriptor.TracePath != "" {
  176. deviceExtras := (*C.WGPUDeviceExtras)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUDeviceExtras{}))))
  177. defer C.free(unsafe.Pointer(deviceExtras))
  178. deviceExtras.chain.next = nil
  179. deviceExtras.chain.sType = C.WGPUSType_DeviceExtras
  180. tracePath := C.CString(descriptor.TracePath)
  181. defer C.free(unsafe.Pointer(tracePath))
  182. deviceExtras.tracePath = tracePath
  183. desc.nextInChain = (*C.WGPUChainedStruct)(unsafe.Pointer(deviceExtras))
  184. }
  185. }
  186. var status RequestDeviceStatus
  187. var device *Device
  188. var cb requestDeviceCb = func(s RequestDeviceStatus, d *Device, _ string) {
  189. status = s
  190. device = d
  191. }
  192. handle := cgo.NewHandle(cb)
  193. C.wgpuAdapterRequestDevice(p.ref, desc, C.WGPUAdapterRequestDeviceCallback(C.gowebgpu_request_device_callback_c), unsafe.Pointer(&handle))
  194. if status != RequestDeviceStatusSuccess {
  195. return nil, errors.New("failed to request device")
  196. }
  197. return device, nil
  198. }
  199. func (p *Adapter) Release() {
  200. C.wgpuAdapterRelease(p.ref)
  201. }