Skip to content

Commit

Permalink
Migrate MTLResource and MTLBuffer.
Browse files Browse the repository at this point in the history
  • Loading branch information
maleadt committed Mar 6, 2023
1 parent 8e3b5d4 commit e092234
Show file tree
Hide file tree
Showing 16 changed files with 167 additions and 146 deletions.
2 changes: 1 addition & 1 deletion Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions lib/cmt/cmt.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module cmt

using cmt_jll
using ObjectiveC, .Foundation

include("libcmt.jl")

Expand Down
37 changes: 16 additions & 21 deletions lib/cmt/libcmt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1997,23 +1992,23 @@ 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)
ccall((:mtBlitCommandEncoderGenerateMipmaps, libcmt), Cvoid, (Ptr{MtBlitCommandEncoder}, Ptr{MtTexture}), 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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -2313,23 +2308,23 @@ 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)
ccall((:mtArgumentEncoderSetTextureAtIndex, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{MtTexture}, NsUInteger), 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)
ccall((:mtArgumentEncoderSetSamplerStateAtIndex, libcmt), Cvoid, (Ptr{MtArgumentEncoder}, Ptr{MtSamplerState}, NsUInteger), 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)
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions lib/mtl/MTL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module MTL

using ..cmt

using CEnum
using ObjectiveC, ObjectiveC.Foundation


Expand Down
124 changes: 61 additions & 63 deletions lib/mtl/buffer.jl
Original file line number Diff line number Diff line change
@@ -1,66 +1,70 @@
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


## 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,
Expand All @@ -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,
Expand All @@ -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`,
Expand All @@ -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]
6 changes: 3 additions & 3 deletions lib/mtl/command_enc/blit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit e092234

Please sign in to comment.