diff --git a/Manifest.toml b/Manifest.toml index 8dd3b0fe2..78e49636b 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -157,7 +157,7 @@ version = "1.2.0" [[deps.ObjectiveC]] deps = ["Lazy", "MacroTools"] -git-tree-sha1 = "4fff0d1f044c9f9b4068a93ce95f79c45b27e976" +git-tree-sha1 = "d11e4f666c9d9e1e4df33fefd6e2c516d6a32039" repo-rev = "tb/modernize" repo-url = "https://github.com/JuliaInterop/ObjectiveC.jl" uuid = "e86c9b32-1129-44ac-8ea0-90d5bb39ded9" diff --git a/lib/cmt/cmt.jl b/lib/cmt/cmt.jl index 4fd3abc55..f720c1e19 100644 --- a/lib/cmt/cmt.jl +++ b/lib/cmt/cmt.jl @@ -1,6 +1,7 @@ module cmt using cmt_jll +using ObjectiveC, .Foundation include("libcmt.jl") diff --git a/lib/cmt/libcmt.jl b/lib/cmt/libcmt.jl index 1ad4b4835..cd056e539 100644 --- a/lib/cmt/libcmt.jl +++ b/lib/cmt/libcmt.jl @@ -6,11 +6,6 @@ const NsInteger = Clong const CfTimeInterval = Cdouble -struct NsRange - location::NsUInteger - length::NsUInteger -end - struct NsError #= /Users/tim/Julia/pkg/Metal/res/wrap.jl:39 =# end @@ -1273,7 +1268,7 @@ function mtFunctionConstantValuesSetWithName(funval, value, typ, name) end function mtFunctionConstantValuesSetWithRange(funval, value, typ, range) - ccall((:mtFunctionConstantValuesSetWithRange, libcmt), Cvoid, (Ptr{MtFunctionConstantValues}, Ptr{Cvoid}, MtDataType, NsRange), funval, value, typ, range) + ccall((:mtFunctionConstantValuesSetWithRange, libcmt), Cvoid, (Ptr{MtFunctionConstantValues}, Ptr{Cvoid}, MtDataType, NSRange), funval, value, typ, range) end function mtFunctionConstantValuesReset(funval) @@ -1417,11 +1412,11 @@ function mtBufferLength(buf) end function mtBufferDidModifyRange(buf, ran) - ccall((:mtBufferDidModifyRange, libcmt), Cvoid, (Ptr{MtBuffer}, NsRange), buf, ran) + ccall((:mtBufferDidModifyRange, libcmt), Cvoid, (Ptr{MtBuffer}, NSRange), buf, ran) end function mtBufferAddDebugMarkerRange(buf, string, range) - ccall((:mtBufferAddDebugMarkerRange, libcmt), Cvoid, (Ptr{MtBuffer}, Cstring, NsRange), buf, string, range) + ccall((:mtBufferAddDebugMarkerRange, libcmt), Cvoid, (Ptr{MtBuffer}, Cstring, NSRange), buf, string, range) end function mtBufferRemoveAllDebugMarkers(buf) @@ -1957,7 +1952,7 @@ function mtIndirectCommandBufferRenderCommandAtIndex(icb, index) end function mtIndirectCommandBufferResetWithRange(icb, range) - ccall((:mtIndirectCommandBufferResetWithRange, libcmt), Cvoid, (Ptr{MtIndirectCommandBuffer}, NsRange), icb, range) + ccall((:mtIndirectCommandBufferResetWithRange, libcmt), Cvoid, (Ptr{MtIndirectCommandBuffer}, NSRange), icb, range) end function mtCommandEncoderEndEncoding(ce) @@ -1997,7 +1992,7 @@ function mtBlitCommandEncoderCopyFromBufferToBuffer(bce, src, src_offset, dst, d end function mtBlitCommandEncoderFillBuffer(bce, src, range, val) - ccall((:mtBlitCommandEncoderFillBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtBuffer}, NsRange, UInt8), bce, src, range, val) + ccall((:mtBlitCommandEncoderFillBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtBuffer}, NSRange, UInt8), bce, src, range, val) end function mtBlitCommandEncoderGenerateMipmaps(bce, texture) @@ -2005,15 +2000,15 @@ function mtBlitCommandEncoderGenerateMipmaps(bce, texture) end function mtBlitCommandEncoderCopyIndirectCommandBuffer(bce, src, range, dst, dst_index) - ccall((:mtBlitCommandEncoderCopyIndirectCommandBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtIndirectCommandBuffer}, NsRange, Ptr{MtIndirectCommandBuffer}, NsUInteger), bce, src, range, dst, dst_index) + ccall((:mtBlitCommandEncoderCopyIndirectCommandBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtIndirectCommandBuffer}, NSRange, Ptr{MtIndirectCommandBuffer}, NsUInteger), bce, src, range, dst, dst_index) end function mtBlitCommandEncoderOptimizeIndirectCommandBuffer(bce, buffer, range) - ccall((:mtBlitCommandEncoderOptimizeIndirectCommandBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtIndirectCommandBuffer}, NsRange), bce, buffer, range) + ccall((:mtBlitCommandEncoderOptimizeIndirectCommandBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtIndirectCommandBuffer}, NSRange), bce, buffer, range) end function mtBlitCommandEncoderResetCommandsInBuffer(bce, buffer, range) - ccall((:mtBlitCommandEncoderResetCommandsInBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtIndirectCommandBuffer}, NsRange), bce, buffer, range) + ccall((:mtBlitCommandEncoderResetCommandsInBuffer, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtIndirectCommandBuffer}, NSRange), bce, buffer, range) end function mtBlitCommandEncoderSynchronizeResource(bce, resource) @@ -2053,7 +2048,7 @@ function mtBlitCommandEncoderSampleCountersInBuffer(icb, sbuf, sampleindex, barr end function mtBlitCommandEncoderResolveCounters(icb, sbuf, range, dst, dst_offset) - ccall((:mtBlitCommandEncoderResolveCounters, libcmt), Cvoid, (Ptr{MtIndirectCommandBuffer}, Ptr{MtCounterSampleBuffer}, NsRange, Ptr{MtBuffer}, NsUInteger), icb, sbuf, range, dst, dst_offset) + ccall((:mtBlitCommandEncoderResolveCounters, libcmt), Cvoid, (Ptr{MtIndirectCommandBuffer}, Ptr{MtCounterSampleBuffer}, NSRange, Ptr{MtBuffer}, NsUInteger), icb, sbuf, range, dst, dst_offset) end function mtNewComputeCommandEncoder(cmdb) @@ -2077,7 +2072,7 @@ function mtComputeCommandEncoderSetBufferOffsetAtIndex(cce, buf, offset, indx) end function mtComputeCommandEncoderSetBuffersOffsetsWithRange(cce, bufs, offsets, range) - ccall((:mtComputeCommandEncoderSetBuffersOffsetsWithRange, libcmt), Cvoid, (Ptr{MtComputeCommandEncoder}, Ptr{Ptr{MtBuffer}}, Ptr{NsUInteger}, NsRange), cce, bufs, offsets, range) + ccall((:mtComputeCommandEncoderSetBuffersOffsetsWithRange, libcmt), Cvoid, (Ptr{MtComputeCommandEncoder}, Ptr{Ptr{MtBuffer}}, Ptr{NsUInteger}, NSRange), cce, bufs, offsets, range) end function mtComputeCommandEncoderBufferSetOffsetAtIndex(cce, offset, indx) @@ -2093,7 +2088,7 @@ function mtComputeCommandEncoderSetSamplerStateAtIndex(cce, sampler, indx) end function mtComputeCommandEncoderSetSamplerStatesWithRange(cce, samplers, range) - ccall((:mtComputeCommandEncoderSetSamplerStatesWithRange, libcmt), Cvoid, (Ptr{MtComputeCommandEncoder}, Ptr{Ptr{MtSamplerState}}, NsRange), cce, samplers, range) + ccall((:mtComputeCommandEncoderSetSamplerStatesWithRange, libcmt), Cvoid, (Ptr{MtComputeCommandEncoder}, Ptr{Ptr{MtSamplerState}}, NSRange), cce, samplers, range) end function mtComputeCommandEncoderSetSamplerStateLodMinClampLodMaxClampAtIndex(cce, sampler, lodMinClamp, lodMaxClamp, indx) @@ -2105,7 +2100,7 @@ function mtComputeCommandEncoderSetTextureAtIndex(cce, tex, indx) end function mtComputeCommandEncoderSetTexturesWithRange(cce, textures, range) - ccall((:mtComputeCommandEncoderSetTexturesWithRange, libcmt), Cvoid, (Ptr{MtComputeCommandEncoder}, Ptr{Ptr{MtTexture}}, NsRange), cce, textures, range) + ccall((:mtComputeCommandEncoderSetTexturesWithRange, libcmt), Cvoid, (Ptr{MtComputeCommandEncoder}, Ptr{Ptr{MtTexture}}, NSRange), cce, textures, range) end function mtComputeCommandEncoderSetThreadgroupMemoryLengthAtIndex(cce, length, indx) @@ -2313,7 +2308,7 @@ function mtArgumentEncoderSetBufferOffsetAtIndex(cce, buf, offset, indx) end function mtArgumentEncoderSetBuffersOffsetsWithRange(cce, bufs, offsets, range) - ccall((:mtArgumentEncoderSetBuffersOffsetsWithRange, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtBuffer}}, Ptr{NsUInteger}, NsRange), cce, bufs, offsets, range) + ccall((:mtArgumentEncoderSetBuffersOffsetsWithRange, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtBuffer}}, Ptr{NsUInteger}, NSRange), cce, bufs, offsets, range) end function mtArgumentEncoderSetTextureAtIndex(cce, tex, indx) @@ -2321,7 +2316,7 @@ function mtArgumentEncoderSetTextureAtIndex(cce, tex, indx) end function mtArgumentEncoderSetTexturesWithRange(cce, textures, range) - ccall((:mtArgumentEncoderSetTexturesWithRange, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtTexture}}, NsRange), cce, textures, range) + ccall((:mtArgumentEncoderSetTexturesWithRange, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtTexture}}, NSRange), cce, textures, range) end function mtArgumentEncoderSetSamplerStateAtIndex(cce, sampler, indx) @@ -2329,7 +2324,7 @@ function mtArgumentEncoderSetSamplerStateAtIndex(cce, sampler, indx) end function mtArgumentEncoderSetSamplerStatesWithRange(cce, samplers, range) - ccall((:mtArgumentEncoderSetSamplerStatesWithRange, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtSamplerState}}, NsRange), cce, samplers, range) + ccall((:mtArgumentEncoderSetSamplerStatesWithRange, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtSamplerState}}, NSRange), cce, samplers, range) end function mtArgumentEncoderConstantDataAtIndex(cce, index) @@ -2341,7 +2336,7 @@ function mtArgumentEncoderSetIndirectCommandBuffer(cce, cbuf, index) end function mtArgumentEncoderSetIndirectCommandBuffers(cce, cbufs, range) - ccall((:mtArgumentEncoderSetIndirectCommandBuffers, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtIndirectCommandBuffer}}, NsRange), cce, cbufs, range) + ccall((:mtArgumentEncoderSetIndirectCommandBuffers, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{Ptr{MtIndirectCommandBuffer}}, NSRange), cce, cbufs, range) end function mtArgumentEncoderAlignment(cce) diff --git a/lib/mtl/MTL.jl b/lib/mtl/MTL.jl index dfc6279f7..160e0108d 100644 --- a/lib/mtl/MTL.jl +++ b/lib/mtl/MTL.jl @@ -2,6 +2,7 @@ module MTL using ..cmt +using CEnum using ObjectiveC, ObjectiveC.Foundation diff --git a/lib/mtl/buffer.jl b/lib/mtl/buffer.jl index a978f075c..870a4fbd2 100644 --- a/lib/mtl/buffer.jl +++ b/lib/mtl/buffer.jl @@ -1,44 +1,39 @@ -export MtlBuffer, device, contents, alloc, free, handle - -const MTLBuffer = Ptr{MtBuffer} +export MTLBuffer, device, contents, alloc, free, handle # From docs: "MSL implements a buffer as a pointer to a built-in or user defined data type described in the # device, constant, or threadgroup address space. -struct MtlBuffer <: MtlResource - handle::MTLBuffer -end +@objcwrapper MTLBuffer <: MTLResource -Base.unsafe_convert(::Type{MTLBuffer}, buf::MtlBuffer) = buf.handle +# compatibility with cmt +Base.unsafe_convert(T::Type{Ptr{MtBuffer}}, obj::MTLBuffer) = + reinterpret(T, Base.unsafe_convert(id, obj)) +MTLBuffer(ptr::Ptr{MtBuffer}) = MTLBuffer(reinterpret(id, ptr)) -Base.:(==)(a::MtlBuffer, b::MtlBuffer) = a.handle == b.handle -Base.hash(buf::MtlBuffer, h::UInt) = hash(buf.handle, h) +# TODO: here ## properties -Base.propertynames(o::MtlBuffer) = ( - :length, - invoke(propertynames, Tuple{MtlResource}, o)... -) - -function Base.getproperty(o::MtlBuffer, f::Symbol) - if f === :length - mtBufferLength(o) - elseif f === :gpuAddress - # XXX: even though the gpuAddress property is only documented in Metal 3, - # it seems to be present in earlier versions of the API as well. - # can we rely on this? - Base.bitcast(Ptr{Nothing}, mtBufferGPUAddress(o)) - else - invoke(getproperty, Tuple{MtlResource, Symbol}, o, f) - end -end +const buffer_properties = [ + (:contents, Ptr{Cvoid}), + (:length, NSUInteger), + (:remoteStorageBuffer, :(id{MTLBuffer})), + (:gpuAddress, UInt64 => Ptr{Cvoid}), +] + +Base.propertynames(::MTLBuffer) = map(first, buffer_properties) -Base.sizeof(buf::MtlBuffer) = Int(buf.length) +@eval Base.getproperty(obj::MTLBuffer, f::Symbol) = + $(emit_getproperties(:obj, MTLBuffer, :f, buffer_properties)) -function contents(buf::MtlBuffer) - buf.handle == C_NULL && return C_NULL - ptr = Base.bitcast(Ptr{Cvoid}, mtBufferContents(buf)) +@eval Base.setproperty!(obj::MTLBuffer, f::Symbol, val) = + $(emit_setproperties(:obj, MTLBuffer, :f, :val, buffer_properties)) + +Base.sizeof(buf::MTLBuffer) = Int(buf.length) + +# TODO: remove this +function contents(buf::MTLBuffer) + ptr = @objc [buf::id{MTLBuffer} contents]::Ptr{Cvoid} ptr == C_NULL && error("Cannot access the contents of a private buffer") return ptr end @@ -46,21 +41,30 @@ end ## allocation -alloc_buffer(dev::MTLDevice, bytesize, opts::MtlResourceOptions) = - mtDeviceNewBufferWithLength(dev, bytesize, opts) -alloc_buffer(dev::MtlHeap, bytesize, opts::MtlResourceOptions) = - mtHeapNewBufferWithLength(heap, bytesize, opts) -alloc_buffer(dev::MTLDevice, bytesize, opts::MtlResourceOptions, ptr::Ptr) = - mtDeviceNewBufferWithBytes(dev, ptr, bytesize, opts) -alloc_buffer(dev::MtlHeap, bytesize, opts::MtlResourceOptions, ptr::Ptr) = - mtHeapNewBufferWithBytes(heap, ptr, bytesize, opts) +# from device +alloc_buffer(dev::MTLDevice, bytesize, opts::MTLResourceOptions) = + @objc [dev::id{MTLDevice} newBufferWithLength:bytesize::NSUInteger + options:opts::MTLResourceOptions]::id{MTLBuffer} +alloc_buffer(dev::MTLDevice, bytesize, opts::MTLResourceOptions, ptr::Ptr) = + @objc [dev::id{MTLDevice} newBufferWithBytes:ptr::Ptr{Cvoid} + length:bytesize::NSUInteger + options:opts::MTLResourceOptions]::id{MTLBuffer} + +# from heap +alloc_buffer(dev::MtlHeap, bytesize, opts::MTLResourceOptions) = + @objc [dev::id{MTLHeap} newBufferWithLength:bytesize::NSUInteger + options:opts::MTLResourceOptions]::id{MTLBuffer} +alloc_buffer(dev::MtlHeap, bytesize, opts::MTLResourceOptions, ptr::Ptr) = + @objc [dev::id{MTLHeap} newBufferWithBytes:ptr::Ptr{Cvoid} + length:bytesize::NSUInteger + options:opts::MTLResourceOptions]::id{MTLBuffer} alloc_buffer(dev, bytesize, opts::Integer) = - alloc_buffer(dev, bytesize, Base.bitcast(MtlResourceOptions, UInt32(opts))) + alloc_buffer(dev, bytesize, MTLResourceOptions(opts)) alloc_buffer(dev, bytesize, opts::Integer, ptr) = - alloc_buffer(dev, bytesize, Base.bitcast(MtlResourceOptions, UInt32(opts)), ptr) + alloc_buffer(dev, bytesize, MTLResourceOptions(opts), ptr) -function MtlBuffer(dev::Union{MTLDevice,MtlHeap}, +function MTLBuffer(dev::Union{MTLDevice,MtlHeap}, bytesize::Integer; storage = Private, hazard_tracking = DefaultTracking, @@ -70,10 +74,10 @@ function MtlBuffer(dev::Union{MTLDevice,MtlHeap}, @assert 0 < bytesize <= dev.maxBufferLength # XXX: not supported by MtlHeap ptr = alloc_buffer(dev, bytesize, opts) - return MtlBuffer(ptr) + return MTLBuffer(ptr) end -function MtlBuffer(dev::Union{MTLDevice,MtlHeap}, +function MTLBuffer(dev::Union{MTLDevice,MtlHeap}, bytesize::Integer, ptr::Ptr; storage = Managed, @@ -85,12 +89,12 @@ function MtlBuffer(dev::Union{MTLDevice,MtlHeap}, @assert 0 < bytesize <= dev.maxBufferLength # XXX: not supported by MtlHeap ptr = alloc_buffer(dev, bytesize, opts, ptr) - return MtlBuffer(ptr) + return MTLBuffer(ptr) end """ alloc(device, bytesize, [ptr=nothing]; storage=Default, hazard_tracking=Default, chache_mode=Default) - MtlBuffer(device, bytesize...) + MTLBuffer(device, bytesize...) Allocates a Metal buffer on `device` of`bytesize` bytes. If a CPU-pointer is passed as last argument, then the buffer is initialized with the content of the memory starting at `ptr`, @@ -108,39 +112,33 @@ The storage kwarg controls where the buffer is stored. Possible values are: Note that `Private` buffers can't be directly accessed from the CPU, therefore you cannot use this option if you pass a ptr to initialize the memory. """ -alloc(args...; kwargs...) = MtlBuffer(args...; kwargs...) +alloc(args...; kwargs...) = MTLBuffer(args...; kwargs...) """ - free(buffer::MtlBuffer) + free(buffer::MTLBuffer) Frees the buffer if the handle is valid. This does not protect against double-freeing of the same buffer! """ -free(buf::MtlBuffer) = mtRelease(buf.handle) +free(buf::MTLBuffer) = @objc [buf::id{MTLBuffer} release]::Nothing """ - DidModifyRange!(buf::MtlBuffer, range::UnitRange) + DidModifyRange!(buf::MTLBuffer, range::UnitRange) Notifies the GPU that the range of bytes specified by `range` have been modified on the CPU, and that they should be transferred to the device before executing any following command. Only valid for `Managed` buffers. """ -function DidModifyRange!(buf::MtlBuffer, range::UnitRange) - mtBufferDidModifyRange(buf, range) +function DidModifyRange!(buf::MTLBuffer, range) + @objc [buf::id{MTLBuffer} didModifyRange:range::NSRange]::Nothing end # Views on different device -NewBuffer(buf::MtlBuffer, d::MTLDevice) = - mtBufferNewRemoteBufferViewForDevice(buf, d); - -function ParentBuffer(buf::MtlBuffer) - orig = mtBufferRemoteStorageBuffer(buf); - if orig == C_NULL - return nothing - else - return MtlBuffer(orig) - end -end +NewBuffer(buf::MTLBuffer, d::MTLDevice) = + @objc [buf::id{MTLBuffer} newRemoteBufferViewForDevice:d::id{MTLDevice}]::id{MTLBuffer} + +# TODO: remove this +ParentBuffer(buf::MTLBuffer) = buf.remoteStorageBuffer -handle_array(vec::Vector{<:MtlBuffer}) = [buf.handle for buf in vec] +handle_array(vec::Vector{<:MTLBuffer}) = [buf.handle for buf in vec] diff --git a/lib/mtl/command_enc/blit.jl b/lib/mtl/command_enc/blit.jl index cd5c17808..b1cc737a7 100644 --- a/lib/mtl/command_enc/blit.jl +++ b/lib/mtl/command_enc/blit.jl @@ -26,13 +26,13 @@ end ## # Copy from device to device -append_copy!(enc::MtlBlitCommandEncoder, dst::MtlBuffer, doff, src::MtlBuffer, soff, len) = +append_copy!(enc::MtlBlitCommandEncoder, dst::MTLBuffer, doff, src::MTLBuffer, soff, len) = mtBlitCommandEncoderCopyFromBufferToBuffer(enc, src, soff, dst, doff, len) -append_fillbuffer!(enc::MtlBlitCommandEncoder, src::MtlBuffer, +append_fillbuffer!(enc::MtlBlitCommandEncoder, src::MTLBuffer, val::Union{Int8, UInt8}, bytesize, offset=0) = mtBlitCommandEncoderFillBuffer(enc, src, UnitRange(offset:bytesize-1), val) # only for managed resources -append_sync!(enc::MtlBlitCommandEncoder, src::MtlBuffer) = +append_sync!(enc::MtlBlitCommandEncoder, src::MTLBuffer) = mtBlitCommandencoderSynchronizeResource!(enc, src) diff --git a/lib/mtl/command_enc/compute.jl b/lib/mtl/command_enc/compute.jl index 1712c2b1b..12cdaab7b 100644 --- a/lib/mtl/command_enc/compute.jl +++ b/lib/mtl/command_enc/compute.jl @@ -27,12 +27,12 @@ device(cce::MtlComputeCommandEncoder) = cce.cmdbuf.device set_function!(cce::MtlComputeCommandEncoder, pip::MtlComputePipelineState) = mtComputeCommandEncoderSetComputePipelineState(cce, pip) -set_buffer!(cce::MtlComputeCommandEncoder, buf::MtlBuffer, offset::Integer, index::Integer) = +set_buffer!(cce::MtlComputeCommandEncoder, buf::MTLBuffer, offset::Integer, index::Integer) = mtComputeCommandEncoderSetBufferOffsetAtIndex(cce, buf, offset, index - 1) #set_bufferoffset!(cce::MtlComputeCommandEncoder, offset::Integer, index::Integer) = # mtComputeCommandEncoderBufferSetOffsetAtIndex(cce, offset, index) set_buffers!(cce::MtlComputeCommandEncoder, bufs::Vector{T}, - offsets::Vector{Int}, indices::UnitRange{Int}) where {T<:MtlBuffer} = + offsets::Vector{Int}, indices::UnitRange{Int}) where {T<:MTLBuffer} = mtComputeCommandEncoderSetBuffersOffsetsWithRange(cce, handle_array(bufs), offsets, indices .- 1) #=set_buffers!(cce::MtlComputeCommandEncoder, bufs::Vector{MtlPtr{T}}, offsets::Vector{Int}, indices::UnitRange{Int}) where {T} = @@ -59,8 +59,8 @@ append_current_function!(cce::MtlComputeCommandEncoder, gridSize::MtSize, thread dispatchThreadgroups!(cce, gridSize, threadGroupSize) #### use -use!(cce::MtlComputeCommandEncoder, buf::MtlBuffer, mode::MtResourceUsage=ReadWriteUsage) = +use!(cce::MtlComputeCommandEncoder, buf::MTLBuffer, mode::MtResourceUsage=ReadWriteUsage) = mtComputeCommandEncoderUseResourceUsage(cce, buf, mode) -use!(cce::MtlComputeCommandEncoder, buf::Vector{MtlBuffer}, mode::MtResourceUsage=ReadWriteUsage) = +use!(cce::MtlComputeCommandEncoder, buf::Vector{MTLBuffer}, mode::MtResourceUsage=ReadWriteUsage) = mtComputeCommandEncoderUseResourceCountUsage(cce, handle_array(buf), length(buf), mode) diff --git a/lib/mtl/events.jl b/lib/mtl/events.jl index 672478d48..f27b1a441 100644 --- a/lib/mtl/events.jl +++ b/lib/mtl/events.jl @@ -41,6 +41,8 @@ const shared_event_properties = [ (:signaledValue, UInt64) ] +# TODO: these don't include MTLEvent's properties. +# use an emit_propertynames Base.propertynames(::MTLSharedEvent) = map(first, shared_event_properties) @eval Base.getproperty(ev::MTLSharedEvent, f::Symbol) = diff --git a/lib/mtl/resource.jl b/lib/mtl/resource.jl index 11a5d062a..5f47d3592 100644 --- a/lib/mtl/resource.jl +++ b/lib/mtl/resource.jl @@ -1,40 +1,61 @@ -export MtlResource +export MTLResource -const MTLResource = Ptr{MtResource} +@objcwrapper MTLResource <: NSObject -abstract type MtlResource end - -Base.unsafe_convert(::Type{MTLResource}, res::MtlResource) = Base.bitcast(MTLResource, res.handle) +# compatibility with cmt +Base.unsafe_convert(T::Type{Ptr{MtResource}}, obj::MTLResource) = + reinterpret(T, Base.unsafe_convert(id, obj)) +MTLResource(ptr::Ptr{MtResource}) = MTLResource(reinterpret(id, ptr)) ## properties -Base.propertynames(::MtlResource) = - (:device, :label, :cpuCacheMode, :storageMode, :hazardTrackingMode, :resourceOptions) - -function Base.getproperty(res::MtlResource, f::Symbol) - if f === :device - MTLDevice(mtResourceDevice(res)) - elseif f === :label - ptr = mtResourceLabel(res) - ptr == C_NULL ? nothing : unsafe_string(ptr) - elseif f === :cpuCacheMode - mtResourceCPUCacheMode(res) - elseif f === :storageMode - mtResourceStorageMode(res) - elseif f === :hazardTrackingMode - mtResourceHazardTrackingMode(res) - elseif f === :resourceOptions - mtResourceOptions(res) - else - getfield(res, f) - end +@cenum MTLCPUCacheMode::NSUInteger begin + MTLCPUCacheModeDefaultCache = 0 + MTLCPUCacheModeWriteCombined = 1 +end + +@cenum MTLHazardTrackingMode::NSUInteger begin + MTLHazardTrackingModeDefault = 0 + MTLHazardTrackingModeUntracked = 1 + MTLHazardTrackingModeTracked = 2 end -function Base.setproperty!(res::MtlResource, f::Symbol, val) - if f === :label - mtResourceLabelSet(res, val) - else - setfield!(res, f, val) - end +@cenum MTLStorageMode::NSUInteger begin + MTLStorageModeShared = 0 + MTLStorageModeManaged = 1 + MTLStorageModePrivate = 2 + MTLStorageModeMemoryless = 3 end + +@cenum MTLResourceOptions::NSUInteger begin + MTLResourceCPUCacheModeDefaultCache = 0 + MTLResourceCPUCacheModeWriteCombined = 1 + MTLResourceStorageModeShared = 0 + MTLResourceStorageModeManaged = 16 + MTLResourceStorageModePrivate = 32 + MTLResourceStorageModeMemoryless = 48 + MTLResourceHazardTrackingModeDefault = 0 + MTLResourceHazardTrackingModeUntracked = 256 + MTLResourceHazardTrackingModeTracked = 512 +end + +const resource_properties = [ + # identifying the resource + (:device, :(id{MTLDevice})), + (:label, :(id{NSString}), + :setLabel), + # reading memory and storage properties + (:cpuCacheMode, :(MTLCPUCacheMode)), + (:storageMode, :(MTLStorageMode)), + (:hazardTrackingMode, :(MTLHazardTrackingMode)), + (:resourceOptions, :(MTLResourceOptions)), +] + +Base.propertynames(::MTLResource) = map(first, resource_properties) + +@eval Base.getproperty(obj::MTLResource, f::Symbol) = + $(emit_getproperties(:obj, MTLResource, :f, resource_properties)) + +@eval Base.setproperty!(obj::MTLResource, f::Symbol, val) = + $(emit_setproperties(:obj, MTLResource, :f, :val, resource_properties)) diff --git a/lib/mtl/size.jl b/lib/mtl/size.jl index 6b5bbfc0b..a93ca1b6d 100644 --- a/lib/mtl/size.jl +++ b/lib/mtl/size.jl @@ -22,8 +22,8 @@ Base.convert(::Type{MtSize}, sz::MTLSize) = MtSize(sz.width, sz.height, sz.depth ## ranges # convert from 1 based indexing to 0 based indexing -Base.convert(::Type{NsRange}, range::UnitRange{T}) where T <: Integer = - NsRange(first(range), length(range)) +Base.convert(::Type{NSRange}, range::UnitRange{T}) where T <: Integer = + NSRange(first(range), length(range)) # used for byte ranges. -Base.convert(::Type{NsRange}, range::StepRange{T}) where T <: Integer = - NsRange(first(range)-step(range), length(range)*step(range)) +Base.convert(::Type{NSRange}, range::StepRange{T}) where T <: Integer = + NSRange(first(range)-step(range), length(range)*step(range)) diff --git a/src/Metal.jl b/src/Metal.jl index a1d3a1f44..b8a7c8d92 100644 --- a/src/Metal.jl +++ b/src/Metal.jl @@ -8,6 +8,7 @@ using LLVM using LLVM.Interop using Metal_LLVM_Tools_jll using ExprTools: splitdef, combinedef +using ObjectiveC, .Foundation # C wrappers include("../lib/cmt/cmt.jl") diff --git a/src/array.jl b/src/array.jl index 6733cf868..e35b92826 100644 --- a/src/array.jl +++ b/src/array.jl @@ -27,7 +27,7 @@ function contains_double(T) end mutable struct MtlArray{T,N} <: AbstractGPUArray{T,N} - buffer::MtlBuffer + buffer::Union{MTLBuffer,Nothing} maxsize::Int # maximum data size; excluding any selector bytes offset::Int # offset of the data in the buffer, in number of elements @@ -49,20 +49,22 @@ mutable struct MtlArray{T,N} <: AbstractGPUArray{T,N} buf = alloc(dev, bufsize; storage=storage) buf.label = "MtlArray{$(T),$(N)}(dims=$dims)" else - buf = MtlBuffer(C_NULL) + buf = nothing end obj = new(buf, maxsize, 0, dims) finalizer(obj) do arr - free(arr.buffer) + if arr.buffer !== nothing + free(arr.buffer) + end end return obj end - function MtlArray{T,N}(buffer::MtlBuffer, dims::Dims{N}; + function MtlArray{T,N}(buffer::MTLBuffer, dims::Dims{N}; maxsize::Int=prod(dims) * sizeof(T), offset::Int=0) where {T,N} Base.allocatedinline(T) || error("MtlArray only supports element types that are stored inline") - MTL.mtRetain(buffer.handle) + retain(buffer) obj = new{T,N}(buffer, maxsize, offset, dims) finalizer(obj) do arr free(arr.buffer) @@ -508,7 +510,7 @@ end ## unsafe_wrap -function Base.unsafe_wrap(t::Type{<:Array{T}}, buf::MtlBuffer, dims; own=false) where T +function Base.unsafe_wrap(t::Type{<:Array{T}}, buf::MTLBuffer, dims; own=false) where T ptr = convert(Ptr{T}, contents(buf)) return unsafe_wrap(t, ptr, dims; own) end diff --git a/src/compiler/execution.jl b/src/compiler/execution.jl index 69637c80d..3257c4198 100644 --- a/src/compiler/execution.jl +++ b/src/compiler/execution.jl @@ -84,8 +84,8 @@ struct Adaptor end # convert Metal buffers to their GPU address -function Adapt.adapt_storage(to::Adaptor, buf::MtlBuffer) - if to.cce !== nothing && buf.handle != C_NULL +function Adapt.adapt_storage(to::Adaptor, buf::MTLBuffer) + if to.cce !== nothing MTL.use!(to.cce, buf, MTL.ReadWriteUsage) end reinterpret(Core.LLVMPtr{Nothing,AS.Device}, buf.gpuAddress) @@ -203,14 +203,14 @@ function (kernel::HostKernel)(args...; grid=1, threads=1, queue=global_queue(cur cmdbuf = MtlCommandBuffer(queue) cmdbuf.label = "MtlCommandBuffer($(nameof(kernel.f)))" - argument_buffers = MtlBuffer[] + argument_buffers = MTLBuffer[] MtlComputeCommandEncoder(cmdbuf) do cce MTL.set_function!(cce, kernel.pipeline_state) # encode arguments idx = 1 for arg in (kernel.f, args...) - if arg isa MtlBuffer + if arg isa MTLBuffer # top-level buffers are passed as a pointer-valued argument set_buffer!(cce, arg, 0, idx) elseif arg isa MtlPointer @@ -226,7 +226,7 @@ function (kernel::HostKernel)(args...; grid=1, threads=1, queue=global_queue(cur @assert isbits(arg) argument_buffer = alloc(kernel.fun.lib.device, sizeof(argtyp), storage=Shared) - argument_buffer.label = "MtlBuffer for kernel argument" + argument_buffer.label = "MTLBuffer for kernel argument" unsafe_store!(convert(Ptr{argtyp}, contents(argument_buffer)), arg) set_buffer!(cce, argument_buffer, 0, idx) push!(argument_buffers, argument_buffer) diff --git a/src/memory.jl b/src/memory.jl index 1d64f74c0..ef2c4a7fc 100644 --- a/src/memory.jl +++ b/src/memory.jl @@ -4,14 +4,14 @@ ## pointer type -# we cannot take a MtlBuffer's handle and work with that as it were a pointer to memory. +# we cannot take a MTLBuffer's handle and work with that as it were a pointer to memory. # instead, the Metal APIs always take the original handle and an offset parameter. struct MtlPointer{T} - buffer::MtlBuffer + buffer::MTLBuffer offset::UInt # in bytes - function MtlPointer{T}(buffer::MtlBuffer, offset=0) where {T} + function MtlPointer{T}(buffer::MTLBuffer, offset=0) where {T} new(buffer, offset) end end @@ -44,7 +44,7 @@ end function Base.unsafe_copyto!(dev::MTLDevice, dst::Ptr{T}, src::MtlPointer{T}, N::Integer; queue::MtlCommandQueue=global_queue(dev), async::Bool=false) where T storage_type = src.buffer.storageMode - if storage_type == MTL.MtStorageModePrivate + if storage_type == MTL.MTLStorageModePrivate tmp_buf = alloc(T, dev, N, storage=Shared) unsafe_copyto!(dev, tmp_buf, 1, src.buffer, src.offset, N; queue, async) unsafe_copyto!(dst, contents(tmp_buf), N) @@ -61,7 +61,7 @@ end function Base.unsafe_copyto!(dev::MTLDevice, dst::MtlPointer{T}, src::Ptr{T}, N::Integer; queue::MtlCommandQueue=global_queue(dev), async::Bool=false) where T storage_type = dst.buffer.storageMode - if storage_type == MTL.MtStorageModePrivate + if storage_type == MTL.MTLStorageModePrivate tmp_buf = alloc(T, dev, N, src, storage=Shared) unsafe_copyto!(dev, tmp_buf, src, N; queue, async) unsafe_copyto!(dev, dst.buffer, dst.offset, tmp_buf, 1, N; queue, async) diff --git a/test/array.jl b/test/array.jl index f35b65fa7..b4c3ad16f 100644 --- a/test/array.jl +++ b/test/array.jl @@ -9,7 +9,7 @@ let mtl_arr = MtlArray{Int}(undef, 1) end let mtl_arr = MtlArray{Int}(undef, 0) - @test pointer(mtl_arr).buffer.handle == C_NULL + @test pointer(mtl_arr).buffer === nothing end @testset "mtl" begin diff --git a/test/metal.jl b/test/metal.jl index 49b73d20c..822e2f9d5 100644 --- a/test/metal.jl +++ b/test/metal.jl @@ -230,12 +230,12 @@ end dev = first(devices()) -buf = MtlBuffer(dev, 8; storage=Shared) +buf = MTLBuffer(dev, 8; storage=Shared) @test buf.length == 8 @test sizeof(buf) == 8 -# MtlResource properties +# MTLResource properties @test buf.device == dev @test buf.label === nothing buf.label = "MyBuffer"