queue.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //go:build !js
  2. package wgpu
  3. /*
  4. #include <stdlib.h>
  5. #include "./lib/wgpu.h"
  6. extern void gowebgpu_error_callback_c(WGPUErrorType type, char const * message, void * userdata);
  7. extern void gowebgpu_queue_work_done_callback_c(WGPUQueueWorkDoneStatus status, void * userdata);
  8. static inline void gowebgpu_queue_write_buffer(WGPUQueue queue, WGPUBuffer buffer, uint64_t bufferOffset, void const * data, size_t size, WGPUDevice device, void * error_userdata) {
  9. wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
  10. wgpuQueueWriteBuffer(queue, buffer, bufferOffset, data, size);
  11. wgpuDevicePopErrorScope(device, gowebgpu_error_callback_c, error_userdata);
  12. }
  13. static inline void gowebgpu_queue_write_texture(WGPUQueue queue, WGPUImageCopyTexture const * destination, void const * data, size_t dataSize, WGPUTextureDataLayout const * dataLayout, WGPUExtent3D const * writeSize, WGPUDevice device, void * error_userdata) {
  14. wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
  15. wgpuQueueWriteTexture(queue, destination, data, dataSize, dataLayout, writeSize);
  16. wgpuDevicePopErrorScope(device, gowebgpu_error_callback_c, error_userdata);
  17. }
  18. static inline void gowebgpu_queue_release(WGPUQueue queue, WGPUDevice device) {
  19. wgpuDeviceRelease(device);
  20. wgpuQueueRelease(queue);
  21. }
  22. */
  23. import "C"
  24. import (
  25. "errors"
  26. "runtime/cgo"
  27. "unsafe"
  28. )
  29. type Queue struct {
  30. deviceRef C.WGPUDevice
  31. ref C.WGPUQueue
  32. }
  33. //export gowebgpu_queue_work_done_callback_go
  34. func gowebgpu_queue_work_done_callback_go(status C.WGPUQueueWorkDoneStatus, userdata unsafe.Pointer) {
  35. handle := *(*cgo.Handle)(userdata)
  36. defer handle.Delete()
  37. cb, ok := handle.Value().(QueueWorkDoneCallback)
  38. if ok {
  39. cb(QueueWorkDoneStatus(status))
  40. }
  41. }
  42. func (p *Queue) OnSubmittedWorkDone(callback QueueWorkDoneCallback) {
  43. handle := cgo.NewHandle(callback)
  44. C.wgpuQueueOnSubmittedWorkDone(p.ref, C.WGPUQueueOnSubmittedWorkDoneCallback(C.gowebgpu_queue_work_done_callback_c), unsafe.Pointer(&handle))
  45. }
  46. func (p *Queue) Submit(commands ...*CommandBuffer) (submissionIndex SubmissionIndex) {
  47. commandCount := len(commands)
  48. if commandCount == 0 {
  49. r := C.wgpuQueueSubmitForIndex(p.ref, 0, nil)
  50. return SubmissionIndex(r)
  51. }
  52. commandRefs := C.malloc(C.size_t(commandCount) * C.size_t(unsafe.Sizeof(C.WGPUCommandBuffer(nil))))
  53. defer C.free(commandRefs)
  54. commandRefsSlice := unsafe.Slice((*C.WGPUCommandBuffer)(commandRefs), commandCount)
  55. for i, v := range commands {
  56. commandRefsSlice[i] = v.ref
  57. }
  58. r := C.wgpuQueueSubmitForIndex(
  59. p.ref,
  60. C.size_t(commandCount),
  61. (*C.WGPUCommandBuffer)(commandRefs),
  62. )
  63. return SubmissionIndex(r)
  64. }
  65. func (p *Queue) WriteBuffer(buffer *Buffer, bufferOffset uint64, data []byte) (err error) {
  66. var cb errorCallback = func(_ ErrorType, message string) {
  67. err = errors.New("wgpu.(*Queue).WriteBuffer(): " + message)
  68. }
  69. errorCallbackHandle := cgo.NewHandle(cb)
  70. defer errorCallbackHandle.Delete()
  71. size := len(data)
  72. if size == 0 {
  73. C.gowebgpu_queue_write_buffer(
  74. p.ref,
  75. buffer.ref,
  76. C.uint64_t(bufferOffset),
  77. nil,
  78. 0,
  79. p.deviceRef,
  80. unsafe.Pointer(&errorCallbackHandle),
  81. )
  82. return
  83. }
  84. C.gowebgpu_queue_write_buffer(
  85. p.ref,
  86. buffer.ref,
  87. C.uint64_t(bufferOffset),
  88. unsafe.Pointer(&data[0]),
  89. C.size_t(size),
  90. p.deviceRef,
  91. unsafe.Pointer(&errorCallbackHandle),
  92. )
  93. return
  94. }
  95. func (p *Queue) WriteTexture(destination *ImageCopyTexture, data []byte, dataLayout *TextureDataLayout, writeSize *Extent3D) (err error) {
  96. var dst C.WGPUImageCopyTexture
  97. if destination != nil {
  98. dst = C.WGPUImageCopyTexture{
  99. mipLevel: C.uint32_t(destination.MipLevel),
  100. origin: C.WGPUOrigin3D{
  101. x: C.uint32_t(destination.Origin.X),
  102. y: C.uint32_t(destination.Origin.Y),
  103. z: C.uint32_t(destination.Origin.Z),
  104. },
  105. aspect: C.WGPUTextureAspect(destination.Aspect),
  106. }
  107. if destination.Texture != nil {
  108. dst.texture = destination.Texture.ref
  109. }
  110. }
  111. var layout C.WGPUTextureDataLayout
  112. if dataLayout != nil {
  113. layout = C.WGPUTextureDataLayout{
  114. offset: C.uint64_t(dataLayout.Offset),
  115. bytesPerRow: C.uint32_t(dataLayout.BytesPerRow),
  116. rowsPerImage: C.uint32_t(dataLayout.RowsPerImage),
  117. }
  118. }
  119. var writeExtent C.WGPUExtent3D
  120. if writeSize != nil {
  121. writeExtent = C.WGPUExtent3D{
  122. width: C.uint32_t(writeSize.Width),
  123. height: C.uint32_t(writeSize.Height),
  124. depthOrArrayLayers: C.uint32_t(writeSize.DepthOrArrayLayers),
  125. }
  126. }
  127. var cb errorCallback = func(_ ErrorType, message string) {
  128. err = errors.New("wgpu.(*Queue).WriteTexture(): " + message)
  129. }
  130. errorCallbackHandle := cgo.NewHandle(cb)
  131. defer errorCallbackHandle.Delete()
  132. size := len(data)
  133. if size == 0 {
  134. C.gowebgpu_queue_write_texture(
  135. p.ref,
  136. &dst,
  137. nil,
  138. 0,
  139. &layout,
  140. &writeExtent,
  141. p.deviceRef,
  142. unsafe.Pointer(&errorCallbackHandle),
  143. )
  144. return
  145. }
  146. C.gowebgpu_queue_write_texture(
  147. p.ref,
  148. &dst,
  149. unsafe.Pointer(&data[0]),
  150. C.size_t(size),
  151. &layout,
  152. &writeExtent,
  153. p.deviceRef,
  154. unsafe.Pointer(&errorCallbackHandle),
  155. )
  156. return
  157. }
  158. func (p *Queue) Release() {
  159. C.gowebgpu_queue_release(p.ref, p.deviceRef)
  160. }