| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- //go:build !js
- package wgpu
- /*
- #include <stdlib.h>
- #include "./lib/wgpu.h"
- extern void gowebgpu_request_device_callback_c(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, void *userdata);
- extern void gowebgpu_device_lost_callback_c(WGPUDeviceLostReason reason, char const * message, void * userdata);
- */
- import "C"
- import (
- "errors"
- "runtime/cgo"
- "unsafe"
- )
- type Adapter struct {
- ref C.WGPUAdapter
- }
- func (p *Adapter) EnumerateFeatures() []FeatureName {
- size := C.wgpuAdapterEnumerateFeatures(p.ref, nil)
- if size == 0 {
- return nil
- }
- features := make([]FeatureName, size)
- C.wgpuAdapterEnumerateFeatures(p.ref, (*C.WGPUFeatureName)(unsafe.Pointer(&features[0])))
- return features
- }
- func (p *Adapter) GetLimits() SupportedLimits {
- var supportedLimits C.WGPUSupportedLimits
- extras := (*C.WGPUSupportedLimitsExtras)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUSupportedLimitsExtras{}))))
- defer C.free(unsafe.Pointer(extras))
- supportedLimits.nextInChain = (*C.WGPUChainedStructOut)(unsafe.Pointer(extras))
- C.wgpuAdapterGetLimits(p.ref, &supportedLimits)
- limits := supportedLimits.limits
- return SupportedLimits{
- Limits{
- MaxTextureDimension1D: uint32(limits.maxTextureDimension1D),
- MaxTextureDimension2D: uint32(limits.maxTextureDimension2D),
- MaxTextureDimension3D: uint32(limits.maxTextureDimension3D),
- MaxTextureArrayLayers: uint32(limits.maxTextureArrayLayers),
- MaxBindGroups: uint32(limits.maxBindGroups),
- MaxBindingsPerBindGroup: uint32(limits.maxBindingsPerBindGroup),
- MaxDynamicUniformBuffersPerPipelineLayout: uint32(limits.maxDynamicUniformBuffersPerPipelineLayout),
- MaxDynamicStorageBuffersPerPipelineLayout: uint32(limits.maxDynamicStorageBuffersPerPipelineLayout),
- MaxSampledTexturesPerShaderStage: uint32(limits.maxSampledTexturesPerShaderStage),
- MaxSamplersPerShaderStage: uint32(limits.maxSamplersPerShaderStage),
- MaxStorageBuffersPerShaderStage: uint32(limits.maxStorageBuffersPerShaderStage),
- MaxStorageTexturesPerShaderStage: uint32(limits.maxStorageTexturesPerShaderStage),
- MaxUniformBuffersPerShaderStage: uint32(limits.maxUniformBuffersPerShaderStage),
- MaxUniformBufferBindingSize: uint64(limits.maxUniformBufferBindingSize),
- MaxStorageBufferBindingSize: uint64(limits.maxStorageBufferBindingSize),
- MinUniformBufferOffsetAlignment: uint32(limits.minUniformBufferOffsetAlignment),
- MinStorageBufferOffsetAlignment: uint32(limits.minStorageBufferOffsetAlignment),
- MaxVertexBuffers: uint32(limits.maxVertexBuffers),
- MaxBufferSize: uint64(limits.maxBufferSize),
- MaxVertexAttributes: uint32(limits.maxVertexAttributes),
- MaxVertexBufferArrayStride: uint32(limits.maxVertexBufferArrayStride),
- MaxInterStageShaderComponents: uint32(limits.maxInterStageShaderComponents),
- MaxInterStageShaderVariables: uint32(limits.maxInterStageShaderVariables),
- MaxColorAttachments: uint32(limits.maxColorAttachments),
- MaxColorAttachmentBytesPerSample: uint32(limits.maxColorAttachmentBytesPerSample),
- MaxComputeWorkgroupStorageSize: uint32(limits.maxComputeWorkgroupStorageSize),
- MaxComputeInvocationsPerWorkgroup: uint32(limits.maxComputeInvocationsPerWorkgroup),
- MaxComputeWorkgroupSizeX: uint32(limits.maxComputeWorkgroupSizeX),
- MaxComputeWorkgroupSizeY: uint32(limits.maxComputeWorkgroupSizeY),
- MaxComputeWorkgroupSizeZ: uint32(limits.maxComputeWorkgroupSizeZ),
- MaxComputeWorkgroupsPerDimension: uint32(limits.maxComputeWorkgroupsPerDimension),
- MaxPushConstantSize: uint32(extras.limits.maxPushConstantSize),
- },
- }
- }
- func (p *Adapter) GetInfo() AdapterInfo {
- var info C.WGPUAdapterInfo
- C.wgpuAdapterGetInfo(p.ref, &info)
- return AdapterInfo{
- VendorId: uint32(info.vendorID),
- VendorName: C.GoString(info.vendor),
- Architecture: C.GoString(info.architecture),
- DeviceId: uint32(info.deviceID),
- Name: C.GoString(info.device),
- DriverDescription: C.GoString(info.description),
- AdapterType: AdapterType(info.adapterType),
- BackendType: BackendType(info.backendType),
- }
- }
- func (p *Adapter) HasFeature(feature FeatureName) bool {
- hasFeature := C.wgpuAdapterHasFeature(p.ref, C.WGPUFeatureName(feature))
- return goBool(hasFeature)
- }
- type requestDeviceCb func(status RequestDeviceStatus, device *Device, message string)
- //export gowebgpu_request_device_callback_go
- func gowebgpu_request_device_callback_go(status C.WGPURequestDeviceStatus, device C.WGPUDevice, message *C.char, userdata unsafe.Pointer) {
- handle := *(*cgo.Handle)(userdata)
- defer handle.Delete()
- cb, ok := handle.Value().(requestDeviceCb)
- if ok {
- cb(RequestDeviceStatus(status), &Device{ref: device}, C.GoString(message))
- }
- }
- //export gowebgpu_device_lost_callback_go
- func gowebgpu_device_lost_callback_go(reason C.WGPUDeviceLostReason, message *C.char, userdata unsafe.Pointer) {
- handle := *(*cgo.Handle)(userdata)
- defer handle.Delete()
- cb, ok := handle.Value().(DeviceLostCallback)
- if ok {
- cb(DeviceLostReason(reason), C.GoString(message))
- }
- }
- func (p *Adapter) RequestDevice(descriptor *DeviceDescriptor) (*Device, error) {
- var desc *C.WGPUDeviceDescriptor = nil
- if descriptor != nil {
- desc = &C.WGPUDeviceDescriptor{}
- if descriptor.Label != "" {
- label := C.CString(descriptor.Label)
- defer C.free(unsafe.Pointer(label))
- desc.label = label
- }
- requiredFeatureCount := len(descriptor.RequiredFeatures)
- if requiredFeatureCount != 0 {
- requiredFeatures := C.malloc(C.size_t(requiredFeatureCount) * C.size_t(unsafe.Sizeof(C.WGPUFeatureName(0))))
- defer C.free(requiredFeatures)
- requiredFeaturesSlice := unsafe.Slice((*FeatureName)(requiredFeatures), requiredFeatureCount)
- copy(requiredFeaturesSlice, descriptor.RequiredFeatures)
- desc.requiredFeatures = (*C.WGPUFeatureName)(requiredFeatures)
- desc.requiredFeatureCount = C.size_t(requiredFeatureCount)
- }
- if descriptor.RequiredLimits != nil {
- requiredLimits := (*C.WGPURequiredLimits)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPURequiredLimits{}))))
- defer C.free(unsafe.Pointer(requiredLimits))
- l := descriptor.RequiredLimits.Limits
- requiredLimits.limits = C.WGPULimits{
- maxTextureDimension1D: C.uint32_t(l.MaxTextureDimension1D),
- maxTextureDimension2D: C.uint32_t(l.MaxTextureDimension2D),
- maxTextureDimension3D: C.uint32_t(l.MaxTextureDimension3D),
- maxTextureArrayLayers: C.uint32_t(l.MaxTextureArrayLayers),
- maxBindGroups: C.uint32_t(l.MaxBindGroups),
- maxBindingsPerBindGroup: C.uint32_t(l.MaxBindingsPerBindGroup),
- maxDynamicUniformBuffersPerPipelineLayout: C.uint32_t(l.MaxDynamicUniformBuffersPerPipelineLayout),
- maxDynamicStorageBuffersPerPipelineLayout: C.uint32_t(l.MaxDynamicStorageBuffersPerPipelineLayout),
- maxSampledTexturesPerShaderStage: C.uint32_t(l.MaxSampledTexturesPerShaderStage),
- maxSamplersPerShaderStage: C.uint32_t(l.MaxSamplersPerShaderStage),
- maxStorageBuffersPerShaderStage: C.uint32_t(l.MaxStorageBuffersPerShaderStage),
- maxStorageTexturesPerShaderStage: C.uint32_t(l.MaxStorageTexturesPerShaderStage),
- maxUniformBuffersPerShaderStage: C.uint32_t(l.MaxUniformBuffersPerShaderStage),
- maxUniformBufferBindingSize: C.uint64_t(l.MaxUniformBufferBindingSize),
- maxStorageBufferBindingSize: C.uint64_t(l.MaxStorageBufferBindingSize),
- minUniformBufferOffsetAlignment: C.uint32_t(l.MinUniformBufferOffsetAlignment),
- minStorageBufferOffsetAlignment: C.uint32_t(l.MinStorageBufferOffsetAlignment),
- maxVertexBuffers: C.uint32_t(l.MaxVertexBuffers),
- maxBufferSize: C.uint64_t(l.MaxBufferSize),
- maxVertexAttributes: C.uint32_t(l.MaxVertexAttributes),
- maxVertexBufferArrayStride: C.uint32_t(l.MaxVertexBufferArrayStride),
- maxInterStageShaderComponents: C.uint32_t(l.MaxInterStageShaderComponents),
- maxInterStageShaderVariables: C.uint32_t(l.MaxInterStageShaderVariables),
- maxColorAttachments: C.uint32_t(l.MaxColorAttachments),
- maxComputeWorkgroupStorageSize: C.uint32_t(l.MaxComputeWorkgroupStorageSize),
- maxComputeInvocationsPerWorkgroup: C.uint32_t(l.MaxComputeInvocationsPerWorkgroup),
- maxComputeWorkgroupSizeX: C.uint32_t(l.MaxComputeWorkgroupSizeX),
- maxComputeWorkgroupSizeY: C.uint32_t(l.MaxComputeWorkgroupSizeY),
- maxComputeWorkgroupSizeZ: C.uint32_t(l.MaxComputeWorkgroupSizeZ),
- maxComputeWorkgroupsPerDimension: C.uint32_t(l.MaxComputeWorkgroupsPerDimension),
- }
- desc.requiredLimits = requiredLimits
- requiredLimitsExtras := (*C.WGPURequiredLimitsExtras)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPURequiredLimitsExtras{}))))
- defer C.free(unsafe.Pointer(requiredLimitsExtras))
- requiredLimitsExtras.chain.next = nil
- requiredLimitsExtras.chain.sType = C.WGPUSType_RequiredLimitsExtras
- requiredLimitsExtras.limits.maxPushConstantSize = C.uint32_t(l.MaxPushConstantSize)
- desc.requiredLimits.nextInChain = (*C.WGPUChainedStruct)(unsafe.Pointer(requiredLimitsExtras))
- }
- if descriptor.DeviceLostCallback != nil {
- handle := cgo.NewHandle(descriptor.DeviceLostCallback)
- desc.deviceLostCallback = C.WGPUDeviceLostCallback(C.gowebgpu_device_lost_callback_c)
- desc.deviceLostUserdata = unsafe.Pointer(&handle)
- }
- if descriptor.TracePath != "" {
- deviceExtras := (*C.WGPUDeviceExtras)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUDeviceExtras{}))))
- defer C.free(unsafe.Pointer(deviceExtras))
- deviceExtras.chain.next = nil
- deviceExtras.chain.sType = C.WGPUSType_DeviceExtras
- tracePath := C.CString(descriptor.TracePath)
- defer C.free(unsafe.Pointer(tracePath))
- deviceExtras.tracePath = tracePath
- desc.nextInChain = (*C.WGPUChainedStruct)(unsafe.Pointer(deviceExtras))
- }
- }
- var status RequestDeviceStatus
- var device *Device
- var cb requestDeviceCb = func(s RequestDeviceStatus, d *Device, _ string) {
- status = s
- device = d
- }
- handle := cgo.NewHandle(cb)
- C.wgpuAdapterRequestDevice(p.ref, desc, C.WGPUAdapterRequestDeviceCallback(C.gowebgpu_request_device_callback_c), unsafe.Pointer(&handle))
- if status != RequestDeviceStatusSuccess {
- return nil, errors.New("failed to request device")
- }
- return device, nil
- }
- func (p *Adapter) Release() {
- C.wgpuAdapterRelease(p.ref)
- }
|