Add getPlatform API to Engine, move functionality into MetalPlatform (#4007)
This change allows access to the Engine's underlying Platform object. This is useful for Metal clients to access a new method on MetalPlatform, createAndEnqueueCommandBuffer.
This commit is contained in:
@@ -115,7 +115,7 @@ if (FILAMENT_SUPPORTS_METAL)
|
||||
src/metal/MetalResourceTracker.cpp
|
||||
src/metal/MetalState.mm
|
||||
src/metal/MetalTimerQuery.mm
|
||||
src/metal/PlatformMetal.mm
|
||||
src/metal/MetalPlatform.mm
|
||||
)
|
||||
|
||||
list(APPEND SRCS ${METAL_SRCS})
|
||||
|
||||
66
filament/backend/include/private/backend/MetalPlatform.h
Normal file
66
filament/backend/include/private/backend/MetalPlatform.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* 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 TNT_FILAMENT_DRIVER_PLATFORM_METAL_H
|
||||
#define TNT_FILAMENT_DRIVER_PLATFORM_METAL_H
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
class MetalPlatform : public DefaultPlatform {
|
||||
public:
|
||||
~MetalPlatform() override;
|
||||
|
||||
Driver* createDriver(void* sharedContext) noexcept override;
|
||||
int getOSVersion() const noexcept override { return 0; }
|
||||
|
||||
/**
|
||||
* Obtain the preferred Metal device object for the backend to use.
|
||||
*
|
||||
* On desktop platforms, there may be multiple GPUs suitable for rendering, and this method is
|
||||
* free to decide which one to use. On mobile systems with a single GPU, implementations should
|
||||
* simply return the result of MTLCreateSystemDefaultDevice();
|
||||
*/
|
||||
virtual id<MTLDevice> createDevice() noexcept;
|
||||
|
||||
/**
|
||||
* Create a command submission queue on the Metal device object.
|
||||
*
|
||||
* @param device The device which was returned from createDevice()
|
||||
*/
|
||||
virtual id<MTLCommandQueue> createCommandQueue(id<MTLDevice> device) noexcept;
|
||||
|
||||
/**
|
||||
* Obtain a MTLCommandBuffer enqueued on this Platform's MTLCommandQueue. The command buffer is
|
||||
* guaranteed to execute before all subsequent command buffers created either by Filament, or
|
||||
* further calls to this method.
|
||||
*/
|
||||
id<MTLCommandBuffer> createAndEnqueueCommandBuffer() noexcept;
|
||||
|
||||
private:
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_PLATFORM_METAL_H
|
||||
@@ -63,7 +63,9 @@
|
||||
#endif
|
||||
|
||||
#if defined (FILAMENT_SUPPORTS_METAL)
|
||||
#include "metal/PlatformMetal.h"
|
||||
namespace filament::backend {
|
||||
filament::backend::DefaultPlatform* createDefaultMetalPlatform();
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "noop/PlatformNoop.h"
|
||||
@@ -107,7 +109,7 @@ DefaultPlatform* DefaultPlatform::create(Backend* backend) noexcept {
|
||||
}
|
||||
if (*backend == Backend::METAL) {
|
||||
#if defined(FILAMENT_SUPPORTS_METAL)
|
||||
return new PlatformMetal();
|
||||
return createDefaultMetalPlatform();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "MetalState.h"
|
||||
#include "MetalTimerQuery.h"
|
||||
|
||||
#include "private/backend/MetalPlatform.h"
|
||||
|
||||
#include <CoreVideo/CVMetalTexture.h>
|
||||
#include <CoreVideo/CVPixelBuffer.h>
|
||||
#include <Metal/Metal.h>
|
||||
@@ -56,27 +58,8 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
|
||||
mContext(new MetalContext) {
|
||||
mContext->driver = this;
|
||||
|
||||
#if !defined(IOS)
|
||||
const bool forceIntegrated =
|
||||
NSProcessInfo.processInfo.environment[@"FILAMENT_FORCE_INTEGRATED_GPU"] != nil;
|
||||
if (forceIntegrated) {
|
||||
// Find the first low power device, which is likely the integrated GPU.
|
||||
NSArray<id<MTLDevice>>* const devices = MTLCopyAllDevices();
|
||||
for (id<MTLDevice> device in devices) {
|
||||
if (device.isLowPower) {
|
||||
mContext->device = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mContext->device = MTLCreateSystemDefaultDevice();
|
||||
}
|
||||
|
||||
utils::slog.i << "Selected physical device '"
|
||||
<< [mContext->device.name cStringUsingEncoding:NSUTF8StringEncoding] << "'"
|
||||
<< utils::io::endl;
|
||||
mContext->device = mPlatform.createDevice();
|
||||
assert_invariant(mContext->device);
|
||||
|
||||
// In order to support texture swizzling, the GPU needs to support it and the system be running
|
||||
// macOS 10.15+ / iOS 13+.
|
||||
@@ -102,8 +85,7 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
|
||||
}
|
||||
#endif
|
||||
|
||||
mContext->commandQueue = [mContext->device newCommandQueue];
|
||||
mContext->commandQueue.label = @"Filament";
|
||||
mContext->commandQueue = mPlatform.createCommandQueue(mContext->device);
|
||||
mContext->pipelineStateCache.setDevice(mContext->device);
|
||||
mContext->depthStencilStateCache.setDevice(mContext->device);
|
||||
mContext->samplerStateCache.setDevice(mContext->device);
|
||||
|
||||
79
filament/backend/src/metal/MetalPlatform.mm
Normal file
79
filament/backend/src/metal/MetalPlatform.mm
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "private/backend/MetalPlatform.h"
|
||||
|
||||
#include "MetalDriverFactory.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
DefaultPlatform* createDefaultMetalPlatform() {
|
||||
return new MetalPlatform();
|
||||
}
|
||||
|
||||
MetalPlatform::~MetalPlatform() = default;
|
||||
|
||||
Driver* MetalPlatform::createDriver(void* sharedContext) noexcept {
|
||||
return MetalDriverFactory::create(this);
|
||||
}
|
||||
|
||||
id<MTLDevice> MetalPlatform::createDevice() noexcept {
|
||||
id<MTLDevice> result;
|
||||
|
||||
#if !defined(IOS)
|
||||
const bool forceIntegrated =
|
||||
NSProcessInfo.processInfo.environment[@"FILAMENT_FORCE_INTEGRATED_GPU"] != nil;
|
||||
if (forceIntegrated) {
|
||||
// Find the first low power device, which is likely the integrated GPU.
|
||||
NSArray<id<MTLDevice>>* const devices = MTLCopyAllDevices();
|
||||
for (id<MTLDevice> device in devices) {
|
||||
if (device.isLowPower) {
|
||||
result = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
result = MTLCreateSystemDefaultDevice();
|
||||
}
|
||||
|
||||
utils::slog.i << "Selected physical device '"
|
||||
<< [result.name cStringUsingEncoding:NSUTF8StringEncoding] << "'"
|
||||
<< utils::io::endl;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
id<MTLCommandQueue> MetalPlatform::createCommandQueue(id<MTLDevice> device) noexcept {
|
||||
mCommandQueue = [device newCommandQueue];
|
||||
mCommandQueue.label = @"Filament";
|
||||
return mCommandQueue;
|
||||
}
|
||||
|
||||
id<MTLCommandBuffer> MetalPlatform::createAndEnqueueCommandBuffer() noexcept {
|
||||
id<MTLCommandBuffer> commandBuffer = [mCommandQueue commandBuffer];
|
||||
[commandBuffer enqueue];
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* 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 TNT_FILAMENT_DRIVER_PLATFORM_METAL_H
|
||||
#define TNT_FILAMENT_DRIVER_PLATFORM_METAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
class MetalPlatform : public DefaultPlatform {
|
||||
public:
|
||||
~MetalPlatform() override;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
|
||||
class PlatformMetal final : public backend::MetalPlatform {
|
||||
public:
|
||||
backend::Driver* createDriver(void* sharedContext) noexcept override;
|
||||
int getOSVersion() const noexcept override { return 0; }
|
||||
~PlatformMetal() override;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_PLATFORM_METAL_H
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "PlatformMetal.h"
|
||||
#include "MetalDriverFactory.h"
|
||||
|
||||
namespace filament {
|
||||
|
||||
namespace backend {
|
||||
MetalPlatform::~MetalPlatform() = default;
|
||||
} // namespace backend
|
||||
|
||||
|
||||
using namespace backend;
|
||||
|
||||
Driver* PlatformMetal::createDriver(void* sharedContext) noexcept {
|
||||
return MetalDriverFactory::create(this);
|
||||
}
|
||||
|
||||
PlatformMetal::~PlatformMetal() = default;
|
||||
|
||||
|
||||
} // namespace filament
|
||||
@@ -459,6 +459,32 @@ public:
|
||||
*/
|
||||
Backend getBackend() const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the Platform object that belongs to this Engine.
|
||||
*
|
||||
* When Engine::create is called with no platform argument, Filament creates an appropriate
|
||||
* Platform subclass automatically. The specific subclass created depends on the backend and
|
||||
* OS. For example, when the OpenGL backend is used, the Platform object will be a descendant of
|
||||
* OpenGLPlatform.
|
||||
*
|
||||
* dynamic_cast should be used to cast the returned Platform object into a specific subclass.
|
||||
* Note that RTTI must be available to use dynamic_cast.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Platform* platform = engine->getPlatform();
|
||||
* // static_cast also works, but more dangerous.
|
||||
* SpecificPlatform* specificPlatform = dynamic_cast<SpecificPlatform*>(platform);
|
||||
* specificPlatform->platformSpecificMethod();
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* When a custom Platform is passed to Engine::create, Filament will use it instead, and this
|
||||
* method will return it.
|
||||
*
|
||||
* @return A pointer to the Platform object that was provided to Engine::create, or the
|
||||
* Filament-created one.
|
||||
*/
|
||||
Platform* getPlatform() const noexcept;
|
||||
|
||||
/**
|
||||
* Allocate a small amount of memory directly in the command stream. The allocated memory is
|
||||
* guaranteed to be preserved until the current command buffer is executed
|
||||
|
||||
@@ -899,6 +899,10 @@ Backend Engine::getBackend() const noexcept {
|
||||
return upcast(this)->getBackend();
|
||||
}
|
||||
|
||||
Platform* Engine::getPlatform() const noexcept {
|
||||
return upcast(this)->getPlatform();
|
||||
}
|
||||
|
||||
Renderer* Engine::createRenderer() noexcept {
|
||||
return upcast(this)->createRenderer();
|
||||
}
|
||||
|
||||
@@ -210,6 +210,10 @@ public:
|
||||
return mBackend;
|
||||
}
|
||||
|
||||
Platform* getPlatform() const noexcept {
|
||||
return mPlatform;
|
||||
}
|
||||
|
||||
ResourceAllocator& getResourceAllocator() noexcept {
|
||||
assert_invariant(mResourceAllocator);
|
||||
return *mResourceAllocator;
|
||||
|
||||
Reference in New Issue
Block a user