Compare commits
2 Commits
gitIgnoreU
...
pf/test-ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8f088140c | ||
|
|
1c72d108fb |
@@ -194,6 +194,8 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
|||||||
src/vulkan/VulkanDriver.cpp
|
src/vulkan/VulkanDriver.cpp
|
||||||
src/vulkan/VulkanDriver.h
|
src/vulkan/VulkanDriver.h
|
||||||
src/vulkan/VulkanDriverFactory.h
|
src/vulkan/VulkanDriverFactory.h
|
||||||
|
src/vulkan/VulkanExternalImageManager.cpp
|
||||||
|
src/vulkan/VulkanExternalImageManager.h
|
||||||
src/vulkan/VulkanFboCache.cpp
|
src/vulkan/VulkanFboCache.cpp
|
||||||
src/vulkan/VulkanFboCache.h
|
src/vulkan/VulkanFboCache.h
|
||||||
src/vulkan/VulkanHandles.cpp
|
src/vulkan/VulkanHandles.cpp
|
||||||
|
|||||||
@@ -149,6 +149,13 @@ public:
|
|||||||
* - PlatformEGLAndroid
|
* - PlatformEGLAndroid
|
||||||
*/
|
*/
|
||||||
bool assertNativeWindowIsValid = false;
|
bool assertNativeWindowIsValid = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The action to take if a Drawable cannot be acquired. If true, the
|
||||||
|
* frame is aborted instead of panic. This is only supported for:
|
||||||
|
* - PlatformMetal
|
||||||
|
*/
|
||||||
|
bool metalDisablePanicOnDrawableFailure = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Platform() noexcept;
|
Platform() noexcept;
|
||||||
|
|||||||
@@ -294,6 +294,16 @@ public:
|
|||||||
VkQueue getProtectedGraphicsQueue() const noexcept;
|
VkQueue getProtectedGraphicsQueue() const noexcept;
|
||||||
|
|
||||||
struct ExternalImageMetadata {
|
struct ExternalImageMetadata {
|
||||||
|
/**
|
||||||
|
* The Filament texture format.
|
||||||
|
*/
|
||||||
|
TextureFormat filamentFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Filament texture usage.
|
||||||
|
*/
|
||||||
|
TextureUsage filamentUsage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The width of the external image
|
* The width of the external image
|
||||||
*/
|
*/
|
||||||
@@ -304,11 +314,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
|
|
||||||
/**
|
|
||||||
* The layerCount of the external image
|
|
||||||
*/
|
|
||||||
uint32_t layerCount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layer count of the external image
|
* The layer count of the external image
|
||||||
*/
|
*/
|
||||||
@@ -324,11 +329,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
|
|
||||||
/**
|
|
||||||
* An external buffer can be protected. This tells you if it is.
|
|
||||||
*/
|
|
||||||
bool isProtected;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of external format (opaque int) if used.
|
* The type of external format (opaque int) if used.
|
||||||
*/
|
*/
|
||||||
@@ -348,20 +348,44 @@ public:
|
|||||||
* Heap information
|
* Heap information
|
||||||
*/
|
*/
|
||||||
uint32_t memoryTypeBits;
|
uint32_t memoryTypeBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ycbcr conversion components
|
||||||
|
*/
|
||||||
|
VkComponentMapping ycbcrConversionComponents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ycbcr model
|
||||||
|
*/
|
||||||
|
VkSamplerYcbcrModelConversion ycbcrModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ycbcr range
|
||||||
|
*/
|
||||||
|
VkSamplerYcbcrRange ycbcrRange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ycbcr x chroma offset
|
||||||
|
*/
|
||||||
|
VkChromaLocation xChromaOffset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ycbcr y chroma offset
|
||||||
|
*/
|
||||||
|
VkChromaLocation yChromaOffset;
|
||||||
};
|
};
|
||||||
virtual ExternalImageMetadata getExternalImageMetadata(ExternalImageHandleRef externalImage);
|
|
||||||
|
|
||||||
|
// Note that the image metadata might change per-frame, hence we need a method for extracting
|
||||||
|
// it.
|
||||||
|
virtual ExternalImageMetadata extractExternalImageMetadata(ExternalImageHandleRef image) const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
using ImageData = std::pair<VkImage, VkDeviceMemory>;
|
using ImageData = std::pair<VkImage, VkDeviceMemory>;
|
||||||
virtual ImageData createExternalImageData(ExternalImageHandleRef externalImage,
|
virtual ImageData createVkImageFromExternal(ExternalImageHandleRef image) const {
|
||||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex,
|
return { VK_NULL_HANDLE, VK_NULL_HANDLE };
|
||||||
VkImageUsageFlags usage);
|
}
|
||||||
|
|
||||||
virtual VkSampler createExternalSampler(SamplerYcbcrConversion chroma,
|
|
||||||
SamplerParams sampler, uint32_t internalFormat);
|
|
||||||
|
|
||||||
virtual VkImageView createExternalImageView(SamplerYcbcrConversion chroma,
|
|
||||||
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
|
|
||||||
VkImageViewType viewType, VkComponentMapping swizzle);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ExtensionSet getSwapchainInstanceExtensions() const;
|
virtual ExtensionSet getSwapchainInstanceExtensions() const;
|
||||||
@@ -374,20 +398,6 @@ private:
|
|||||||
// Platform dependent helper methods
|
// Platform dependent helper methods
|
||||||
static ExtensionSet getSwapchainInstanceExtensionsImpl();
|
static ExtensionSet getSwapchainInstanceExtensionsImpl();
|
||||||
|
|
||||||
static ExternalImageMetadata getExternalImageMetadataImpl(ExternalImageHandleRef externalImage,
|
|
||||||
VkDevice device);
|
|
||||||
|
|
||||||
static ImageData createExternalImageDataImpl(ExternalImageHandleRef externalImage,
|
|
||||||
VkDevice device, const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex,
|
|
||||||
VkImageUsageFlags usage);
|
|
||||||
static VkSampler createExternalSamplerImpl(VkDevice device,
|
|
||||||
SamplerYcbcrConversion chroma, SamplerParams sampler,
|
|
||||||
uint32_t internalFormat);
|
|
||||||
static VkImageView createExternalImageViewImpl(VkDevice device,
|
|
||||||
SamplerYcbcrConversion chroma, uint32_t internalFormat, VkImage image,
|
|
||||||
VkImageSubresourceRange range, VkImageViewType viewType,
|
|
||||||
VkComponentMapping swizzle);
|
|
||||||
|
|
||||||
// Platform dependent helper methods
|
// Platform dependent helper methods
|
||||||
static SurfaceBundle createVkSurfaceKHRImpl(void* nativeWindow, VkInstance instance,
|
static SurfaceBundle createVkSurfaceKHRImpl(void* nativeWindow, VkInstance instance,
|
||||||
uint64_t flags) noexcept;
|
uint64_t flags) noexcept;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace filament::backend {
|
|||||||
|
|
||||||
class VulkanPlatformAndroid : public VulkanPlatform {
|
class VulkanPlatformAndroid : public VulkanPlatform {
|
||||||
public:
|
public:
|
||||||
Platform::ExternalImageHandle UTILS_PUBLIC createExternalImage(AHardwareBuffer const* buffer,
|
ExternalImageHandle UTILS_PUBLIC createExternalImage(AHardwareBuffer const* buffer,
|
||||||
bool sRGB) noexcept;
|
bool sRGB) noexcept;
|
||||||
|
|
||||||
struct UTILS_PUBLIC ExternalImageDescAndroid {
|
struct UTILS_PUBLIC ExternalImageDescAndroid {
|
||||||
@@ -39,31 +39,26 @@ public:
|
|||||||
ExternalImageDescAndroid UTILS_PUBLIC getExternalImageDesc(
|
ExternalImageDescAndroid UTILS_PUBLIC getExternalImageDesc(
|
||||||
ExternalImageHandleRef externalImage) const noexcept;
|
ExternalImageHandleRef externalImage) const noexcept;
|
||||||
|
|
||||||
|
virtual ExternalImageMetadata extractExternalImageMetadata(
|
||||||
|
ExternalImageHandleRef image) const override;
|
||||||
|
|
||||||
|
virtual ImageData createVkImageFromExternal(ExternalImageHandleRef image) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual ExtensionSet getSwapchainInstanceExtensions() const override;
|
||||||
|
|
||||||
|
using SurfaceBundle = VulkanPlatform::SurfaceBundle;
|
||||||
|
virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
|
||||||
|
uint64_t flags) const noexcept override;
|
||||||
|
|
||||||
|
private:
|
||||||
struct ExternalImageVulkanAndroid : public Platform::ExternalImage {
|
struct ExternalImageVulkanAndroid : public Platform::ExternalImage {
|
||||||
AHardwareBuffer* aHardwareBuffer = nullptr;
|
AHardwareBuffer* aHardwareBuffer = nullptr;
|
||||||
bool sRGB = false;
|
bool sRGB = false;
|
||||||
unsigned int width; // Texture width
|
|
||||||
unsigned int height; // Texture height
|
|
||||||
TextureFormat format;// Texture format
|
|
||||||
TextureUsage usage; // Texture usage flags
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~ExternalImageVulkanAndroid() override;
|
~ExternalImageVulkanAndroid() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ExternalImageMetadata getExternalImageMetadata(ExternalImageHandleRef externalImage);
|
|
||||||
|
|
||||||
using ImageData = VulkanPlatform::ImageData;
|
|
||||||
virtual ImageData createExternalImageData(ExternalImageHandleRef externalImage,
|
|
||||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex,
|
|
||||||
VkImageUsageFlags usage);
|
|
||||||
|
|
||||||
virtual ExtensionSet getSwapchainInstanceExtensions() const;
|
|
||||||
|
|
||||||
using SurfaceBundle = VulkanPlatform::SurfaceBundle;
|
|
||||||
virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
|
|
||||||
uint64_t flags) const noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace filament::backend
|
}// namespace filament::backend
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ PlatformMetal::~PlatformMetal() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
||||||
|
pImpl->mDrawableFailureBehavior = driverConfig.metalDisablePanicOnDrawableFailure
|
||||||
|
? DrawableFailureBehavior::ABORT_FRAME
|
||||||
|
: DrawableFailureBehavior::PANIC;
|
||||||
return MetalDriverFactory::create(this, driverConfig);
|
return MetalDriverFactory::create(this, driverConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define FVK_DEBUG_FLAGS (FVK_DEBUG_PERFORMANCE | FVK_DEBUG_FORWARDED_FLAG)
|
#define FVK_DEBUG_FLAGS (FVK_DEBUG_PERFORMANCE | FVK_DEBUG_FORWARDED_FLAG | FVK_DEBUG_VALIDATION)
|
||||||
#else
|
#else
|
||||||
#define FVK_DEBUG_FLAGS 0
|
#define FVK_DEBUG_FLAGS 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -200,9 +200,7 @@ Dispatcher VulkanDriver::getDispatcher() const noexcept {
|
|||||||
VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& context,
|
VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& context,
|
||||||
Platform::DriverConfig const& driverConfig) noexcept
|
Platform::DriverConfig const& driverConfig) noexcept
|
||||||
: mPlatform(platform),
|
: mPlatform(platform),
|
||||||
mResourceManager(
|
mResourceManager(driverConfig.handleArenaSize, driverConfig.disableHandleUseAfterFreeCheck,
|
||||||
driverConfig.handleArenaSize,
|
|
||||||
driverConfig.disableHandleUseAfterFreeCheck,
|
|
||||||
driverConfig.disableHeapHandleTags),
|
driverConfig.disableHeapHandleTags),
|
||||||
mAllocator(createAllocator(mPlatform->getInstance(), mPlatform->getPhysicalDevice(),
|
mAllocator(createAllocator(mPlatform->getInstance(), mPlatform->getPhysicalDevice(),
|
||||||
mPlatform->getDevice())),
|
mPlatform->getDevice())),
|
||||||
@@ -221,6 +219,8 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
|
|||||||
mDescriptorSetLayoutCache(mPlatform->getDevice(), &mResourceManager),
|
mDescriptorSetLayoutCache(mPlatform->getDevice(), &mResourceManager),
|
||||||
mDescriptorSetCache(mPlatform->getDevice(), &mResourceManager),
|
mDescriptorSetCache(mPlatform->getDevice(), &mResourceManager),
|
||||||
mQueryManager(mPlatform->getDevice()),
|
mQueryManager(mPlatform->getDevice()),
|
||||||
|
mExternalImageManager(platform, &mSamplerCache, &mYcbcrConversionCache, &mDescriptorSetCache,
|
||||||
|
&mDescriptorSetLayoutCache),
|
||||||
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported),
|
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported),
|
||||||
mStereoscopicType(driverConfig.stereoscopicType) {
|
mStereoscopicType(driverConfig.stereoscopicType) {
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ void VulkanDriver::terminate() {
|
|||||||
|
|
||||||
mCurrentSwapChain = {};
|
mCurrentSwapChain = {};
|
||||||
mDefaultRenderTarget = {};
|
mDefaultRenderTarget = {};
|
||||||
mBoundPipeline = {};
|
mPipelineState = {};
|
||||||
|
|
||||||
mQueryManager.terminate();
|
mQueryManager.terminate();
|
||||||
|
|
||||||
@@ -325,6 +325,10 @@ void VulkanDriver::terminate() {
|
|||||||
|
|
||||||
mCommands.terminate();
|
mCommands.terminate();
|
||||||
|
|
||||||
|
// Must come before samplerCache, ycbcrConversionCache, descriptorSetCache,
|
||||||
|
// descriptorSetLayoutCache
|
||||||
|
mExternalImageManager.terminate();
|
||||||
|
|
||||||
mStagePool.terminate();
|
mStagePool.terminate();
|
||||||
mPipelineCache.terminate();
|
mPipelineCache.terminate();
|
||||||
mFramebufferCache.reset();
|
mFramebufferCache.reset();
|
||||||
@@ -381,6 +385,10 @@ void VulkanDriver::beginFrame(int64_t monotonic_clock_ns,
|
|||||||
int64_t refreshIntervalNs, uint32_t frameId) {
|
int64_t refreshIntervalNs, uint32_t frameId) {
|
||||||
FVK_PROFILE_MARKER(PROFILE_NAME_BEGINFRAME);
|
FVK_PROFILE_MARKER(PROFILE_NAME_BEGINFRAME);
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
|
||||||
|
if (mAppState.hasExternalSamplers()) {
|
||||||
|
mExternalImageManager.onBeginFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
|
void VulkanDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
|
||||||
@@ -421,12 +429,16 @@ void VulkanDriver::updateDescriptorSetTexture(
|
|||||||
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
|
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
|
||||||
auto texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
|
auto texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
|
||||||
|
|
||||||
// TODO: YcbcrConversion?
|
if (mExternalImageManager.isExternallySampledTexture(texture)) {
|
||||||
VulkanSamplerCache::Params cacheParams = {
|
mExternalImageManager.bindExternallySampledTexture(set, binding, texture, params);
|
||||||
.sampler = params,
|
mAppState.hasBoundExternalImages = true;
|
||||||
};
|
} else {
|
||||||
VkSampler const vksampler = mSamplerCache.getSampler(cacheParams);
|
VulkanSamplerCache::Params cacheParams = {
|
||||||
mDescriptorSetCache.updateSampler(set, binding, texture, vksampler);
|
.sampler = params,
|
||||||
|
};
|
||||||
|
VkSampler const vksampler = mSamplerCache.getSampler(cacheParams);
|
||||||
|
mDescriptorSetCache.updateSampler(set, binding, texture, vksampler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDriver::flush(int) {
|
void VulkanDriver::flush(int) {
|
||||||
@@ -563,41 +575,35 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
|
|||||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||||
Platform::ExternalImageHandleRef externalImage) {
|
Platform::ExternalImageHandleRef externalImage) {
|
||||||
FVK_SYSTRACE_SCOPE();
|
FVK_SYSTRACE_SCOPE();
|
||||||
auto const& metadata = mPlatform->getExternalImageMetadata(externalImage);
|
auto const& metadata = mPlatform->extractExternalImageMetadata(externalImage);
|
||||||
if (metadata.isProtected) {
|
|
||||||
usage |= backend::TextureUsage::PROTECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageUsageFlags vkUsage = metadata.usage;
|
// In theory the following are reasonable expectations, but in practice it's hard for client's
|
||||||
if (any(usage & TextureUsage::BLIT_SRC)) {
|
// to match up the dimensions of the texture with that of the AHB.
|
||||||
vkUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
// assert_invariant(width == metadata.width);
|
||||||
}
|
// assert_invariant(height == metadata.height);
|
||||||
|
// assert_invariant(format == metadata.filamentFormat);
|
||||||
if (any(usage & (TextureUsage::BLIT_DST | TextureUsage::UPLOADABLE))) {
|
// assert_invariant(fvkutils::getVkFormat(format) == metadata.format);
|
||||||
vkUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_invariant(width == metadata.width);
|
|
||||||
assert_invariant(height == metadata.height);
|
|
||||||
assert_invariant(fvkutils::getVkFormat(format) == metadata.format);
|
|
||||||
|
|
||||||
VkMemoryPropertyFlags const requiredMemoryFlags = any(usage & TextureUsage::UPLOADABLE)
|
|
||||||
? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
|
||||||
: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
|
||||||
uint32_t const memoryTypeIndex =
|
|
||||||
mContext.selectMemoryType(metadata.memoryTypeBits, requiredMemoryFlags);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(memoryTypeIndex != VK_MAX_MEMORY_TYPES)
|
|
||||||
<< "failed to find a valid memory type for external image memory.";
|
|
||||||
|
|
||||||
VkImage vkimg;
|
VkImage vkimg;
|
||||||
VkDeviceMemory deviceMemory;
|
VkDeviceMemory deviceMemory;
|
||||||
std::tie(vkimg, deviceMemory) =
|
std::tie(vkimg, deviceMemory) = mPlatform->createVkImageFromExternal(externalImage);
|
||||||
mPlatform->createExternalImageData(externalImage, metadata, memoryTypeIndex, vkUsage);
|
|
||||||
|
VkSamplerYcbcrConversion conversion =
|
||||||
|
mExternalImageManager.getVkSamplerYcbcrConversion(metadata);
|
||||||
|
|
||||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mContext,
|
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mContext,
|
||||||
mPlatform->getDevice(), mAllocator, &mResourceManager, &mCommands, vkimg, deviceMemory,
|
mPlatform->getDevice(), mAllocator, &mResourceManager, &mCommands, vkimg, deviceMemory,
|
||||||
metadata.format, VK_NULL_HANDLE, metadata.samples, metadata.width, metadata.height,
|
metadata.format, conversion, metadata.samples, metadata.width, metadata.height,
|
||||||
metadata.layerCount, usage, mStagePool);
|
metadata.layers, usage, mStagePool);
|
||||||
|
|
||||||
|
if (conversion != VK_NULL_HANDLE) {
|
||||||
|
mExternalImageManager.addExternallySampledTexture(texture, externalImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlike uploaded textures or swapchains, we need to explicit transition this
|
||||||
|
// texture into the read layout.
|
||||||
|
auto& commands = mCommands.get();
|
||||||
|
texture->transitionLayout(&commands, texture->getPrimaryViewRange(), VulkanLayout::READ_ONLY);
|
||||||
|
|
||||||
texture.inc();
|
texture.inc();
|
||||||
}
|
}
|
||||||
@@ -630,6 +636,8 @@ void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
|
|||||||
}
|
}
|
||||||
auto texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
|
auto texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
|
||||||
texture.dec();
|
texture.dec();
|
||||||
|
|
||||||
|
mExternalImageManager.removeExternallySampledTexture(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||||
@@ -798,6 +806,11 @@ void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
|||||||
fvkmemory::resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
|
fvkmemory::resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
|
||||||
auto set = mDescriptorSetCache.createSet(dsh, layout);
|
auto set = mDescriptorSetCache.createSet(dsh, layout);
|
||||||
set.inc();
|
set.inc();
|
||||||
|
|
||||||
|
if (layout->hasExternalSamplers()) {
|
||||||
|
mAppState.hasExternalSamplerLayouts = true;
|
||||||
|
mExternalImageManager.addDescriptorSet(layout, set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<HwVertexBufferInfo> VulkanDriver::createVertexBufferInfoS() noexcept {
|
Handle<HwVertexBufferInfo> VulkanDriver::createVertexBufferInfoS() noexcept {
|
||||||
@@ -917,11 +930,19 @@ void VulkanDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
|||||||
void VulkanDriver::destroyDescriptorSetLayout(Handle<HwDescriptorSetLayout> dslh) {
|
void VulkanDriver::destroyDescriptorSetLayout(Handle<HwDescriptorSetLayout> dslh) {
|
||||||
auto layout = resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
|
auto layout = resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
|
||||||
layout.dec();
|
layout.dec();
|
||||||
|
|
||||||
|
if (layout->hasExternalSamplers()) {
|
||||||
|
mExternalImageManager.removeDescriptorSetLayout(layout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
|
void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
|
||||||
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
|
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
|
||||||
set.dec();
|
set.dec();
|
||||||
|
|
||||||
|
if (mAppState.hasExternalSamplers()) {
|
||||||
|
mExternalImageManager.removeDescriptorSet(set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream) {
|
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream) {
|
||||||
@@ -1482,7 +1503,6 @@ void VulkanDriver::endRenderPass(int) {
|
|||||||
// pipeline barrier between framebuffer writes and shader reads.
|
// pipeline barrier between framebuffer writes and shader reads.
|
||||||
rt->emitBarriersEndRenderPass(*mCurrentRenderPass.commandBuffer);
|
rt->emitBarriersEndRenderPass(*mCurrentRenderPass.commandBuffer);
|
||||||
|
|
||||||
mRenderPassFboInfo = {};
|
|
||||||
mCurrentRenderPass.renderTarget = {};
|
mCurrentRenderPass.renderTarget = {};
|
||||||
mCurrentRenderPass.renderPass = VK_NULL_HANDLE;
|
mCurrentRenderPass.renderPass = VK_NULL_HANDLE;
|
||||||
|
|
||||||
@@ -1542,10 +1562,10 @@ void VulkanDriver::commit(Handle<HwSwapChain> sch) {
|
|||||||
|
|
||||||
void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||||
backend::PushConstantVariant value) {
|
backend::PushConstantVariant value) {
|
||||||
assert_invariant(mBoundPipeline.program && "Expect a program when writing to push constants");
|
assert_invariant(mPipelineState.program && "Expect a program when writing to push constants");
|
||||||
assert_invariant(mCurrentRenderPass.commandBuffer && "Should be called within a renderpass");
|
assert_invariant(mCurrentRenderPass.commandBuffer && "Should be called within a renderpass");
|
||||||
mBoundPipeline.program->writePushConstant(mCurrentRenderPass.commandBuffer->buffer(),
|
mPipelineState.program->writePushConstant(mCurrentRenderPass.commandBuffer->buffer(),
|
||||||
mBoundPipeline.pipelineLayout, stage, index, value);
|
mPipelineState.pipelineLayout, stage, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDriver::insertEventMarker(char const* string) {
|
void VulkanDriver::insertEventMarker(char const* string) {
|
||||||
@@ -1724,6 +1744,27 @@ void VulkanDriver::blitDEPRECATED(TargetBufferFlags buffers,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||||
|
// We need to determine whether to delay bindning until draw().
|
||||||
|
mPipelineState.bindInDraw.first = false;
|
||||||
|
if (mAppState.hasExternalSamplers()) {
|
||||||
|
auto& layouts = pipelineState.pipelineLayout.setLayout;
|
||||||
|
auto haveExternalSamplers = [&](auto hwHandle) {
|
||||||
|
if (!hwHandle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto layout =
|
||||||
|
resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, hwHandle);
|
||||||
|
return layout->hasExternalSamplers();
|
||||||
|
};
|
||||||
|
if (std::any_of(layouts.begin(), layouts.end(), haveExternalSamplers)) {
|
||||||
|
mPipelineState.bindInDraw = { true, pipelineState };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bindPipelineImpl(pipelineState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanDriver::bindPipelineImpl(PipelineState const& pipelineState) {
|
||||||
FVK_SYSTRACE_SCOPE();
|
FVK_SYSTRACE_SCOPE();
|
||||||
auto commands = mCurrentRenderPass.commandBuffer;
|
auto commands = mCurrentRenderPass.commandBuffer;
|
||||||
auto vbi = resource_ptr<VulkanVertexBufferInfo>::cast(&mResourceManager,
|
auto vbi = resource_ptr<VulkanVertexBufferInfo>::cast(&mResourceManager,
|
||||||
@@ -1792,10 +1833,11 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
|||||||
|
|
||||||
constexpr uint8_t descriptorSetMaskTable[4] = {0x1, 0x3, 0x7, 0xF};
|
constexpr uint8_t descriptorSetMaskTable[4] = {0x1, 0x3, 0x7, 0xF};
|
||||||
|
|
||||||
mBoundPipeline = {
|
mPipelineState = {
|
||||||
.program = program,
|
.program = program,
|
||||||
.pipelineLayout = pipelineLayout,
|
.pipelineLayout = pipelineLayout,
|
||||||
.descriptorSetMask = fvkutils::DescriptorSetMask(descriptorSetMaskTable[layoutCount]),
|
.descriptorSetMask = fvkutils::DescriptorSetMask(descriptorSetMaskTable[layoutCount]),
|
||||||
|
.bindInDraw = {false, {}},
|
||||||
};
|
};
|
||||||
|
|
||||||
mPipelineCache.bindLayout(pipelineLayout);
|
mPipelineCache.bindLayout(pipelineLayout);
|
||||||
@@ -1842,14 +1884,24 @@ void VulkanDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t ins
|
|||||||
FVK_SYSTRACE_SCOPE();
|
FVK_SYSTRACE_SCOPE();
|
||||||
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();
|
VkCommandBuffer cmdbuffer = mCurrentRenderPass.commandBuffer->buffer();
|
||||||
|
|
||||||
|
if (mAppState.hasExternalSamplers()) {
|
||||||
|
auto const& [bindInDraw, pipelineSt] = mPipelineState.bindInDraw;
|
||||||
|
bool const hasUpdated =
|
||||||
|
mExternalImageManager.prepareBindSets(mDescriptorSetCache.getBoundSets());
|
||||||
|
if (bindInDraw || hasUpdated) {
|
||||||
|
bindPipelineImpl(pipelineSt);
|
||||||
|
}
|
||||||
|
mPipelineState.bindInDraw.first = false;
|
||||||
|
}
|
||||||
|
|
||||||
mDescriptorSetCache.commit(mCurrentRenderPass.commandBuffer,
|
mDescriptorSetCache.commit(mCurrentRenderPass.commandBuffer,
|
||||||
mBoundPipeline.pipelineLayout,
|
mPipelineState.pipelineLayout,
|
||||||
mBoundPipeline.descriptorSetMask);
|
mPipelineState.descriptorSetMask);
|
||||||
|
|
||||||
// Finally, make the actual draw call. TODO: support subranges
|
// Finally, make the actual draw call. TODO: support subranges
|
||||||
const uint32_t firstIndex = indexOffset;
|
uint32_t const firstIndex = indexOffset;
|
||||||
const int32_t vertexOffset = 0;
|
constexpr int32_t vertexOffset = 0;
|
||||||
const uint32_t firstInstId = 0;
|
constexpr uint32_t firstInstId = 0;
|
||||||
|
|
||||||
vkCmdDrawIndexed(cmdbuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstId);
|
vkCmdDrawIndexed(cmdbuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "VulkanYcbcrConversionCache.h"
|
#include "VulkanYcbcrConversionCache.h"
|
||||||
#include "vulkan/VulkanDescriptorSetCache.h"
|
#include "vulkan/VulkanDescriptorSetCache.h"
|
||||||
#include "vulkan/VulkanDescriptorSetLayoutCache.h"
|
#include "vulkan/VulkanDescriptorSetLayoutCache.h"
|
||||||
|
#include "vulkan/VulkanExternalImageManager.h"
|
||||||
#include "vulkan/VulkanPipelineLayoutCache.h"
|
#include "vulkan/VulkanPipelineLayoutCache.h"
|
||||||
#include "vulkan/memory/ResourceManager.h"
|
#include "vulkan/memory/ResourceManager.h"
|
||||||
#include "vulkan/memory/ResourcePointer.h"
|
#include "vulkan/memory/ResourcePointer.h"
|
||||||
@@ -119,6 +120,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void collectGarbage();
|
void collectGarbage();
|
||||||
|
void bindPipelineImpl(PipelineState const& pipelineState);
|
||||||
|
|
||||||
VulkanPlatform* mPlatform = nullptr;
|
VulkanPlatform* mPlatform = nullptr;
|
||||||
fvkmemory::ResourceManager mResourceManager;
|
fvkmemory::ResourceManager mResourceManager;
|
||||||
@@ -143,21 +145,29 @@ private:
|
|||||||
VulkanDescriptorSetLayoutCache mDescriptorSetLayoutCache;
|
VulkanDescriptorSetLayoutCache mDescriptorSetLayoutCache;
|
||||||
VulkanDescriptorSetCache mDescriptorSetCache;
|
VulkanDescriptorSetCache mDescriptorSetCache;
|
||||||
VulkanQueryManager mQueryManager;
|
VulkanQueryManager mQueryManager;
|
||||||
|
VulkanExternalImageManager mExternalImageManager;
|
||||||
|
|
||||||
// This is necessary for us to write to push constants after binding a pipeline.
|
// This is necessary for us to write to push constants after binding a pipeline.
|
||||||
struct {
|
struct {
|
||||||
|
// For push constant
|
||||||
resource_ptr<VulkanProgram> program;
|
resource_ptr<VulkanProgram> program;
|
||||||
|
// For push commiting dynamic ubos in draw()
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
fvkutils::DescriptorSetMask descriptorSetMask;
|
fvkutils::DescriptorSetMask descriptorSetMask;
|
||||||
} mBoundPipeline = {};
|
|
||||||
|
|
||||||
// We need to store information about a render pass to enable better barriers at the end of a
|
std::pair<bool, PipelineState> bindInDraw = {false, {}};
|
||||||
// renderpass.
|
} mPipelineState = {};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
using AttachmentArray =
|
// This tracks whether the app has seen external samplers bound to a the descriptor set.
|
||||||
fvkutils::StaticVector<VulkanAttachment, MAX_RENDERTARGET_ATTACHMENT_TEXTURES>;
|
// This will force bindPipeline to take a slow path.
|
||||||
AttachmentArray attachments;
|
bool hasExternalSamplerLayouts = false;
|
||||||
} mRenderPassFboInfo = {};
|
bool hasBoundExternalImages = false;
|
||||||
|
|
||||||
|
bool hasExternalSamplers() const noexcept {
|
||||||
|
return hasExternalSamplerLayouts && hasBoundExternalImages;
|
||||||
|
}
|
||||||
|
} mAppState;
|
||||||
|
|
||||||
bool const mIsSRGBSwapChainSupported;
|
bool const mIsSRGBSwapChainSupported;
|
||||||
backend::StereoscopicType const mStereoscopicType;
|
backend::StereoscopicType const mStereoscopicType;
|
||||||
|
|||||||
280
filament/backend/src/vulkan/VulkanExternalImageManager.cpp
Normal file
280
filament/backend/src/vulkan/VulkanExternalImageManager.cpp
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 "VulkanExternalImageManager.h"
|
||||||
|
|
||||||
|
#include "VulkanDescriptorSetCache.h"
|
||||||
|
#include "VulkanDescriptorSetLayoutCache.h"
|
||||||
|
#include "VulkanSamplerCache.h"
|
||||||
|
#include "VulkanYcbcrConversionCache.h"
|
||||||
|
#include "vulkan/memory/ResourcePointer.h"
|
||||||
|
#include "vulkan/utils/Conversion.h"
|
||||||
|
|
||||||
|
#include <backend/platforms/VulkanPlatform.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void erase(std::vector<T>& v, std::function<bool(T const&)> f) {
|
||||||
|
auto newEnd = std::remove_if(v.begin(), v.end(), f);
|
||||||
|
v.erase(newEnd, v.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous
|
||||||
|
|
||||||
|
VulkanExternalImageManager::VulkanExternalImageManager(VulkanPlatform* platform,
|
||||||
|
VulkanSamplerCache* samplerCache, VulkanYcbcrConversionCache* ycbcrConversionCache,
|
||||||
|
VulkanDescriptorSetCache* setCache, VulkanDescriptorSetLayoutCache* layoutCache)
|
||||||
|
: mPlatform(platform),
|
||||||
|
mSamplerCache(samplerCache),
|
||||||
|
mYcbcrConversionCache(ycbcrConversionCache),
|
||||||
|
mDescriptorSetCache(setCache),
|
||||||
|
mDescriptorSetLayoutCache(layoutCache) {
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanExternalImageManager::~VulkanExternalImageManager() = default;
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::terminate() {
|
||||||
|
mSetAndLayouts.clear();
|
||||||
|
mSetBindings.clear();
|
||||||
|
mImages.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::onBeginFrame() {
|
||||||
|
std::for_each(mImages.begin(), mImages.end(), [](ImageData& image) {
|
||||||
|
image.hasBeenValidated = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanExternalImageManager::prepareBindSets(SetArray const& sets) {
|
||||||
|
bool hasUpdated = false;
|
||||||
|
for (auto set: sets) {
|
||||||
|
if (!set) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (auto itr = std::find_if(mSetAndLayouts.begin(), mSetAndLayouts.end(),
|
||||||
|
[&](auto const& setAndLayout) { return setAndLayout.first == set; });
|
||||||
|
itr != mSetAndLayouts.end()) {
|
||||||
|
hasUpdated = updateSetAndLayout(itr->first, itr->second) || hasUpdated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanExternalImageManager::updateSetAndLayout(
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSet> set,
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout) {
|
||||||
|
auto findImage = [&](fvkmemory::resource_ptr<VulkanTexture> texture) -> ImageData* {
|
||||||
|
auto itr = std::find_if(mImages.begin(), mImages.end(), [&](ImageData const& data) {
|
||||||
|
return data.ptr == texture;
|
||||||
|
});
|
||||||
|
assert_invariant(itr != mImages.end());
|
||||||
|
return &(*itr);
|
||||||
|
};
|
||||||
|
|
||||||
|
//std::vector<std::pair<uint8_t, ImageData*>> externalImages;
|
||||||
|
utils::FixedCapacityVector<std::pair<uint8_t, VkSampler>> samplerAndBindings;
|
||||||
|
samplerAndBindings.reserve(MAX_SAMPLER_COUNT);
|
||||||
|
|
||||||
|
bool hasImageUpdates = false;
|
||||||
|
for (auto& bindingInfo : mSetBindings) {
|
||||||
|
if (bindingInfo.set != set) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto imageData = findImage(bindingInfo.image);
|
||||||
|
hasImageUpdates = updateImage(imageData) || hasImageUpdates;
|
||||||
|
|
||||||
|
auto samplerParams = bindingInfo.samplerParams;
|
||||||
|
// according to spec, these must match chromaFilter
|
||||||
|
// https://registry.khronos.org/vulkan/specs/latest/man/html/VkSamplerCreateInfo.html#VUID-VkSamplerCreateInfo-minFilter-01645
|
||||||
|
samplerParams.filterMag = SamplerMagFilter::NEAREST;
|
||||||
|
samplerParams.filterMin = SamplerMinFilter::NEAREST;
|
||||||
|
|
||||||
|
auto sampler = mSamplerCache->getSampler({
|
||||||
|
.sampler = samplerParams,
|
||||||
|
.conversion = imageData->conversion,
|
||||||
|
});
|
||||||
|
samplerAndBindings.push_back({ bindingInfo.binding, sampler });
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to sort by binding number
|
||||||
|
std::sort(samplerAndBindings.begin(), samplerAndBindings.end());
|
||||||
|
|
||||||
|
utils::FixedCapacityVector<VkSampler> outSamplers;
|
||||||
|
outSamplers.reserve(MAX_SAMPLER_COUNT);
|
||||||
|
std::for_each(samplerAndBindings.begin(), samplerAndBindings.end(),
|
||||||
|
[&](auto const& b) { outSamplers.push_back(b.second); });
|
||||||
|
|
||||||
|
VkDescriptorSetLayout const oldLayout = layout->getVkLayout();
|
||||||
|
VkDescriptorSetLayout const newLayout =
|
||||||
|
mDescriptorSetLayoutCache->getVkLayout(layout->bitmask, outSamplers);
|
||||||
|
bool const hasLayoutUpdate = oldLayout != newLayout;
|
||||||
|
layout->setVkLayout(newLayout);
|
||||||
|
|
||||||
|
assert_invariant(
|
||||||
|
(!hasImageUpdates && !hasLayoutUpdate) ||
|
||||||
|
(hasImageUpdates && hasLayoutUpdate));
|
||||||
|
|
||||||
|
if (!hasLayoutUpdate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto foldBitsInHalf = [](auto bitset) {
|
||||||
|
constexpr size_t BITMASK_LOWER_BITS_LEN = sizeof(bitset) * 4;
|
||||||
|
decltype(bitset) outBitset;
|
||||||
|
bitset.forEachSetBit([&](size_t index) { outBitset.set(index % BITMASK_LOWER_BITS_LEN); });
|
||||||
|
return outBitset;
|
||||||
|
};
|
||||||
|
// We need to build a new descriptor set from the new layout
|
||||||
|
VkDescriptorSet oldSet = set->getVkSet();
|
||||||
|
VkDescriptorSet newSet = mDescriptorSetCache->getVkSet(layout);
|
||||||
|
|
||||||
|
using Bitmask = fvkutils::UniformBufferBitmask;
|
||||||
|
static_assert(sizeof(Bitmask) * 8 == fvkutils::MAX_DESCRIPTOR_SET_BITMASK_BITS);
|
||||||
|
|
||||||
|
auto const ubo = layout->bitmask.ubo | layout->bitmask.dynamicUbo;
|
||||||
|
auto const samplers = layout->bitmask.sampler & (~layout->bitmask.externalSampler);
|
||||||
|
|
||||||
|
// each bitmask denotes a binding index, and separated into two stages - vertex and buffer
|
||||||
|
// We fold the two stages into just the lower half of the bits to denote a combined set of
|
||||||
|
// bindings.
|
||||||
|
Bitmask const copyBindings = foldBitsInHalf(ubo | samplers);
|
||||||
|
|
||||||
|
// TODO: fix the size for better memory
|
||||||
|
std::vector<VkCopyDescriptorSet> copies;
|
||||||
|
copyBindings.forEachSetBit([&](size_t index) {
|
||||||
|
copies.push_back({
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,
|
||||||
|
.srcSet = oldSet,
|
||||||
|
.srcBinding = (uint32_t) index,
|
||||||
|
.dstSet = newSet,
|
||||||
|
.dstBinding = (uint32_t) index,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
vkUpdateDescriptorSets(mPlatform->getDevice(), 0, nullptr, copies.size(), copies.data());
|
||||||
|
|
||||||
|
set->setVkSet(newSet);
|
||||||
|
|
||||||
|
// We need to release the vkset, which is no longer used, back into the pool.
|
||||||
|
mDescriptorSetCache->manualRecyle(layout->count, oldLayout, oldSet);
|
||||||
|
|
||||||
|
// We need to update the external samplers in the set
|
||||||
|
for (auto& bindingInfo: mSetBindings) {
|
||||||
|
if (bindingInfo.set != set) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mDescriptorSetCache->updateSampler(set, bindingInfo.binding, bindingInfo.image,
|
||||||
|
VK_NULL_HANDLE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSamplerYcbcrConversion VulkanExternalImageManager::getVkSamplerYcbcrConversion(
|
||||||
|
VulkanPlatform::ExternalImageMetadata const& metadata) {
|
||||||
|
// This external image does not require external sampler (YUV conversion).
|
||||||
|
if (metadata.externalFormat == 0) {
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
VulkanYcbcrConversionCache::Params ycbcrParams = {
|
||||||
|
.conversion = {
|
||||||
|
.ycbcrModel = fvkutils::getYcbcrModelConversionFilament(metadata.ycbcrModel),
|
||||||
|
.r = fvkutils::getSwizzleFilament(metadata.ycbcrConversionComponents.r, 0),
|
||||||
|
.g = fvkutils::getSwizzleFilament(metadata.ycbcrConversionComponents.g, 1),
|
||||||
|
.b = fvkutils::getSwizzleFilament(metadata.ycbcrConversionComponents.b, 2),
|
||||||
|
.a = fvkutils::getSwizzleFilament(metadata.ycbcrConversionComponents.a, 3),
|
||||||
|
.ycbcrRange = fvkutils::getYcbcrRangeFilament(metadata.ycbcrRange),
|
||||||
|
.xChromaOffset = fvkutils::getChromaLocationFilament(metadata.xChromaOffset),
|
||||||
|
.yChromaOffset = fvkutils::getChromaLocationFilament(metadata.yChromaOffset),
|
||||||
|
|
||||||
|
// Unclear where to get the chromaFilter, we just assume it's nearest.
|
||||||
|
.chromaFilter = SamplerMagFilter::NEAREST,
|
||||||
|
},
|
||||||
|
.format = metadata.filamentFormat,
|
||||||
|
.externalFormat = metadata.externalFormat,
|
||||||
|
};
|
||||||
|
return mYcbcrConversionCache->getConversion(ycbcrParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanExternalImageManager::updateImage(ImageData* image) {
|
||||||
|
if (image->hasBeenValidated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
image->hasBeenValidated = true;
|
||||||
|
|
||||||
|
auto metadata = mPlatform->extractExternalImageMetadata(image->platformHandle);
|
||||||
|
auto vkYcbcr = getVkSamplerYcbcrConversion(metadata);
|
||||||
|
if (vkYcbcr == image->conversion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->ptr->setYcbcrConversion(vkYcbcr, metadata.externalFormat != 0);
|
||||||
|
image->conversion = vkYcbcr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::addDescriptorSet(
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout,
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSet> set) {
|
||||||
|
mSetAndLayouts.push_back({set, layout});
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::removeDescriptorSet(
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSet> inSet) {
|
||||||
|
erase<SetAndLayout>(mSetAndLayouts,
|
||||||
|
[&](auto const& setLayout) { return (setLayout.first == inSet); });
|
||||||
|
erase<SetBindingInfo>(mSetBindings,
|
||||||
|
[&](auto const& bindingInfo) { return (bindingInfo.set == inSet); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::removeDescriptorSetLayout(
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> inLayout) {
|
||||||
|
erase<SetAndLayout>(mSetAndLayouts,
|
||||||
|
[&](auto const& setLayout) { return (setLayout.second == inLayout); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::bindExternallySampledTexture(
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSet> set, uint8_t bindingPoint,
|
||||||
|
fvkmemory::resource_ptr<VulkanTexture> image, SamplerParams samplerParams) {
|
||||||
|
// Should we do duplicate validation here?
|
||||||
|
mSetBindings.push_back({ bindingPoint, image, set, samplerParams });
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::addExternallySampledTexture(
|
||||||
|
fvkmemory::resource_ptr<VulkanTexture> image,
|
||||||
|
Platform::ExternalImageHandleRef platformHandleRef) {
|
||||||
|
mImages.push_back({ image, platformHandleRef, false });
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanExternalImageManager::removeExternallySampledTexture(
|
||||||
|
fvkmemory::resource_ptr<VulkanTexture> image) {
|
||||||
|
erase<SetBindingInfo>(mSetBindings,
|
||||||
|
[&](auto const& bindingInfo) { return (bindingInfo.image == image); });
|
||||||
|
erase<ImageData>(mImages, [&](auto const& imageData) { return imageData.ptr == image; });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanExternalImageManager::isExternallySampledTexture(
|
||||||
|
fvkmemory::resource_ptr<VulkanTexture> image) const {
|
||||||
|
return std::find_if(mImages.begin(), mImages.end(),
|
||||||
|
[&](auto const& imageData) { return imageData.ptr == image; }) != mImages.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namesapce filament::backend
|
||||||
115
filament/backend/src/vulkan/VulkanExternalImageManager.h
Normal file
115
filament/backend/src/vulkan/VulkanExternalImageManager.h
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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_BACKEND_CACHING_VULKANEXTERNALIMAGEMANAGER_H
|
||||||
|
#define TNT_FILAMENT_BACKEND_CACHING_VULKANEXTERNALIMAGEMANAGER_H
|
||||||
|
|
||||||
|
#include "VulkanHandles.h"
|
||||||
|
|
||||||
|
#include <backend/DriverEnums.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
class VulkanYcbcrConversionCache;
|
||||||
|
class VulkanSamplerCache;
|
||||||
|
class VulkanDescriptorSetLayoutCache;
|
||||||
|
class VulkanDescriptorSetCache;
|
||||||
|
|
||||||
|
// Manages the logic of external images and their quirks wrt Vulikan.
|
||||||
|
class VulkanExternalImageManager {
|
||||||
|
public:
|
||||||
|
|
||||||
|
VulkanExternalImageManager(
|
||||||
|
VulkanPlatform* platform,
|
||||||
|
VulkanSamplerCache* samplerCache,
|
||||||
|
VulkanYcbcrConversionCache* ycbcrConversionCache,
|
||||||
|
VulkanDescriptorSetCache* setCache,
|
||||||
|
VulkanDescriptorSetLayoutCache* layoutCache);
|
||||||
|
|
||||||
|
~VulkanExternalImageManager();
|
||||||
|
|
||||||
|
void terminate();
|
||||||
|
|
||||||
|
void onBeginFrame();
|
||||||
|
|
||||||
|
using SetArray = std::array<fvkmemory::resource_ptr<VulkanDescriptorSet>,
|
||||||
|
VulkanDescriptorSetLayout::UNIQUE_DESCRIPTOR_SET_COUNT>;
|
||||||
|
|
||||||
|
// This sets the currently bound layouts objects for the pipeline
|
||||||
|
bool prepareBindSets(SetArray const& layouts);
|
||||||
|
|
||||||
|
void addDescriptorSet(fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout,
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSet> set);
|
||||||
|
|
||||||
|
void removeDescriptorSetLayout(fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout);
|
||||||
|
|
||||||
|
void removeDescriptorSet(fvkmemory::resource_ptr<VulkanDescriptorSet> set);
|
||||||
|
|
||||||
|
void bindExternallySampledTexture(fvkmemory::resource_ptr<VulkanDescriptorSet> set,
|
||||||
|
uint8_t bindingPoint, fvkmemory::resource_ptr<VulkanTexture> image,
|
||||||
|
SamplerParams samplerParams);
|
||||||
|
|
||||||
|
void addExternallySampledTexture(fvkmemory::resource_ptr<VulkanTexture> image,
|
||||||
|
Platform::ExternalImageHandleRef platformHandleRef);
|
||||||
|
|
||||||
|
void removeExternallySampledTexture(fvkmemory::resource_ptr<VulkanTexture> image);
|
||||||
|
|
||||||
|
bool isExternallySampledTexture(fvkmemory::resource_ptr<VulkanTexture> image) const;
|
||||||
|
|
||||||
|
VkSamplerYcbcrConversion getVkSamplerYcbcrConversion(
|
||||||
|
VulkanPlatform::ExternalImageMetadata const& metadata);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct ImageData {
|
||||||
|
fvkmemory::resource_ptr<VulkanTexture> ptr;
|
||||||
|
Platform::ExternalImageHandle platformHandle;
|
||||||
|
bool hasBeenValidated = false; // indicates whether the image has been validated *this frame*
|
||||||
|
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool updateSetAndLayout(fvkmemory::resource_ptr<VulkanDescriptorSet> set,
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout);
|
||||||
|
bool updateImage(ImageData* imageData);
|
||||||
|
|
||||||
|
VulkanPlatform* mPlatform;
|
||||||
|
VulkanSamplerCache* mSamplerCache;
|
||||||
|
VulkanYcbcrConversionCache* mYcbcrConversionCache;
|
||||||
|
VulkanDescriptorSetCache* mDescriptorSetCache;
|
||||||
|
VulkanDescriptorSetLayoutCache* mDescriptorSetLayoutCache;
|
||||||
|
|
||||||
|
using SetAndLayout = std::pair<fvkmemory::resource_ptr<VulkanDescriptorSet>,
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSetLayout>>;
|
||||||
|
|
||||||
|
struct SetBindingInfo {
|
||||||
|
uint8_t binding = 0;
|
||||||
|
fvkmemory::resource_ptr<VulkanTexture> image;
|
||||||
|
fvkmemory::resource_ptr<VulkanDescriptorSet> set;
|
||||||
|
SamplerParams samplerParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use vectors instead of hash maps because we only expect small number of entries.
|
||||||
|
std::vector<SetAndLayout> mSetAndLayouts;
|
||||||
|
std::vector<SetBindingInfo> mSetBindings;
|
||||||
|
std::vector<ImageData> mImages;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // filament::backend
|
||||||
|
|
||||||
|
#endif // TNT_FILAMENT_BACKEND_CACHING_VULKANEXTERNALIMAGEMANAGER_H
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "VulkanConstants.h"
|
#include "VulkanConstants.h"
|
||||||
#include "vulkan/utils/Conversion.h"
|
#include "vulkan/utils/Conversion.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,10 @@ public:
|
|||||||
return id() == other.id() && type() == other.type();
|
return id() == other.id() && type() == other.type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(resource_ptr<D> const& other) const {
|
||||||
|
return !((*this) == other);
|
||||||
|
}
|
||||||
|
|
||||||
inline explicit operator bool() const {
|
inline explicit operator bool() const {
|
||||||
return bool(mRef);
|
return bool(mRef);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -993,30 +993,6 @@ VkQueue VulkanPlatform::getProtectedGraphicsQueue() const noexcept {
|
|||||||
return mImpl->mProtectedGraphicsQueue;
|
return mImpl->mProtectedGraphicsQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadata(
|
|
||||||
ExternalImageHandleRef externalImage) {
|
|
||||||
return getExternalImageMetadataImpl(externalImage, mImpl->mDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageData(
|
|
||||||
ExternalImageHandleRef externalImage, const ExternalImageMetadata& metadata,
|
|
||||||
uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
|
||||||
return createExternalImageDataImpl(externalImage, mImpl->mDevice, metadata, memoryTypeIndex,
|
|
||||||
usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSampler VulkanPlatform::createExternalSampler(SamplerYcbcrConversion chroma,
|
|
||||||
SamplerParams sampler, uint32_t internalFormat) {
|
|
||||||
return createExternalSamplerImpl(mImpl->mDevice, chroma, sampler, internalFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageView VulkanPlatform::createExternalImageView(SamplerYcbcrConversion chroma,
|
|
||||||
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
|
|
||||||
VkImageViewType viewType, VkComponentMapping swizzle) {
|
|
||||||
return createExternalImageViewImpl(mImpl->mDevice, chroma, internalFormat, image, range,
|
|
||||||
viewType, swizzle);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() const {
|
ExtensionSet VulkanPlatform::getSwapchainInstanceExtensions() const {
|
||||||
return getSwapchainInstanceExtensionsImpl();
|
return getSwapchainInstanceExtensionsImpl();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
#include <backend/platforms/VulkanPlatformAndroid.h>
|
#include <backend/platforms/VulkanPlatformAndroid.h>
|
||||||
|
|
||||||
|
#include "vulkan/VulkanConstants.h"
|
||||||
|
#include "vulkan/VulkanContext.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
#include <private/backend/BackendUtilsAndroid.h>
|
#include <private/backend/BackendUtilsAndroid.h>
|
||||||
|
|
||||||
#include "vulkan/VulkanConstants.h"
|
|
||||||
|
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include "vulkan/utils/Image.h"
|
|
||||||
#include "vulkan/utils/Conversion.h"
|
|
||||||
|
|
||||||
#include <bluevk/BlueVK.h>
|
#include <bluevk/BlueVK.h>
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ VkFormat transformVkFormat(VkFormat format, bool sRGB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isProtectedFromUsage(uint64_t usage) {
|
bool isProtectedFromUsage(uint64_t usage) {
|
||||||
return (usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) ? true : false;
|
return usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer_Desc& desc,
|
std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer_Desc& desc,
|
||||||
@@ -120,7 +120,9 @@ std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer
|
|||||||
usage = 0;
|
usage = 0;
|
||||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
|
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
|
||||||
usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
|
||||||
|
// We shouldn't be using external samplers as input attachments
|
||||||
|
// usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||||
}
|
}
|
||||||
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) {
|
if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) {
|
||||||
if (isDepthFormat) {
|
if (isDepthFormat) {
|
||||||
@@ -136,87 +138,38 @@ std::pair<VkFormat, VkImageUsageFlags> getVKFormatAndUsage(const AHardwareBuffer
|
|||||||
return { format, usage };
|
return { format, usage };
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanPlatform::ImageData allocateExternalImage(AHardwareBuffer* buffer, VkDevice device,
|
std::pair<TextureFormat, TextureUsage> getFilamentFormatAndUsage(const AHardwareBuffer_Desc& desc,
|
||||||
VulkanPlatform::ExternalImageMetadata const& metadata, uint32_t memoryTypeIndex,
|
bool sRGB) {
|
||||||
VkImageUsageFlags usage) {
|
auto const format = mapToFilamentFormat(desc.format, sRGB);
|
||||||
VulkanPlatform::ImageData data;
|
return {
|
||||||
|
format,
|
||||||
// if external format we need to specifiy it in the allocation
|
mapToFilamentUsage(desc.usage, format),
|
||||||
const bool useExternalFormat = metadata.format == VK_FORMAT_UNDEFINED;
|
|
||||||
|
|
||||||
const VkExternalFormatANDROID externalFormat = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
|
||||||
.pNext = nullptr,
|
|
||||||
// pass down the format (external means we don't have it VK defined)
|
|
||||||
.externalFormat = metadata.externalFormat,
|
|
||||||
};
|
};
|
||||||
const VkExternalMemoryImageCreateInfo externalCreateInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
|
||||||
.pNext = useExternalFormat ? &externalFormat : nullptr,
|
|
||||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkImageCreateInfo imageInfo{ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
|
||||||
imageInfo.pNext = &externalCreateInfo;
|
|
||||||
imageInfo.format = metadata.format;
|
|
||||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
||||||
imageInfo.extent = {
|
|
||||||
metadata.width,
|
|
||||||
metadata.height,
|
|
||||||
1u,
|
|
||||||
};
|
|
||||||
imageInfo.mipLevels = 1;
|
|
||||||
imageInfo.arrayLayers = metadata.layers;
|
|
||||||
imageInfo.samples = metadata.samples;
|
|
||||||
imageInfo.usage = usage;
|
|
||||||
|
|
||||||
VkResult result = vkCreateImage(device, &imageInfo, VKALLOC, &data.first);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
||||||
<< "vkCreateImage failed with error=" << static_cast<int32_t>(result);
|
|
||||||
|
|
||||||
// Allocate the memory
|
|
||||||
VkImportAndroidHardwareBufferInfoANDROID androidHardwareBufferInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.buffer = buffer,
|
|
||||||
};
|
|
||||||
VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
|
||||||
.pNext = &androidHardwareBufferInfo,
|
|
||||||
.image = data.first,
|
|
||||||
.buffer = VK_NULL_HANDLE,
|
|
||||||
};
|
|
||||||
VkMemoryAllocateInfo allocInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
||||||
.pNext = &memoryDedicatedAllocateInfo,
|
|
||||||
.allocationSize = metadata.allocationSize,
|
|
||||||
.memoryTypeIndex = memoryTypeIndex,
|
|
||||||
};
|
|
||||||
result = vkAllocateMemory(device, &allocInfo, VKALLOC, &data.second);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
||||||
<< "vkAllocateMemory failed with error=" << static_cast<int32_t>(result);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}// namespace
|
}// namespace
|
||||||
|
|
||||||
VulkanPlatformAndroid::ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid() = default;
|
VulkanPlatformAndroid::ExternalImageVulkanAndroid::~ExternalImageVulkanAndroid() {
|
||||||
|
if (__builtin_available(android 26, *)) {
|
||||||
|
if (aHardwareBuffer) {
|
||||||
|
AHardwareBuffer_release(aHardwareBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Platform::ExternalImageHandle VulkanPlatformAndroid::createExternalImage(
|
Platform::ExternalImageHandle VulkanPlatformAndroid::createExternalImage(
|
||||||
AHardwareBuffer const* buffer, bool sRGB) noexcept {
|
AHardwareBuffer const* buffer, bool sRGB) noexcept {
|
||||||
if (__builtin_available(android 26, *)) {
|
if (__builtin_available(android 26, *)) {
|
||||||
|
auto bufferImpl = const_cast<AHardwareBuffer*>(buffer);
|
||||||
|
AHardwareBuffer_acquire(bufferImpl);
|
||||||
|
|
||||||
AHardwareBuffer_Desc hardwareBufferDescription = {};
|
AHardwareBuffer_Desc hardwareBufferDescription = {};
|
||||||
AHardwareBuffer_describe(buffer, &hardwareBufferDescription);
|
AHardwareBuffer_describe(buffer, &hardwareBufferDescription);
|
||||||
|
|
||||||
auto* const p = new (std::nothrow) ExternalImageVulkanAndroid;
|
auto* const p = new (std::nothrow) ExternalImageVulkanAndroid;
|
||||||
p->aHardwareBuffer = const_cast<AHardwareBuffer*>(buffer);
|
p->aHardwareBuffer = const_cast<AHardwareBuffer*>(buffer);
|
||||||
p->sRGB = sRGB;
|
p->sRGB = sRGB;
|
||||||
p->height = hardwareBufferDescription.height;
|
|
||||||
p->width = hardwareBufferDescription.width;
|
|
||||||
TextureFormat textureFormat = mapToFilamentFormat(hardwareBufferDescription.format, sRGB);
|
|
||||||
p->format = textureFormat;
|
|
||||||
p->usage = mapToFilamentUsage(hardwareBufferDescription.usage, textureFormat);
|
|
||||||
return Platform::ExternalImageHandle{ p };
|
return Platform::ExternalImageHandle{ p };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,23 +178,20 @@ Platform::ExternalImageHandle VulkanPlatformAndroid::createExternalImage(
|
|||||||
|
|
||||||
VulkanPlatformAndroid::ExternalImageDescAndroid VulkanPlatformAndroid::getExternalImageDesc(
|
VulkanPlatformAndroid::ExternalImageDescAndroid VulkanPlatformAndroid::getExternalImageDesc(
|
||||||
ExternalImageHandleRef externalImage) const noexcept {
|
ExternalImageHandleRef externalImage) const noexcept {
|
||||||
auto const* fvkExternalImage =
|
auto metadata = extractExternalImageMetadata(externalImage);
|
||||||
static_cast<ExternalImageVulkanAndroid const*>(externalImage.get());
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
.width = fvkExternalImage->width,
|
.width = metadata.width,
|
||||||
.height = fvkExternalImage->height,
|
.height = metadata.height,
|
||||||
.format = fvkExternalImage->format,
|
.format = metadata.filamentFormat,
|
||||||
.usage = fvkExternalImage->usage,
|
.usage = metadata.filamentUsage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanPlatform::ExternalImageMetadata VulkanPlatformAndroid::getExternalImageMetadata(
|
VulkanPlatform::ExternalImageMetadata VulkanPlatformAndroid::extractExternalImageMetadata(
|
||||||
ExternalImageHandleRef externalImage) {
|
ExternalImageHandleRef image) const {
|
||||||
auto const* fvkExternalImage =
|
auto const* fvkExternalImage = static_cast<ExternalImageVulkanAndroid const*>(image.get());
|
||||||
static_cast<ExternalImageVulkanAndroid const*>(externalImage.get());
|
|
||||||
|
|
||||||
ExternalImageMetadata metadata;
|
ExternalImageMetadata metadata = {};
|
||||||
AHardwareBuffer* buffer = fvkExternalImage->aHardwareBuffer;
|
AHardwareBuffer* buffer = fvkExternalImage->aHardwareBuffer;
|
||||||
if (__builtin_available(android 26, *)) {
|
if (__builtin_available(android 26, *)) {
|
||||||
AHardwareBuffer_Desc bufferDesc;
|
AHardwareBuffer_Desc bufferDesc;
|
||||||
@@ -249,16 +199,30 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatformAndroid::getExternalImageMet
|
|||||||
metadata.width = bufferDesc.width;
|
metadata.width = bufferDesc.width;
|
||||||
metadata.height = bufferDesc.height;
|
metadata.height = bufferDesc.height;
|
||||||
metadata.layers = bufferDesc.layers;
|
metadata.layers = bufferDesc.layers;
|
||||||
metadata.isProtected = isProtectedFromUsage(bufferDesc.usage);
|
|
||||||
std::tie(metadata.format, metadata.usage) =
|
std::tie(metadata.format, metadata.usage) =
|
||||||
getVKFormatAndUsage(bufferDesc, fvkExternalImage->sRGB);
|
getVKFormatAndUsage(bufferDesc, fvkExternalImage->sRGB);
|
||||||
}
|
std::tie(metadata.filamentFormat, metadata.filamentUsage) =
|
||||||
|
getFilamentFormatAndUsage(bufferDesc, fvkExternalImage->sRGB);
|
||||||
|
|
||||||
|
if (isProtectedFromUsage(bufferDesc.usage)) {
|
||||||
|
metadata.filamentUsage |= TextureUsage::PROTECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: The following seems unnecessary. we should be able to discern directly from the
|
||||||
|
// bufferDesc.
|
||||||
|
if (any(metadata.filamentUsage & TextureUsage::BLIT_SRC)) {
|
||||||
|
metadata.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (any(metadata.filamentUsage & (TextureUsage::BLIT_DST | TextureUsage::UPLOADABLE))) {
|
||||||
|
metadata.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
metadata.samples = VK_SAMPLE_COUNT_1_BIT;
|
metadata.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
|
|
||||||
VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = {
|
VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
|
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
|
||||||
.pNext = nullptr,
|
|
||||||
};
|
};
|
||||||
VkAndroidHardwareBufferPropertiesANDROID properties = {
|
VkAndroidHardwareBufferPropertiesANDROID properties = {
|
||||||
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
|
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
|
||||||
@@ -268,138 +232,116 @@ VulkanPlatform::ExternalImageMetadata VulkanPlatformAndroid::getExternalImageMet
|
|||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||||
<< "vkGetAndroidHardwareBufferProperties failed with error="
|
<< "vkGetAndroidHardwareBufferProperties failed with error="
|
||||||
<< static_cast<int32_t>(result);
|
<< static_cast<int32_t>(result);
|
||||||
|
|
||||||
VkFormat bufferPropertiesFormat = transformVkFormat(formatInfo.format, fvkExternalImage->sRGB);
|
VkFormat bufferPropertiesFormat = transformVkFormat(formatInfo.format, fvkExternalImage->sRGB);
|
||||||
FILAMENT_CHECK_POSTCONDITION(metadata.format == bufferPropertiesFormat)
|
FILAMENT_CHECK_POSTCONDITION(metadata.format == bufferPropertiesFormat)
|
||||||
<< "mismatched image format( " << metadata.format << ") and queried format("
|
<< "mismatched image format( " << metadata.format << ") and queried format("
|
||||||
<< bufferPropertiesFormat << ") for external image (AHB)";
|
<< bufferPropertiesFormat << ") for external image (AHB)";
|
||||||
metadata.externalFormat = formatInfo.externalFormat;
|
metadata.externalFormat = formatInfo.externalFormat;
|
||||||
|
|
||||||
|
// Choose either externalFormat > 0 or metadata.format and prefer the latter.
|
||||||
|
if (metadata.externalFormat > 0 && metadata.format != VK_FORMAT_UNDEFINED) {
|
||||||
|
// See VUID-VkImageCreateInfo-pNext-09457
|
||||||
|
metadata.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
metadata.externalFormat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
metadata.allocationSize = properties.allocationSize;
|
metadata.allocationSize = properties.allocationSize;
|
||||||
metadata.memoryTypeBits = properties.memoryTypeBits;
|
metadata.memoryTypeBits = properties.memoryTypeBits;
|
||||||
|
|
||||||
|
metadata.ycbcrConversionComponents = formatInfo.samplerYcbcrConversionComponents;
|
||||||
|
metadata.ycbcrModel = formatInfo.suggestedYcbcrModel;
|
||||||
|
metadata.ycbcrRange = formatInfo.suggestedYcbcrRange;
|
||||||
|
metadata.xChromaOffset = formatInfo.suggestedXChromaOffset;
|
||||||
|
metadata.yChromaOffset = formatInfo.suggestedYChromaOffset;
|
||||||
|
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanPlatformAndroid::ImageData VulkanPlatformAndroid::createExternalImageData(
|
VulkanPlatformAndroid::ImageData VulkanPlatformAndroid::createVkImageFromExternal(
|
||||||
ExternalImageHandleRef externalImage, const ExternalImageMetadata& metadata,
|
ExternalImageHandleRef externalImage) const {
|
||||||
uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
auto const& metadata = extractExternalImageMetadata(externalImage);
|
||||||
|
|
||||||
auto const* fvkExternalImage =
|
auto const* fvkExternalImage =
|
||||||
static_cast<ExternalImageVulkanAndroid const*>(externalImage.get());
|
static_cast<ExternalImageVulkanAndroid const*>(externalImage.get());
|
||||||
ImageData data = allocateExternalImage(fvkExternalImage->aHardwareBuffer, getDevice(), metadata,
|
AHardwareBuffer* buffer = fvkExternalImage->aHardwareBuffer;
|
||||||
memoryTypeIndex, usage);
|
|
||||||
VkResult result = vkBindImageMemory(getDevice(), data.first, data.second, 0);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
||||||
<< "vkBindImageMemory error=" << static_cast<int32_t>(result);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device, SamplerYcbcrConversion chroma,
|
// if external format we need to specifiy it in the allocation
|
||||||
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
|
bool const useExternalFormat = metadata.format == VK_FORMAT_UNDEFINED;
|
||||||
VkImageViewType viewType, VkComponentMapping swizzle){
|
|
||||||
VkExternalFormatANDROID externalFormat = {
|
VkExternalFormatANDROID const externalFormat = {
|
||||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
||||||
.externalFormat = internalFormat,
|
|
||||||
};
|
|
||||||
|
|
||||||
TextureSwizzle const swizzleArray[] = {chroma.r, chroma.g, chroma.b, chroma.a};
|
|
||||||
VkSamplerYcbcrConversionCreateInfo conversionInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
|
|
||||||
.pNext = &externalFormat,
|
|
||||||
.format = VK_FORMAT_UNDEFINED,
|
|
||||||
.ycbcrModel = fvkutils::getYcbcrModelConversion(chroma.ycbcrModel),
|
|
||||||
.ycbcrRange = fvkutils::getYcbcrRange(chroma.ycbcrRange),
|
|
||||||
.components = fvkutils::getSwizzleMap(swizzleArray),
|
|
||||||
.xChromaOffset = fvkutils::getChromaLocation(chroma.xChromaOffset),
|
|
||||||
.yChromaOffset = fvkutils::getChromaLocation(chroma.yChromaOffset),
|
|
||||||
.chromaFilter = fvkutils::getFilter(chroma.chromaFilter),
|
|
||||||
};
|
|
||||||
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
|
|
||||||
VkResult result = vkCreateSamplerYcbcrConversion(device, &conversionInfo,
|
|
||||||
nullptr, &conversion);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
||||||
<< "Unable to create Ycbcr Conversion."
|
|
||||||
<< " error=" << static_cast<int32_t>(result);
|
|
||||||
|
|
||||||
VkSamplerYcbcrConversionInfo samplerYcbcrConversionInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
|
|
||||||
.conversion = conversion,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
||||||
.pNext = &samplerYcbcrConversionInfo,
|
|
||||||
.flags = 0,
|
|
||||||
.image = image,
|
|
||||||
.viewType = viewType,
|
|
||||||
.format = VK_FORMAT_UNDEFINED,
|
|
||||||
.components = swizzle,
|
|
||||||
.subresourceRange = range,
|
|
||||||
};
|
|
||||||
VkImageView imageView;
|
|
||||||
result = vkCreateImageView(device, &viewInfo, VKALLOC, &imageView);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
||||||
<< "Unable to create VkImageView."
|
|
||||||
<< " error=" << static_cast<int32_t>(result);
|
|
||||||
|
|
||||||
return imageView;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSampler VulkanPlatform::createExternalSamplerImpl(
|
|
||||||
VkDevice device, SamplerYcbcrConversion chroma, SamplerParams params,
|
|
||||||
uint32_t internalFormat) {
|
|
||||||
VkExternalFormatANDROID externalFormat = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
|
|
||||||
.externalFormat = internalFormat,
|
|
||||||
};
|
|
||||||
|
|
||||||
TextureSwizzle const swizzleArray[] = {chroma.r, chroma.g, chroma.b, chroma.a};
|
|
||||||
VkSamplerYcbcrConversionCreateInfo conversionInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
|
|
||||||
.pNext = &externalFormat,
|
|
||||||
.format = VK_FORMAT_UNDEFINED,
|
|
||||||
.ycbcrModel = fvkutils::getYcbcrModelConversion(chroma.ycbcrModel),
|
|
||||||
.ycbcrRange = fvkutils::getYcbcrRange(chroma.ycbcrRange),
|
|
||||||
.components = fvkutils::getSwizzleMap(swizzleArray),
|
|
||||||
.xChromaOffset = fvkutils::getChromaLocation(chroma.xChromaOffset),
|
|
||||||
.yChromaOffset = fvkutils::getChromaLocation(chroma.yChromaOffset),
|
|
||||||
.chromaFilter = fvkutils::getFilter(chroma.chromaFilter),
|
|
||||||
};
|
|
||||||
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
|
|
||||||
VkResult result = vkCreateSamplerYcbcrConversion(device, &conversionInfo,
|
|
||||||
nullptr, &conversion);
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
||||||
<< "Unable to create Ycbcr Conversion."
|
|
||||||
<< " error=" << static_cast<int32_t>(result);
|
|
||||||
|
|
||||||
VkSamplerYcbcrConversionInfo samplerYcbcrConversionInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
|
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.conversion = conversion,
|
.externalFormat = metadata.externalFormat,
|
||||||
|
};
|
||||||
|
VkExternalMemoryImageCreateInfo const externalCreateInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||||
|
.pNext = useExternalFormat ? &externalFormat : nullptr,
|
||||||
|
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkSamplerCreateInfo samplerInfo = {
|
VkImageCreateInfo const imageInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||||
.pNext = &samplerYcbcrConversionInfo,
|
.pNext = &externalCreateInfo,
|
||||||
.magFilter = fvkutils::getFilter(params.filterMag),
|
.flags = useExternalFormat ? VK_IMAGE_CREATE_ALIAS_BIT : 0u,
|
||||||
.minFilter = fvkutils::getFilter(params.filterMin),
|
.imageType = VK_IMAGE_TYPE_2D,
|
||||||
.mipmapMode = fvkutils::getMipmapMode(params.filterMin),
|
.format = metadata.format,
|
||||||
.addressModeU = fvkutils::getWrapMode(params.wrapS),
|
.extent = {
|
||||||
.addressModeV = fvkutils::getWrapMode(params.wrapT),
|
metadata.width,
|
||||||
.addressModeW = fvkutils::getWrapMode(params.wrapR),
|
metadata.height,
|
||||||
.anisotropyEnable = params.anisotropyLog2 == 0 ? VK_FALSE : VK_TRUE,
|
1u,
|
||||||
.maxAnisotropy = (float)(1u << params.anisotropyLog2),
|
},
|
||||||
.compareEnable = fvkutils::getCompareEnable(params.compareMode),
|
.mipLevels = 1,
|
||||||
.compareOp = fvkutils::getCompareOp(params.compareFunc),
|
.arrayLayers = metadata.layers,
|
||||||
.minLod = 0.0f,
|
.samples = metadata.samples,
|
||||||
.maxLod = fvkutils::getMaxLod(params.filterMin),
|
.usage = metadata.usage,
|
||||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
|
||||||
.unnormalizedCoordinates = VK_FALSE,
|
|
||||||
};
|
};
|
||||||
VkSampler sampler;
|
|
||||||
result = vkCreateSampler(device, &samplerInfo, VKALLOC, &sampler);
|
VkDevice const device = getDevice();
|
||||||
|
|
||||||
|
VkImage image;
|
||||||
|
VkResult result = vkCreateImage(device, &imageInfo, VKALLOC, &image);
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||||
<< "Unable to create sampler."
|
<< "vkCreateImage failed with error=" << static_cast<int32_t>(result);
|
||||||
<< " error=" << static_cast<int32_t>(result);
|
|
||||||
return sampler;
|
// Allocate the memory
|
||||||
|
VkImportAndroidHardwareBufferInfoANDROID const androidHardwareBufferInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
|
||||||
|
.buffer = buffer,
|
||||||
|
};
|
||||||
|
VkMemoryDedicatedAllocateInfo const memoryDedicatedAllocateInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||||
|
.pNext = &androidHardwareBufferInfo,
|
||||||
|
.image = image,
|
||||||
|
.buffer = VK_NULL_HANDLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(getPhysicalDevice(), &memoryProperties);
|
||||||
|
|
||||||
|
|
||||||
|
VkMemoryPropertyFlags const requiredMemoryFlags =
|
||||||
|
any(metadata.filamentUsage & TextureUsage::UPLOADABLE)
|
||||||
|
? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||||
|
: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
|
|
||||||
|
uint32_t const memoryTypeIndex = VulkanContext::selectMemoryType(memoryProperties,
|
||||||
|
metadata.memoryTypeBits, requiredMemoryFlags);
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo const allocInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = &memoryDedicatedAllocateInfo,
|
||||||
|
.allocationSize = metadata.allocationSize,
|
||||||
|
.memoryTypeIndex = memoryTypeIndex,
|
||||||
|
};
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
result = vkAllocateMemory(device, &allocInfo, VKALLOC, &memory);
|
||||||
|
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||||
|
<< "vkAllocateMemory failed with error=" << static_cast<int32_t>(result);
|
||||||
|
|
||||||
|
result = vkBindImageMemory(getDevice(), image, memory, 0);
|
||||||
|
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
||||||
|
<< "vkBindImageMemory error=" << static_cast<int32_t>(result);
|
||||||
|
return { image, memory };
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanPlatform::ExtensionSet VulkanPlatformAndroid::getSwapchainInstanceExtensions() const {
|
VulkanPlatform::ExtensionSet VulkanPlatformAndroid::getSwapchainInstanceExtensions() const {
|
||||||
@@ -427,20 +369,9 @@ VulkanPlatform::SurfaceBundle VulkanPlatformAndroid::createVkSurfaceKHR(void* na
|
|||||||
// Deprecated platform dependent helper methods
|
// Deprecated platform dependent helper methods
|
||||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() { return {}; }
|
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() { return {}; }
|
||||||
|
|
||||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
|
||||||
ExternalImageHandleRef externalImage, VkDevice device) {
|
|
||||||
return ExternalImageMetadata{};
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
|
|
||||||
ExternalImageHandleRef externalImage, VkDevice device,
|
|
||||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
|
||||||
return ImageData{};
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
|
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
|
||||||
VkInstance instance, uint64_t flags) noexcept {
|
VkInstance instance, uint64_t flags) noexcept {
|
||||||
return SurfaceBundle{};
|
return SurfaceBundle{};
|
||||||
}
|
}
|
||||||
|
|
||||||
}// namespace filament::backend
|
} // namespace filament::backend
|
||||||
|
|||||||
@@ -63,30 +63,6 @@ VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
|
||||||
ExternalImageHandleRef externalImage, VkDevice device) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
|
|
||||||
ExternalImageHandleRef externalImage, VkDevice device,
|
|
||||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSampler VulkanPlatform::createExternalSamplerImpl(VkDevice device,
|
|
||||||
SamplerYcbcrConversion chroma,
|
|
||||||
SamplerParams sampler,
|
|
||||||
uint32_t internalFormat) {
|
|
||||||
return VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device,
|
|
||||||
SamplerYcbcrConversion chroma, uint32_t internalFormat, VkImage image,
|
|
||||||
VkImageSubresourceRange range, VkImageViewType viewType, VkComponentMapping swizzle) {
|
|
||||||
return VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
|
VulkanPlatform::SurfaceBundle VulkanPlatform::createVkSurfaceKHRImpl(void* nativeWindow,
|
||||||
VkInstance instance, uint64_t flags) noexcept {
|
VkInstance instance, uint64_t flags) noexcept {
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
|
|||||||
@@ -84,30 +84,6 @@ using namespace bluevk;
|
|||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
VulkanPlatform::ExternalImageMetadata VulkanPlatform::getExternalImageMetadataImpl(
|
|
||||||
ExternalImageHandleRef externalImage, VkDevice device) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::ImageData VulkanPlatform::createExternalImageDataImpl(
|
|
||||||
ExternalImageHandleRef externalImage, VkDevice device,
|
|
||||||
const ExternalImageMetadata& metadata, uint32_t memoryTypeIndex, VkImageUsageFlags usage) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSampler VulkanPlatform::createExternalSamplerImpl(VkDevice device,
|
|
||||||
SamplerYcbcrConversion chroma,
|
|
||||||
SamplerParams sampler,
|
|
||||||
uint32_t internalFormat) {
|
|
||||||
return VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device,
|
|
||||||
SamplerYcbcrConversion chroma, uint32_t internalFormat, VkImage image,
|
|
||||||
VkImageSubresourceRange range, VkImageViewType viewType, VkComponentMapping swizzle) {
|
|
||||||
return VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() {
|
VulkanPlatform::ExtensionSet VulkanPlatform::getSwapchainInstanceExtensionsImpl() {
|
||||||
VulkanPlatform::ExtensionSet const ret = {
|
VulkanPlatform::ExtensionSet const ret = {
|
||||||
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
#if defined(__linux__) && defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||||
|
|||||||
@@ -317,6 +317,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
size_t metalUploadBufferSizeBytes = 512 * 1024;
|
size_t metalUploadBufferSizeBytes = 512 * 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The action to take if a Drawable cannot be acquired.
|
||||||
|
*
|
||||||
|
* Each frame rendered requires a CAMetalDrawable texture, which is
|
||||||
|
* presented on-screen at the completion of each frame. These are
|
||||||
|
* limited and provided round-robin style by the system.
|
||||||
|
*/
|
||||||
|
bool metalDisablePanicOnDrawableFailure = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to `true` to forcibly disable parallel shader compilation in the backend.
|
* Set to `true` to forcibly disable parallel shader compilation in the backend.
|
||||||
* Currently only honored by the GL and Metal backends.
|
* Currently only honored by the GL and Metal backends.
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ Engine* FEngine::create(Builder const& builder) {
|
|||||||
.forceGLES2Context = instance->getConfig().forceGLES2Context,
|
.forceGLES2Context = instance->getConfig().forceGLES2Context,
|
||||||
.stereoscopicType = instance->getConfig().stereoscopicType,
|
.stereoscopicType = instance->getConfig().stereoscopicType,
|
||||||
.assertNativeWindowIsValid = instance->features.backend.opengl.assert_native_window_is_valid,
|
.assertNativeWindowIsValid = instance->features.backend.opengl.assert_native_window_is_valid,
|
||||||
|
.metalDisablePanicOnDrawableFailure = instance->getConfig().metalDisablePanicOnDrawableFailure,
|
||||||
};
|
};
|
||||||
instance->mDriver = platform->createDriver(sharedContext, driverConfig);
|
instance->mDriver = platform->createDriver(sharedContext, driverConfig);
|
||||||
|
|
||||||
@@ -733,6 +734,7 @@ int FEngine::loop() {
|
|||||||
.forceGLES2Context = mConfig.forceGLES2Context,
|
.forceGLES2Context = mConfig.forceGLES2Context,
|
||||||
.stereoscopicType = mConfig.stereoscopicType,
|
.stereoscopicType = mConfig.stereoscopicType,
|
||||||
.assertNativeWindowIsValid = features.backend.opengl.assert_native_window_is_valid,
|
.assertNativeWindowIsValid = features.backend.opengl.assert_native_window_is_valid,
|
||||||
|
.metalDisablePanicOnDrawableFailure = mConfig.metalDisablePanicOnDrawableFailure,
|
||||||
};
|
};
|
||||||
mDriver = mPlatform->createDriver(mSharedGLContext, driverConfig);
|
mDriver = mPlatform->createDriver(mSharedGLContext, driverConfig);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user