| /* |
| * MVKImage.h |
| * |
| * Copyright (c) 2015-2020 The Brenwill Workshop Ltd. (http://www.brenwill.com) |
| * |
| * 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. |
| */ |
| |
| #pragma once |
| |
| #include "MVKResource.h" |
| #include "MVKCommandResourceFactory.h" |
| #include "MVKSync.h" |
| #include "MVKSmallVector.h" |
| #include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h> |
| #include <unordered_map> |
| #include <mutex> |
| |
| #import <IOSurface/IOSurfaceRef.h> |
| |
| class MVKImage; |
| class MVKImageView; |
| class MVKSwapchain; |
| class MVKCommandEncoder; |
| |
| |
| #pragma mark - |
| #pragma mark MVKImagePlane |
| |
| /** Tracks the state of an image subresource. */ |
| typedef struct { |
| VkImageSubresource subresource; |
| VkSubresourceLayout layout; |
| VkImageLayout layoutState; |
| } MVKImageSubresource; |
| |
| class MVKImagePlane : public MVKBaseObject { |
| |
| public: |
| |
| /** Returns the Vulkan API opaque object controlling this object. */ |
| MVKVulkanAPIObject* getVulkanAPIObject() override; |
| |
| /** Returns the Metal texture underlying this image plane. */ |
| id<MTLTexture> getMTLTexture(); |
| |
| /** Returns a Metal texture that interprets the pixels in the specified format. */ |
| id<MTLTexture> getMTLTexture(MTLPixelFormat mtlPixFmt); |
| |
| void releaseMTLTexture(); |
| |
| ~MVKImagePlane(); |
| |
| protected: |
| friend class MVKImageMemoryBinding; |
| friend MVKImage; |
| |
| MTLTextureDescriptor* newMTLTextureDescriptor(); |
| void initSubresources(const VkImageCreateInfo* pCreateInfo); |
| MVKImageSubresource* getSubresource(uint32_t mipLevel, uint32_t arrayLayer); |
| void updateMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size); |
| void getMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size); |
| bool overlaps(VkSubresourceLayout& imgLayout, VkDeviceSize offset, VkDeviceSize size); |
| void propagateDebugName(); |
| MVKImageMemoryBinding* getMemoryBinding() const; |
| void applyImageMemoryBarrier(VkPipelineStageFlags srcStageMask, |
| VkPipelineStageFlags dstStageMask, |
| MVKPipelineBarrier& barrier, |
| MVKCommandEncoder* cmdEncoder, |
| MVKCommandUse cmdUse); |
| void pullFromDeviceOnCompletion(MVKCommandEncoder* cmdEncoder, |
| MVKImageSubresource& subresource, |
| const MVKMappedMemoryRange& mappedRange); |
| |
| MVKImagePlane(MVKImage* image, uint8_t planeIndex); |
| |
| MVKImage* _image; |
| uint8_t _planeIndex; |
| VkExtent2D _blockTexelSize; |
| uint32_t _bytesPerBlock; |
| MTLPixelFormat _mtlPixFmt; |
| id<MTLTexture> _mtlTexture; |
| std::unordered_map<NSUInteger, id<MTLTexture>> _mtlTextureViews; |
| MVKSmallVector<MVKImageSubresource, 1> _subresources; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKImageMemoryBinding |
| |
| class MVKImageMemoryBinding : public MVKResource { |
| |
| public: |
| |
| /** Returns the Vulkan type of this object. */ |
| VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_UNKNOWN; } |
| |
| /** Returns the debug report object type of this object. */ |
| VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; } |
| |
| /** Returns the memory requirements of this resource by populating the specified structure. */ |
| VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements); |
| |
| /** Returns the memory requirements of this resource by populating the specified structure. */ |
| VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements); |
| |
| /** Binds this resource to the specified offset within the specified memory allocation. */ |
| VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override; |
| |
| /** Applies the specified global memory barrier. */ |
| void applyMemoryBarrier(VkPipelineStageFlags srcStageMask, |
| VkPipelineStageFlags dstStageMask, |
| MVKPipelineBarrier& barrier, |
| MVKCommandEncoder* cmdEncoder, |
| MVKCommandUse cmdUse) override; |
| |
| ~MVKImageMemoryBinding(); |
| |
| protected: |
| friend MVKDeviceMemory; |
| friend MVKImagePlane; |
| friend MVKImage; |
| |
| void propagateDebugName() override; |
| bool needsHostReadSync(VkPipelineStageFlags srcStageMask, |
| VkPipelineStageFlags dstStageMask, |
| MVKPipelineBarrier& barrier); |
| bool shouldFlushHostMemory(); |
| VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size); |
| VkResult pullFromDevice(VkDeviceSize offset, VkDeviceSize size); |
| uint8_t beginPlaneIndex() const; |
| uint8_t endPlaneIndex() const; |
| |
| MVKImageMemoryBinding(MVKDevice* device, MVKImage* image, uint8_t planeIndex); |
| |
| MVKImage* _image; |
| uint8_t _planeIndex; |
| bool _usesTexelBuffer; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKImage |
| |
| /** Represents a Vulkan image. */ |
| class MVKImage : public MVKVulkanAPIDeviceObject { |
| |
| public: |
| |
| /** Returns the Vulkan type of this object. */ |
| VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_IMAGE; } |
| |
| /** Returns the debug report object type of this object. */ |
| VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; } |
| |
| /** Returns the plane index of VkImageAspectFlags. */ |
| static uint8_t getPlaneFromVkImageAspectFlags(VkImageAspectFlags aspectMask); |
| |
| /** |
| * Returns the Vulkan image type of this image. |
| * This may be different than the value originally specified for the image |
| * if a 1D texture is being handled via a Metal 2D texture with height of 1. |
| */ |
| VkImageType getImageType(); |
| |
| /** Returns the Vulkan image format of this image. */ |
| VkFormat getVkFormat() { return _vkFormat; }; |
| |
| /** Returns whether this image has a depth or stencil format. */ |
| bool getIsDepthStencil(); |
| |
| /** Returns whether this image is compressed. */ |
| bool getIsCompressed(); |
| |
| /** Returns whether this image has a linear memory layout. */ |
| bool getIsLinear() { return _isLinear; } |
| |
| /** |
| * Returns the 3D extent of this image at the base mipmap level. |
| * For 2D or cube images, the Z component will be 1. |
| */ |
| inline VkExtent3D getExtent3D() { return _extent; } |
| |
| /** |
| * Returns the 3D extent of this image at the specified mipmap level. |
| * For 2D or cube images, the Z component will be 1. |
| */ |
| VkExtent3D getExtent3D(uint8_t planeIndex, uint32_t mipLevel); |
| |
| /** Returns the number of mipmap levels in this image. */ |
| inline uint32_t getMipLevelCount() { return _mipLevels; } |
| |
| /** |
| * Returns the number of layers at each mipmap level. For an array image type, this is |
| * the number of elements in the array. For cube image type, this is a multiple of 6. |
| */ |
| inline uint32_t getLayerCount() { return _arrayLayers; } |
| |
| /** Returns the number of samples for each pixel of this image. */ |
| inline VkSampleCountFlagBits getSampleCount() { return _samples; } |
| |
| /** |
| * Returns the number of bytes per image row at the specified zero-based mip level. |
| * For non-compressed formats, this is the number of bytes in a row of texels. |
| * For compressed formats, this is the number of bytes in a row of blocks, which |
| * will typically span more than one row of texels. |
| */ |
| VkDeviceSize getBytesPerRow(uint8_t planeIndex, uint32_t mipLevel); |
| |
| /** |
| * Returns the number of bytes per image layer (for cube, array, or 3D images) |
| * at the specified zero-based mip level. This value will normally be the number |
| * of bytes per row (as returned by the getBytesPerRow() function, multiplied by |
| * the height of each 2D image. |
| */ |
| VkDeviceSize getBytesPerLayer(uint8_t planeIndex, uint32_t mipLevel); |
| |
| /** Returns the number of planes of this image view. */ |
| inline uint8_t getPlaneCount() { return _planes.size(); } |
| |
| /** Populates the specified layout for the specified sub-resource. */ |
| VkResult getSubresourceLayout(const VkImageSubresource* pSubresource, |
| VkSubresourceLayout* pLayout); |
| |
| /** Populates the specified transfer image descriptor data structure. */ |
| void getTransferDescriptorData(MVKImageDescriptorData& imgData); |
| |
| |
| #pragma mark Resource memory |
| |
| /** Returns the memory requirements of this resource by populating the specified structure. */ |
| VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements, uint8_t planeIndex); |
| |
| /** Returns the memory requirements of this resource by populating the specified structure. */ |
| VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements); |
| |
| /** Binds this resource to the specified offset within the specified memory allocation. */ |
| virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex); |
| |
| /** Binds this resource to the specified offset within the specified memory allocation. */ |
| virtual VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo); |
| |
| /** Applies the specified image memory barrier. */ |
| void applyImageMemoryBarrier(VkPipelineStageFlags srcStageMask, |
| VkPipelineStageFlags dstStageMask, |
| MVKPipelineBarrier& barrier, |
| MVKCommandEncoder* cmdEncoder, |
| MVKCommandUse cmdUse); |
| |
| /** Flush underlying buffer memory into the image if necessary */ |
| void flushToDevice(VkDeviceSize offset, VkDeviceSize size); |
| |
| #pragma mark Metal |
| |
| /** Returns the Metal texture underlying this image. */ |
| virtual id<MTLTexture> getMTLTexture(uint8_t planeIndex); |
| |
| /** Returns a Metal texture that interprets the pixels in the specified format. */ |
| id<MTLTexture> getMTLTexture(uint8_t planeIndex, MTLPixelFormat mtlPixFmt); |
| |
| /** |
| * Sets this image to use the specified MTLTexture. |
| * |
| * Any differences in the properties of mtlTexture and this image will modify the |
| * properties of this image. |
| * |
| * If a MTLTexture has already been created for this image, it will be destroyed. |
| */ |
| VkResult setMTLTexture(uint8_t planeIndex, id<MTLTexture> mtlTexture); |
| |
| /** |
| * Indicates that this VkImage should use an IOSurface to underlay the Metal texture. |
| * |
| * If ioSurface is provided and is not nil, it will be used as the IOSurface. |
| * |
| * If ioSurface is not provided, or is nil, this image will create and use an IOSurface |
| * whose properties are compatible with the properties of this image. |
| * |
| * If a MTLTexture has already been created for this image, it will be destroyed. |
| * |
| * Returns: |
| * - VK_SUCCESS. |
| * - VK_ERROR_FEATURE_NOT_PRESENT if IOSurfaces are not supported on the platform. |
| * - VK_ERROR_INITIALIZATION_FAILED if ioSurface is specified and is not compatible with this VkImage. |
| */ |
| VkResult useIOSurface(IOSurfaceRef ioSurface = nil); |
| |
| /** |
| * Returns the IOSurface underlying the MTLTexture, |
| * or nil if no IOSurface has been set via useIOSurface(). |
| */ |
| IOSurfaceRef getIOSurface(); |
| |
| /** Returns the Metal pixel format of this image. */ |
| inline MTLPixelFormat getMTLPixelFormat(uint8_t planeIndex) { return _planes[planeIndex]->_mtlPixFmt; } |
| |
| /** Returns the Metal texture type of this image. */ |
| inline MTLTextureType getMTLTextureType() { return _mtlTextureType; } |
| |
| /** |
| * Returns whether the Metal texel size is the same as the Vulkan texel size. |
| * |
| * If a different MTLPixelFormat was substituted for the desired VkFormat, the texel |
| * size may be different. This can occur for certain depth formats when the format |
| * is not supported on a platform, and the application has not verified this. |
| * In this case, a different depth format will automatically be substituted. |
| * With depth formats, this is usually accpetable, but can cause problems when |
| * attempting to copy a depth image with a substituted format to and from a buffer. |
| */ |
| inline bool hasExpectedTexelSize() { return _hasExpectedTexelSize; } |
| |
| /** Returns the Metal resource options for this image. */ |
| MTLStorageMode getMTLStorageMode(); |
| |
| /** Returns the Metal CPU cache mode used by this image. */ |
| MTLCPUCacheMode getMTLCPUCacheMode(); |
| |
| #pragma mark Construction |
| |
| MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo); |
| |
| ~MVKImage() override; |
| |
| protected: |
| friend MVKDeviceMemory; |
| friend MVKDevice; |
| friend MVKImageMemoryBinding; |
| friend MVKImagePlane; |
| friend class MVKImageViewPlane; |
| friend MVKImageView; |
| |
| void propagateDebugName() override; |
| void validateConfig(const VkImageCreateInfo* pCreateInfo, bool isAttachment); |
| VkSampleCountFlagBits validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment); |
| uint32_t validateMipLevels(const VkImageCreateInfo* pCreateInfo, bool isAttachment); |
| bool validateLinear(const VkImageCreateInfo* pCreateInfo, bool isAttachment); |
| void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes); |
| void releaseIOSurface(); |
| |
| MVKSmallVector<MVKImageMemoryBinding*, 3> _memoryBindings; |
| MVKSmallVector<MVKImagePlane*, 3> _planes; |
| VkExtent3D _extent; |
| uint32_t _mipLevels; |
| uint32_t _arrayLayers; |
| VkSampleCountFlagBits _samples; |
| VkImageUsageFlags _usage; |
| VkFormat _vkFormat; |
| MTLTextureType _mtlTextureType; |
| std::mutex _lock; |
| IOSurfaceRef _ioSurface; |
| VkDeviceSize _rowByteAlignment; |
| bool _isDepthStencilAttachment; |
| bool _canSupportMTLTextureView; |
| bool _hasExpectedTexelSize; |
| bool _hasChromaSubsampling; |
| bool _isLinear; |
| bool _is3DCompressed; |
| bool _isAliasable; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKSwapchainImage |
| |
| /** Abstract class of Vulkan image used as a rendering destination within a swapchain. */ |
| class MVKSwapchainImage : public MVKImage { |
| |
| public: |
| |
| /** Binds this resource to the specified offset within the specified memory allocation. */ |
| VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex) override; |
| |
| #pragma mark Metal |
| |
| /** Returns the Metal texture used by the CAMetalDrawable underlying this image. */ |
| id<MTLTexture> getMTLTexture(uint8_t planeIndex) override; |
| |
| |
| #pragma mark Construction |
| |
| /** Constructs an instance for the specified device and swapchain. */ |
| MVKSwapchainImage(MVKDevice* device, |
| const VkImageCreateInfo* pCreateInfo, |
| MVKSwapchain* swapchain, |
| uint32_t swapchainIndex); |
| |
| protected: |
| friend class MVKPeerSwapchainImage; |
| |
| virtual id<CAMetalDrawable> getCAMetalDrawable() = 0; |
| |
| MVKSwapchain* _swapchain; |
| uint32_t _swapchainIndex; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKPresentableSwapchainImage |
| |
| /** Indicates the relative availability of each image in the swapchain. */ |
| typedef struct MVKSwapchainImageAvailability { |
| uint64_t acquisitionID; /**< When this image was last made available, relative to the other images in the swapchain. Smaller value is earlier. */ |
| bool isAvailable; /**< Indicates whether this image is currently available. */ |
| |
| bool operator< (const MVKSwapchainImageAvailability& rhs) const; |
| } MVKSwapchainImageAvailability; |
| |
| /** Tracks a semaphore and fence for later signaling. */ |
| typedef std::pair<MVKSemaphore*, MVKFence*> MVKSwapchainSignaler; |
| |
| |
| /** Represents a Vulkan swapchain image that can be submitted to the presentation engine. */ |
| class MVKPresentableSwapchainImage : public MVKSwapchainImage { |
| |
| public: |
| |
| #pragma mark Metal |
| |
| /** |
| * Presents the contained drawable to the OS, releases the Metal drawable and its |
| * texture back to the Metal layer's pool, and makes the image memory available for new use. |
| * |
| * If mtlCmdBuff is not nil, the contained drawable is scheduled for presentation using |
| * the presentDrawable: method of the command buffer. If mtlCmdBuff is nil, the contained |
| * drawable is presented immediately using the present method of the drawable. |
| */ |
| void presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff, bool hasPresentTime, uint32_t presentID, uint64_t desiredPresentTime); |
| |
| |
| #pragma mark Construction |
| |
| /** Constructs an instance for the specified device and swapchain. */ |
| MVKPresentableSwapchainImage(MVKDevice* device, |
| const VkImageCreateInfo* pCreateInfo, |
| MVKSwapchain* swapchain, |
| uint32_t swapchainIndex); |
| |
| ~MVKPresentableSwapchainImage() override; |
| |
| protected: |
| friend MVKSwapchain; |
| |
| id<CAMetalDrawable> getCAMetalDrawable() override; |
| void releaseMetalDrawable(); |
| MVKSwapchainImageAvailability getAvailability(); |
| void makeAvailable(); |
| void acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence); |
| void signal(MVKSwapchainSignaler& signaler, id<MTLCommandBuffer> mtlCmdBuff); |
| void signalPresentationSemaphore(id<MTLCommandBuffer> mtlCmdBuff); |
| static void markAsTracked(MVKSwapchainSignaler& signaler); |
| static void unmarkAsTracked(MVKSwapchainSignaler& signaler); |
| void renderWatermark(id<MTLCommandBuffer> mtlCmdBuff); |
| |
| id<CAMetalDrawable> _mtlDrawable; |
| MVKSwapchainImageAvailability _availability; |
| MVKSmallVector<MVKSwapchainSignaler, 1> _availabilitySignalers; |
| MVKSwapchainSignaler _preSignaler; |
| std::mutex _availabilityLock; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKPeerSwapchainImage |
| |
| /** Represents a Vulkan swapchain image that can be associated as a peer to a swapchain image. */ |
| class MVKPeerSwapchainImage : public MVKSwapchainImage { |
| |
| public: |
| |
| /** Binds this resource according to the specified bind information. */ |
| VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) override; |
| |
| |
| #pragma mark Construction |
| |
| /** Constructs an instance for the specified device and swapchain. */ |
| MVKPeerSwapchainImage(MVKDevice* device, |
| const VkImageCreateInfo* pCreateInfo, |
| MVKSwapchain* swapchain, |
| uint32_t swapchainIndex); |
| |
| protected: |
| id<CAMetalDrawable> getCAMetalDrawable() override; |
| |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKImageViewPlane |
| |
| class MVKImageViewPlane : public MVKBaseDeviceObject { |
| |
| /** Returns the Vulkan API opaque object controlling this object. */ |
| MVKVulkanAPIObject* getVulkanAPIObject() override; |
| |
| public: |
| /** Returns the Metal texture underlying this image view. */ |
| id<MTLTexture> getMTLTexture(); |
| |
| void releaseMTLTexture(); |
| |
| ~MVKImageViewPlane(); |
| |
| protected: |
| void propagateDebugName(); |
| id<MTLTexture> newMTLTexture(); |
| MVKImageViewPlane(MVKImageView* imageView, uint8_t planeIndex, MTLPixelFormat mtlPixFmt, const VkImageViewCreateInfo* pCreateInfo); |
| |
| friend MVKImageView; |
| MVKImageView* _imageView; |
| uint8_t _planeIndex; |
| MTLPixelFormat _mtlPixFmt; |
| uint32_t _packedSwizzle; |
| id<MTLTexture> _mtlTexture; |
| bool _useMTLTextureView; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKImageView |
| |
| /** Represents a Vulkan image view. */ |
| class MVKImageView : public MVKVulkanAPIDeviceObject { |
| |
| public: |
| |
| /** Returns the Vulkan type of this object. */ |
| VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_IMAGE_VIEW; } |
| |
| /** Returns the debug report object type of this object. */ |
| VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT; } |
| |
| #pragma mark Metal |
| |
| /** Returns the Metal texture underlying this image view. */ |
| id<MTLTexture> getMTLTexture(uint8_t planeIndex) { return _planes[planeIndex]->getMTLTexture(); } |
| |
| /** Returns the Metal pixel format of this image view. */ |
| inline MTLPixelFormat getMTLPixelFormat(uint8_t planeIndex) { return _planes[planeIndex]->_mtlPixFmt; } |
| |
| /** Returns the packed component swizzle of this image view. */ |
| inline uint32_t getPackedSwizzle() { return _planes[0]->_packedSwizzle; } |
| |
| /** Returns the number of planes of this image view. */ |
| inline uint8_t getPlaneCount() { return _planes.size(); } |
| |
| /** Returns the Metal texture type of this image view. */ |
| inline MTLTextureType getMTLTextureType() { return _mtlTextureType; } |
| |
| /** |
| * Populates the texture of the specified render pass descriptor |
| * with the Metal texture underlying this image. |
| */ |
| void populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc); |
| |
| /** |
| * Populates the resolve texture of the specified render pass descriptor |
| * with the Metal texture underlying this image. |
| */ |
| void populateMTLRenderPassAttachmentDescriptorResolve(MTLRenderPassAttachmentDescriptor* mtlAttDesc); |
| |
| /** |
| * Returns, in mtlPixFmt, a MTLPixelFormat, based on the MTLPixelFormat converted from |
| * the VkFormat, but possibly modified by the swizzles defined in the VkComponentMapping |
| * of the VkImageViewCreateInfo. |
| * |
| * Metal prior to version 3.0 does not support native per-texture swizzles, so if the swizzle |
| * is not an identity swizzle, this function attempts to find an alternate MTLPixelFormat that |
| * coincidentally matches the swizzled format. |
| * |
| * If a replacement MTLFormat was found, it is returned and useSwizzle is set to false. |
| * If a replacement MTLFormat could not be found, the original MTLPixelFormat is returned, |
| * and the useSwizzle is set to true, indicating that either native or shader swizzling |
| * should be used for this image view. |
| * |
| * This is a static function that can be used to validate image view formats prior to creating one. |
| */ |
| static VkResult validateSwizzledMTLPixelFormat(const VkImageViewCreateInfo* pCreateInfo, |
| MVKVulkanAPIObject* apiObject, |
| bool hasNativeSwizzleSupport, |
| bool hasShaderSwizzleSupport, |
| MTLPixelFormat& mtlPixFmt, |
| bool& useSwizzle); |
| |
| |
| #pragma mark Construction |
| |
| MVKImageView(MVKDevice* device, |
| const VkImageViewCreateInfo* pCreateInfo, |
| const MVKConfiguration* pAltMVKConfig = nullptr); |
| |
| ~MVKImageView(); |
| |
| protected: |
| friend MVKImageViewPlane; |
| |
| void propagateDebugName() override; |
| |
| MVKImage* _image; |
| MVKSmallVector<MVKImageViewPlane*, 3> _planes; |
| VkImageSubresourceRange _subresourceRange; |
| VkImageUsageFlags _usage; |
| std::mutex _lock; |
| MTLTextureType _mtlTextureType; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKSamplerYcbcrConversion |
| |
| /** Represents a Vulkan sampler ycbcr conversion. */ |
| class MVKSamplerYcbcrConversion : public MVKVulkanAPIDeviceObject { |
| |
| public: |
| /** Returns the Vulkan type of this object. */ |
| VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION; } |
| |
| /** Returns the debug report object type of this object. */ |
| VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT; } |
| |
| /** Returns the number of planes of this ycbcr conversion. */ |
| inline uint8_t getPlaneCount() { return _planes; } |
| |
| /** Writes this conversion settings to a MSL constant sampler */ |
| void updateConstExprSampler(SPIRV_CROSS_NAMESPACE::MSLConstexprSampler& constExprSampler) const; |
| |
| MVKSamplerYcbcrConversion(MVKDevice* device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo); |
| |
| ~MVKSamplerYcbcrConversion() override {} |
| |
| protected: |
| void propagateDebugName() override {} |
| |
| uint8_t _planes, _bpc; |
| SPIRV_CROSS_NAMESPACE::MSLFormatResolution _resolution; |
| SPIRV_CROSS_NAMESPACE::MSLSamplerFilter _chroma_filter; |
| SPIRV_CROSS_NAMESPACE::MSLChromaLocation _x_chroma_offset, _y_chroma_offset; |
| SPIRV_CROSS_NAMESPACE::MSLComponentSwizzle _swizzle[4]; |
| SPIRV_CROSS_NAMESPACE::MSLSamplerYCbCrModelConversion _ycbcr_model; |
| SPIRV_CROSS_NAMESPACE::MSLSamplerYCbCrRange _ycbcr_range; |
| bool _forceExplicitReconstruction; |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKSampler |
| |
| /** Represents a Vulkan sampler. */ |
| class MVKSampler : public MVKVulkanAPIDeviceObject { |
| |
| public: |
| |
| /** Returns the Vulkan type of this object. */ |
| VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_SAMPLER; } |
| |
| /** Returns the debug report object type of this object. */ |
| VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT; } |
| |
| /** Returns the Metal sampler state. */ |
| inline id<MTLSamplerState> getMTLSamplerState() { return _mtlSamplerState; } |
| |
| /** Returns the number of planes if this is a ycbcr conversion or 0 otherwise. */ |
| inline uint8_t getPlaneCount() { return (_ycbcrConversion) ? _ycbcrConversion->getPlaneCount() : 0; } |
| |
| |
| /** |
| * If this sampler requires hardcoding in MSL, populates the hardcoded sampler in the resource binding. |
| * Returns whether this sampler requires hardcoding in MSL, and the constant sampler was populated. |
| */ |
| bool getConstexprSampler(mvk::MSLResourceBinding& resourceBinding); |
| |
| /** Returns whether this sampler must be implemented as a hardcoded constant sampler in the shader MSL code. */ |
| inline bool getRequiresConstExprSampler() { return _requiresConstExprSampler; } |
| |
| MVKSampler(MVKDevice* device, const VkSamplerCreateInfo* pCreateInfo); |
| |
| ~MVKSampler() override; |
| |
| protected: |
| void propagateDebugName() override {} |
| MTLSamplerDescriptor* newMTLSamplerDescriptor(const VkSamplerCreateInfo* pCreateInfo); |
| void initConstExprSampler(const VkSamplerCreateInfo* pCreateInfo); |
| |
| id<MTLSamplerState> _mtlSamplerState; |
| SPIRV_CROSS_NAMESPACE::MSLConstexprSampler _constExprSampler; |
| MVKSamplerYcbcrConversion* _ycbcrConversion; |
| bool _requiresConstExprSampler; |
| }; |