Metal: Wrap NS classes and protocols in NSRef.
This makes refcounting of these objects more automatic to try and prevent leaks or use-after-frees in the future. Also removes operator* from RefBase (and Ref) because it is never used and cannot work in a normal way for ObjectiveC protocols that cannot be dereferenced. Bug: dawn:89 Change-Id: I2e3fbfd638e2ba76d8c563f30bc489a384152552 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/32161 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Stephen White <senorblanco@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
1805e46a15
commit
0055d95fa7
|
@ -167,6 +167,7 @@ if (is_win || is_linux || is_chromeos || is_mac || is_fuchsia || is_android) {
|
||||||
"Log.h",
|
"Log.h",
|
||||||
"Math.cpp",
|
"Math.cpp",
|
||||||
"Math.h",
|
"Math.h",
|
||||||
|
"NSRef.h",
|
||||||
"PlacementAllocated.h",
|
"PlacementAllocated.h",
|
||||||
"Platform.h",
|
"Platform.h",
|
||||||
"RefBase.h",
|
"RefBase.h",
|
||||||
|
|
|
@ -29,6 +29,7 @@ target_sources(dawn_common PRIVATE
|
||||||
"Log.h"
|
"Log.h"
|
||||||
"Math.cpp"
|
"Math.cpp"
|
||||||
"Math.h"
|
"Math.h"
|
||||||
|
"NSRef.h"
|
||||||
"PlacementAllocated.h"
|
"PlacementAllocated.h"
|
||||||
"Platform.h"
|
"Platform.h"
|
||||||
"RefBase.h"
|
"RefBase.h"
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef COMMON_NSREF_H_
|
||||||
|
#define COMMON_NSREF_H_
|
||||||
|
|
||||||
|
#include "common/RefBase.h"
|
||||||
|
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
|
||||||
|
#if !defined(__OBJC__)
|
||||||
|
# error "NSRef can only be used in Objective C/C++ code."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This file contains smart pointers that automatically reference and release Objective C objects
|
||||||
|
// and prototocals in a manner very similar to Ref<>. Note that NSRef<> and NSPRef's constructor add
|
||||||
|
// a reference to the object by default, so the pattern to get a reference for a newly created
|
||||||
|
// NSObject is the following:
|
||||||
|
//
|
||||||
|
// NSRef<NSFoo> foo = AcquireNSRef([NSFoo alloc]);
|
||||||
|
//
|
||||||
|
// NSRef overloads -> and * but these operators don't work extremely well with Objective C's
|
||||||
|
// features. For example automatic dereferencing when doing the following doesn't work:
|
||||||
|
//
|
||||||
|
// NSFoo* foo;
|
||||||
|
// foo.member = 1;
|
||||||
|
// someVar = foo.member;
|
||||||
|
//
|
||||||
|
// Instead use the message passing syntax:
|
||||||
|
//
|
||||||
|
// NSRef<NSFoo> foo;
|
||||||
|
// [*foo setMember: 1];
|
||||||
|
// someVar = [*foo member];
|
||||||
|
//
|
||||||
|
// Also did you notive the extra '*' in the example above? That's because Objective C's message
|
||||||
|
// passing doesn't automatically call a C++ operator to dereference smart pointers (like -> does) so
|
||||||
|
// we have to dereference manually using '*'. In some cases the extra * or message passing syntax
|
||||||
|
// can get a bit annoying so instead a local "naked" pointer can be borrowed from the NSRef. This
|
||||||
|
// would change the syntax overload in the following:
|
||||||
|
//
|
||||||
|
// NSRef<NSFoo> foo;
|
||||||
|
// [*foo setA:1];
|
||||||
|
// [*foo setB:2];
|
||||||
|
// [*foo setC:3];
|
||||||
|
//
|
||||||
|
// Into (note access to members of ObjC classes referenced via pointer is done with . and not ->):
|
||||||
|
//
|
||||||
|
// NSRef<NSFoo> fooRef;
|
||||||
|
// NSFoo* foo = fooRef.Get();
|
||||||
|
// foo.a = 1;
|
||||||
|
// foo.b = 2;
|
||||||
|
// boo.c = 3;
|
||||||
|
//
|
||||||
|
// Which can be subjectively easier to read.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct NSRefTraits {
|
||||||
|
static constexpr T kNullValue = nullptr;
|
||||||
|
static void Reference(T value) {
|
||||||
|
[value retain];
|
||||||
|
}
|
||||||
|
static void Release(T value) {
|
||||||
|
[value release];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class NSRef : public RefBase<T*, NSRefTraits<T*>> {
|
||||||
|
public:
|
||||||
|
using RefBase<T*, NSRefTraits<T*>>::RefBase;
|
||||||
|
|
||||||
|
const T* operator*() const {
|
||||||
|
return this->Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator*() {
|
||||||
|
return this->Get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NSRef<T> AcquireNSRef(T* pointee) {
|
||||||
|
NSRef<T> ref;
|
||||||
|
ref.Acquire(pointee);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a RefBase<> for an Objective C protocol (hence the P). Objective C protocols must always
|
||||||
|
// be referenced with id<ProtocolName> and not just ProtocolName* so they cannot use NSRef<>
|
||||||
|
// itself. That's what the P in NSPRef stands for: Protocol.
|
||||||
|
template <typename T>
|
||||||
|
class NSPRef : public RefBase<T, NSRefTraits<T>> {
|
||||||
|
public:
|
||||||
|
using RefBase<T, NSRefTraits<T>>::RefBase;
|
||||||
|
|
||||||
|
const T operator*() const {
|
||||||
|
return this->Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator*() {
|
||||||
|
return this->Get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
NSPRef<T> AcquireNSPRef(T pointee) {
|
||||||
|
NSPRef<T> ref;
|
||||||
|
ref.Acquire(pointee);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COMMON_NSREF_H_
|
|
@ -137,14 +137,6 @@ class RefBase {
|
||||||
return mValue != kNullValue;
|
return mValue != kNullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operator * and -> to act like a pointer.
|
|
||||||
const typename Traits::PointedType& operator*() const {
|
|
||||||
return *mValue;
|
|
||||||
}
|
|
||||||
typename Traits::PointedType& operator*() {
|
|
||||||
return *mValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T operator->() const {
|
const T operator->() const {
|
||||||
return mValue;
|
return mValue;
|
||||||
}
|
}
|
||||||
|
@ -166,6 +158,11 @@ class RefBase {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Acquire(T value) {
|
||||||
|
Release();
|
||||||
|
mValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Friend is needed so that instances of RefBase<U> can call Reference and Release on
|
// Friend is needed so that instances of RefBase<U> can call Reference and Release on
|
||||||
// RefBase<T>.
|
// RefBase<T>.
|
||||||
|
|
|
@ -42,7 +42,6 @@ class RefCounted {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct RefCountedTraits {
|
struct RefCountedTraits {
|
||||||
using PointedType = T;
|
|
||||||
static constexpr T* kNullValue = nullptr;
|
static constexpr T* kNullValue = nullptr;
|
||||||
static void Reference(T* value) {
|
static void Reference(T* value) {
|
||||||
value->Reference();
|
value->Reference();
|
||||||
|
@ -60,8 +59,8 @@ class Ref : public RefBase<T*, RefCountedTraits<T>> {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Ref<T> AcquireRef(T* pointee) {
|
Ref<T> AcquireRef(T* pointee) {
|
||||||
Ref<T> ref(pointee);
|
Ref<T> ref;
|
||||||
ref->Release();
|
ref.Acquire(pointee);
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "dawn_native/metal/BackendMTL.h"
|
#include "dawn_native/metal/BackendMTL.h"
|
||||||
|
|
||||||
#include "common/GPUInfo.h"
|
#include "common/GPUInfo.h"
|
||||||
|
#include "common/NSRef.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "dawn_native/Instance.h"
|
#include "dawn_native/Instance.h"
|
||||||
#include "dawn_native/MetalBackend.h"
|
#include "dawn_native/MetalBackend.h"
|
||||||
|
@ -176,8 +177,8 @@ namespace dawn_native { namespace metal {
|
||||||
class Adapter : public AdapterBase {
|
class Adapter : public AdapterBase {
|
||||||
public:
|
public:
|
||||||
Adapter(InstanceBase* instance, id<MTLDevice> device)
|
Adapter(InstanceBase* instance, id<MTLDevice> device)
|
||||||
: AdapterBase(instance, wgpu::BackendType::Metal), mDevice([device retain]) {
|
: AdapterBase(instance, wgpu::BackendType::Metal), mDevice(device) {
|
||||||
mPCIInfo.name = std::string([mDevice.name UTF8String]);
|
mPCIInfo.name = std::string([[*mDevice name] UTF8String]);
|
||||||
|
|
||||||
PCIIDs ids;
|
PCIIDs ids;
|
||||||
if (!instance->ConsumedError(GetDevicePCIInfo(device, &ids))) {
|
if (!instance->ConsumedError(GetDevicePCIInfo(device, &ids))) {
|
||||||
|
@ -206,10 +207,6 @@ namespace dawn_native { namespace metal {
|
||||||
InitializeSupportedExtensions();
|
InitializeSupportedExtensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Adapter() override {
|
|
||||||
[mDevice release];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
|
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
|
||||||
return Device::Create(this, mDevice, descriptor);
|
return Device::Create(this, mDevice, descriptor);
|
||||||
|
@ -217,14 +214,14 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
void InitializeSupportedExtensions() {
|
void InitializeSupportedExtensions() {
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
if ([mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
|
if ([*mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
|
||||||
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
|
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (@available(macOS 10.15, iOS 14.0, *)) {
|
if (@available(macOS 10.15, iOS 14.0, *)) {
|
||||||
if ([mDevice supportsFamily:MTLGPUFamilyMac2] ||
|
if ([*mDevice supportsFamily:MTLGPUFamilyMac2] ||
|
||||||
[mDevice supportsFamily:MTLGPUFamilyApple5]) {
|
[*mDevice supportsFamily:MTLGPUFamilyApple5]) {
|
||||||
mSupportedExtensions.EnableExtension(Extension::PipelineStatisticsQuery);
|
mSupportedExtensions.EnableExtension(Extension::PipelineStatisticsQuery);
|
||||||
mSupportedExtensions.EnableExtension(Extension::TimestampQuery);
|
mSupportedExtensions.EnableExtension(Extension::TimestampQuery);
|
||||||
}
|
}
|
||||||
|
@ -233,7 +230,7 @@ namespace dawn_native { namespace metal {
|
||||||
mSupportedExtensions.EnableExtension(Extension::ShaderFloat16);
|
mSupportedExtensions.EnableExtension(Extension::ShaderFloat16);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLDevice> mDevice = nil;
|
NSPRef<id<MTLDevice>> mDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implementation of the Metal backend's BackendConnection
|
// Implementation of the Metal backend's BackendConnection
|
||||||
|
@ -251,13 +248,12 @@ namespace dawn_native { namespace metal {
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
if (@available(macOS 10.11, *)) {
|
if (@available(macOS 10.11, *)) {
|
||||||
supportedVersion = YES;
|
supportedVersion = YES;
|
||||||
NSArray<id<MTLDevice>>* devices = MTLCopyAllDevices();
|
|
||||||
|
|
||||||
for (id<MTLDevice> device in devices) {
|
NSRef<NSArray<id<MTLDevice>>> devices = AcquireNSRef(MTLCopyAllDevices());
|
||||||
|
|
||||||
|
for (id<MTLDevice> device in devices.Get()) {
|
||||||
adapters.push_back(std::make_unique<Adapter>(GetInstance(), device));
|
adapters.push_back(std::make_unique<Adapter>(GetInstance(), device));
|
||||||
}
|
}
|
||||||
|
|
||||||
[devices release];
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#ifndef DAWNNATIVE_METAL_BUFFERMTL_H_
|
#ifndef DAWNNATIVE_METAL_BUFFERMTL_H_
|
||||||
#define DAWNNATIVE_METAL_BUFFERMTL_H_
|
#define DAWNNATIVE_METAL_BUFFERMTL_H_
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
#include "common/SerialQueue.h"
|
#include "common/SerialQueue.h"
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ namespace dawn_native { namespace metal {
|
||||||
void InitializeToZero(CommandRecordingContext* commandContext);
|
void InitializeToZero(CommandRecordingContext* commandContext);
|
||||||
void ClearBuffer(CommandRecordingContext* commandContext, uint8_t clearValue);
|
void ClearBuffer(CommandRecordingContext* commandContext, uint8_t clearValue);
|
||||||
|
|
||||||
id<MTLBuffer> mMtlBuffer = nil;
|
NSPRef<id<MTLBuffer>> mMtlBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -84,9 +84,10 @@ namespace dawn_native { namespace metal {
|
||||||
return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation is too large");
|
return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation is too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
mMtlBuffer = [ToBackend(GetDevice())->GetMTLDevice() newBufferWithLength:currentSize
|
mMtlBuffer.Acquire([ToBackend(GetDevice())->GetMTLDevice()
|
||||||
options:storageMode];
|
newBufferWithLength:currentSize
|
||||||
if (mMtlBuffer == nil) {
|
options:storageMode]);
|
||||||
|
if (mMtlBuffer == nullptr) {
|
||||||
return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation failed");
|
return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLBuffer> Buffer::GetMTLBuffer() const {
|
id<MTLBuffer> Buffer::GetMTLBuffer() const {
|
||||||
return mMtlBuffer;
|
return mMtlBuffer.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Buffer::IsCPUWritableAtCreation() const {
|
bool Buffer::IsCPUWritableAtCreation() const {
|
||||||
|
@ -128,7 +129,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Buffer::GetMappedPointerImpl() {
|
void* Buffer::GetMappedPointerImpl() {
|
||||||
return [mMtlBuffer contents];
|
return [*mMtlBuffer contents];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::UnmapImpl() {
|
void Buffer::UnmapImpl() {
|
||||||
|
@ -136,8 +137,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::DestroyImpl() {
|
void Buffer::DestroyImpl() {
|
||||||
[mMtlBuffer release];
|
mMtlBuffer = nullptr;
|
||||||
mMtlBuffer = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::EnsureDataInitialized(CommandRecordingContext* commandContext) {
|
void Buffer::EnsureDataInitialized(CommandRecordingContext* commandContext) {
|
||||||
|
@ -196,7 +196,7 @@ namespace dawn_native { namespace metal {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[commandContext->EnsureBlit() fillBuffer:mMtlBuffer
|
[commandContext->EnsureBlit() fillBuffer:mMtlBuffer.Get()
|
||||||
range:NSMakeRange(0, GetSize())
|
range:NSMakeRange(0, GetSize())
|
||||||
value:clearValue];
|
value:clearValue];
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,9 +53,12 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an autoreleased MTLRenderPassDescriptor matching desc
|
NSRef<MTLRenderPassDescriptor> CreateMTLRenderPassDescriptor(
|
||||||
MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) {
|
BeginRenderPassCmd* renderPass) {
|
||||||
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
// Note that this creates a descriptor that's autoreleased so we don't use AcquireNSRef
|
||||||
|
NSRef<MTLRenderPassDescriptor> descriptorRef =
|
||||||
|
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
MTLRenderPassDescriptor* descriptor = descriptorRef.Get();
|
||||||
|
|
||||||
for (ColorAttachmentIndex attachment :
|
for (ColorAttachmentIndex attachment :
|
||||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||||
|
@ -167,7 +170,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptor;
|
return descriptorRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for Toggle EmulateStoreAndMSAAResolve
|
// Helper function for Toggle EmulateStoreAndMSAAResolve
|
||||||
|
@ -175,10 +178,13 @@ namespace dawn_native { namespace metal {
|
||||||
CommandRecordingContext* commandContext,
|
CommandRecordingContext* commandContext,
|
||||||
const MTLRenderPassDescriptor* mtlRenderPass,
|
const MTLRenderPassDescriptor* mtlRenderPass,
|
||||||
const std::array<id<MTLTexture>, kMaxColorAttachments>& resolveTextures) {
|
const std::array<id<MTLTexture>, kMaxColorAttachments>& resolveTextures) {
|
||||||
MTLRenderPassDescriptor* mtlRenderPassForResolve =
|
// Note that this creates a descriptor that's autoreleased so we don't use AcquireNSRef
|
||||||
|
NSRef<MTLRenderPassDescriptor> mtlRenderPassForResolveRef =
|
||||||
[MTLRenderPassDescriptor renderPassDescriptor];
|
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
MTLRenderPassDescriptor* mtlRenderPassForResolve = mtlRenderPassForResolveRef.Get();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||||
if (resolveTextures[i] == nil) {
|
if (resolveTextures[i] == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,11 +205,13 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions for Toggle AlwaysResolveIntoZeroLevelAndLayer
|
// Helper functions for Toggle AlwaysResolveIntoZeroLevelAndLayer
|
||||||
id<MTLTexture> CreateResolveTextureForWorkaround(Device* device,
|
NSPRef<id<MTLTexture>> CreateResolveTextureForWorkaround(Device* device,
|
||||||
MTLPixelFormat mtlFormat,
|
MTLPixelFormat mtlFormat,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height) {
|
uint32_t height) {
|
||||||
MTLTextureDescriptor* mtlDesc = [MTLTextureDescriptor new];
|
NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
|
||||||
|
MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
|
||||||
|
|
||||||
mtlDesc.textureType = MTLTextureType2D;
|
mtlDesc.textureType = MTLTextureType2D;
|
||||||
mtlDesc.usage = MTLTextureUsageRenderTarget;
|
mtlDesc.usage = MTLTextureUsageRenderTarget;
|
||||||
mtlDesc.pixelFormat = mtlFormat;
|
mtlDesc.pixelFormat = mtlFormat;
|
||||||
|
@ -214,10 +222,8 @@ namespace dawn_native { namespace metal {
|
||||||
mtlDesc.arrayLength = 1;
|
mtlDesc.arrayLength = 1;
|
||||||
mtlDesc.storageMode = MTLStorageModePrivate;
|
mtlDesc.storageMode = MTLStorageModePrivate;
|
||||||
mtlDesc.sampleCount = 1;
|
mtlDesc.sampleCount = 1;
|
||||||
id<MTLTexture> resolveTexture =
|
|
||||||
[device->GetMTLDevice() newTextureWithDescriptor:mtlDesc];
|
return AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc]);
|
||||||
[mtlDesc release];
|
|
||||||
return resolveTexture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyIntoTrueResolveTarget(CommandRecordingContext* commandContext,
|
void CopyIntoTrueResolveTarget(CommandRecordingContext* commandContext,
|
||||||
|
@ -350,11 +356,11 @@ namespace dawn_native { namespace metal {
|
||||||
group->GetLayout()->GetBindingInfo(bindingIndex);
|
group->GetLayout()->GetBindingInfo(bindingIndex);
|
||||||
|
|
||||||
bool hasVertStage =
|
bool hasVertStage =
|
||||||
bindingInfo.visibility & wgpu::ShaderStage::Vertex && render != nil;
|
bindingInfo.visibility & wgpu::ShaderStage::Vertex && render != nullptr;
|
||||||
bool hasFragStage =
|
bool hasFragStage =
|
||||||
bindingInfo.visibility & wgpu::ShaderStage::Fragment && render != nil;
|
bindingInfo.visibility & wgpu::ShaderStage::Fragment && render != nullptr;
|
||||||
bool hasComputeStage =
|
bool hasComputeStage =
|
||||||
bindingInfo.visibility & wgpu::ShaderStage::Compute && compute != nil;
|
bindingInfo.visibility & wgpu::ShaderStage::Compute && compute != nullptr;
|
||||||
|
|
||||||
uint32_t vertIndex = 0;
|
uint32_t vertIndex = 0;
|
||||||
uint32_t fragIndex = 0;
|
uint32_t fragIndex = 0;
|
||||||
|
@ -461,12 +467,12 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void ApplyBindGroup(id<MTLRenderCommandEncoder> encoder, Args&&... args) {
|
void ApplyBindGroup(id<MTLRenderCommandEncoder> encoder, Args&&... args) {
|
||||||
ApplyBindGroupImpl(encoder, nil, std::forward<Args&&>(args)...);
|
ApplyBindGroupImpl(encoder, nullptr, std::forward<Args&&>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void ApplyBindGroup(id<MTLComputeCommandEncoder> encoder, Args&&... args) {
|
void ApplyBindGroup(id<MTLComputeCommandEncoder> encoder, Args&&... args) {
|
||||||
ApplyBindGroupImpl(nil, encoder, std::forward<Args&&>(args)...);
|
ApplyBindGroupImpl(nullptr, encoder, std::forward<Args&&>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
StorageBufferLengthTracker* mLengthTracker;
|
StorageBufferLengthTracker* mLengthTracker;
|
||||||
|
@ -578,8 +584,9 @@ namespace dawn_native { namespace metal {
|
||||||
commandContext->EndBlit();
|
commandContext->EndBlit();
|
||||||
|
|
||||||
LazyClearRenderPassAttachments(cmd);
|
LazyClearRenderPassAttachments(cmd);
|
||||||
MTLRenderPassDescriptor* descriptor = CreateMTLRenderPassDescriptor(cmd);
|
NSRef<MTLRenderPassDescriptor> descriptor = CreateMTLRenderPassDescriptor(cmd);
|
||||||
DAWN_TRY(EncodeRenderPass(commandContext, descriptor, cmd->width, cmd->height));
|
DAWN_TRY(EncodeRenderPass(commandContext, descriptor.Get(), cmd->width,
|
||||||
|
cmd->height));
|
||||||
|
|
||||||
nextPassNumber++;
|
nextPassNumber++;
|
||||||
break;
|
break;
|
||||||
|
@ -792,9 +799,9 @@ namespace dawn_native { namespace metal {
|
||||||
char* label = mCommands.NextData<char>(cmd->length + 1);
|
char* label = mCommands.NextData<char>(cmd->length + 1);
|
||||||
|
|
||||||
if (@available(macos 10.13, *)) {
|
if (@available(macos 10.13, *)) {
|
||||||
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
|
NSRef<NSString> mtlLabel =
|
||||||
[commandContext->GetCommands() pushDebugGroup:mtlLabel];
|
AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
|
||||||
[mtlLabel release];
|
[commandContext->GetCommands() pushDebugGroup:mtlLabel.Get()];
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -876,10 +883,9 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::InsertDebugMarker: {
|
case Command::InsertDebugMarker: {
|
||||||
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
|
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
|
||||||
char* label = mCommands.NextData<char>(cmd->length + 1);
|
char* label = mCommands.NextData<char>(cmd->length + 1);
|
||||||
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
|
NSRef<NSString> mtlLabel =
|
||||||
|
AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
|
||||||
[encoder insertDebugSignpost:mtlLabel];
|
[encoder insertDebugSignpost:mtlLabel.Get()];
|
||||||
[mtlLabel release];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,10 +899,9 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::PushDebugGroup: {
|
case Command::PushDebugGroup: {
|
||||||
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
|
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
|
||||||
char* label = mCommands.NextData<char>(cmd->length + 1);
|
char* label = mCommands.NextData<char>(cmd->length + 1);
|
||||||
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
|
NSRef<NSString> mtlLabel =
|
||||||
|
AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
|
||||||
[encoder pushDebugGroup:mtlLabel];
|
[encoder pushDebugGroup:mtlLabel.Get()];
|
||||||
[mtlLabel release];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,9 +949,9 @@ namespace dawn_native { namespace metal {
|
||||||
// Use temporary resolve texture on the resolve targets with non-zero resolveLevel or
|
// Use temporary resolve texture on the resolve targets with non-zero resolveLevel or
|
||||||
// resolveSlice.
|
// resolveSlice.
|
||||||
bool useTemporaryResolveTexture = false;
|
bool useTemporaryResolveTexture = false;
|
||||||
std::array<id<MTLTexture>, kMaxColorAttachments> temporaryResolveTextures = {};
|
std::array<NSPRef<id<MTLTexture>>, kMaxColorAttachments> temporaryResolveTextures = {};
|
||||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||||
if (mtlRenderPass.colorAttachments[i].resolveTexture == nil) {
|
if (mtlRenderPass.colorAttachments[i].resolveTexture == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +968,8 @@ namespace dawn_native { namespace metal {
|
||||||
temporaryResolveTextures[i] =
|
temporaryResolveTextures[i] =
|
||||||
CreateResolveTextureForWorkaround(device, mtlFormat, width, height);
|
CreateResolveTextureForWorkaround(device, mtlFormat, width, height);
|
||||||
|
|
||||||
mtlRenderPass.colorAttachments[i].resolveTexture = temporaryResolveTextures[i];
|
mtlRenderPass.colorAttachments[i].resolveTexture =
|
||||||
|
temporaryResolveTextures[i].Get();
|
||||||
mtlRenderPass.colorAttachments[i].resolveLevel = 0;
|
mtlRenderPass.colorAttachments[i].resolveLevel = 0;
|
||||||
mtlRenderPass.colorAttachments[i].resolveSlice = 0;
|
mtlRenderPass.colorAttachments[i].resolveSlice = 0;
|
||||||
useTemporaryResolveTexture = true;
|
useTemporaryResolveTexture = true;
|
||||||
|
@ -974,16 +980,14 @@ namespace dawn_native { namespace metal {
|
||||||
if (useTemporaryResolveTexture) {
|
if (useTemporaryResolveTexture) {
|
||||||
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||||
if (trueResolveTextures[i] == nil) {
|
if (trueResolveTextures[i] == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(temporaryResolveTextures[i] != nil);
|
ASSERT(temporaryResolveTextures[i] != nullptr);
|
||||||
CopyIntoTrueResolveTarget(commandContext, trueResolveTextures[i],
|
CopyIntoTrueResolveTarget(commandContext, trueResolveTextures[i],
|
||||||
trueResolveLevels[i], trueResolveSlices[i],
|
trueResolveLevels[i], trueResolveSlices[i],
|
||||||
temporaryResolveTextures[i], width, height);
|
temporaryResolveTextures[i].Get(), width, height);
|
||||||
[temporaryResolveTextures[i] release];
|
|
||||||
temporaryResolveTextures[i] = nil;
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1006,7 @@ namespace dawn_native { namespace metal {
|
||||||
resolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;
|
resolveTextures[i] = mtlRenderPass.colorAttachments[i].resolveTexture;
|
||||||
|
|
||||||
mtlRenderPass.colorAttachments[i].storeAction = MTLStoreActionStore;
|
mtlRenderPass.colorAttachments[i].storeAction = MTLStoreActionStore;
|
||||||
mtlRenderPass.colorAttachments[i].resolveTexture = nil;
|
mtlRenderPass.colorAttachments[i].resolveTexture = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,7 +1028,7 @@ namespace dawn_native { namespace metal {
|
||||||
uint32_t height) {
|
uint32_t height) {
|
||||||
bool enableVertexPulling = GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling);
|
bool enableVertexPulling = GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling);
|
||||||
RenderPipeline* lastPipeline = nullptr;
|
RenderPipeline* lastPipeline = nullptr;
|
||||||
id<MTLBuffer> indexBuffer = nil;
|
id<MTLBuffer> indexBuffer = nullptr;
|
||||||
uint32_t indexBufferBaseOffset = 0;
|
uint32_t indexBufferBaseOffset = 0;
|
||||||
wgpu::IndexFormat indexBufferFormat = wgpu::IndexFormat::Undefined;
|
wgpu::IndexFormat indexBufferFormat = wgpu::IndexFormat::Undefined;
|
||||||
StorageBufferLengthTracker storageBufferLengths = {};
|
StorageBufferLengthTracker storageBufferLengths = {};
|
||||||
|
@ -1148,10 +1152,9 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::InsertDebugMarker: {
|
case Command::InsertDebugMarker: {
|
||||||
InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
|
InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
|
||||||
char* label = iter->NextData<char>(cmd->length + 1);
|
char* label = iter->NextData<char>(cmd->length + 1);
|
||||||
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
|
NSRef<NSString> mtlLabel =
|
||||||
|
AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
|
||||||
[encoder insertDebugSignpost:mtlLabel];
|
[encoder insertDebugSignpost:mtlLabel.Get()];
|
||||||
[mtlLabel release];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1165,10 +1168,9 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::PushDebugGroup: {
|
case Command::PushDebugGroup: {
|
||||||
PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
|
PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
|
||||||
char* label = iter->NextData<char>(cmd->length + 1);
|
char* label = iter->NextData<char>(cmd->length + 1);
|
||||||
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
|
NSRef<NSString> mtlLabel =
|
||||||
|
AcquireNSRef([[NSString alloc] initWithUTF8String:label]);
|
||||||
[encoder pushDebugGroup:mtlLabel];
|
[encoder pushDebugGroup:mtlLabel.Get()];
|
||||||
[mtlLabel release];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#ifndef DAWNNATIVE_METAL_COMMANDRECORDINGCONTEXT_H_
|
#ifndef DAWNNATIVE_METAL_COMMANDRECORDINGCONTEXT_H_
|
||||||
#define DAWNNATIVE_METAL_COMMANDRECORDINGCONTEXT_H_
|
#define DAWNNATIVE_METAL_COMMANDRECORDINGCONTEXT_H_
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
@ -23,7 +25,7 @@ namespace dawn_native { namespace metal {
|
||||||
class CommandRecordingContext {
|
class CommandRecordingContext {
|
||||||
public:
|
public:
|
||||||
CommandRecordingContext();
|
CommandRecordingContext();
|
||||||
CommandRecordingContext(id<MTLCommandBuffer> commands);
|
CommandRecordingContext(NSPRef<id<MTLCommandBuffer>> commands);
|
||||||
|
|
||||||
CommandRecordingContext(const CommandRecordingContext& rhs) = delete;
|
CommandRecordingContext(const CommandRecordingContext& rhs) = delete;
|
||||||
CommandRecordingContext& operator=(const CommandRecordingContext& rhs) = delete;
|
CommandRecordingContext& operator=(const CommandRecordingContext& rhs) = delete;
|
||||||
|
@ -35,7 +37,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
id<MTLCommandBuffer> GetCommands();
|
id<MTLCommandBuffer> GetCommands();
|
||||||
|
|
||||||
id<MTLCommandBuffer> AcquireCommands();
|
NSPRef<id<MTLCommandBuffer>> AcquireCommands();
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> EnsureBlit();
|
id<MTLBlitCommandEncoder> EnsureBlit();
|
||||||
void EndBlit();
|
void EndBlit();
|
||||||
|
@ -47,10 +49,10 @@ namespace dawn_native { namespace metal {
|
||||||
void EndRender();
|
void EndRender();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
id<MTLCommandBuffer> mCommands = nil;
|
NSPRef<id<MTLCommandBuffer>> mCommands;
|
||||||
id<MTLBlitCommandEncoder> mBlit = nil;
|
NSPRef<id<MTLBlitCommandEncoder>> mBlit;
|
||||||
id<MTLComputeCommandEncoder> mCompute = nil;
|
NSPRef<id<MTLComputeCommandEncoder>> mCompute;
|
||||||
id<MTLRenderCommandEncoder> mRender = nil;
|
NSPRef<id<MTLRenderCommandEncoder>> mRender;
|
||||||
bool mInEncoder = false;
|
bool mInEncoder = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
CommandRecordingContext::CommandRecordingContext() = default;
|
CommandRecordingContext::CommandRecordingContext() = default;
|
||||||
|
|
||||||
CommandRecordingContext::CommandRecordingContext(id<MTLCommandBuffer> commands)
|
CommandRecordingContext::CommandRecordingContext(NSPRef<id<MTLCommandBuffer>> commands)
|
||||||
: mCommands(commands) {
|
: mCommands(std::move(commands)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandRecordingContext::CommandRecordingContext(CommandRecordingContext&& rhs)
|
CommandRecordingContext::CommandRecordingContext(CommandRecordingContext&& rhs)
|
||||||
|
@ -35,90 +35,87 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
CommandRecordingContext::~CommandRecordingContext() {
|
CommandRecordingContext::~CommandRecordingContext() {
|
||||||
// Commands must be acquired.
|
// Commands must be acquired.
|
||||||
ASSERT(mCommands == nil);
|
ASSERT(mCommands == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLCommandBuffer> CommandRecordingContext::GetCommands() {
|
id<MTLCommandBuffer> CommandRecordingContext::GetCommands() {
|
||||||
return mCommands;
|
return mCommands.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLCommandBuffer> CommandRecordingContext::AcquireCommands() {
|
NSPRef<id<MTLCommandBuffer>> CommandRecordingContext::AcquireCommands() {
|
||||||
if (mCommands == nil) {
|
// A blit encoder can be left open from WriteBuffer, make sure we close it.
|
||||||
return nil;
|
if (mCommands != nullptr) {
|
||||||
|
EndBlit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// A blit encoder can be left open from WriteBuffer, make sure we close it.
|
|
||||||
EndBlit();
|
|
||||||
|
|
||||||
ASSERT(!mInEncoder);
|
ASSERT(!mInEncoder);
|
||||||
id<MTLCommandBuffer> commands = mCommands;
|
return std::move(mCommands);
|
||||||
mCommands = nil;
|
|
||||||
return commands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> CommandRecordingContext::EnsureBlit() {
|
id<MTLBlitCommandEncoder> CommandRecordingContext::EnsureBlit() {
|
||||||
ASSERT(mCommands != nil);
|
ASSERT(mCommands != nullptr);
|
||||||
|
|
||||||
if (mBlit == nil) {
|
if (mBlit == nullptr) {
|
||||||
ASSERT(!mInEncoder);
|
ASSERT(!mInEncoder);
|
||||||
mInEncoder = true;
|
mInEncoder = true;
|
||||||
// The autorelease pool may drain before the encoder is ended. Retain so it stays alive.
|
|
||||||
mBlit = [[mCommands blitCommandEncoder] retain];
|
// The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
|
||||||
|
// draining from under us.
|
||||||
|
mBlit = [*mCommands blitCommandEncoder];
|
||||||
}
|
}
|
||||||
return mBlit;
|
return mBlit.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandRecordingContext::EndBlit() {
|
void CommandRecordingContext::EndBlit() {
|
||||||
ASSERT(mCommands != nil);
|
ASSERT(mCommands != nullptr);
|
||||||
|
|
||||||
if (mBlit != nil) {
|
if (mBlit != nullptr) {
|
||||||
[mBlit endEncoding];
|
[*mBlit endEncoding];
|
||||||
[mBlit release];
|
mBlit = nullptr;
|
||||||
mBlit = nil;
|
|
||||||
mInEncoder = false;
|
mInEncoder = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputeCommandEncoder> CommandRecordingContext::BeginCompute() {
|
id<MTLComputeCommandEncoder> CommandRecordingContext::BeginCompute() {
|
||||||
ASSERT(mCommands != nil);
|
ASSERT(mCommands != nullptr);
|
||||||
ASSERT(mCompute == nil);
|
ASSERT(mCompute == nullptr);
|
||||||
ASSERT(!mInEncoder);
|
ASSERT(!mInEncoder);
|
||||||
|
|
||||||
mInEncoder = true;
|
mInEncoder = true;
|
||||||
// The autorelease pool may drain before the encoder is ended. Retain so it stays alive.
|
// The encoder is created autoreleased. Retain it to avoid the autoreleasepool from draining
|
||||||
mCompute = [[mCommands computeCommandEncoder] retain];
|
// from under us.
|
||||||
return mCompute;
|
mCompute = [*mCommands computeCommandEncoder];
|
||||||
|
return mCompute.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandRecordingContext::EndCompute() {
|
void CommandRecordingContext::EndCompute() {
|
||||||
ASSERT(mCommands != nil);
|
ASSERT(mCommands != nullptr);
|
||||||
ASSERT(mCompute != nil);
|
ASSERT(mCompute != nullptr);
|
||||||
|
|
||||||
[mCompute endEncoding];
|
[*mCompute endEncoding];
|
||||||
[mCompute release];
|
mCompute = nullptr;
|
||||||
mCompute = nil;
|
|
||||||
mInEncoder = false;
|
mInEncoder = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLRenderCommandEncoder> CommandRecordingContext::BeginRender(
|
id<MTLRenderCommandEncoder> CommandRecordingContext::BeginRender(
|
||||||
MTLRenderPassDescriptor* descriptor) {
|
MTLRenderPassDescriptor* descriptor) {
|
||||||
ASSERT(mCommands != nil);
|
ASSERT(mCommands != nullptr);
|
||||||
ASSERT(mRender == nil);
|
ASSERT(mRender == nullptr);
|
||||||
ASSERT(!mInEncoder);
|
ASSERT(!mInEncoder);
|
||||||
|
|
||||||
mInEncoder = true;
|
mInEncoder = true;
|
||||||
// The autorelease pool may drain before the encoder is ended. Retain so it stays alive.
|
// The encoder is created autoreleased. Retain it to avoid the autoreleasepool from draining
|
||||||
mRender = [[mCommands renderCommandEncoderWithDescriptor:descriptor] retain];
|
// from under us.
|
||||||
return mRender;
|
mRender = [*mCommands renderCommandEncoderWithDescriptor:descriptor];
|
||||||
|
return mRender.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandRecordingContext::EndRender() {
|
void CommandRecordingContext::EndRender() {
|
||||||
ASSERT(mCommands != nil);
|
ASSERT(mCommands != nullptr);
|
||||||
ASSERT(mRender != nil);
|
ASSERT(mRender != nullptr);
|
||||||
|
|
||||||
[mRender endEncoding];
|
[*mRender endEncoding];
|
||||||
[mRender release];
|
mRender = nullptr;
|
||||||
mRender = nil;
|
|
||||||
mInEncoder = false;
|
mInEncoder = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/ComputePipeline.h"
|
#include "dawn_native/ComputePipeline.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
@ -33,11 +35,10 @@ namespace dawn_native { namespace metal {
|
||||||
bool RequiresStorageBufferLength() const;
|
bool RequiresStorageBufferLength() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~ComputePipeline() override;
|
|
||||||
using ComputePipelineBase::ComputePipelineBase;
|
using ComputePipelineBase::ComputePipelineBase;
|
||||||
MaybeError Initialize(const ComputePipelineDescriptor* descriptor);
|
MaybeError Initialize(const ComputePipelineDescriptor* descriptor);
|
||||||
|
|
||||||
id<MTLComputePipelineState> mMtlComputePipelineState = nil;
|
NSPRef<id<MTLComputePipelineState>> mMtlComputePipelineState;
|
||||||
MTLSize mLocalWorkgroupSize;
|
MTLSize mLocalWorkgroupSize;
|
||||||
bool mRequiresStorageBufferLength;
|
bool mRequiresStorageBufferLength;
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,10 +37,11 @@ namespace dawn_native { namespace metal {
|
||||||
DAWN_TRY(computeModule->CreateFunction(computeEntryPoint, SingleShaderStage::Compute,
|
DAWN_TRY(computeModule->CreateFunction(computeEntryPoint, SingleShaderStage::Compute,
|
||||||
ToBackend(GetLayout()), &computeData));
|
ToBackend(GetLayout()), &computeData));
|
||||||
|
|
||||||
NSError* error = nil;
|
NSError* error = nullptr;
|
||||||
mMtlComputePipelineState =
|
mMtlComputePipelineState.Acquire([mtlDevice
|
||||||
[mtlDevice newComputePipelineStateWithFunction:computeData.function error:&error];
|
newComputePipelineStateWithFunction:computeData.function.Get()
|
||||||
if (error != nil) {
|
error:&error]);
|
||||||
|
if (error != nullptr) {
|
||||||
NSLog(@" error => %@", error);
|
NSLog(@" error => %@", error);
|
||||||
return DAWN_INTERNAL_ERROR("Error creating pipeline state");
|
return DAWN_INTERNAL_ERROR("Error creating pipeline state");
|
||||||
}
|
}
|
||||||
|
@ -53,12 +54,8 @@ namespace dawn_native { namespace metal {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipeline::~ComputePipeline() {
|
|
||||||
[mMtlComputePipelineState release];
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComputePipeline::Encode(id<MTLComputeCommandEncoder> encoder) {
|
void ComputePipeline::Encode(id<MTLComputeCommandEncoder> encoder) {
|
||||||
[encoder setComputePipelineState:mMtlComputePipelineState];
|
[encoder setComputePipelineState:mMtlComputePipelineState.Get()];
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLSize ComputePipeline::GetLocalWorkGroupSize() const {
|
MTLSize ComputePipeline::GetLocalWorkGroupSize() const {
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace dawn_native { namespace metal {
|
||||||
class Device : public DeviceBase {
|
class Device : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
static ResultOrError<Device*> Create(AdapterBase* adapter,
|
static ResultOrError<Device*> Create(AdapterBase* adapter,
|
||||||
id<MTLDevice> mtlDevice,
|
NSPRef<id<MTLDevice>> mtlDevice,
|
||||||
const DeviceDescriptor* descriptor);
|
const DeviceDescriptor* descriptor);
|
||||||
~Device() override;
|
~Device() override;
|
||||||
|
|
||||||
|
@ -72,7 +72,9 @@ namespace dawn_native { namespace metal {
|
||||||
uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
|
uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Device(AdapterBase* adapter, id<MTLDevice> mtlDevice, const DeviceDescriptor* descriptor);
|
Device(AdapterBase* adapter,
|
||||||
|
NSPRef<id<MTLDevice>> mtlDevice,
|
||||||
|
const DeviceDescriptor* descriptor);
|
||||||
|
|
||||||
ResultOrError<BindGroupBase*> CreateBindGroupImpl(
|
ResultOrError<BindGroupBase*> CreateBindGroupImpl(
|
||||||
const BindGroupDescriptor* descriptor) override;
|
const BindGroupDescriptor* descriptor) override;
|
||||||
|
@ -108,8 +110,8 @@ namespace dawn_native { namespace metal {
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
id<MTLDevice> mMtlDevice = nil;
|
NSPRef<id<MTLDevice>> mMtlDevice;
|
||||||
id<MTLCommandQueue> mCommandQueue = nil;
|
NSPRef<id<MTLCommandQueue>> mCommandQueue;
|
||||||
|
|
||||||
CommandRecordingContext mCommandContext;
|
CommandRecordingContext mCommandContext;
|
||||||
|
|
||||||
|
@ -120,7 +122,7 @@ namespace dawn_native { namespace metal {
|
||||||
// mLastSubmittedCommands will be accessed in a Metal schedule handler that can be fired on
|
// mLastSubmittedCommands will be accessed in a Metal schedule handler that can be fired on
|
||||||
// a different thread so we guard access to it with a mutex.
|
// a different thread so we guard access to it with a mutex.
|
||||||
std::mutex mLastSubmittedCommandsMutex;
|
std::mutex mLastSubmittedCommandsMutex;
|
||||||
id<MTLCommandBuffer> mLastSubmittedCommands = nil;
|
NSPRef<id<MTLCommandBuffer>> mLastSubmittedCommands;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -44,18 +44,17 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ResultOrError<Device*> Device::Create(AdapterBase* adapter,
|
ResultOrError<Device*> Device::Create(AdapterBase* adapter,
|
||||||
id<MTLDevice> mtlDevice,
|
NSPRef<id<MTLDevice>> mtlDevice,
|
||||||
const DeviceDescriptor* descriptor) {
|
const DeviceDescriptor* descriptor) {
|
||||||
Ref<Device> device = AcquireRef(new Device(adapter, mtlDevice, descriptor));
|
Ref<Device> device = AcquireRef(new Device(adapter, std::move(mtlDevice), descriptor));
|
||||||
DAWN_TRY(device->Initialize());
|
DAWN_TRY(device->Initialize());
|
||||||
return device.Detach();
|
return device.Detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(AdapterBase* adapter,
|
Device::Device(AdapterBase* adapter,
|
||||||
id<MTLDevice> mtlDevice,
|
NSPRef<id<MTLDevice>> mtlDevice,
|
||||||
const DeviceDescriptor* descriptor)
|
const DeviceDescriptor* descriptor)
|
||||||
: DeviceBase(adapter, descriptor), mMtlDevice([mtlDevice retain]), mCompletedSerial(0) {
|
: DeviceBase(adapter, descriptor), mMtlDevice(std::move(mtlDevice)), mCompletedSerial(0) {
|
||||||
[mMtlDevice retain];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
@ -69,7 +68,7 @@ namespace dawn_native { namespace metal {
|
||||||
ForceSetToggle(Toggle::MetalEnableVertexPulling, false);
|
ForceSetToggle(Toggle::MetalEnableVertexPulling, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCommandQueue = [mMtlDevice newCommandQueue];
|
mCommandQueue.Acquire([*mMtlDevice newCommandQueue]);
|
||||||
|
|
||||||
return DeviceBase::Initialize(new Queue(this));
|
return DeviceBase::Initialize(new Queue(this));
|
||||||
}
|
}
|
||||||
|
@ -80,18 +79,18 @@ namespace dawn_native { namespace metal {
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
if (@available(macOS 10.12, *)) {
|
if (@available(macOS 10.12, *)) {
|
||||||
haveStoreAndMSAAResolve =
|
haveStoreAndMSAAResolve =
|
||||||
[mMtlDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
|
[*mMtlDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
|
||||||
}
|
}
|
||||||
#elif defined(DAWN_PLATFORM_IOS)
|
#elif defined(DAWN_PLATFORM_IOS)
|
||||||
haveStoreAndMSAAResolve =
|
haveStoreAndMSAAResolve =
|
||||||
[mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
|
[*mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
|
||||||
#endif
|
#endif
|
||||||
// On tvOS, we would need MTLFeatureSet_tvOS_GPUFamily2_v1.
|
// On tvOS, we would need MTLFeatureSet_tvOS_GPUFamily2_v1.
|
||||||
SetToggle(Toggle::EmulateStoreAndMSAAResolve, !haveStoreAndMSAAResolve);
|
SetToggle(Toggle::EmulateStoreAndMSAAResolve, !haveStoreAndMSAAResolve);
|
||||||
|
|
||||||
bool haveSamplerCompare = true;
|
bool haveSamplerCompare = true;
|
||||||
#if defined(DAWN_PLATFORM_IOS)
|
#if defined(DAWN_PLATFORM_IOS)
|
||||||
haveSamplerCompare = [mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
|
haveSamplerCompare = [*mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
|
||||||
#endif
|
#endif
|
||||||
// TODO(crbug.com/dawn/342): Investigate emulation -- possibly expensive.
|
// TODO(crbug.com/dawn/342): Investigate emulation -- possibly expensive.
|
||||||
SetToggle(Toggle::MetalDisableSamplerCompare, !haveSamplerCompare);
|
SetToggle(Toggle::MetalDisableSamplerCompare, !haveSamplerCompare);
|
||||||
|
@ -99,7 +98,7 @@ namespace dawn_native { namespace metal {
|
||||||
bool haveBaseVertexBaseInstance = true;
|
bool haveBaseVertexBaseInstance = true;
|
||||||
#if defined(DAWN_PLATFORM_IOS)
|
#if defined(DAWN_PLATFORM_IOS)
|
||||||
haveBaseVertexBaseInstance =
|
haveBaseVertexBaseInstance =
|
||||||
[mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
|
[*mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1];
|
||||||
#endif
|
#endif
|
||||||
// TODO(crbug.com/dawn/343): Investigate emulation.
|
// TODO(crbug.com/dawn/343): Investigate emulation.
|
||||||
SetToggle(Toggle::DisableBaseVertex, !haveBaseVertexBaseInstance);
|
SetToggle(Toggle::DisableBaseVertex, !haveBaseVertexBaseInstance);
|
||||||
|
@ -187,7 +186,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
if (mCommandContext.GetCommands() != nil) {
|
if (mCommandContext.GetCommands() != nullptr) {
|
||||||
SubmitPendingCommandBuffer();
|
SubmitPendingCommandBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,33 +194,33 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLDevice> Device::GetMTLDevice() {
|
id<MTLDevice> Device::GetMTLDevice() {
|
||||||
return mMtlDevice;
|
return mMtlDevice.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLCommandQueue> Device::GetMTLQueue() {
|
id<MTLCommandQueue> Device::GetMTLQueue() {
|
||||||
return mCommandQueue;
|
return mCommandQueue.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandRecordingContext* Device::GetPendingCommandContext() {
|
CommandRecordingContext* Device::GetPendingCommandContext() {
|
||||||
if (mCommandContext.GetCommands() == nil) {
|
if (mCommandContext.GetCommands() == nullptr) {
|
||||||
TRACE_EVENT0(GetPlatform(), General, "[MTLCommandQueue commandBuffer]");
|
TRACE_EVENT0(GetPlatform(), General, "[MTLCommandQueue commandBuffer]");
|
||||||
// The MTLCommandBuffer will be autoreleased by default.
|
// The MTLCommandBuffer will be autoreleased by default.
|
||||||
// The autorelease pool may drain before the command buffer is submitted. Retain so it
|
// The autorelease pool may drain before the command buffer is submitted. Retain so it
|
||||||
// stays alive.
|
// stays alive.
|
||||||
mCommandContext = CommandRecordingContext([[mCommandQueue commandBuffer] retain]);
|
mCommandContext = CommandRecordingContext([*mCommandQueue commandBuffer]);
|
||||||
}
|
}
|
||||||
return &mCommandContext;
|
return &mCommandContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::SubmitPendingCommandBuffer() {
|
void Device::SubmitPendingCommandBuffer() {
|
||||||
if (mCommandContext.GetCommands() == nil) {
|
if (mCommandContext.GetCommands() == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IncrementLastSubmittedCommandSerial();
|
IncrementLastSubmittedCommandSerial();
|
||||||
|
|
||||||
// Acquire the pending command buffer, which is retained. It must be released later.
|
// Acquire the pending command buffer, which is retained. It must be released later.
|
||||||
id<MTLCommandBuffer> pendingCommands = mCommandContext.AcquireCommands();
|
NSPRef<id<MTLCommandBuffer>> pendingCommands = mCommandContext.AcquireCommands();
|
||||||
|
|
||||||
// Replace mLastSubmittedCommands with the mutex held so we avoid races between the
|
// Replace mLastSubmittedCommands with the mutex held so we avoid races between the
|
||||||
// schedule handler and this code.
|
// schedule handler and this code.
|
||||||
|
@ -230,12 +229,15 @@ namespace dawn_native { namespace metal {
|
||||||
mLastSubmittedCommands = pendingCommands;
|
mLastSubmittedCommands = pendingCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pendingCommands addScheduledHandler:^(id<MTLCommandBuffer>) {
|
// Make a local copy of the pointer to the commands because it's not clear how ObjC blocks
|
||||||
|
// handle types with copy / move constructors being referenced in the block..
|
||||||
|
id<MTLCommandBuffer> pendingCommandsPointer = pendingCommands.Get();
|
||||||
|
[*pendingCommands addScheduledHandler:^(id<MTLCommandBuffer>) {
|
||||||
// This is DRF because we hold the mutex for mLastSubmittedCommands and pendingCommands
|
// This is DRF because we hold the mutex for mLastSubmittedCommands and pendingCommands
|
||||||
// is a local value (and not the member itself).
|
// is a local value (and not the member itself).
|
||||||
std::lock_guard<std::mutex> lock(mLastSubmittedCommandsMutex);
|
std::lock_guard<std::mutex> lock(mLastSubmittedCommandsMutex);
|
||||||
if (this->mLastSubmittedCommands == pendingCommands) {
|
if (this->mLastSubmittedCommands.Get() == pendingCommandsPointer) {
|
||||||
this->mLastSubmittedCommands = nil;
|
this->mLastSubmittedCommands = nullptr;
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -243,7 +245,7 @@ namespace dawn_native { namespace metal {
|
||||||
// mLastSubmittedSerial so it is captured by value.
|
// mLastSubmittedSerial so it is captured by value.
|
||||||
ExecutionSerial pendingSerial = GetLastSubmittedCommandSerial();
|
ExecutionSerial pendingSerial = GetLastSubmittedCommandSerial();
|
||||||
// this ObjC block runs on a different thread
|
// this ObjC block runs on a different thread
|
||||||
[pendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
|
[*pendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
|
||||||
TRACE_EVENT_ASYNC_END0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
TRACE_EVENT_ASYNC_END0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
||||||
uint64_t(pendingSerial));
|
uint64_t(pendingSerial));
|
||||||
ASSERT(uint64_t(pendingSerial) > mCompletedSerial.load());
|
ASSERT(uint64_t(pendingSerial) > mCompletedSerial.load());
|
||||||
|
@ -252,8 +254,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
TRACE_EVENT_ASYNC_BEGIN0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
TRACE_EVENT_ASYNC_BEGIN0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
||||||
uint64_t(pendingSerial));
|
uint64_t(pendingSerial));
|
||||||
[pendingCommands commit];
|
[*pendingCommands commit];
|
||||||
[pendingCommands release];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
|
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
|
||||||
|
@ -356,11 +357,12 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
void Device::WaitForCommandsToBeScheduled() {
|
void Device::WaitForCommandsToBeScheduled() {
|
||||||
SubmitPendingCommandBuffer();
|
SubmitPendingCommandBuffer();
|
||||||
[mLastSubmittedCommands waitUntilScheduled];
|
[*mLastSubmittedCommands waitUntilScheduled];
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::WaitForIdleForDestruction() {
|
MaybeError Device::WaitForIdleForDestruction() {
|
||||||
[mCommandContext.AcquireCommands() release];
|
// Forget all pending commands.
|
||||||
|
mCommandContext.AcquireCommands();
|
||||||
CheckPassedSerials();
|
CheckPassedSerials();
|
||||||
|
|
||||||
// Wait for all commands to be finished so we can free resources
|
// Wait for all commands to be finished so we can free resources
|
||||||
|
@ -375,13 +377,11 @@ namespace dawn_native { namespace metal {
|
||||||
void Device::ShutDownImpl() {
|
void Device::ShutDownImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
[mCommandContext.AcquireCommands() release];
|
// Forget all pending commands.
|
||||||
|
mCommandContext.AcquireCommands();
|
||||||
|
|
||||||
[mCommandQueue release];
|
mCommandQueue = nullptr;
|
||||||
mCommandQueue = nil;
|
mMtlDevice = nullptr;
|
||||||
|
|
||||||
[mMtlDevice release];
|
|
||||||
mMtlDevice = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Device::GetOptimalBytesPerRowAlignment() const {
|
uint32_t Device::GetOptimalBytesPerRowAlignment() const {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/QuerySet.h"
|
#include "dawn_native/QuerySet.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
@ -40,9 +42,11 @@ namespace dawn_native { namespace metal {
|
||||||
// Dawn API
|
// Dawn API
|
||||||
void DestroyImpl() override;
|
void DestroyImpl() override;
|
||||||
|
|
||||||
id<MTLBuffer> mVisibilityBuffer = nil;
|
NSPRef<id<MTLBuffer>> mVisibilityBuffer;
|
||||||
|
// Note that mCounterSampleBuffer cannot be an NSRef because the API_AVAILABLE macros don't
|
||||||
|
// propagate nicely through templates.
|
||||||
id<MTLCounterSampleBuffer> mCounterSampleBuffer API_AVAILABLE(macos(10.15),
|
id<MTLCounterSampleBuffer> mCounterSampleBuffer API_AVAILABLE(macos(10.15),
|
||||||
ios(14.0)) = nil;
|
ios(14.0)) = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -26,7 +26,9 @@ namespace dawn_native { namespace metal {
|
||||||
Device* device,
|
Device* device,
|
||||||
MTLCommonCounterSet counterSet,
|
MTLCommonCounterSet counterSet,
|
||||||
uint32_t count) API_AVAILABLE(macos(10.15), ios(14.0)) {
|
uint32_t count) API_AVAILABLE(macos(10.15), ios(14.0)) {
|
||||||
MTLCounterSampleBufferDescriptor* descriptor = [MTLCounterSampleBufferDescriptor new];
|
NSRef<MTLCounterSampleBufferDescriptor> descriptorRef =
|
||||||
|
AcquireNSRef([MTLCounterSampleBufferDescriptor new]);
|
||||||
|
MTLCounterSampleBufferDescriptor* descriptor = descriptorRef.Get();
|
||||||
|
|
||||||
// To determine which counters are available from a device, we need to iterate through
|
// To determine which counters are available from a device, we need to iterate through
|
||||||
// the counterSets property of a MTLDevice. Then configure which counters will be
|
// the counterSets property of a MTLDevice. Then configure which counters will be
|
||||||
|
@ -38,18 +40,19 @@ namespace dawn_native { namespace metal {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(descriptor.counterSet != nil);
|
ASSERT(descriptor.counterSet != nullptr);
|
||||||
|
|
||||||
descriptor.sampleCount = count;
|
descriptor.sampleCount = count;
|
||||||
descriptor.storageMode = MTLStorageModePrivate;
|
descriptor.storageMode = MTLStorageModePrivate;
|
||||||
if (device->IsToggleEnabled(Toggle::MetalUseSharedModeForCounterSampleBuffer)) {
|
if (device->IsToggleEnabled(Toggle::MetalUseSharedModeForCounterSampleBuffer)) {
|
||||||
descriptor.storageMode = MTLStorageModeShared;
|
descriptor.storageMode = MTLStorageModeShared;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSError* error = nil;
|
NSError* error = nullptr;
|
||||||
id<MTLCounterSampleBuffer> counterSampleBuffer =
|
id<MTLCounterSampleBuffer> counterSampleBuffer =
|
||||||
[device->GetMTLDevice() newCounterSampleBufferWithDescriptor:descriptor
|
[device->GetMTLDevice() newCounterSampleBufferWithDescriptor:descriptor
|
||||||
error:&error];
|
error:&error];
|
||||||
if (error != nil) {
|
if (error != nullptr) {
|
||||||
const char* errorString = [error.localizedDescription UTF8String];
|
const char* errorString = [error.localizedDescription UTF8String];
|
||||||
return DAWN_INTERNAL_ERROR(std::string("Error creating query set: ") + errorString);
|
return DAWN_INTERNAL_ERROR(std::string("Error creating query set: ") + errorString);
|
||||||
}
|
}
|
||||||
|
@ -73,9 +76,9 @@ namespace dawn_native { namespace metal {
|
||||||
case wgpu::QueryType::Occlusion: {
|
case wgpu::QueryType::Occlusion: {
|
||||||
// Create buffer for writing 64-bit results.
|
// Create buffer for writing 64-bit results.
|
||||||
NSUInteger bufferSize = static_cast<NSUInteger>(GetQueryCount() * sizeof(uint64_t));
|
NSUInteger bufferSize = static_cast<NSUInteger>(GetQueryCount() * sizeof(uint64_t));
|
||||||
mVisibilityBuffer =
|
mVisibilityBuffer = AcquireNSPRef([device->GetMTLDevice()
|
||||||
[device->GetMTLDevice() newBufferWithLength:bufferSize
|
newBufferWithLength:bufferSize
|
||||||
options:MTLResourceStorageModePrivate];
|
options:MTLResourceStorageModePrivate]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case wgpu::QueryType::PipelineStatistics:
|
case wgpu::QueryType::PipelineStatistics:
|
||||||
|
@ -105,7 +108,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLBuffer> QuerySet::GetVisibilityBuffer() const {
|
id<MTLBuffer> QuerySet::GetVisibilityBuffer() const {
|
||||||
return mVisibilityBuffer;
|
return mVisibilityBuffer.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLCounterSampleBuffer> QuerySet::GetCounterSampleBuffer() const
|
id<MTLCounterSampleBuffer> QuerySet::GetCounterSampleBuffer() const
|
||||||
|
@ -118,16 +121,13 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuerySet::DestroyImpl() {
|
void QuerySet::DestroyImpl() {
|
||||||
if (mVisibilityBuffer != nil) {
|
mVisibilityBuffer = nullptr;
|
||||||
[mVisibilityBuffer release];
|
|
||||||
mVisibilityBuffer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// mCounterSampleBuffer isn't an NSRef because API_AVAILABLE doesn't work will with
|
||||||
|
// templates.
|
||||||
if (@available(macOS 10.15, iOS 14.0, *)) {
|
if (@available(macOS 10.15, iOS 14.0, *)) {
|
||||||
if (mCounterSampleBuffer != nil) {
|
[mCounterSampleBuffer release];
|
||||||
[mCounterSampleBuffer release];
|
mCounterSampleBuffer = nullptr;
|
||||||
mCounterSampleBuffer = nil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
@ -43,7 +45,6 @@ namespace dawn_native { namespace metal {
|
||||||
wgpu::ShaderStage GetStagesRequiringStorageBufferLength() const;
|
wgpu::ShaderStage GetStagesRequiringStorageBufferLength() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~RenderPipeline() override;
|
|
||||||
using RenderPipelineBase::RenderPipelineBase;
|
using RenderPipelineBase::RenderPipelineBase;
|
||||||
MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
|
MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
|
||||||
|
|
||||||
|
@ -52,8 +53,8 @@ namespace dawn_native { namespace metal {
|
||||||
MTLPrimitiveType mMtlPrimitiveTopology;
|
MTLPrimitiveType mMtlPrimitiveTopology;
|
||||||
MTLWinding mMtlFrontFace;
|
MTLWinding mMtlFrontFace;
|
||||||
MTLCullMode mMtlCullMode;
|
MTLCullMode mMtlCullMode;
|
||||||
id<MTLRenderPipelineState> mMtlRenderPipelineState = nil;
|
NSPRef<id<MTLRenderPipelineState>> mMtlRenderPipelineState;
|
||||||
id<MTLDepthStencilState> mMtlDepthStencilState = nil;
|
NSPRef<id<MTLDepthStencilState>> mMtlDepthStencilState;
|
||||||
ityp::array<VertexBufferSlot, uint32_t, kMaxVertexBuffers> mMtlVertexBufferIndices;
|
ityp::array<VertexBufferSlot, uint32_t, kMaxVertexBuffers> mMtlVertexBufferIndices;
|
||||||
|
|
||||||
wgpu::ShaderStage mStagesRequiringStorageBufferLength = wgpu::ShaderStage::None;
|
wgpu::ShaderStage mStagesRequiringStorageBufferLength = wgpu::ShaderStage::None;
|
||||||
|
|
|
@ -236,17 +236,23 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLDepthStencilDescriptor* MakeDepthStencilDesc(
|
NSRef<MTLDepthStencilDescriptor> MakeDepthStencilDesc(
|
||||||
const DepthStencilStateDescriptor* descriptor) {
|
const DepthStencilStateDescriptor* descriptor) {
|
||||||
MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = [MTLDepthStencilDescriptor new];
|
NSRef<MTLDepthStencilDescriptor> mtlDepthStencilDescRef =
|
||||||
|
AcquireNSRef([MTLDepthStencilDescriptor new]);
|
||||||
|
MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = mtlDepthStencilDescRef.Get();
|
||||||
|
|
||||||
mtlDepthStencilDescriptor.depthCompareFunction =
|
mtlDepthStencilDescriptor.depthCompareFunction =
|
||||||
ToMetalCompareFunction(descriptor->depthCompare);
|
ToMetalCompareFunction(descriptor->depthCompare);
|
||||||
mtlDepthStencilDescriptor.depthWriteEnabled = descriptor->depthWriteEnabled;
|
mtlDepthStencilDescriptor.depthWriteEnabled = descriptor->depthWriteEnabled;
|
||||||
|
|
||||||
if (StencilTestEnabled(descriptor)) {
|
if (StencilTestEnabled(descriptor)) {
|
||||||
MTLStencilDescriptor* backFaceStencil = [MTLStencilDescriptor new];
|
NSRef<MTLStencilDescriptor> backFaceStencilRef =
|
||||||
MTLStencilDescriptor* frontFaceStencil = [MTLStencilDescriptor new];
|
AcquireNSRef([MTLStencilDescriptor new]);
|
||||||
|
MTLStencilDescriptor* backFaceStencil = backFaceStencilRef.Get();
|
||||||
|
NSRef<MTLStencilDescriptor> frontFaceStencilRef =
|
||||||
|
AcquireNSRef([MTLStencilDescriptor new]);
|
||||||
|
MTLStencilDescriptor* frontFaceStencil = frontFaceStencilRef.Get();
|
||||||
|
|
||||||
backFaceStencil.stencilCompareFunction =
|
backFaceStencil.stencilCompareFunction =
|
||||||
ToMetalCompareFunction(descriptor->stencilBack.compare);
|
ToMetalCompareFunction(descriptor->stencilBack.compare);
|
||||||
|
@ -272,12 +278,9 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
mtlDepthStencilDescriptor.backFaceStencil = backFaceStencil;
|
mtlDepthStencilDescriptor.backFaceStencil = backFaceStencil;
|
||||||
mtlDepthStencilDescriptor.frontFaceStencil = frontFaceStencil;
|
mtlDepthStencilDescriptor.frontFaceStencil = frontFaceStencil;
|
||||||
|
|
||||||
[backFaceStencil release];
|
|
||||||
[frontFaceStencil release];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mtlDepthStencilDescriptor;
|
return mtlDepthStencilDescRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLWinding MTLFrontFace(wgpu::FrontFace face) {
|
MTLWinding MTLFrontFace(wgpu::FrontFace face) {
|
||||||
|
@ -317,20 +320,19 @@ namespace dawn_native { namespace metal {
|
||||||
mMtlCullMode = ToMTLCullMode(GetCullMode());
|
mMtlCullMode = ToMTLCullMode(GetCullMode());
|
||||||
auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
|
auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
|
||||||
|
|
||||||
MTLRenderPipelineDescriptor* descriptorMTL = [MTLRenderPipelineDescriptor new];
|
NSRef<MTLRenderPipelineDescriptor> descriptorMTLRef =
|
||||||
|
AcquireNSRef([MTLRenderPipelineDescriptor new]);
|
||||||
|
MTLRenderPipelineDescriptor* descriptorMTL = descriptorMTLRef.Get();
|
||||||
|
|
||||||
// TODO: MakeVertexDesc should be const in the future, so we don't need to call it here when
|
// TODO: MakeVertexDesc should be const in the future, so we don't need to call it here when
|
||||||
// vertex pulling is enabled
|
// vertex pulling is enabled
|
||||||
MTLVertexDescriptor* vertexDesc = MakeVertexDesc();
|
NSRef<MTLVertexDescriptor> vertexDesc = MakeVertexDesc();
|
||||||
descriptorMTL.vertexDescriptor = vertexDesc;
|
|
||||||
[vertexDesc release];
|
|
||||||
|
|
||||||
|
// Calling MakeVertexDesc first is important since it sets indices for packed bindings
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling)) {
|
if (GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling)) {
|
||||||
// Calling MakeVertexDesc first is important since it sets indices for packed bindings
|
vertexDesc = AcquireNSRef([MTLVertexDescriptor new]);
|
||||||
MTLVertexDescriptor* emptyVertexDesc = [MTLVertexDescriptor new];
|
|
||||||
descriptorMTL.vertexDescriptor = emptyVertexDesc;
|
|
||||||
[emptyVertexDesc release];
|
|
||||||
}
|
}
|
||||||
|
descriptorMTL.vertexDescriptor = vertexDesc.Get();
|
||||||
|
|
||||||
ShaderModule* vertexModule = ToBackend(descriptor->vertexStage.module);
|
ShaderModule* vertexModule = ToBackend(descriptor->vertexStage.module);
|
||||||
const char* vertexEntryPoint = descriptor->vertexStage.entryPoint;
|
const char* vertexEntryPoint = descriptor->vertexStage.entryPoint;
|
||||||
|
@ -339,7 +341,7 @@ namespace dawn_native { namespace metal {
|
||||||
ToBackend(GetLayout()), &vertexData, 0xFFFFFFFF,
|
ToBackend(GetLayout()), &vertexData, 0xFFFFFFFF,
|
||||||
this));
|
this));
|
||||||
|
|
||||||
descriptorMTL.vertexFunction = vertexData.function;
|
descriptorMTL.vertexFunction = vertexData.function.Get();
|
||||||
if (vertexData.needsStorageBufferLength) {
|
if (vertexData.needsStorageBufferLength) {
|
||||||
mStagesRequiringStorageBufferLength |= wgpu::ShaderStage::Vertex;
|
mStagesRequiringStorageBufferLength |= wgpu::ShaderStage::Vertex;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +353,7 @@ namespace dawn_native { namespace metal {
|
||||||
ToBackend(GetLayout()), &fragmentData,
|
ToBackend(GetLayout()), &fragmentData,
|
||||||
descriptor->sampleMask));
|
descriptor->sampleMask));
|
||||||
|
|
||||||
descriptorMTL.fragmentFunction = fragmentData.function;
|
descriptorMTL.fragmentFunction = fragmentData.function.Get();
|
||||||
if (fragmentData.needsStorageBufferLength) {
|
if (fragmentData.needsStorageBufferLength) {
|
||||||
mStagesRequiringStorageBufferLength |= wgpu::ShaderStage::Fragment;
|
mStagesRequiringStorageBufferLength |= wgpu::ShaderStage::Fragment;
|
||||||
}
|
}
|
||||||
|
@ -384,11 +386,11 @@ namespace dawn_native { namespace metal {
|
||||||
descriptorMTL.alphaToCoverageEnabled = descriptor->alphaToCoverageEnabled;
|
descriptorMTL.alphaToCoverageEnabled = descriptor->alphaToCoverageEnabled;
|
||||||
|
|
||||||
{
|
{
|
||||||
NSError* error = nil;
|
NSError* error = nullptr;
|
||||||
mMtlRenderPipelineState = [mtlDevice newRenderPipelineStateWithDescriptor:descriptorMTL
|
mMtlRenderPipelineState =
|
||||||
error:&error];
|
AcquireNSPRef([mtlDevice newRenderPipelineStateWithDescriptor:descriptorMTL
|
||||||
[descriptorMTL release];
|
error:&error]);
|
||||||
if (error != nil) {
|
if (error != nullptr) {
|
||||||
NSLog(@" error => %@", error);
|
NSLog(@" error => %@", error);
|
||||||
return DAWN_INTERNAL_ERROR("Error creating rendering pipeline state");
|
return DAWN_INTERNAL_ERROR("Error creating rendering pipeline state");
|
||||||
}
|
}
|
||||||
|
@ -397,19 +399,14 @@ namespace dawn_native { namespace metal {
|
||||||
// Create depth stencil state and cache it, fetch the cached depth stencil state when we
|
// Create depth stencil state and cache it, fetch the cached depth stencil state when we
|
||||||
// call setDepthStencilState() for a given render pipeline in CommandEncoder, in order to
|
// call setDepthStencilState() for a given render pipeline in CommandEncoder, in order to
|
||||||
// improve performance.
|
// improve performance.
|
||||||
MTLDepthStencilDescriptor* depthStencilDesc =
|
NSRef<MTLDepthStencilDescriptor> depthStencilDesc =
|
||||||
MakeDepthStencilDesc(GetDepthStencilStateDescriptor());
|
MakeDepthStencilDesc(GetDepthStencilStateDescriptor());
|
||||||
mMtlDepthStencilState = [mtlDevice newDepthStencilStateWithDescriptor:depthStencilDesc];
|
mMtlDepthStencilState =
|
||||||
[depthStencilDesc release];
|
AcquireNSPRef([mtlDevice newDepthStencilStateWithDescriptor:depthStencilDesc.Get()]);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipeline::~RenderPipeline() {
|
|
||||||
[mMtlRenderPipelineState release];
|
|
||||||
[mMtlDepthStencilState release];
|
|
||||||
}
|
|
||||||
|
|
||||||
MTLPrimitiveType RenderPipeline::GetMTLPrimitiveTopology() const {
|
MTLPrimitiveType RenderPipeline::GetMTLPrimitiveTopology() const {
|
||||||
return mMtlPrimitiveTopology;
|
return mMtlPrimitiveTopology;
|
||||||
}
|
}
|
||||||
|
@ -423,11 +420,11 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipeline::Encode(id<MTLRenderCommandEncoder> encoder) {
|
void RenderPipeline::Encode(id<MTLRenderCommandEncoder> encoder) {
|
||||||
[encoder setRenderPipelineState:mMtlRenderPipelineState];
|
[encoder setRenderPipelineState:mMtlRenderPipelineState.Get()];
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLDepthStencilState> RenderPipeline::GetMTLDepthStencilState() {
|
id<MTLDepthStencilState> RenderPipeline::GetMTLDepthStencilState() {
|
||||||
return mMtlDepthStencilState;
|
return mMtlDepthStencilState.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderPipeline::GetMtlVertexBufferIndex(VertexBufferSlot slot) const {
|
uint32_t RenderPipeline::GetMtlVertexBufferIndex(VertexBufferSlot slot) const {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/Sampler.h"
|
#include "dawn_native/Sampler.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
@ -31,9 +33,8 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Sampler(Device* device, const SamplerDescriptor* descriptor);
|
Sampler(Device* device, const SamplerDescriptor* descriptor);
|
||||||
~Sampler() override;
|
|
||||||
|
|
||||||
id<MTLSamplerState> mMtlSamplerState = nil;
|
NSPRef<id<MTLSamplerState>> mMtlSamplerState;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -62,7 +62,8 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor)
|
Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor)
|
||||||
: SamplerBase(device, descriptor) {
|
: SamplerBase(device, descriptor) {
|
||||||
MTLSamplerDescriptor* mtlDesc = [MTLSamplerDescriptor new];
|
NSRef<MTLSamplerDescriptor> mtlDescRef = AcquireNSRef([MTLSamplerDescriptor new]);
|
||||||
|
MTLSamplerDescriptor* mtlDesc = mtlDescRef.Get();
|
||||||
|
|
||||||
mtlDesc.minFilter = FilterModeToMinMagFilter(descriptor->minFilter);
|
mtlDesc.minFilter = FilterModeToMinMagFilter(descriptor->minFilter);
|
||||||
mtlDesc.magFilter = FilterModeToMinMagFilter(descriptor->magFilter);
|
mtlDesc.magFilter = FilterModeToMinMagFilter(descriptor->magFilter);
|
||||||
|
@ -83,17 +84,12 @@ namespace dawn_native { namespace metal {
|
||||||
// Metal debug device errors.
|
// Metal debug device errors.
|
||||||
}
|
}
|
||||||
|
|
||||||
mMtlSamplerState = [device->GetMTLDevice() newSamplerStateWithDescriptor:mtlDesc];
|
mMtlSamplerState =
|
||||||
|
AcquireNSPRef([device->GetMTLDevice() newSamplerStateWithDescriptor:mtlDesc]);
|
||||||
[mtlDesc release];
|
|
||||||
}
|
|
||||||
|
|
||||||
Sampler::~Sampler() {
|
|
||||||
[mMtlSamplerState release];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLSamplerState> Sampler::GetMTLSamplerState() {
|
id<MTLSamplerState> Sampler::GetMTLSamplerState() {
|
||||||
return mMtlSamplerState;
|
return mMtlSamplerState.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -17,10 +17,11 @@
|
||||||
|
|
||||||
#include "dawn_native/ShaderModule.h"
|
#include "dawn_native/ShaderModule.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#include "dawn_native/Error.h"
|
#include "dawn_native/Error.h"
|
||||||
|
|
||||||
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace spirv_cross {
|
namespace spirv_cross {
|
||||||
class CompilerMSL;
|
class CompilerMSL;
|
||||||
}
|
}
|
||||||
|
@ -37,11 +38,8 @@ namespace dawn_native { namespace metal {
|
||||||
const ShaderModuleDescriptor* descriptor);
|
const ShaderModuleDescriptor* descriptor);
|
||||||
|
|
||||||
struct MetalFunctionData {
|
struct MetalFunctionData {
|
||||||
id<MTLFunction> function = nil;
|
NSPRef<id<MTLFunction>> function;
|
||||||
bool needsStorageBufferLength;
|
bool needsStorageBufferLength;
|
||||||
~MetalFunctionData() {
|
|
||||||
[function release];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
MaybeError CreateFunction(const char* entryPointName,
|
MaybeError CreateFunction(const char* entryPointName,
|
||||||
SingleShaderStage stage,
|
SingleShaderStage stage,
|
||||||
|
|
|
@ -142,7 +142,6 @@ namespace dawn_native { namespace metal {
|
||||||
{
|
{
|
||||||
// SPIRV-Cross also supports re-ordering attributes but it seems to do the correct thing
|
// SPIRV-Cross also supports re-ordering attributes but it seems to do the correct thing
|
||||||
// by default.
|
// by default.
|
||||||
NSString* mslSource;
|
|
||||||
std::string msl = compiler.compile();
|
std::string msl = compiler.compile();
|
||||||
|
|
||||||
// Some entry point names are forbidden in MSL so SPIRV-Cross modifies them. Query the
|
// Some entry point names are forbidden in MSL so SPIRV-Cross modifies them. Query the
|
||||||
|
@ -159,14 +158,17 @@ namespace dawn_native { namespace metal {
|
||||||
#pragma clang diagnostic ignored "-Wall"
|
#pragma clang diagnostic ignored "-Wall"
|
||||||
#endif
|
#endif
|
||||||
)" + msl;
|
)" + msl;
|
||||||
mslSource = [[NSString alloc] initWithUTF8String:msl.c_str()];
|
|
||||||
|
NSRef<NSString> mslSource =
|
||||||
|
AcquireNSRef([[NSString alloc] initWithUTF8String:msl.c_str()]);
|
||||||
|
|
||||||
auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
|
auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
|
||||||
NSError* error = nil;
|
NSError* error = nullptr;
|
||||||
id<MTLLibrary> library = [mtlDevice newLibraryWithSource:mslSource
|
NSPRef<id<MTLLibrary>> library =
|
||||||
options:nil
|
AcquireNSPRef([mtlDevice newLibraryWithSource:mslSource.Get()
|
||||||
error:&error];
|
options:nullptr
|
||||||
if (error != nil) {
|
error:&error]);
|
||||||
|
if (error != nullptr) {
|
||||||
if (error.code != MTLLibraryErrorCompileWarning) {
|
if (error.code != MTLLibraryErrorCompileWarning) {
|
||||||
const char* errorString = [error.localizedDescription UTF8String];
|
const char* errorString = [error.localizedDescription UTF8String];
|
||||||
return DAWN_VALIDATION_ERROR(std::string("Unable to create library object: ") +
|
return DAWN_VALIDATION_ERROR(std::string("Unable to create library object: ") +
|
||||||
|
@ -174,9 +176,9 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* name = [[NSString alloc] initWithUTF8String:modifiedEntryPointName.c_str()];
|
NSRef<NSString> name =
|
||||||
out->function = [library newFunctionWithName:name];
|
AcquireNSRef([[NSString alloc] initWithUTF8String:modifiedEntryPointName.c_str()]);
|
||||||
[library release];
|
out->function = AcquireNSPRef([*library newFunctionWithName:name.Get()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
out->needsStorageBufferLength = compiler.needs_buffer_size_buffer();
|
out->needsStorageBufferLength = compiler.needs_buffer_size_buffer();
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/StagingBuffer.h"
|
#include "dawn_native/StagingBuffer.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
@ -26,7 +28,6 @@ namespace dawn_native { namespace metal {
|
||||||
class StagingBuffer : public StagingBufferBase {
|
class StagingBuffer : public StagingBufferBase {
|
||||||
public:
|
public:
|
||||||
StagingBuffer(size_t size, Device* device);
|
StagingBuffer(size_t size, Device* device);
|
||||||
~StagingBuffer() override;
|
|
||||||
|
|
||||||
id<MTLBuffer> GetBufferHandle() const;
|
id<MTLBuffer> GetBufferHandle() const;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Device* mDevice;
|
Device* mDevice;
|
||||||
id<MTLBuffer> mBuffer = nil;
|
NSPRef<id<MTLBuffer>> mBuffer;
|
||||||
};
|
};
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,15 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
MaybeError StagingBuffer::Initialize() {
|
MaybeError StagingBuffer::Initialize() {
|
||||||
const size_t bufferSize = GetSize();
|
const size_t bufferSize = GetSize();
|
||||||
mBuffer = [mDevice->GetMTLDevice() newBufferWithLength:bufferSize
|
mBuffer = AcquireNSPRef([mDevice->GetMTLDevice()
|
||||||
options:MTLResourceStorageModeShared];
|
newBufferWithLength:bufferSize
|
||||||
|
options:MTLResourceStorageModeShared]);
|
||||||
|
|
||||||
if (mBuffer == nil) {
|
if (mBuffer == nullptr) {
|
||||||
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
mMappedPointer = [mBuffer contents];
|
mMappedPointer = [*mBuffer contents];
|
||||||
if (mMappedPointer == nullptr) {
|
if (mMappedPointer == nullptr) {
|
||||||
return DAWN_INTERNAL_ERROR("Unable to map staging buffer.");
|
return DAWN_INTERNAL_ERROR("Unable to map staging buffer.");
|
||||||
}
|
}
|
||||||
|
@ -38,13 +39,8 @@ namespace dawn_native { namespace metal {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingBuffer::~StagingBuffer() {
|
|
||||||
[mBuffer release];
|
|
||||||
mBuffer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
id<MTLBuffer> StagingBuffer::GetBufferHandle() const {
|
id<MTLBuffer> StagingBuffer::GetBufferHandle() const {
|
||||||
return mBuffer;
|
return mBuffer.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "dawn_native/SwapChain.h"
|
#include "dawn_native/SwapChain.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
|
||||||
@class CAMetalLayer;
|
@class CAMetalLayer;
|
||||||
@protocol CAMetalDrawable;
|
@protocol CAMetalDrawable;
|
||||||
|
|
||||||
|
@ -47,9 +49,9 @@ namespace dawn_native { namespace metal {
|
||||||
using NewSwapChainBase::NewSwapChainBase;
|
using NewSwapChainBase::NewSwapChainBase;
|
||||||
MaybeError Initialize(NewSwapChainBase* previousSwapChain);
|
MaybeError Initialize(NewSwapChainBase* previousSwapChain);
|
||||||
|
|
||||||
CAMetalLayer* mLayer = nullptr;
|
NSRef<CAMetalLayer> mLayer;
|
||||||
|
|
||||||
id<CAMetalDrawable> mCurrentDrawable = nil;
|
NSPRef<id<CAMetalDrawable>> mCurrentDrawable;
|
||||||
Ref<Texture> mTexture;
|
Ref<Texture> mTexture;
|
||||||
|
|
||||||
MaybeError PresentImpl() override;
|
MaybeError PresentImpl() override;
|
||||||
|
|
|
@ -92,15 +92,15 @@ namespace dawn_native { namespace metal {
|
||||||
CGSize size = {};
|
CGSize size = {};
|
||||||
size.width = GetWidth();
|
size.width = GetWidth();
|
||||||
size.height = GetHeight();
|
size.height = GetHeight();
|
||||||
[mLayer setDrawableSize:size];
|
[*mLayer setDrawableSize:size];
|
||||||
|
|
||||||
[mLayer setFramebufferOnly:(GetUsage() == wgpu::TextureUsage::RenderAttachment)];
|
[*mLayer setFramebufferOnly:(GetUsage() == wgpu::TextureUsage::RenderAttachment)];
|
||||||
[mLayer setDevice:ToBackend(GetDevice())->GetMTLDevice()];
|
[*mLayer setDevice:ToBackend(GetDevice())->GetMTLDevice()];
|
||||||
[mLayer setPixelFormat:MetalPixelFormat(GetFormat())];
|
[*mLayer setPixelFormat:MetalPixelFormat(GetFormat())];
|
||||||
|
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
if (@available(macos 10.13, *)) {
|
if (@available(macos 10.13, *)) {
|
||||||
[mLayer setDisplaySyncEnabled:(GetPresentMode() != wgpu::PresentMode::Immediate)];
|
[*mLayer setDisplaySyncEnabled:(GetPresentMode() != wgpu::PresentMode::Immediate)];
|
||||||
}
|
}
|
||||||
#endif // defined(DAWN_PLATFORM_MACOS)
|
#endif // defined(DAWN_PLATFORM_MACOS)
|
||||||
|
|
||||||
|
@ -110,40 +110,36 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError SwapChain::PresentImpl() {
|
MaybeError SwapChain::PresentImpl() {
|
||||||
ASSERT(mCurrentDrawable != nil);
|
ASSERT(mCurrentDrawable != nullptr);
|
||||||
[mCurrentDrawable present];
|
[*mCurrentDrawable present];
|
||||||
|
|
||||||
mTexture->Destroy();
|
mTexture->Destroy();
|
||||||
mTexture = nullptr;
|
mTexture = nullptr;
|
||||||
|
|
||||||
[mCurrentDrawable release];
|
mCurrentDrawable = nullptr;
|
||||||
mCurrentDrawable = nil;
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<TextureViewBase*> SwapChain::GetCurrentTextureViewImpl() {
|
ResultOrError<TextureViewBase*> SwapChain::GetCurrentTextureViewImpl() {
|
||||||
ASSERT(mCurrentDrawable == nil);
|
ASSERT(mCurrentDrawable == nullptr);
|
||||||
mCurrentDrawable = [mLayer nextDrawable];
|
mCurrentDrawable = [*mLayer nextDrawable];
|
||||||
[mCurrentDrawable retain];
|
|
||||||
|
|
||||||
TextureDescriptor textureDesc = GetSwapChainBaseTextureDescriptor(this);
|
TextureDescriptor textureDesc = GetSwapChainBaseTextureDescriptor(this);
|
||||||
|
|
||||||
// mTexture will add a reference to mCurrentDrawable.texture to keep it alive.
|
mTexture = AcquireRef(
|
||||||
mTexture =
|
new Texture(ToBackend(GetDevice()), &textureDesc, [*mCurrentDrawable texture]));
|
||||||
AcquireRef(new Texture(ToBackend(GetDevice()), &textureDesc, mCurrentDrawable.texture));
|
|
||||||
return mTexture->CreateView(nullptr);
|
return mTexture->CreateView(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChain::DetachFromSurfaceImpl() {
|
void SwapChain::DetachFromSurfaceImpl() {
|
||||||
ASSERT((mTexture.Get() == nullptr) == (mCurrentDrawable == nil));
|
ASSERT((mTexture.Get() == nullptr) == (mCurrentDrawable == nullptr));
|
||||||
|
|
||||||
if (mTexture.Get() != nullptr) {
|
if (mTexture.Get() != nullptr) {
|
||||||
mTexture->Destroy();
|
mTexture->Destroy();
|
||||||
mTexture = nullptr;
|
mTexture = nullptr;
|
||||||
|
|
||||||
[mCurrentDrawable release];
|
mCurrentDrawable = nullptr;
|
||||||
mCurrentDrawable = nil;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,11 @@
|
||||||
|
|
||||||
#include "dawn_native/Texture.h"
|
#include "dawn_native/Texture.h"
|
||||||
|
|
||||||
|
#include "common/NSRef.h"
|
||||||
|
#include "dawn_native/DawnNative.h"
|
||||||
|
|
||||||
#include <IOSurface/IOSurfaceRef.h>
|
#include <IOSurface/IOSurfaceRef.h>
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
#include "dawn_native/DawnNative.h"
|
|
||||||
|
|
||||||
namespace dawn_native { namespace metal {
|
namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
|
@ -34,7 +36,9 @@ namespace dawn_native { namespace metal {
|
||||||
class Texture final : public TextureBase {
|
class Texture final : public TextureBase {
|
||||||
public:
|
public:
|
||||||
Texture(Device* device, const TextureDescriptor* descriptor);
|
Texture(Device* device, const TextureDescriptor* descriptor);
|
||||||
Texture(Device* device, const TextureDescriptor* descriptor, id<MTLTexture> mtlTexture);
|
Texture(Device* device,
|
||||||
|
const TextureDescriptor* descriptor,
|
||||||
|
NSPRef<id<MTLTexture>> mtlTexture);
|
||||||
Texture(Device* device,
|
Texture(Device* device,
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface,
|
||||||
|
@ -51,7 +55,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
MaybeError ClearTexture(const SubresourceRange& range, TextureBase::ClearValue clearValue);
|
MaybeError ClearTexture(const SubresourceRange& range, TextureBase::ClearValue clearValue);
|
||||||
|
|
||||||
id<MTLTexture> mMtlTexture = nil;
|
NSPRef<id<MTLTexture>> mMtlTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureView final : public TextureViewBase {
|
class TextureView final : public TextureViewBase {
|
||||||
|
@ -61,9 +65,7 @@ namespace dawn_native { namespace metal {
|
||||||
id<MTLTexture> GetMTLTexture();
|
id<MTLTexture> GetMTLTexture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~TextureView() override;
|
NSPRef<id<MTLTexture>> mMtlTextureView;
|
||||||
|
|
||||||
id<MTLTexture> mMtlTextureView = nil;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -298,9 +298,10 @@ namespace dawn_native { namespace metal {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLTextureDescriptor* CreateMetalTextureDescriptor(DeviceBase* device,
|
NSRef<MTLTextureDescriptor> CreateMetalTextureDescriptor(DeviceBase* device,
|
||||||
const TextureDescriptor* descriptor) {
|
const TextureDescriptor* descriptor) {
|
||||||
MTLTextureDescriptor* mtlDesc = [MTLTextureDescriptor new];
|
NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
|
||||||
|
MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
|
||||||
|
|
||||||
mtlDesc.width = descriptor->size.width;
|
mtlDesc.width = descriptor->size.width;
|
||||||
mtlDesc.height = descriptor->size.height;
|
mtlDesc.height = descriptor->size.height;
|
||||||
|
@ -338,14 +339,14 @@ namespace dawn_native { namespace metal {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mtlDesc;
|
return mtlDescRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
|
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
|
||||||
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
|
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
|
||||||
MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
|
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
|
||||||
mMtlTexture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc];
|
mMtlTexture =
|
||||||
[mtlDesc release];
|
AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()]);
|
||||||
|
|
||||||
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
||||||
device->ConsumedError(
|
device->ConsumedError(
|
||||||
|
@ -353,9 +354,11 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(Device* device, const TextureDescriptor* descriptor, id<MTLTexture> mtlTexture)
|
Texture::Texture(Device* device,
|
||||||
: TextureBase(device, descriptor, TextureState::OwnedInternal), mMtlTexture(mtlTexture) {
|
const TextureDescriptor* descriptor,
|
||||||
[mMtlTexture retain];
|
NSPRef<id<MTLTexture>> mtlTexture)
|
||||||
|
: TextureBase(device, descriptor, TextureState::OwnedInternal),
|
||||||
|
mMtlTexture(std::move(mtlTexture)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(Device* device,
|
Texture::Texture(Device* device,
|
||||||
|
@ -365,13 +368,13 @@ namespace dawn_native { namespace metal {
|
||||||
: TextureBase(device,
|
: TextureBase(device,
|
||||||
reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor),
|
reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor),
|
||||||
TextureState::OwnedInternal) {
|
TextureState::OwnedInternal) {
|
||||||
MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(
|
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(
|
||||||
device, reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor));
|
device, reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor));
|
||||||
mtlDesc.storageMode = kIOSurfaceStorageMode;
|
[*mtlDesc setStorageMode:kIOSurfaceStorageMode];
|
||||||
mMtlTexture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc
|
|
||||||
iosurface:ioSurface
|
mMtlTexture = AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
|
||||||
plane:plane];
|
iosurface:ioSurface
|
||||||
[mtlDesc release];
|
plane:plane]);
|
||||||
|
|
||||||
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
|
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
|
||||||
}
|
}
|
||||||
|
@ -381,14 +384,11 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::DestroyImpl() {
|
void Texture::DestroyImpl() {
|
||||||
if (GetTextureState() == TextureState::OwnedInternal) {
|
mMtlTexture = nullptr;
|
||||||
[mMtlTexture release];
|
|
||||||
mMtlTexture = nil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> Texture::GetMTLTexture() {
|
id<MTLTexture> Texture::GetMTLTexture() {
|
||||||
return mMtlTexture;
|
return mMtlTexture.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Texture::ClearTexture(const SubresourceRange& range,
|
MaybeError Texture::ClearTexture(const SubresourceRange& range,
|
||||||
|
@ -419,8 +419,11 @@ namespace dawn_native { namespace metal {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLRenderPassDescriptor* descriptor =
|
// Note that this creates a descriptor that's autoreleased so we don't use
|
||||||
|
// AcquireNSRef
|
||||||
|
NSRef<MTLRenderPassDescriptor> descriptorRef =
|
||||||
[MTLRenderPassDescriptor renderPassDescriptor];
|
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
MTLRenderPassDescriptor* descriptor = descriptorRef.Get();
|
||||||
|
|
||||||
// At least one aspect needs clearing. Iterate the aspects individually to
|
// At least one aspect needs clearing. Iterate the aspects individually to
|
||||||
// determine which to clear.
|
// determine which to clear.
|
||||||
|
@ -462,7 +465,7 @@ namespace dawn_native { namespace metal {
|
||||||
// Create multiple render passes with each subresource as a color attachment to
|
// Create multiple render passes with each subresource as a color attachment to
|
||||||
// clear them all. Only do this for array layers to ensure all attachments have
|
// clear them all. Only do this for array layers to ensure all attachments have
|
||||||
// the same size.
|
// the same size.
|
||||||
MTLRenderPassDescriptor* descriptor = nil;
|
NSRef<MTLRenderPassDescriptor> descriptor;
|
||||||
uint32_t attachment = 0;
|
uint32_t attachment = 0;
|
||||||
|
|
||||||
for (uint32_t arrayLayer = range.baseArrayLayer;
|
for (uint32_t arrayLayer = range.baseArrayLayer;
|
||||||
|
@ -474,30 +477,33 @@ namespace dawn_native { namespace metal {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor == nil) {
|
if (descriptor == nullptr) {
|
||||||
|
// Note that this creates a descriptor that's autoreleased so we don't
|
||||||
|
// use AcquireNSRef
|
||||||
descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor.colorAttachments[attachment].texture = GetMTLTexture();
|
[*descriptor colorAttachments][attachment].texture = GetMTLTexture();
|
||||||
descriptor.colorAttachments[attachment].loadAction = MTLLoadActionClear;
|
[*descriptor colorAttachments][attachment].loadAction = MTLLoadActionClear;
|
||||||
descriptor.colorAttachments[attachment].storeAction = MTLStoreActionStore;
|
[*descriptor colorAttachments][attachment].storeAction =
|
||||||
descriptor.colorAttachments[attachment].clearColor =
|
MTLStoreActionStore;
|
||||||
|
[*descriptor colorAttachments][attachment].clearColor =
|
||||||
MTLClearColorMake(dClearColor, dClearColor, dClearColor, dClearColor);
|
MTLClearColorMake(dClearColor, dClearColor, dClearColor, dClearColor);
|
||||||
descriptor.colorAttachments[attachment].level = level;
|
[*descriptor colorAttachments][attachment].level = level;
|
||||||
descriptor.colorAttachments[attachment].slice = arrayLayer;
|
[*descriptor colorAttachments][attachment].slice = arrayLayer;
|
||||||
|
|
||||||
attachment++;
|
attachment++;
|
||||||
|
|
||||||
if (attachment == kMaxColorAttachments) {
|
if (attachment == kMaxColorAttachments) {
|
||||||
attachment = 0;
|
attachment = 0;
|
||||||
commandContext->BeginRender(descriptor);
|
commandContext->BeginRender(descriptor.Get());
|
||||||
commandContext->EndRender();
|
commandContext->EndRender();
|
||||||
descriptor = nil;
|
descriptor = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor != nil) {
|
if (descriptor != nullptr) {
|
||||||
commandContext->BeginRender(descriptor);
|
commandContext->BeginRender(descriptor.Get());
|
||||||
commandContext->EndRender();
|
commandContext->EndRender();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,9 +597,9 @@ namespace dawn_native { namespace metal {
|
||||||
id<MTLTexture> mtlTexture = ToBackend(texture)->GetMTLTexture();
|
id<MTLTexture> mtlTexture = ToBackend(texture)->GetMTLTexture();
|
||||||
|
|
||||||
if (!UsageNeedsTextureView(texture->GetUsage())) {
|
if (!UsageNeedsTextureView(texture->GetUsage())) {
|
||||||
mMtlTextureView = nil;
|
mMtlTextureView = nullptr;
|
||||||
} else if (!RequiresCreatingNewTextureView(texture, descriptor)) {
|
} else if (!RequiresCreatingNewTextureView(texture, descriptor)) {
|
||||||
mMtlTextureView = [mtlTexture retain];
|
mMtlTextureView = mtlTexture;
|
||||||
} else {
|
} else {
|
||||||
MTLPixelFormat format = MetalPixelFormat(descriptor->format);
|
MTLPixelFormat format = MetalPixelFormat(descriptor->format);
|
||||||
if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
||||||
|
@ -616,19 +622,16 @@ namespace dawn_native { namespace metal {
|
||||||
auto arrayLayerRange =
|
auto arrayLayerRange =
|
||||||
NSMakeRange(descriptor->baseArrayLayer, descriptor->arrayLayerCount);
|
NSMakeRange(descriptor->baseArrayLayer, descriptor->arrayLayerCount);
|
||||||
|
|
||||||
mMtlTextureView = [mtlTexture newTextureViewWithPixelFormat:format
|
mMtlTextureView =
|
||||||
|
AcquireNSPRef([mtlTexture newTextureViewWithPixelFormat:format
|
||||||
textureType:textureViewType
|
textureType:textureViewType
|
||||||
levels:mipLevelRange
|
levels:mipLevelRange
|
||||||
slices:arrayLayerRange];
|
slices:arrayLayerRange]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureView::~TextureView() {
|
|
||||||
[mMtlTextureView release];
|
|
||||||
}
|
|
||||||
|
|
||||||
id<MTLTexture> TextureView::GetMTLTexture() {
|
id<MTLTexture> TextureView::GetMTLTexture() {
|
||||||
ASSERT(mMtlTextureView != nil);
|
ASSERT(mMtlTextureView != nullptr);
|
||||||
return mMtlTextureView;
|
return mMtlTextureView.Get();
|
||||||
}
|
}
|
||||||
}} // namespace dawn_native::metal
|
}} // namespace dawn_native::metal
|
||||||
|
|
|
@ -118,7 +118,6 @@ TEST(Ref, Gets) {
|
||||||
test->Release();
|
test->Release();
|
||||||
|
|
||||||
EXPECT_EQ(test.Get(), original);
|
EXPECT_EQ(test.Get(), original);
|
||||||
EXPECT_EQ(&*test, original);
|
|
||||||
EXPECT_EQ(test->GetThis(), original);
|
EXPECT_EQ(test->GetThis(), original);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +126,6 @@ TEST(Ref, DefaultsToNull) {
|
||||||
Ref<RCTest> test;
|
Ref<RCTest> test;
|
||||||
|
|
||||||
EXPECT_EQ(test.Get(), nullptr);
|
EXPECT_EQ(test.Get(), nullptr);
|
||||||
EXPECT_EQ(&*test, nullptr);
|
|
||||||
EXPECT_EQ(test->GetThis(), nullptr);
|
EXPECT_EQ(test->GetThis(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue