Merge pull request #909 from Lichtso/VK_KHR_sampler_ycbcr_conversion
VK_KHR_sampler_ycbcr_conversion
This commit is contained in:
commit
348c064b75
@ -256,6 +256,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
|
|||||||
- `VK_KHR_push_descriptor`
|
- `VK_KHR_push_descriptor`
|
||||||
- `VK_KHR_relaxed_block_layout`
|
- `VK_KHR_relaxed_block_layout`
|
||||||
- `VK_KHR_sampler_mirror_clamp_to_edge` *(macOS)*
|
- `VK_KHR_sampler_mirror_clamp_to_edge` *(macOS)*
|
||||||
|
- `VK_KHR_sampler_ycbcr_conversion`
|
||||||
- `VK_KHR_shader_draw_parameters`
|
- `VK_KHR_shader_draw_parameters`
|
||||||
- `VK_KHR_shader_float16_int8`
|
- `VK_KHR_shader_float16_int8`
|
||||||
- `VK_KHR_storage_buffer_storage_class`
|
- `VK_KHR_storage_buffer_storage_class`
|
||||||
|
@ -90,7 +90,9 @@ void MVKCmdPipelineBarrier<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MVKPipelineBarrier::Image:
|
case MVKPipelineBarrier::Image:
|
||||||
resources[rezCnt++] = b.mvkImage->getMTLTexture();
|
for (uint8_t planeIndex = 0; planeIndex < b.mvkImage->getPlaneCount(); planeIndex++) {
|
||||||
|
resources[rezCnt++] = b.mvkImage->getMTLTexture(planeIndex);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -103,7 +103,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
|
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
|
||||||
bool canCopyFormats();
|
bool canCopyFormats(const VkImageBlit& region);
|
||||||
bool canCopy(const VkImageBlit& region);
|
bool canCopy(const VkImageBlit& region);
|
||||||
void populateVertices(MVKVertexPosTex* vertices, const VkImageBlit& region);
|
void populateVertices(MVKVertexPosTex* vertices, const VkImageBlit& region);
|
||||||
|
|
||||||
@ -125,8 +125,9 @@ typedef MVKCmdBlitImage<4> MVKCmdBlitImageMulti;
|
|||||||
|
|
||||||
/** Describes Metal texture resolve parameters. */
|
/** Describes Metal texture resolve parameters. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t level;
|
VkImageCopy* copyRegion;
|
||||||
uint32_t slice;
|
uint32_t level;
|
||||||
|
uint32_t slice;
|
||||||
} MVKMetalResolveSlice;
|
} MVKMetalResolveSlice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,129 +62,138 @@ VkResult MVKCmdCopyImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
|||||||
_dstLayout = dstImageLayout;
|
_dstLayout = dstImageLayout;
|
||||||
|
|
||||||
_vkImageCopies.clear(); // Clear for reuse
|
_vkImageCopies.clear(); // Clear for reuse
|
||||||
for (uint32_t i = 0; i < regionCount; i++) {
|
for (uint32_t regionIdx = 0; regionIdx < regionCount; regionIdx++) {
|
||||||
_vkImageCopies.push_back(pRegions[i]);
|
auto& vkIR = pRegions[regionIdx];
|
||||||
}
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.srcSubresource.aspectMask);
|
||||||
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.dstSubresource.aspectMask);
|
||||||
// Validate
|
|
||||||
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
// Validate
|
||||||
if ((_dstImage->getSampleCount() != _srcImage->getSampleCount()) ||
|
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
||||||
(pixFmts->getBytesPerBlock(_dstImage->getMTLPixelFormat()) != pixFmts->getBytesPerBlock(_srcImage->getMTLPixelFormat()))) {
|
if ((_dstImage->getSampleCount() != _srcImage->getSampleCount()) ||
|
||||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Cannot copy between incompatible formats, such as formats of different pixel sizes, or between images with different sample counts.");
|
(pixFmts->getBytesPerBlock(_dstImage->getMTLPixelFormat(dstPlaneIndex)) != pixFmts->getBytesPerBlock(_srcImage->getMTLPixelFormat(srcPlaneIndex)))) {
|
||||||
}
|
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Cannot copy between incompatible formats, such as formats of different pixel sizes, or between images with different sample counts.");
|
||||||
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
|
}
|
||||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture.");
|
|
||||||
|
_vkImageCopies.push_back(vkIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
|
||||||
|
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture.");
|
||||||
|
}
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void MVKCmdCopyImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse commandUse) {
|
void MVKCmdCopyImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse commandUse) {
|
||||||
|
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
||||||
|
uint32_t copyCnt = (uint32_t)_vkImageCopies.size();
|
||||||
|
VkBufferImageCopy vkSrcCopies[copyCnt];
|
||||||
|
VkBufferImageCopy vkDstCopies[copyCnt];
|
||||||
|
size_t tmpBuffSize = 0;
|
||||||
|
|
||||||
MTLPixelFormat srcMTLPixFmt = _srcImage->getMTLPixelFormat();
|
for (uint32_t copyIdx = 0; copyIdx < copyCnt; copyIdx++) {
|
||||||
bool isSrcCompressed = _srcImage->getIsCompressed();
|
auto& vkIC = _vkImageCopies[copyIdx];
|
||||||
|
|
||||||
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIC.srcSubresource.aspectMask);
|
||||||
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIC.dstSubresource.aspectMask);
|
||||||
|
|
||||||
|
MTLPixelFormat srcMTLPixFmt = _srcImage->getMTLPixelFormat(srcPlaneIndex);
|
||||||
|
bool isSrcCompressed = _srcImage->getIsCompressed();
|
||||||
|
|
||||||
MTLPixelFormat dstMTLPixFmt = _dstImage->getMTLPixelFormat();
|
MTLPixelFormat dstMTLPixFmt = _dstImage->getMTLPixelFormat(dstPlaneIndex);
|
||||||
bool isDstCompressed = _dstImage->getIsCompressed();
|
bool isDstCompressed = _dstImage->getIsCompressed();
|
||||||
|
|
||||||
// If source and destination have different formats and at least one is compressed, use a temporary intermediary buffer
|
// If source and destination have different formats and at least one is compressed, use a temporary intermediary buffer
|
||||||
bool useTempBuffer = (srcMTLPixFmt != dstMTLPixFmt) && (isSrcCompressed || isDstCompressed);
|
bool useTempBuffer = (srcMTLPixFmt != dstMTLPixFmt) && (isSrcCompressed || isDstCompressed);
|
||||||
if (useTempBuffer) {
|
|
||||||
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
|
||||||
uint32_t copyCnt = (uint32_t)_vkImageCopies.size();
|
|
||||||
VkBufferImageCopy vkSrcCopies[copyCnt];
|
|
||||||
VkBufferImageCopy vkDstCopies[copyCnt];
|
|
||||||
size_t tmpBuffSize = 0;
|
|
||||||
for (uint32_t copyIdx = 0; copyIdx < copyCnt; copyIdx++) {
|
|
||||||
auto& vkIC = _vkImageCopies[copyIdx];
|
|
||||||
|
|
||||||
// Add copy from source image to temp buffer.
|
if (useTempBuffer) {
|
||||||
auto& srcCpy = vkSrcCopies[copyIdx];
|
// Add copy from source image to temp buffer.
|
||||||
srcCpy.bufferOffset = tmpBuffSize;
|
auto& srcCpy = vkSrcCopies[copyIdx];
|
||||||
srcCpy.bufferRowLength = 0;
|
srcCpy.bufferOffset = tmpBuffSize;
|
||||||
srcCpy.bufferImageHeight = 0;
|
srcCpy.bufferRowLength = 0;
|
||||||
srcCpy.imageSubresource = vkIC.srcSubresource;
|
srcCpy.bufferImageHeight = 0;
|
||||||
srcCpy.imageOffset = vkIC.srcOffset;
|
srcCpy.imageSubresource = vkIC.srcSubresource;
|
||||||
srcCpy.imageExtent = vkIC.extent;
|
srcCpy.imageOffset = vkIC.srcOffset;
|
||||||
|
srcCpy.imageExtent = vkIC.extent;
|
||||||
|
|
||||||
// Add copy from temp buffer to destination image.
|
// Add copy from temp buffer to destination image.
|
||||||
// Extent is provided in source texels. If the source is compressed but the
|
// Extent is provided in source texels. If the source is compressed but the
|
||||||
// destination is not, each destination pixel will consume an entire source block,
|
// destination is not, each destination pixel will consume an entire source block,
|
||||||
// so we must downscale the destination extent by the size of the source block.
|
// so we must downscale the destination extent by the size of the source block.
|
||||||
VkExtent3D dstExtent = vkIC.extent;
|
VkExtent3D dstExtent = vkIC.extent;
|
||||||
if (isSrcCompressed && !isDstCompressed) {
|
if (isSrcCompressed && !isDstCompressed) {
|
||||||
VkExtent2D srcBlockExtent = pixFmts->getBlockTexelSize(srcMTLPixFmt);
|
VkExtent2D srcBlockExtent = pixFmts->getBlockTexelSize(srcMTLPixFmt);
|
||||||
dstExtent.width /= srcBlockExtent.width;
|
dstExtent.width /= srcBlockExtent.width;
|
||||||
dstExtent.height /= srcBlockExtent.height;
|
dstExtent.height /= srcBlockExtent.height;
|
||||||
}
|
}
|
||||||
auto& dstCpy = vkDstCopies[copyIdx];
|
auto& dstCpy = vkDstCopies[copyIdx];
|
||||||
dstCpy.bufferOffset = tmpBuffSize;
|
dstCpy.bufferOffset = tmpBuffSize;
|
||||||
dstCpy.bufferRowLength = 0;
|
dstCpy.bufferRowLength = 0;
|
||||||
dstCpy.bufferImageHeight = 0;
|
dstCpy.bufferImageHeight = 0;
|
||||||
dstCpy.imageSubresource = vkIC.dstSubresource;
|
dstCpy.imageSubresource = vkIC.dstSubresource;
|
||||||
dstCpy.imageOffset = vkIC.dstOffset;
|
dstCpy.imageOffset = vkIC.dstOffset;
|
||||||
dstCpy.imageExtent = dstExtent;
|
dstCpy.imageExtent = dstExtent;
|
||||||
|
|
||||||
size_t bytesPerRow = pixFmts->getBytesPerRow(srcMTLPixFmt, vkIC.extent.width);
|
size_t bytesPerRow = pixFmts->getBytesPerRow(srcMTLPixFmt, vkIC.extent.width);
|
||||||
size_t bytesPerRegion = pixFmts->getBytesPerLayer(srcMTLPixFmt, bytesPerRow, vkIC.extent.height);
|
size_t bytesPerRegion = pixFmts->getBytesPerLayer(srcMTLPixFmt, bytesPerRow, vkIC.extent.height);
|
||||||
tmpBuffSize += bytesPerRegion;
|
tmpBuffSize += bytesPerRegion;
|
||||||
}
|
} else {
|
||||||
|
// Map the source pixel format to the dest pixel format through a texture view on the source texture.
|
||||||
|
// If the source and dest pixel formats are the same, this will simply degenerate to the source texture itself.
|
||||||
|
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture(srcPlaneIndex, _dstImage->getMTLPixelFormat(dstPlaneIndex));
|
||||||
|
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture(dstPlaneIndex);
|
||||||
|
if ( !srcMTLTex || !dstMTLTex ) { return; }
|
||||||
|
|
||||||
MVKBufferDescriptorData tempBuffData;
|
id<MTLBlitCommandEncoder> mtlBlitEnc = cmdEncoder->getMTLBlitEncoder(commandUse);
|
||||||
tempBuffData.size = tmpBuffSize;
|
|
||||||
tempBuffData.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
VkBuffer tempBuff = (VkBuffer)cmdEncoder->getCommandEncodingPool()->getTransferMVKBuffer(tempBuffData);
|
|
||||||
|
|
||||||
MVKCmdBufferImageCopy<N> cpyCmd;
|
// If copies can be performed using direct texture-texture copying, do so
|
||||||
|
uint32_t srcLevel = vkIC.srcSubresource.mipLevel;
|
||||||
|
MTLOrigin srcOrigin = mvkMTLOriginFromVkOffset3D(vkIC.srcOffset);
|
||||||
|
MTLSize srcSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(vkIC.extent),
|
||||||
|
srcOrigin,
|
||||||
|
mvkMTLSizeFromVkExtent3D(_srcImage->getExtent3D(srcPlaneIndex, srcLevel)));
|
||||||
|
uint32_t dstLevel = vkIC.dstSubresource.mipLevel;
|
||||||
|
MTLOrigin dstOrigin = mvkMTLOriginFromVkOffset3D(vkIC.dstOffset);
|
||||||
|
uint32_t srcBaseLayer = vkIC.srcSubresource.baseArrayLayer;
|
||||||
|
uint32_t dstBaseLayer = vkIC.dstSubresource.baseArrayLayer;
|
||||||
|
uint32_t layCnt = vkIC.srcSubresource.layerCount;
|
||||||
|
|
||||||
// Copy from source image to buffer
|
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
||||||
// Create and execute a temporary buffer image command.
|
[mtlBlitEnc copyFromTexture: srcMTLTex
|
||||||
// To be threadsafe...do NOT acquire and return the command from the pool.
|
sourceSlice: srcBaseLayer + layIdx
|
||||||
cpyCmd.setContent(cmdEncoder->_cmdBuffer, tempBuff, (VkImage)_srcImage, _srcLayout, copyCnt, vkSrcCopies, false);
|
sourceLevel: srcLevel
|
||||||
cpyCmd.encode(cmdEncoder);
|
sourceOrigin: srcOrigin
|
||||||
|
sourceSize: srcSize
|
||||||
|
toTexture: dstMTLTex
|
||||||
|
destinationSlice: dstBaseLayer + layIdx
|
||||||
|
destinationLevel: dstLevel
|
||||||
|
destinationOrigin: dstOrigin];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy from buffer to destination image
|
if (tmpBuffSize > 0) {
|
||||||
// Create and execute a temporary buffer image command.
|
MVKBufferDescriptorData tempBuffData;
|
||||||
// To be threadsafe...do NOT acquire and return the command from the pool.
|
tempBuffData.size = tmpBuffSize;
|
||||||
cpyCmd.setContent(cmdEncoder->_cmdBuffer, tempBuff, (VkImage)_dstImage, _dstLayout, copyCnt, vkDstCopies, true);
|
tempBuffData.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
cpyCmd.encode(cmdEncoder);
|
VkBuffer tempBuff = (VkBuffer)cmdEncoder->getCommandEncodingPool()->getTransferMVKBuffer(tempBuffData);
|
||||||
|
|
||||||
} else {
|
MVKCmdBufferImageCopy<N> cpyCmd;
|
||||||
// Map the source pixel format to the dest pixel format through a texture view on the source texture.
|
|
||||||
// If the source and dest pixel formats are the same, this will simply degenerate to the source texture itself.
|
|
||||||
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture(_dstImage->getMTLPixelFormat());
|
|
||||||
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture();
|
|
||||||
if ( !srcMTLTex || !dstMTLTex ) { return; }
|
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> mtlBlitEnc = cmdEncoder->getMTLBlitEncoder(commandUse);
|
// Copy from source image to buffer
|
||||||
|
// Create and execute a temporary buffer image command.
|
||||||
|
// To be threadsafe...do NOT acquire and return the command from the pool.
|
||||||
|
cpyCmd.setContent(cmdEncoder->_cmdBuffer, tempBuff, (VkImage)_srcImage, _srcLayout, copyCnt, vkSrcCopies, false);
|
||||||
|
cpyCmd.encode(cmdEncoder);
|
||||||
|
|
||||||
// If copies can be performed using direct texture-texture copying, do so
|
// Copy from buffer to destination image
|
||||||
for (auto& cpyRgn : _vkImageCopies) {
|
// Create and execute a temporary buffer image command.
|
||||||
uint32_t srcLevel = cpyRgn.srcSubresource.mipLevel;
|
// To be threadsafe...do NOT acquire and return the command from the pool.
|
||||||
MTLOrigin srcOrigin = mvkMTLOriginFromVkOffset3D(cpyRgn.srcOffset);
|
cpyCmd.setContent(cmdEncoder->_cmdBuffer, tempBuff, (VkImage)_dstImage, _dstLayout, copyCnt, vkDstCopies, true);
|
||||||
MTLSize srcSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(cpyRgn.extent),
|
cpyCmd.encode(cmdEncoder);
|
||||||
srcOrigin,
|
}
|
||||||
mvkMTLSizeFromVkExtent3D(_srcImage->getExtent3D(srcLevel)));
|
|
||||||
uint32_t dstLevel = cpyRgn.dstSubresource.mipLevel;
|
|
||||||
MTLOrigin dstOrigin = mvkMTLOriginFromVkOffset3D(cpyRgn.dstOffset);
|
|
||||||
uint32_t srcBaseLayer = cpyRgn.srcSubresource.baseArrayLayer;
|
|
||||||
uint32_t dstBaseLayer = cpyRgn.dstSubresource.baseArrayLayer;
|
|
||||||
uint32_t layCnt = cpyRgn.srcSubresource.layerCount;
|
|
||||||
|
|
||||||
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
|
||||||
[mtlBlitEnc copyFromTexture: srcMTLTex
|
|
||||||
sourceSlice: srcBaseLayer + layIdx
|
|
||||||
sourceLevel: srcLevel
|
|
||||||
sourceOrigin: srcOrigin
|
|
||||||
sourceSize: srcSize
|
|
||||||
toTexture: dstMTLTex
|
|
||||||
destinationSlice: dstBaseLayer + layIdx
|
|
||||||
destinationLevel: dstLevel
|
|
||||||
destinationOrigin: dstOrigin];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template class MVKCmdCopyImage<1>;
|
template class MVKCmdCopyImage<1>;
|
||||||
@ -208,33 +217,37 @@ VkResult MVKCmdBlitImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
|||||||
|
|
||||||
_srcImage = (MVKImage*)srcImage;
|
_srcImage = (MVKImage*)srcImage;
|
||||||
_srcLayout = srcImageLayout;
|
_srcLayout = srcImageLayout;
|
||||||
|
|
||||||
_dstImage = (MVKImage*)dstImage;
|
_dstImage = (MVKImage*)dstImage;
|
||||||
_dstLayout = dstImageLayout;
|
_dstLayout = dstImageLayout;
|
||||||
|
|
||||||
_filter = filter;
|
_filter = filter;
|
||||||
|
|
||||||
_vkImageBlits.clear(); // Clear for reuse
|
_vkImageBlits.clear(); // Clear for reuse
|
||||||
for (uint32_t i = 0; i < regionCount; i++) {
|
for (uint32_t regionIdx = 0; regionIdx < regionCount; regionIdx++) {
|
||||||
_vkImageBlits.push_back(pRegions[i]);
|
auto& vkIR = pRegions[regionIdx];
|
||||||
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.srcSubresource.aspectMask);
|
||||||
|
|
||||||
|
// Validate - depth stencil formats cannot be scaled or inverted
|
||||||
|
MTLPixelFormat srcMTLPixFmt = _srcImage->getMTLPixelFormat(srcPlaneIndex);
|
||||||
|
if (pixFmts->isDepthFormat(srcMTLPixFmt) || pixFmts->isStencilFormat(srcMTLPixFmt)) {
|
||||||
|
for (auto& vkIB : _vkImageBlits) {
|
||||||
|
if ( !(canCopyFormats(vkIB) && canCopy(vkIB)) ) {
|
||||||
|
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdBlitImage(): Scaling or inverting depth/stencil images is not supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_vkImageBlits.push_back(vkIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate - depth stencil formats cannot be scaled or inverted
|
|
||||||
MTLPixelFormat srcMTLPixFmt = _srcImage->getMTLPixelFormat();
|
|
||||||
if (pixFmts->isDepthFormat(srcMTLPixFmt) || pixFmts->isStencilFormat(srcMTLPixFmt)) {
|
|
||||||
bool canCopyFmts = canCopyFormats();
|
|
||||||
for (auto& vkIB : _vkImageBlits) {
|
|
||||||
if ( !(canCopyFmts && canCopy(vkIB)) ) {
|
|
||||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdBlitImage(): Scaling or inverting depth/stencil images is not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
bool MVKCmdBlitImage<N>::canCopyFormats() {
|
bool MVKCmdBlitImage<N>::canCopyFormats(const VkImageBlit& region) {
|
||||||
return ((_srcImage->getMTLPixelFormat() == _dstImage->getMTLPixelFormat()) &&
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.srcSubresource.aspectMask);
|
||||||
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.dstSubresource.aspectMask);
|
||||||
|
return ((_srcImage->getMTLPixelFormat(srcPlaneIndex) == _dstImage->getMTLPixelFormat(dstPlaneIndex)) &&
|
||||||
(_dstImage->getSampleCount() == _srcImage->getSampleCount()));
|
(_dstImage->getSampleCount() == _srcImage->getSampleCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,8 +268,10 @@ void MVKCmdBlitImage<N>::populateVertices(MVKVertexPosTex* vertices, const VkIma
|
|||||||
const VkOffset3D& do1 = region.dstOffsets[1];
|
const VkOffset3D& do1 = region.dstOffsets[1];
|
||||||
|
|
||||||
// Get the extents of the source and destination textures.
|
// Get the extents of the source and destination textures.
|
||||||
VkExtent3D srcExtent = _srcImage->getExtent3D(region.srcSubresource.mipLevel);
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.srcSubresource.aspectMask);
|
||||||
VkExtent3D dstExtent = _dstImage->getExtent3D(region.dstSubresource.mipLevel);
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.dstSubresource.aspectMask);
|
||||||
|
VkExtent3D srcExtent = _srcImage->getExtent3D(srcPlaneIndex, region.srcSubresource.mipLevel);
|
||||||
|
VkExtent3D dstExtent = _dstImage->getExtent3D(dstPlaneIndex, region.dstSubresource.mipLevel);
|
||||||
|
|
||||||
// Determine the bottom-left and top-right corners of the source and destination
|
// Determine the bottom-left and top-right corners of the source and destination
|
||||||
// texture regions, each as a fraction of the corresponding texture size.
|
// texture regions, each as a fraction of the corresponding texture size.
|
||||||
@ -317,9 +332,8 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
|
|
||||||
// Separate BLITs into those that are really just simple texure region copies,
|
// Separate BLITs into those that are really just simple texure region copies,
|
||||||
// and those that require rendering
|
// and those that require rendering
|
||||||
bool canCopyFmts = canCopyFormats();
|
|
||||||
for (auto& vkIB : _vkImageBlits) {
|
for (auto& vkIB : _vkImageBlits) {
|
||||||
if (canCopyFmts && canCopy(vkIB)) {
|
if (canCopyFormats(vkIB) && canCopy(vkIB)) {
|
||||||
|
|
||||||
const VkOffset3D& so0 = vkIB.srcOffsets[0];
|
const VkOffset3D& so0 = vkIB.srcOffsets[0];
|
||||||
const VkOffset3D& so1 = vkIB.srcOffsets[1];
|
const VkOffset3D& so1 = vkIB.srcOffsets[1];
|
||||||
@ -351,59 +365,61 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform those BLITs that require rendering to destination texture.
|
// Perform those BLITs that require rendering to destination texture.
|
||||||
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture();
|
for (uint32_t blitIdx = 0; blitIdx < blitCnt; blitIdx++) {
|
||||||
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture();
|
auto& mvkIBR = mvkBlitRenders[blitIdx];
|
||||||
if (blitCnt && srcMTLTex && dstMTLTex) {
|
|
||||||
|
|
||||||
cmdEncoder->endCurrentMetalEncoding();
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(mvkIBR.region.srcSubresource.aspectMask);
|
||||||
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(mvkIBR.region.dstSubresource.aspectMask);
|
||||||
|
|
||||||
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture(srcPlaneIndex);
|
||||||
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture(dstPlaneIndex);
|
||||||
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
if (blitCnt && srcMTLTex && dstMTLTex) {
|
||||||
mtlColorAttDesc.storeAction = MTLStoreActionStore;
|
cmdEncoder->endCurrentMetalEncoding();
|
||||||
mtlColorAttDesc.texture = dstMTLTex;
|
|
||||||
|
|
||||||
MVKRPSKeyBlitImg blitKey;
|
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
blitKey.srcMTLPixelFormat = _srcImage->getMTLPixelFormat();
|
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
||||||
blitKey.srcMTLTextureType = _srcImage->getMTLTextureType();
|
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
||||||
blitKey.dstMTLPixelFormat = _dstImage->getMTLPixelFormat();
|
mtlColorAttDesc.storeAction = MTLStoreActionStore;
|
||||||
blitKey.srcFilter = mvkMTLSamplerMinMagFilterFromVkFilter(_filter);
|
mtlColorAttDesc.texture = dstMTLTex;
|
||||||
blitKey.dstSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_dstImage->getSampleCount());
|
|
||||||
id<MTLRenderPipelineState> mtlRPS = cmdEncoder->getCommandEncodingPool()->getCmdBlitImageMTLRenderPipelineState(blitKey);
|
|
||||||
|
|
||||||
uint32_t vtxBuffIdx = cmdEncoder->getDevice()->getMetalBufferIndexForVertexAttributeBinding(kMVKVertexContentBufferIndex);
|
MVKRPSKeyBlitImg blitKey;
|
||||||
|
blitKey.srcMTLPixelFormat = _srcImage->getMTLPixelFormat(srcPlaneIndex);
|
||||||
|
blitKey.srcMTLTextureType = _srcImage->getMTLTextureType();
|
||||||
|
blitKey.dstMTLPixelFormat = _dstImage->getMTLPixelFormat(dstPlaneIndex);
|
||||||
|
blitKey.srcFilter = mvkMTLSamplerMinMagFilterFromVkFilter(_filter);
|
||||||
|
blitKey.dstSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_dstImage->getSampleCount());
|
||||||
|
id<MTLRenderPipelineState> mtlRPS = cmdEncoder->getCommandEncodingPool()->getCmdBlitImageMTLRenderPipelineState(blitKey);
|
||||||
|
|
||||||
for (uint32_t blitIdx = 0; blitIdx < blitCnt; blitIdx++) {
|
uint32_t vtxBuffIdx = cmdEncoder->getDevice()->getMetalBufferIndexForVertexAttributeBinding(kMVKVertexContentBufferIndex);
|
||||||
auto& mvkIBR = mvkBlitRenders[blitIdx];
|
|
||||||
|
mtlColorAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
||||||
|
|
||||||
mtlColorAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
uint32_t layCnt = mvkIBR.region.srcSubresource.layerCount;
|
||||||
|
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
||||||
|
// Update the render pass descriptor for the texture level and slice, and create a render encoder.
|
||||||
|
mtlColorAttDesc.slice = mvkIBR.region.dstSubresource.baseArrayLayer + layIdx;
|
||||||
|
id<MTLRenderCommandEncoder> mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPD];
|
||||||
|
setLabelIfNotNil(mtlRendEnc, mvkMTLRenderCommandEncoderLabel(commandUse));
|
||||||
|
|
||||||
uint32_t layCnt = mvkIBR.region.srcSubresource.layerCount;
|
[mtlRendEnc pushDebugGroup: @"vkCmdBlitImage"];
|
||||||
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
[mtlRendEnc setRenderPipelineState: mtlRPS];
|
||||||
// Update the render pass descriptor for the texture level and slice, and create a render encoder.
|
cmdEncoder->setVertexBytes(mtlRendEnc, mvkIBR.vertices, sizeof(mvkIBR.vertices), vtxBuffIdx);
|
||||||
mtlColorAttDesc.slice = mvkIBR.region.dstSubresource.baseArrayLayer + layIdx;
|
[mtlRendEnc setFragmentTexture: srcMTLTex atIndex: 0];
|
||||||
id<MTLRenderCommandEncoder> mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPD];
|
|
||||||
setLabelIfNotNil(mtlRendEnc, mvkMTLRenderCommandEncoderLabel(commandUse));
|
|
||||||
|
|
||||||
[mtlRendEnc pushDebugGroup: @"vkCmdBlitImage"];
|
struct {
|
||||||
[mtlRendEnc setRenderPipelineState: mtlRPS];
|
uint slice;
|
||||||
cmdEncoder->setVertexBytes(mtlRendEnc, mvkIBR.vertices, sizeof(mvkIBR.vertices), vtxBuffIdx);
|
float lod;
|
||||||
[mtlRendEnc setFragmentTexture: srcMTLTex atIndex: 0];
|
} texSubRez;
|
||||||
|
texSubRez.slice = mvkIBR.region.srcSubresource.baseArrayLayer + layIdx;
|
||||||
|
texSubRez.lod = mvkIBR.region.srcSubresource.mipLevel;
|
||||||
|
cmdEncoder->setFragmentBytes(mtlRendEnc, &texSubRez, sizeof(texSubRez), 0);
|
||||||
|
|
||||||
struct {
|
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: kMVKBlitVertexCount];
|
||||||
uint slice;
|
[mtlRendEnc popDebugGroup];
|
||||||
float lod;
|
[mtlRendEnc endEncoding];
|
||||||
} texSubRez;
|
}
|
||||||
texSubRez.slice = mvkIBR.region.srcSubresource.baseArrayLayer + layIdx;
|
}
|
||||||
texSubRez.lod = mvkIBR.region.srcSubresource.mipLevel;
|
}
|
||||||
cmdEncoder->setFragmentBytes(mtlRendEnc, &texSubRez, sizeof(texSubRez), 0);
|
|
||||||
|
|
||||||
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: kMVKBlitVertexCount];
|
|
||||||
[mtlRendEnc popDebugGroup];
|
|
||||||
[mtlRendEnc endEncoding];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template class MVKCmdBlitImage<1>;
|
template class MVKCmdBlitImage<1>;
|
||||||
@ -428,15 +444,18 @@ VkResult MVKCmdResolveImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
|||||||
|
|
||||||
_vkImageResolves.clear(); // Clear for reuse
|
_vkImageResolves.clear(); // Clear for reuse
|
||||||
_vkImageResolves.reserve(regionCount);
|
_vkImageResolves.reserve(regionCount);
|
||||||
for (uint32_t i = 0; i < regionCount; i++) {
|
for (uint32_t regionIdx = 0; regionIdx < regionCount; regionIdx++) {
|
||||||
_vkImageResolves.push_back(pRegions[i]);
|
auto& vkIR = pRegions[regionIdx];
|
||||||
}
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.dstSubresource.aspectMask);
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
||||||
if ( !mvkAreAllFlagsEnabled(pixFmts->getCapabilities(_dstImage->getMTLPixelFormat()), kMVKMTLFmtCapsResolve) ) {
|
if ( !mvkAreAllFlagsEnabled(pixFmts->getCapabilities(_dstImage->getMTLPixelFormat(dstPlaneIndex)), kMVKMTLFmtCapsResolve) ) {
|
||||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdResolveImage(): %s cannot be used as a resolve destination on this device.", pixFmts->getName(_dstImage->getVkFormat()));
|
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdResolveImage(): %s cannot be used as a resolve destination on this device.", pixFmts->getName(_dstImage->getVkFormat()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_vkImageResolves.push_back(vkIR);
|
||||||
|
}
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -457,10 +476,12 @@ void MVKCmdResolveImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
|||||||
uint32_t sliceCnt = 0;
|
uint32_t sliceCnt = 0;
|
||||||
|
|
||||||
for (VkImageResolve& vkIR : _vkImageResolves) {
|
for (VkImageResolve& vkIR : _vkImageResolves) {
|
||||||
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.srcSubresource.aspectMask);
|
||||||
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.dstSubresource.aspectMask);
|
||||||
|
|
||||||
uint32_t mipLvl = vkIR.dstSubresource.mipLevel;
|
uint32_t mipLvl = vkIR.dstSubresource.mipLevel;
|
||||||
VkExtent3D srcImgExt = _srcImage->getExtent3D(mipLvl);
|
VkExtent3D srcImgExt = _srcImage->getExtent3D(srcPlaneIndex, mipLvl);
|
||||||
VkExtent3D dstImgExt = _dstImage->getExtent3D(mipLvl);
|
VkExtent3D dstImgExt = _dstImage->getExtent3D(dstPlaneIndex, mipLvl);
|
||||||
|
|
||||||
// If the region does not cover the entire content of the source level, expand the
|
// If the region does not cover the entire content of the source level, expand the
|
||||||
// destination content in the region to the temporary image. The purpose of this
|
// destination content in the region to the temporary image. The purpose of this
|
||||||
@ -496,25 +517,23 @@ void MVKCmdResolveImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
|||||||
uint32_t layCnt = vkIR.dstSubresource.layerCount;
|
uint32_t layCnt = vkIR.dstSubresource.layerCount;
|
||||||
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
||||||
MVKMetalResolveSlice& rslvSlice = mtlResolveSlices[sliceCnt++];
|
MVKMetalResolveSlice& rslvSlice = mtlResolveSlices[sliceCnt++];
|
||||||
|
rslvSlice.copyRegion = &cpyRgn;
|
||||||
rslvSlice.level = vkIR.dstSubresource.mipLevel;
|
rslvSlice.level = vkIR.dstSubresource.mipLevel;
|
||||||
rslvSlice.slice = baseLayer + layIdx;
|
rslvSlice.slice = baseLayer + layIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> srcMTLTex;
|
// Expansion and copying is not required. Each mip level of the source image
|
||||||
if (expCnt == 0) {
|
// is being resolved entirely. Resolve directly from the source image.
|
||||||
// Expansion and copying is not required. Each mip level of the source image
|
MVKImage* xfrImage = _srcImage;
|
||||||
// is being resolved entirely. Resolve directly from the source image.
|
if (expCnt) {
|
||||||
srcMTLTex = _srcImage->getMTLTexture();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Expansion and copying is required. Acquire a temporary transfer image, expand
|
// Expansion and copying is required. Acquire a temporary transfer image, expand
|
||||||
// the destination image into it, copy from the source image to the temporary image,
|
// the destination image into it, copy from the source image to the temporary image,
|
||||||
// and then resolve from the temporary image to the destination image.
|
// and then resolve from the temporary image to the destination image.
|
||||||
MVKImageDescriptorData xferImageData;
|
MVKImageDescriptorData xferImageData;
|
||||||
_dstImage->getTransferDescriptorData(xferImageData);
|
_dstImage->getTransferDescriptorData(xferImageData);
|
||||||
xferImageData.samples = _srcImage->getSampleCount();
|
xferImageData.samples = _srcImage->getSampleCount();
|
||||||
MVKImage* xfrImage = cmdEncoder->getCommandEncodingPool()->getTransferMVKImage(xferImageData);
|
xfrImage = cmdEncoder->getCommandEncodingPool()->getTransferMVKImage(xferImageData);
|
||||||
|
|
||||||
// Expand the current content of the destination image to the temporary transfer image.
|
// Expand the current content of the destination image to the temporary transfer image.
|
||||||
MVKCmdBlitImage<N> expCmd;
|
MVKCmdBlitImage<N> expCmd;
|
||||||
@ -530,23 +549,24 @@ void MVKCmdResolveImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
|||||||
(VkImage)xfrImage, _dstLayout,
|
(VkImage)xfrImage, _dstLayout,
|
||||||
copyCnt, copyRegions);
|
copyCnt, copyRegions);
|
||||||
copyCmd.encode(cmdEncoder, kMVKCommandUseResolveCopyImage);
|
copyCmd.encode(cmdEncoder, kMVKCommandUseResolveCopyImage);
|
||||||
|
|
||||||
srcMTLTex = xfrImage->getMTLTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdEncoder->endCurrentMetalEncoding();
|
cmdEncoder->endCurrentMetalEncoding();
|
||||||
|
|
||||||
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
||||||
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
||||||
mtlColorAttDesc.storeAction = MTLStoreActionMultisampleResolve;
|
mtlColorAttDesc.storeAction = MTLStoreActionMultisampleResolve;
|
||||||
mtlColorAttDesc.texture = srcMTLTex;
|
|
||||||
mtlColorAttDesc.resolveTexture = _dstImage->getMTLTexture();
|
|
||||||
|
|
||||||
// For each resolve slice, update the render pass descriptor for
|
// For each resolve slice, update the render pass descriptor for
|
||||||
// the texture level and slice and create a render encoder.
|
// the texture level and slice and create a render encoder.
|
||||||
for (uint32_t sIdx = 0; sIdx < sliceCnt; sIdx++) {
|
for (uint32_t sIdx = 0; sIdx < sliceCnt; sIdx++) {
|
||||||
MVKMetalResolveSlice& rslvSlice = mtlResolveSlices[sIdx];
|
MVKMetalResolveSlice& rslvSlice = mtlResolveSlices[sIdx];
|
||||||
|
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(rslvSlice.copyRegion->srcSubresource.aspectMask);
|
||||||
|
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(rslvSlice.copyRegion->dstSubresource.aspectMask);
|
||||||
|
|
||||||
|
mtlColorAttDesc.texture = xfrImage->getMTLTexture(srcPlaneIndex);
|
||||||
|
mtlColorAttDesc.resolveTexture = _dstImage->getMTLTexture(dstPlaneIndex);
|
||||||
mtlColorAttDesc.level = rslvSlice.level;
|
mtlColorAttDesc.level = rslvSlice.level;
|
||||||
mtlColorAttDesc.slice = rslvSlice.slice;
|
mtlColorAttDesc.slice = rslvSlice.slice;
|
||||||
mtlColorAttDesc.resolveLevel = rslvSlice.level;
|
mtlColorAttDesc.resolveLevel = rslvSlice.level;
|
||||||
@ -675,12 +695,13 @@ VkResult MVKCmdBufferImageCopy<N>::setContent(MVKCommandBuffer* cmdBuff,
|
|||||||
_bufferImageCopyRegions.reserve(regionCount);
|
_bufferImageCopyRegions.reserve(regionCount);
|
||||||
for (uint32_t i = 0; i < regionCount; i++) {
|
for (uint32_t i = 0; i < regionCount; i++) {
|
||||||
_bufferImageCopyRegions.push_back(pRegions[i]);
|
_bufferImageCopyRegions.push_back(pRegions[i]);
|
||||||
}
|
|
||||||
|
// Validate
|
||||||
// Validate
|
if ( !_image->hasExpectedTexelSize() ) {
|
||||||
if ( !_image->hasExpectedTexelSize() ) {
|
MTLPixelFormat mtlPixFmt = _image->getMTLPixelFormat(MVKImage::getPlaneFromVkImageAspectFlags(pRegions[i].imageSubresource.aspectMask));
|
||||||
const char* cmdName = _toImage ? "vkCmdCopyBufferToImage" : "vkCmdCopyImageToBuffer";
|
const char* cmdName = _toImage ? "vkCmdCopyBufferToImage" : "vkCmdCopyImageToBuffer";
|
||||||
return reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "%s(): The image is using Metal format %s as a substitute for Vulkan format %s. Since the pixel size is different, content for the image cannot be copied to or from a buffer.", cmdName, cmdBuff->getPixelFormats()->getName(_image->getMTLPixelFormat()), cmdBuff->getPixelFormats()->getName(_image->getVkFormat()));
|
return reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "%s(): The image is using Metal format %s as a substitute for Vulkan format %s. Since the pixel size is different, content for the image cannot be copied to or from a buffer.", cmdName, cmdBuff->getPixelFormats()->getName(mtlPixFmt), cmdBuff->getPixelFormats()->getName(_image->getVkFormat()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
@ -689,21 +710,23 @@ VkResult MVKCmdBufferImageCopy<N>::setContent(MVKCommandBuffer* cmdBuff,
|
|||||||
template <size_t N>
|
template <size_t N>
|
||||||
void MVKCmdBufferImageCopy<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
void MVKCmdBufferImageCopy<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||||
id<MTLBuffer> mtlBuffer = _buffer->getMTLBuffer();
|
id<MTLBuffer> mtlBuffer = _buffer->getMTLBuffer();
|
||||||
id<MTLTexture> mtlTexture = _image->getMTLTexture();
|
if ( !mtlBuffer ) { return; }
|
||||||
if ( !mtlBuffer || !mtlTexture ) { return; }
|
|
||||||
|
|
||||||
NSUInteger mtlBuffOffsetBase = _buffer->getMTLBufferOffset();
|
NSUInteger mtlBuffOffsetBase = _buffer->getMTLBufferOffset();
|
||||||
MTLPixelFormat mtlPixFmt = _image->getMTLPixelFormat();
|
|
||||||
MVKCommandUse cmdUse = _toImage ? kMVKCommandUseCopyBufferToImage : kMVKCommandUseCopyImageToBuffer;
|
MVKCommandUse cmdUse = _toImage ? kMVKCommandUseCopyBufferToImage : kMVKCommandUseCopyImageToBuffer;
|
||||||
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
||||||
|
|
||||||
for (auto& cpyRgn : _bufferImageCopyRegions) {
|
for (auto& cpyRgn : _bufferImageCopyRegions) {
|
||||||
|
uint8_t planeIndex = MVKImage::getPlaneFromVkImageAspectFlags(cpyRgn.imageSubresource.aspectMask);
|
||||||
|
MTLPixelFormat mtlPixFmt = _image->getMTLPixelFormat(planeIndex);
|
||||||
|
id<MTLTexture> mtlTexture = _image->getMTLTexture(planeIndex);
|
||||||
|
if ( !mtlTexture ) { continue; }
|
||||||
|
|
||||||
uint32_t mipLevel = cpyRgn.imageSubresource.mipLevel;
|
uint32_t mipLevel = cpyRgn.imageSubresource.mipLevel;
|
||||||
MTLOrigin mtlTxtOrigin = mvkMTLOriginFromVkOffset3D(cpyRgn.imageOffset);
|
MTLOrigin mtlTxtOrigin = mvkMTLOriginFromVkOffset3D(cpyRgn.imageOffset);
|
||||||
MTLSize mtlTxtSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(cpyRgn.imageExtent),
|
MTLSize mtlTxtSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(cpyRgn.imageExtent),
|
||||||
mtlTxtOrigin,
|
mtlTxtOrigin,
|
||||||
mvkMTLSizeFromVkExtent3D(_image->getExtent3D(mipLevel)));
|
mvkMTLSizeFromVkExtent3D(_image->getExtent3D(planeIndex, mipLevel)));
|
||||||
NSUInteger mtlBuffOffset = mtlBuffOffsetBase + cpyRgn.bufferOffset;
|
NSUInteger mtlBuffOffset = mtlBuffOffsetBase + cpyRgn.bufferOffset;
|
||||||
|
|
||||||
uint32_t buffImgWd = cpyRgn.bufferRowLength;
|
uint32_t buffImgWd = cpyRgn.bufferRowLength;
|
||||||
@ -1075,29 +1098,31 @@ VkResult MVKCmdClearImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
|||||||
// Add subresource ranges
|
// Add subresource ranges
|
||||||
_subresourceRanges.clear(); // Clear for reuse
|
_subresourceRanges.clear(); // Clear for reuse
|
||||||
_subresourceRanges.reserve(rangeCount);
|
_subresourceRanges.reserve(rangeCount);
|
||||||
for (uint32_t i = 0; i < rangeCount; i++) {
|
bool isDS = isDepthStencilClear();
|
||||||
_subresourceRanges.push_back(pRanges[i]);
|
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) {
|
||||||
}
|
auto& vkIR = pRanges[rangeIdx];
|
||||||
|
uint8_t planeIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.aspectMask);
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
bool isDS = isDepthStencilClear();
|
MVKMTLFmtCaps mtlFmtCaps = cmdBuff->getPixelFormats()->getCapabilities(_image->getMTLPixelFormat(planeIndex));
|
||||||
if (_image->getImageType() == VK_IMAGE_TYPE_1D) {
|
if ((isDS && !mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCapsDSAtt)) ||
|
||||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClear%sImage(): Native 1D images cannot be cleared on this device. Consider enabling MVK_CONFIG_TEXTURE_1D_AS_2D.", (isDS ? "DepthStencil" : "Color"));
|
( !isDS && !mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCapsColorAtt))) {
|
||||||
}
|
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClear%sImage(): Format %s cannot be cleared on this device.", (isDS ? "DepthStencil" : "Color"), cmdBuff->getPixelFormats()->getName(_image->getVkFormat()));
|
||||||
MVKMTLFmtCaps mtlFmtCaps = cmdBuff->getPixelFormats()->getCapabilities(_image->getMTLPixelFormat());
|
}
|
||||||
if ((isDS && !mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCapsDSAtt)) ||
|
|
||||||
( !isDS && !mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCapsColorAtt))) {
|
_subresourceRanges.push_back(vkIR);
|
||||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClear%sImage(): Format %s cannot be cleared on this device.", (isDS ? "DepthStencil" : "Color"), cmdBuff->getPixelFormats()->getName(_image->getVkFormat()));
|
}
|
||||||
}
|
|
||||||
|
// Validate
|
||||||
|
if (_image->getImageType() == VK_IMAGE_TYPE_1D) {
|
||||||
|
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClear%sImage(): Native 1D images cannot be cleared on this device. Consider enabling MVK_CONFIG_TEXTURE_1D_AS_2D.", (isDS ? "DepthStencil" : "Color"));
|
||||||
|
}
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void MVKCmdClearImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
void MVKCmdClearImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||||
id<MTLTexture> imgMTLTex = _image->getMTLTexture();
|
|
||||||
if ( !imgMTLTex ) { return; }
|
|
||||||
|
|
||||||
bool isDS = isDepthStencilClear();
|
bool isDS = isDepthStencilClear();
|
||||||
NSString* mtlRendEncName = (isDS
|
NSString* mtlRendEncName = (isDS
|
||||||
? mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearDepthStencilImage)
|
? mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearDepthStencilImage)
|
||||||
@ -1107,6 +1132,8 @@ void MVKCmdClearImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
|||||||
|
|
||||||
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
||||||
for (auto& srRange : _subresourceRanges) {
|
for (auto& srRange : _subresourceRanges) {
|
||||||
|
id<MTLTexture> imgMTLTex = _image->getMTLTexture(MVKImage::getPlaneFromVkImageAspectFlags(srRange.aspectMask));
|
||||||
|
if ( !imgMTLTex ) { continue; }
|
||||||
|
|
||||||
MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
MTLRenderPassColorAttachmentDescriptor* mtlRPCADesc = nil;
|
MTLRenderPassColorAttachmentDescriptor* mtlRPCADesc = nil;
|
||||||
|
@ -369,7 +369,7 @@ MVKImage* MVKCommandResourceFactory::newMVKImage(MVKImageDescriptorData& imgData
|
|||||||
.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
|
.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
|
||||||
};
|
};
|
||||||
MVKImage* mvkImg = _device->createImage(&createInfo, nullptr);
|
MVKImage* mvkImg = _device->createImage(&createInfo, nullptr);
|
||||||
mvkImg->bindDeviceMemory(_transferImageMemory, 0);
|
mvkImg->bindDeviceMemory(_transferImageMemory, 0, 0);
|
||||||
return mvkImg;
|
return mvkImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,13 @@ public:
|
|||||||
#pragma mark Resource memory
|
#pragma mark Resource memory
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
/** Returns the memory requirements of this resource by populating the specified structure. */
|
||||||
VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements) override;
|
VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements);
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
/** Returns the memory requirements of this resource by populating the specified structure. */
|
||||||
VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements) override;
|
VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements);
|
||||||
|
|
||||||
/** Binds this resource to the specified offset within the specified memory allocation. */
|
/** Binds this resource to the specified offset within the specified memory allocation. */
|
||||||
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
|
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
|
||||||
|
|
||||||
/** Binds this resource to the specified offset within the specified memory allocation. */
|
/** Binds this resource to the specified offset within the specified memory allocation. */
|
||||||
VkResult bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo);
|
VkResult bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo);
|
||||||
|
@ -189,33 +189,32 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder,
|
|||||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||||
const auto& imageInfo = get<VkDescriptorImageInfo>(pData, stride, rezIdx - dstArrayElement);
|
const auto& imageInfo = get<VkDescriptorImageInfo>(pData, stride, rezIdx - dstArrayElement);
|
||||||
MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
|
MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
|
||||||
tb.mtlTexture = imageView->getMTLTexture();
|
uint8_t planeCount = (imageView) ? imageView->getPlaneCount() : 1;
|
||||||
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) {
|
for (uint8_t planeIndex = 0; planeIndex < planeCount; planeIndex++) {
|
||||||
tb.swizzle = imageView->getPackedSwizzle();
|
tb.mtlTexture = imageView->getMTLTexture(planeIndex);
|
||||||
} else {
|
tb.swizzle = (_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ? imageView->getPackedSwizzle() : 0;
|
||||||
tb.swizzle = 0;
|
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
||||||
}
|
id<MTLTexture> mtlTex = tb.mtlTexture;
|
||||||
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
if (mtlTex.parentTexture) { mtlTex = mtlTex.parentTexture; }
|
||||||
id<MTLTexture> mtlTex = tb.mtlTexture;
|
bb.mtlBuffer = mtlTex.buffer;
|
||||||
if (mtlTex.parentTexture) { mtlTex = mtlTex.parentTexture; }
|
bb.offset = mtlTex.bufferOffset;
|
||||||
bb.mtlBuffer = mtlTex.buffer;
|
bb.size = (uint32_t)(mtlTex.height * mtlTex.bufferBytesPerRow);
|
||||||
bb.offset = mtlTex.bufferOffset;
|
}
|
||||||
bb.size = (uint32_t)(mtlTex.height * mtlTex.bufferBytesPerRow);
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
}
|
if (_applyToStage[i]) {
|
||||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx + planeIndex;
|
||||||
if (_applyToStage[i]) {
|
|
||||||
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx;
|
|
||||||
if (i == kMVKShaderStageCompute) {
|
|
||||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
|
||||||
} else {
|
|
||||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
|
||||||
}
|
|
||||||
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
|
||||||
bb.index = mtlIdxs.stages[i].bufferIndex + rezIdx;
|
|
||||||
if (i == kMVKShaderStageCompute) {
|
if (i == kMVKShaderStageCompute) {
|
||||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); }
|
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
||||||
} else {
|
} else {
|
||||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); }
|
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
||||||
|
}
|
||||||
|
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
||||||
|
bb.index = mtlIdxs.stages[i].bufferIndex + rezIdx;
|
||||||
|
if (i == kMVKShaderStageCompute) {
|
||||||
|
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); }
|
||||||
|
} else {
|
||||||
|
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,30 +279,29 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder,
|
|||||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
|
||||||
const auto& imageInfo = get<VkDescriptorImageInfo>(pData, stride, rezIdx - dstArrayElement);
|
const auto& imageInfo = get<VkDescriptorImageInfo>(pData, stride, rezIdx - dstArrayElement);
|
||||||
MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
|
MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
|
||||||
tb.mtlTexture = imageView->getMTLTexture();
|
uint8_t planeCount = (imageView) ? imageView->getPlaneCount() : 1;
|
||||||
if (imageView) {
|
for (uint8_t planeIndex = 0; planeIndex < planeCount; planeIndex++) {
|
||||||
tb.swizzle = imageView->getPackedSwizzle();
|
tb.mtlTexture = imageView->getMTLTexture(planeIndex);
|
||||||
} else {
|
tb.swizzle = (imageView) ? imageView->getPackedSwizzle() : 0;
|
||||||
tb.swizzle = 0;
|
MVKSampler* sampler;
|
||||||
}
|
if (_immutableSamplers.empty()) {
|
||||||
MVKSampler* sampler;
|
sampler = (MVKSampler*)imageInfo.sampler;
|
||||||
if (_immutableSamplers.empty()) {
|
validate(sampler);
|
||||||
sampler = (MVKSampler*)imageInfo.sampler;
|
} else {
|
||||||
validate(sampler);
|
sampler = _immutableSamplers[rezIdx];
|
||||||
} else {
|
}
|
||||||
sampler = _immutableSamplers[rezIdx];
|
sb.mtlSamplerState = sampler->getMTLSamplerState();
|
||||||
}
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
sb.mtlSamplerState = sampler->getMTLSamplerState();
|
if (_applyToStage[i]) {
|
||||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx + planeIndex;
|
||||||
if (_applyToStage[i]) {
|
sb.index = mtlIdxs.stages[i].samplerIndex + rezIdx;
|
||||||
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx;
|
if (i == kMVKShaderStageCompute) {
|
||||||
sb.index = mtlIdxs.stages[i].samplerIndex + rezIdx;
|
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
||||||
if (i == kMVKShaderStageCompute) {
|
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); }
|
||||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
} else {
|
||||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); }
|
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
||||||
} else {
|
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindSamplerState(MVKShaderStage(i), sb); }
|
||||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
}
|
||||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindSamplerState(MVKShaderStage(i), sb); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -327,7 +325,7 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder,
|
|||||||
// If depth compare is required, but unavailable on the device, the sampler can only be used as an immutable sampler
|
// If depth compare is required, but unavailable on the device, the sampler can only be used as an immutable sampler
|
||||||
bool MVKDescriptorSetLayoutBinding::validate(MVKSampler* mvkSampler) {
|
bool MVKDescriptorSetLayoutBinding::validate(MVKSampler* mvkSampler) {
|
||||||
if (mvkSampler->getRequiresConstExprSampler()) {
|
if (mvkSampler->getRequiresConstExprSampler()) {
|
||||||
mvkSampler->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdPushDescriptorSet/vkCmdPushDescriptorSetWithTemplate(): Depth texture samplers using a compare operation can only be used as immutable samplers on this device.");
|
mvkSampler->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdPushDescriptorSet/vkCmdPushDescriptorSetWithTemplate(): Tried to push an immutable sampler.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -437,7 +435,19 @@ void MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStage
|
|||||||
if ( !_device->_pMetalFeatures->arrayOfSamplers ) {
|
if ( !_device->_pMetalFeatures->arrayOfSamplers ) {
|
||||||
_layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of samplers.", _device->getName()));
|
_layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of samplers.", _device->getName()));
|
||||||
}
|
}
|
||||||
|
if ( pBinding->pImmutableSamplers ) {
|
||||||
|
_layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Sampler arrays contaning multi planar samplers are not supported."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( pBinding->pImmutableSamplers ) {
|
||||||
|
for (uint32_t i = 0; i < pBinding->descriptorCount; i++) {
|
||||||
|
uint8_t planeCount = ((MVKSampler*)pBinding->pImmutableSamplers[i])->getPlaneCount();
|
||||||
|
if (planeCount > 1) {
|
||||||
|
pDescSetCounts->textureIndex += planeCount - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||||
@ -688,53 +698,54 @@ void MVKImageDescriptor::bind(MVKCommandEncoder* cmdEncoder,
|
|||||||
MVKShaderResourceBinding& mtlIndexes,
|
MVKShaderResourceBinding& mtlIndexes,
|
||||||
MVKArrayRef<uint32_t> dynamicOffsets,
|
MVKArrayRef<uint32_t> dynamicOffsets,
|
||||||
uint32_t* pDynamicOffsetIndex) {
|
uint32_t* pDynamicOffsetIndex) {
|
||||||
MVKMTLTextureBinding tb;
|
|
||||||
MVKMTLBufferBinding bb;
|
|
||||||
switch (descriptorType) {
|
switch (descriptorType) {
|
||||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||||
if (_mvkImageView) {
|
|
||||||
tb.mtlTexture = _mvkImageView->getMTLTexture();
|
|
||||||
}
|
|
||||||
if ((descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
|
|
||||||
tb.mtlTexture) {
|
|
||||||
tb.swizzle = _mvkImageView->getPackedSwizzle();
|
|
||||||
} else {
|
|
||||||
tb.swizzle = 0;
|
|
||||||
}
|
|
||||||
if (descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE && tb.mtlTexture) {
|
|
||||||
id<MTLTexture> mtlTex = tb.mtlTexture;
|
|
||||||
if (mtlTex.parentTexture) { mtlTex = mtlTex.parentTexture; }
|
|
||||||
bb.mtlBuffer = mtlTex.buffer;
|
|
||||||
bb.offset = mtlTex.bufferOffset;
|
|
||||||
bb.size = (uint32_t)(mtlTex.height * mtlTex.bufferBytesPerRow);
|
|
||||||
}
|
|
||||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
|
||||||
if (stages[i]) {
|
|
||||||
tb.index = mtlIndexes.stages[i].textureIndex + descriptorIndex;
|
|
||||||
if (i == kMVKShaderStageCompute) {
|
|
||||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
|
||||||
} else {
|
|
||||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
|
||||||
}
|
|
||||||
if (descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
|
||||||
bb.index = mtlIndexes.stages[i].bufferIndex + descriptorIndex;
|
|
||||||
if (i == kMVKShaderStageCompute) {
|
|
||||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); }
|
|
||||||
} else {
|
|
||||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t planeCount = (_mvkImageView) ? _mvkImageView->getPlaneCount() : 1;
|
||||||
|
for (uint8_t planeIndex = 0; planeIndex < planeCount; planeIndex++) {
|
||||||
|
MVKMTLTextureBinding tb;
|
||||||
|
MVKMTLBufferBinding bb;
|
||||||
|
|
||||||
|
if (_mvkImageView) {
|
||||||
|
tb.mtlTexture = _mvkImageView->getMTLTexture(planeIndex);
|
||||||
|
}
|
||||||
|
tb.swizzle = ((descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||||
|
descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
|
||||||
|
tb.mtlTexture) ? _mvkImageView->getPackedSwizzle() : 0;
|
||||||
|
if (descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE && tb.mtlTexture) {
|
||||||
|
id<MTLTexture> mtlTex = tb.mtlTexture;
|
||||||
|
if (mtlTex.parentTexture) { mtlTex = mtlTex.parentTexture; }
|
||||||
|
bb.mtlBuffer = mtlTex.buffer;
|
||||||
|
bb.offset = mtlTex.bufferOffset;
|
||||||
|
bb.size = (uint32_t)(mtlTex.height * mtlTex.bufferBytesPerRow);
|
||||||
|
}
|
||||||
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
|
if (stages[i]) {
|
||||||
|
tb.index = mtlIndexes.stages[i].textureIndex + descriptorIndex + planeIndex;
|
||||||
|
if (i == kMVKShaderStageCompute) {
|
||||||
|
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
||||||
|
} else {
|
||||||
|
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
||||||
|
}
|
||||||
|
if (descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
||||||
|
bb.index = mtlIndexes.stages[i].bufferIndex + descriptorIndex + planeIndex;
|
||||||
|
if (i == kMVKShaderStageCompute) {
|
||||||
|
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); }
|
||||||
|
} else {
|
||||||
|
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindBuffer(MVKShaderStage(i), bb); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKImageDescriptor::write(MVKDescriptorSet* mvkDescSet,
|
void MVKImageDescriptor::write(MVKDescriptorSet* mvkDescSet,
|
||||||
@ -845,7 +856,7 @@ void MVKSamplerDescriptorMixin::write(MVKDescriptorSet* mvkDescSet,
|
|||||||
const auto* pImgInfo = &get<VkDescriptorImageInfo>(pData, stride, srcIndex);
|
const auto* pImgInfo = &get<VkDescriptorImageInfo>(pData, stride, srcIndex);
|
||||||
_mvkSampler = (MVKSampler*)pImgInfo->sampler;
|
_mvkSampler = (MVKSampler*)pImgInfo->sampler;
|
||||||
if (_mvkSampler && _mvkSampler->getRequiresConstExprSampler()) {
|
if (_mvkSampler && _mvkSampler->getRequiresConstExprSampler()) {
|
||||||
_mvkSampler->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkUpdateDescriptorSets(): Depth texture samplers using a compare operation can only be used as immutable samplers on this device.");
|
_mvkSampler->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkUpdateDescriptorSets(): Tried to push an immutable sampler.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mvkSampler) { _mvkSampler->retain(); }
|
if (_mvkSampler) { _mvkSampler->retain(); }
|
||||||
|
@ -57,6 +57,7 @@ class MVKPipelineCache;
|
|||||||
class MVKPipelineLayout;
|
class MVKPipelineLayout;
|
||||||
class MVKPipeline;
|
class MVKPipeline;
|
||||||
class MVKSampler;
|
class MVKSampler;
|
||||||
|
class MVKSamplerYcbcrConversion;
|
||||||
class MVKDescriptorSetLayout;
|
class MVKDescriptorSetLayout;
|
||||||
class MVKDescriptorPool;
|
class MVKDescriptorPool;
|
||||||
class MVKDescriptorUpdateTemplate;
|
class MVKDescriptorUpdateTemplate;
|
||||||
@ -521,6 +522,11 @@ public:
|
|||||||
void destroySampler(MVKSampler* mvkSamp,
|
void destroySampler(MVKSampler* mvkSamp,
|
||||||
const VkAllocationCallbacks* pAllocator);
|
const VkAllocationCallbacks* pAllocator);
|
||||||
|
|
||||||
|
MVKSamplerYcbcrConversion* createSamplerYcbcrConversion(const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
|
||||||
|
const VkAllocationCallbacks* pAllocator);
|
||||||
|
void destroySamplerYcbcrConversion(MVKSamplerYcbcrConversion* mvkSampConv,
|
||||||
|
const VkAllocationCallbacks* pAllocator);
|
||||||
|
|
||||||
MVKDescriptorSetLayout* createDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
MVKDescriptorSetLayout* createDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
||||||
const VkAllocationCallbacks* pAllocator);
|
const VkAllocationCallbacks* pAllocator);
|
||||||
void destroyDescriptorSetLayout(MVKDescriptorSetLayout* mvkDSL,
|
void destroyDescriptorSetLayout(MVKDescriptorSetLayout* mvkDSL,
|
||||||
@ -652,6 +658,7 @@ public:
|
|||||||
const VkPhysicalDeviceVariablePointerFeatures _enabledVarPtrFeatures;
|
const VkPhysicalDeviceVariablePointerFeatures _enabledVarPtrFeatures;
|
||||||
const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT _enabledInterlockFeatures;
|
const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT _enabledInterlockFeatures;
|
||||||
const VkPhysicalDeviceHostQueryResetFeaturesEXT _enabledHostQryResetFeatures;
|
const VkPhysicalDeviceHostQueryResetFeaturesEXT _enabledHostQryResetFeatures;
|
||||||
|
const VkPhysicalDeviceSamplerYcbcrConversionFeatures _enabledSamplerYcbcrConversionFeatures;
|
||||||
const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT _enabledScalarLayoutFeatures;
|
const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT _enabledScalarLayoutFeatures;
|
||||||
const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT _enabledTexelBuffAlignFeatures;
|
const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT _enabledTexelBuffAlignFeatures;
|
||||||
const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT _enabledVtxAttrDivFeatures;
|
const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT _enabledVtxAttrDivFeatures;
|
||||||
|
@ -139,6 +139,11 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
|
|||||||
portabilityFeatures->samplerMipLodBias = false;
|
portabilityFeatures->samplerMipLodBias = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
|
||||||
|
auto* samplerYcbcrConvFeatures = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)next;
|
||||||
|
samplerYcbcrConvFeatures->samplerYcbcrConversion = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
|
||||||
auto* shaderIntFuncsFeatures = (VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*)next;
|
auto* shaderIntFuncsFeatures = (VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*)next;
|
||||||
shaderIntFuncsFeatures->shaderIntegerFunctions2 = true;
|
shaderIntFuncsFeatures->shaderIntegerFunctions2 = true;
|
||||||
@ -204,6 +209,11 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
|
|||||||
portabilityProps->minVertexInputBindingStrideAlignment = 4;
|
portabilityProps->minVertexInputBindingStrideAlignment = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: {
|
||||||
|
auto* samplerYcbcrConvProps = (VkSamplerYcbcrConversionImageFormatProperties*)next;
|
||||||
|
samplerYcbcrConvProps->combinedImageSamplerDescriptorCount = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -462,9 +472,9 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma
|
|||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1},
|
.layerCount = 1},
|
||||||
};
|
};
|
||||||
MTLPixelFormat mtlPixFmt;
|
MTLPixelFormat mtlPixFmt = _pixelFormats.getMTLPixelFormat(viewInfo.format);
|
||||||
bool useSwizzle;
|
bool useSwizzle;
|
||||||
return (MVKImageView::validateSwizzledMTLPixelFormat(&viewInfo, &_pixelFormats, this,
|
return (MVKImageView::validateSwizzledMTLPixelFormat(&viewInfo, this,
|
||||||
_metalFeatures.nativeTextureSwizzle,
|
_metalFeatures.nativeTextureSwizzle,
|
||||||
_mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle,
|
_mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle,
|
||||||
mtlPixFmt, useSwizzle) == VK_SUCCESS);
|
mtlPixFmt, useSwizzle) == VK_SUCCESS);
|
||||||
@ -1300,6 +1310,7 @@ void MVKPhysicalDevice::initProperties() {
|
|||||||
uint32_t maxStorage = 0, maxUniform = 0;
|
uint32_t maxStorage = 0, maxUniform = 0;
|
||||||
bool singleTexelStorage = true, singleTexelUniform = true;
|
bool singleTexelStorage = true, singleTexelUniform = true;
|
||||||
_pixelFormats.enumerateSupportedFormats({0, 0, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT}, true, [&](VkFormat vk) {
|
_pixelFormats.enumerateSupportedFormats({0, 0, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT}, true, [&](VkFormat vk) {
|
||||||
|
if ( _pixelFormats.getChromaSubsamplingComponentBits(vk) > 0 ) { return false; } // Skip chroma subsampling formats
|
||||||
MTLPixelFormat mtlFmt = _pixelFormats.getMTLPixelFormat(vk);
|
MTLPixelFormat mtlFmt = _pixelFormats.getMTLPixelFormat(vk);
|
||||||
if ( !mtlFmt ) { return false; } // If format is invalid, avoid validation errors on MTLDevice format alignment calls
|
if ( !mtlFmt ) { return false; } // If format is invalid, avoid validation errors on MTLDevice format alignment calls
|
||||||
|
|
||||||
@ -2230,16 +2241,21 @@ MVKImage* MVKDevice::createImage(const VkImageCreateInfo* pCreateInfo,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (swapchainInfo) {
|
MVKImage* mvkImg = (swapchainInfo)
|
||||||
return (MVKImage*)addResource(new MVKPeerSwapchainImage(this, pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1)));
|
? new MVKPeerSwapchainImage(this, pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1))
|
||||||
}
|
: new MVKImage(this, pCreateInfo);
|
||||||
return (MVKImage*)addResource(new MVKImage(this, pCreateInfo));
|
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||||
|
addResource(memoryBinding.get());
|
||||||
|
}
|
||||||
|
return mvkImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKDevice::destroyImage(MVKImage* mvkImg,
|
void MVKDevice::destroyImage(MVKImage* mvkImg,
|
||||||
const VkAllocationCallbacks* pAllocator) {
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
if (mvkImg) {
|
if (mvkImg) {
|
||||||
removeResource(mvkImg);
|
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||||
|
removeResource(memoryBinding.get());
|
||||||
|
}
|
||||||
mvkImg->destroy();
|
mvkImg->destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2268,13 +2284,19 @@ MVKPresentableSwapchainImage* MVKDevice::createPresentableSwapchainImage(const V
|
|||||||
MVKSwapchain* swapchain,
|
MVKSwapchain* swapchain,
|
||||||
uint32_t swapchainIndex,
|
uint32_t swapchainIndex,
|
||||||
const VkAllocationCallbacks* pAllocator) {
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
return (MVKPresentableSwapchainImage*)addResource(new MVKPresentableSwapchainImage(this, pCreateInfo, swapchain, swapchainIndex));
|
MVKPresentableSwapchainImage* mvkImg = new MVKPresentableSwapchainImage(this, pCreateInfo, swapchain, swapchainIndex);
|
||||||
|
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||||
|
addResource(memoryBinding.get());
|
||||||
|
}
|
||||||
|
return mvkImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKDevice::destroyPresentableSwapchainImage(MVKPresentableSwapchainImage* mvkImg,
|
void MVKDevice::destroyPresentableSwapchainImage(MVKPresentableSwapchainImage* mvkImg,
|
||||||
const VkAllocationCallbacks* pAllocator) {
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
if (mvkImg) {
|
if (mvkImg) {
|
||||||
removeResource(mvkImg);
|
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||||
|
removeResource(memoryBinding.get());
|
||||||
|
}
|
||||||
mvkImg->destroy();
|
mvkImg->destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2438,6 +2460,16 @@ void MVKDevice::destroySampler(MVKSampler* mvkSamp,
|
|||||||
if (mvkSamp) { mvkSamp->destroy(); }
|
if (mvkSamp) { mvkSamp->destroy(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MVKSamplerYcbcrConversion* MVKDevice::createSamplerYcbcrConversion(const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
|
||||||
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
|
return new MVKSamplerYcbcrConversion(this, pCreateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MVKDevice::destroySamplerYcbcrConversion(MVKSamplerYcbcrConversion* mvkSampConv,
|
||||||
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
|
mvkSampConv->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
MVKDescriptorSetLayout* MVKDevice::createDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
MVKDescriptorSetLayout* MVKDevice::createDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
||||||
const VkAllocationCallbacks* pAllocator) {
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
return new MVKDescriptorSetLayout(this, pCreateInfo);
|
return new MVKDescriptorSetLayout(this, pCreateInfo);
|
||||||
@ -2689,6 +2721,7 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
|||||||
_enabledVarPtrFeatures(),
|
_enabledVarPtrFeatures(),
|
||||||
_enabledInterlockFeatures(),
|
_enabledInterlockFeatures(),
|
||||||
_enabledHostQryResetFeatures(),
|
_enabledHostQryResetFeatures(),
|
||||||
|
_enabledSamplerYcbcrConversionFeatures(),
|
||||||
_enabledScalarLayoutFeatures(),
|
_enabledScalarLayoutFeatures(),
|
||||||
_enabledTexelBuffAlignFeatures(),
|
_enabledTexelBuffAlignFeatures(),
|
||||||
_enabledVtxAttrDivFeatures(),
|
_enabledVtxAttrDivFeatures(),
|
||||||
@ -2850,6 +2883,7 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
|||||||
mvkClear(&_enabledVarPtrFeatures);
|
mvkClear(&_enabledVarPtrFeatures);
|
||||||
mvkClear(&_enabledInterlockFeatures);
|
mvkClear(&_enabledInterlockFeatures);
|
||||||
mvkClear(&_enabledHostQryResetFeatures);
|
mvkClear(&_enabledHostQryResetFeatures);
|
||||||
|
mvkClear(&_enabledSamplerYcbcrConversionFeatures);
|
||||||
mvkClear(&_enabledScalarLayoutFeatures);
|
mvkClear(&_enabledScalarLayoutFeatures);
|
||||||
mvkClear(&_enabledTexelBuffAlignFeatures);
|
mvkClear(&_enabledTexelBuffAlignFeatures);
|
||||||
mvkClear(&_enabledVtxAttrDivFeatures);
|
mvkClear(&_enabledVtxAttrDivFeatures);
|
||||||
@ -2872,9 +2906,13 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
|||||||
pdScalarLayoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT;
|
pdScalarLayoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT;
|
||||||
pdScalarLayoutFeatures.pNext = &pdTexelBuffAlignFeatures;
|
pdScalarLayoutFeatures.pNext = &pdTexelBuffAlignFeatures;
|
||||||
|
|
||||||
|
VkPhysicalDeviceSamplerYcbcrConversionFeatures pdSamplerYcbcrConversionFeatures;
|
||||||
|
pdSamplerYcbcrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
|
||||||
|
pdSamplerYcbcrConversionFeatures.pNext = &pdScalarLayoutFeatures;
|
||||||
|
|
||||||
VkPhysicalDeviceHostQueryResetFeaturesEXT pdHostQryResetFeatures;
|
VkPhysicalDeviceHostQueryResetFeaturesEXT pdHostQryResetFeatures;
|
||||||
pdHostQryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT;
|
pdHostQryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT;
|
||||||
pdHostQryResetFeatures.pNext = &pdScalarLayoutFeatures;
|
pdHostQryResetFeatures.pNext = &pdSamplerYcbcrConversionFeatures;
|
||||||
|
|
||||||
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT pdInterlockFeatures;
|
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT pdInterlockFeatures;
|
||||||
pdInterlockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
|
pdInterlockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
|
||||||
@ -2971,6 +3009,13 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
|||||||
&pdHostQryResetFeatures.hostQueryReset, 1);
|
&pdHostQryResetFeatures.hostQueryReset, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
|
||||||
|
auto* requestedFeatures = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)next;
|
||||||
|
enableFeatures(&_enabledSamplerYcbcrConversionFeatures.samplerYcbcrConversion,
|
||||||
|
&requestedFeatures->samplerYcbcrConversion,
|
||||||
|
&pdSamplerYcbcrConversionFeatures.samplerYcbcrConversion, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
|
||||||
auto* requestedFeatures = (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT*)next;
|
auto* requestedFeatures = (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT*)next;
|
||||||
enableFeatures(&_enabledScalarLayoutFeatures.scalarBlockLayout,
|
enableFeatures(&_enabledScalarLayoutFeatures.scalarBlockLayout,
|
||||||
|
@ -24,8 +24,7 @@
|
|||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
class MVKBuffer;
|
class MVKImageMemoryBinding;
|
||||||
class MVKImage;
|
|
||||||
|
|
||||||
// TODO: These are inoperable placeholders until VK_KHR_external_memory_metal defines them properly
|
// TODO: These are inoperable placeholders until VK_KHR_external_memory_metal defines them properly
|
||||||
static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
|
static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
|
||||||
@ -131,15 +130,15 @@ public:
|
|||||||
~MVKDeviceMemory() override;
|
~MVKDeviceMemory() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend MVKBuffer;
|
friend class MVKBuffer;
|
||||||
friend MVKImage;
|
friend class MVKImageMemoryBinding;
|
||||||
|
|
||||||
void propagateDebugName() override;
|
void propagateDebugName() override;
|
||||||
VkDeviceSize adjustMemorySize(VkDeviceSize size, VkDeviceSize offset);
|
VkDeviceSize adjustMemorySize(VkDeviceSize size, VkDeviceSize offset);
|
||||||
VkResult addBuffer(MVKBuffer* mvkBuff);
|
VkResult addBuffer(MVKBuffer* mvkBuff);
|
||||||
void removeBuffer(MVKBuffer* mvkBuff);
|
void removeBuffer(MVKBuffer* mvkBuff);
|
||||||
VkResult addImage(MVKImage* mvkImg);
|
VkResult addImageMemoryBinding(MVKImageMemoryBinding* mvkImg);
|
||||||
void removeImage(MVKImage* mvkImg);
|
void removeImageMemoryBinding(MVKImageMemoryBinding* mvkImg);
|
||||||
bool ensureMTLHeap();
|
bool ensureMTLHeap();
|
||||||
bool ensureMTLBuffer();
|
bool ensureMTLBuffer();
|
||||||
bool ensureHostMemory();
|
bool ensureHostMemory();
|
||||||
@ -148,7 +147,7 @@ protected:
|
|||||||
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||||
|
|
||||||
MVKSmallVector<MVKBuffer*, 4> _buffers;
|
MVKSmallVector<MVKBuffer*, 4> _buffers;
|
||||||
MVKSmallVector<MVKImage*, 4> _images;
|
MVKSmallVector<MVKImageMemoryBinding*, 4> _imageMemoryBindings;
|
||||||
std::mutex _rezLock;
|
std::mutex _rezLock;
|
||||||
VkDeviceSize _allocationSize = 0;
|
VkDeviceSize _allocationSize = 0;
|
||||||
VkDeviceSize _mapOffset = 0;
|
VkDeviceSize _mapOffset = 0;
|
||||||
|
@ -92,7 +92,7 @@ VkResult MVKDeviceMemory::flushToDevice(VkDeviceSize offset, VkDeviceSize size,
|
|||||||
// If we have an MTLHeap object, there's no need to sync memory manually between images and the buffer.
|
// If we have an MTLHeap object, there's no need to sync memory manually between images and the buffer.
|
||||||
if (!_mtlHeap) {
|
if (!_mtlHeap) {
|
||||||
lock_guard<mutex> lock(_rezLock);
|
lock_guard<mutex> lock(_rezLock);
|
||||||
for (auto& img : _images) { img->flushToDevice(offset, memSize); }
|
for (auto& img : _imageMemoryBindings) { img->flushToDevice(offset, memSize); }
|
||||||
for (auto& buf : _buffers) { buf->flushToDevice(offset, memSize); }
|
for (auto& buf : _buffers) { buf->flushToDevice(offset, memSize); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ VkResult MVKDeviceMemory::pullFromDevice(VkDeviceSize offset,
|
|||||||
VkDeviceSize memSize = adjustMemorySize(size, offset);
|
VkDeviceSize memSize = adjustMemorySize(size, offset);
|
||||||
if (memSize > 0 && isMemoryHostAccessible() && (evenIfCoherent || !isMemoryHostCoherent()) && !_mtlHeap) {
|
if (memSize > 0 && isMemoryHostAccessible() && (evenIfCoherent || !isMemoryHostCoherent()) && !_mtlHeap) {
|
||||||
lock_guard<mutex> lock(_rezLock);
|
lock_guard<mutex> lock(_rezLock);
|
||||||
for (auto& img : _images) { img->pullFromDevice(offset, memSize); }
|
for (auto& img : _imageMemoryBindings) { img->pullFromDevice(offset, memSize); }
|
||||||
for (auto& buf : _buffers) { buf->pullFromDevice(offset, memSize); }
|
for (auto& buf : _buffers) { buf->pullFromDevice(offset, memSize); }
|
||||||
|
|
||||||
#if MVK_MACOS
|
#if MVK_MACOS
|
||||||
@ -152,23 +152,23 @@ void MVKDeviceMemory::removeBuffer(MVKBuffer* mvkBuff) {
|
|||||||
mvkRemoveAllOccurances(_buffers, mvkBuff);
|
mvkRemoveAllOccurances(_buffers, mvkBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult MVKDeviceMemory::addImage(MVKImage* mvkImg) {
|
VkResult MVKDeviceMemory::addImageMemoryBinding(MVKImageMemoryBinding* mvkImg) {
|
||||||
lock_guard<mutex> lock(_rezLock);
|
lock_guard<mutex> lock(_rezLock);
|
||||||
|
|
||||||
// If a dedicated alloc, ensure this image is the one and only image
|
// If a dedicated alloc, ensure this image is the one and only image
|
||||||
// I am dedicated to.
|
// I am dedicated to.
|
||||||
if (_isDedicated && (_images.empty() || _images[0] != mvkImg) ) {
|
if (_isDedicated && (_imageMemoryBindings.empty() || _imageMemoryBindings[0] != mvkImg) ) {
|
||||||
return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkImage %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkImg, getDedicatedResource() );
|
return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkImage %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkImg, getDedicatedResource() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_isDedicated) { _images.push_back(mvkImg); }
|
if (!_isDedicated) { _imageMemoryBindings.push_back(mvkImg); }
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKDeviceMemory::removeImage(MVKImage* mvkImg) {
|
void MVKDeviceMemory::removeImageMemoryBinding(MVKImageMemoryBinding* mvkImg) {
|
||||||
lock_guard<mutex> lock(_rezLock);
|
lock_guard<mutex> lock(_rezLock);
|
||||||
mvkRemoveAllOccurances(_images, mvkImg);
|
mvkRemoveAllOccurances(_imageMemoryBindings, mvkImg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that this instance is backed by a MTLHeap object,
|
// Ensures that this instance is backed by a MTLHeap object,
|
||||||
@ -266,7 +266,7 @@ void MVKDeviceMemory::freeHostMemory() {
|
|||||||
|
|
||||||
MVKResource* MVKDeviceMemory::getDedicatedResource() {
|
MVKResource* MVKDeviceMemory::getDedicatedResource() {
|
||||||
MVKAssert(_isDedicated, "This method should only be called on dedicated allocations!");
|
MVKAssert(_isDedicated, "This method should only be called on dedicated allocations!");
|
||||||
return _buffers.empty() ? (MVKResource*)_images[0] : (MVKResource*)_buffers[0];
|
return _buffers.empty() ? (MVKResource*)_imageMemoryBindings[0] : (MVKResource*)_buffers[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
||||||
@ -319,7 +319,9 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_images.push_back((MVKImage*)dedicatedImage);
|
for (auto& memoryBinding : ((MVKImage*)dedicatedImage)->_memoryBindings) {
|
||||||
|
_imageMemoryBindings.push_back(memoryBinding.get());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +369,7 @@ MVKDeviceMemory::~MVKDeviceMemory() {
|
|||||||
// to allow the resource to callback to remove itself from the collection.
|
// to allow the resource to callback to remove itself from the collection.
|
||||||
auto buffCopies = _buffers;
|
auto buffCopies = _buffers;
|
||||||
for (auto& buf : buffCopies) { buf->bindDeviceMemory(nullptr, 0); }
|
for (auto& buf : buffCopies) { buf->bindDeviceMemory(nullptr, 0); }
|
||||||
auto imgCopies = _images;
|
auto imgCopies = _imageMemoryBindings;
|
||||||
for (auto& img : imgCopies) { img->bindDeviceMemory(nullptr, 0); }
|
for (auto& img : imgCopies) { img->bindDeviceMemory(nullptr, 0); }
|
||||||
|
|
||||||
[_mtlBuffer release];
|
[_mtlBuffer release];
|
||||||
|
@ -33,19 +33,112 @@ class MVKSwapchain;
|
|||||||
class MVKCommandEncoder;
|
class MVKCommandEncoder;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKImagePlane
|
||||||
|
|
||||||
/** Tracks the state of an image subresource. */
|
/** Tracks the state of an image subresource. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VkImageSubresource subresource;
|
VkImageSubresource subresource;
|
||||||
VkSubresourceLayout layout;
|
VkSubresourceLayout layout;
|
||||||
VkImageLayout layoutState;
|
VkImageLayout layoutState;
|
||||||
} MVKImageSubresource;
|
} MVKImageSubresource;
|
||||||
|
|
||||||
|
class MVKImagePlane {
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** 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:
|
||||||
|
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);
|
||||||
|
void propagateDebugName();
|
||||||
|
MVKImageMemoryBinding* getMemoryBinding() const;
|
||||||
|
|
||||||
|
MVKImagePlane(MVKImage* image, uint8_t planeIndex);
|
||||||
|
|
||||||
|
friend class MVKImageMemoryBinding;
|
||||||
|
friend MVKImage;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/** 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,
|
||||||
|
VkMemoryBarrier* pMemoryBarrier) override;
|
||||||
|
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 -
|
||||||
#pragma mark MVKImage
|
#pragma mark MVKImage
|
||||||
|
|
||||||
/** Represents a Vulkan image. */
|
/** Represents a Vulkan image. */
|
||||||
class MVKImage : public MVKResource {
|
class MVKImage : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -55,6 +148,9 @@ public:
|
|||||||
/** Returns the debug report object type of this object. */
|
/** Returns the debug report object type of this object. */
|
||||||
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; }
|
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.
|
* Returns the Vulkan image type of this image.
|
||||||
* This may be different than the value originally specified for the image
|
* This may be different than the value originally specified for the image
|
||||||
@ -63,7 +159,7 @@ public:
|
|||||||
VkImageType getImageType();
|
VkImageType getImageType();
|
||||||
|
|
||||||
/** Returns the Vulkan image format of this image. */
|
/** Returns the Vulkan image format of this image. */
|
||||||
VkFormat getVkFormat();
|
VkFormat getVkFormat() { return _vkFormat; };
|
||||||
|
|
||||||
/** Returns whether this image has a depth or stencil format. */
|
/** Returns whether this image has a depth or stencil format. */
|
||||||
bool getIsDepthStencil();
|
bool getIsDepthStencil();
|
||||||
@ -81,7 +177,7 @@ public:
|
|||||||
* Returns the 3D extent of this image at the specified mipmap level.
|
* Returns the 3D extent of this image at the specified mipmap level.
|
||||||
* For 2D or cube images, the Z component will be 1.
|
* For 2D or cube images, the Z component will be 1.
|
||||||
*/
|
*/
|
||||||
VkExtent3D getExtent3D(uint32_t mipLevel);
|
VkExtent3D getExtent3D(uint8_t planeIndex, uint32_t mipLevel);
|
||||||
|
|
||||||
/** Returns the number of mipmap levels in this image. */
|
/** Returns the number of mipmap levels in this image. */
|
||||||
inline uint32_t getMipLevelCount() { return _mipLevels; }
|
inline uint32_t getMipLevelCount() { return _mipLevels; }
|
||||||
@ -101,7 +197,7 @@ public:
|
|||||||
* For compressed formats, this is the number of bytes in a row of blocks, which
|
* For compressed formats, this is the number of bytes in a row of blocks, which
|
||||||
* will typically span more than one row of texels.
|
* will typically span more than one row of texels.
|
||||||
*/
|
*/
|
||||||
VkDeviceSize getBytesPerRow(uint32_t mipLevel);
|
VkDeviceSize getBytesPerRow(uint8_t planeIndex, uint32_t mipLevel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of bytes per image layer (for cube, array, or 3D images)
|
* Returns the number of bytes per image layer (for cube, array, or 3D images)
|
||||||
@ -109,7 +205,10 @@ public:
|
|||||||
* of bytes per row (as returned by the getBytesPerRow() function, multiplied by
|
* of bytes per row (as returned by the getBytesPerRow() function, multiplied by
|
||||||
* the height of each 2D image.
|
* the height of each 2D image.
|
||||||
*/
|
*/
|
||||||
VkDeviceSize getBytesPerLayer(uint32_t mipLevel);
|
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. */
|
/** Populates the specified layout for the specified sub-resource. */
|
||||||
VkResult getSubresourceLayout(const VkImageSubresource* pSubresource,
|
VkResult getSubresourceLayout(const VkImageSubresource* pSubresource,
|
||||||
@ -122,24 +221,17 @@ public:
|
|||||||
#pragma mark Resource memory
|
#pragma mark Resource memory
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
/** Returns the memory requirements of this resource by populating the specified structure. */
|
||||||
VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements) override;
|
VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements, uint8_t planeIndex);
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
/** Returns the memory requirements of this resource by populating the specified structure. */
|
||||||
VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements) override;
|
VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements);
|
||||||
|
|
||||||
/** Binds this resource to the specified offset within the specified memory allocation. */
|
/** Binds this resource to the specified offset within the specified memory allocation. */
|
||||||
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
|
virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex);
|
||||||
|
|
||||||
/** Binds this resource to the specified offset within the specified memory allocation. */
|
/** Binds this resource to the specified offset within the specified memory allocation. */
|
||||||
virtual VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo);
|
virtual VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo);
|
||||||
|
|
||||||
/** Applies the specified global memory barrier. */
|
|
||||||
void applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
|
|
||||||
VkPipelineStageFlags dstStageMask,
|
|
||||||
MVKPipelineBarrier& barrier,
|
|
||||||
MVKCommandEncoder* cmdEncoder,
|
|
||||||
MVKCommandUse cmdUse) override;
|
|
||||||
|
|
||||||
/** Applies the specified image memory barrier. */
|
/** Applies the specified image memory barrier. */
|
||||||
void applyImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
|
void applyImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
|
||||||
VkPipelineStageFlags dstStageMask,
|
VkPipelineStageFlags dstStageMask,
|
||||||
@ -150,10 +242,10 @@ public:
|
|||||||
#pragma mark Metal
|
#pragma mark Metal
|
||||||
|
|
||||||
/** Returns the Metal texture underlying this image. */
|
/** Returns the Metal texture underlying this image. */
|
||||||
virtual id<MTLTexture> getMTLTexture();
|
virtual id<MTLTexture> getMTLTexture(uint8_t planeIndex);
|
||||||
|
|
||||||
/** Returns a Metal texture that interprets the pixels in the specified format. */
|
/** Returns a Metal texture that interprets the pixels in the specified format. */
|
||||||
id<MTLTexture> getMTLTexture(MTLPixelFormat mtlPixFmt);
|
id<MTLTexture> getMTLTexture(uint8_t planeIndex, MTLPixelFormat mtlPixFmt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this image to use the specified MTLTexture.
|
* Sets this image to use the specified MTLTexture.
|
||||||
@ -163,7 +255,7 @@ public:
|
|||||||
*
|
*
|
||||||
* If a MTLTexture has already been created for this image, it will be destroyed.
|
* If a MTLTexture has already been created for this image, it will be destroyed.
|
||||||
*/
|
*/
|
||||||
VkResult setMTLTexture(id<MTLTexture> mtlTexture);
|
VkResult setMTLTexture(uint8_t planeIndex, id<MTLTexture> mtlTexture);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that this VkImage should use an IOSurface to underlay the Metal texture.
|
* Indicates that this VkImage should use an IOSurface to underlay the Metal texture.
|
||||||
@ -189,7 +281,7 @@ public:
|
|||||||
IOSurfaceRef getIOSurface();
|
IOSurfaceRef getIOSurface();
|
||||||
|
|
||||||
/** Returns the Metal pixel format of this image. */
|
/** Returns the Metal pixel format of this image. */
|
||||||
inline MTLPixelFormat getMTLPixelFormat() { return _mtlPixelFormat; }
|
inline MTLPixelFormat getMTLPixelFormat(uint8_t planeIndex) { return _planes[planeIndex]->_mtlPixFmt; }
|
||||||
|
|
||||||
/** Returns the Metal texture type of this image. */
|
/** Returns the Metal texture type of this image. */
|
||||||
inline MTLTextureType getMTLTextureType() { return _mtlTextureType; }
|
inline MTLTextureType getMTLTextureType() { return _mtlTextureType; }
|
||||||
@ -225,50 +317,37 @@ public:
|
|||||||
~MVKImage() override;
|
~MVKImage() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MVKDeviceMemory;
|
friend MVKDeviceMemory;
|
||||||
friend class MVKImageView;
|
friend MVKDevice;
|
||||||
using MVKResource::needsHostReadSync;
|
friend MVKImageMemoryBinding;
|
||||||
|
friend MVKImagePlane;
|
||||||
|
friend class MVKImageViewPlane;
|
||||||
|
friend MVKImageView;
|
||||||
|
|
||||||
void propagateDebugName() override;
|
void propagateDebugName() override;
|
||||||
MVKImageSubresource* getSubresource(uint32_t mipLevel, uint32_t arrayLayer);
|
|
||||||
void validateConfig(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
void validateConfig(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||||
VkSampleCountFlagBits validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
VkSampleCountFlagBits validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||||
uint32_t validateMipLevels(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
uint32_t validateMipLevels(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||||
bool validateLinear(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
bool validateLinear(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||||
bool validateUseTexelBuffer();
|
|
||||||
void initSubresources(const VkImageCreateInfo* pCreateInfo);
|
|
||||||
void initSubresourceLayout(MVKImageSubresource& imgSubRez);
|
|
||||||
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||||
id<MTLTexture> newMTLTexture();
|
|
||||||
void releaseMTLTexture();
|
|
||||||
void releaseIOSurface();
|
void releaseIOSurface();
|
||||||
MTLTextureDescriptor* newMTLTextureDescriptor();
|
|
||||||
void updateMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size);
|
|
||||||
void getMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size);
|
|
||||||
bool shouldFlushHostMemory();
|
|
||||||
VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size);
|
|
||||||
VkResult pullFromDevice(VkDeviceSize offset, VkDeviceSize size);
|
|
||||||
bool needsHostReadSync(VkPipelineStageFlags srcStageMask,
|
|
||||||
VkPipelineStageFlags dstStageMask,
|
|
||||||
MVKPipelineBarrier& barrier);
|
|
||||||
|
|
||||||
MVKSmallVector<MVKImageSubresource, 1> _subresources;
|
MVKSmallVector<std::unique_ptr<MVKImageMemoryBinding>, 3> _memoryBindings;
|
||||||
std::unordered_map<NSUInteger, id<MTLTexture>> _mtlTextureViews;
|
MVKSmallVector<std::unique_ptr<MVKImagePlane>, 3> _planes;
|
||||||
VkExtent3D _extent;
|
VkExtent3D _extent;
|
||||||
uint32_t _mipLevels;
|
uint32_t _mipLevels;
|
||||||
uint32_t _arrayLayers;
|
uint32_t _arrayLayers;
|
||||||
VkSampleCountFlagBits _samples;
|
VkSampleCountFlagBits _samples;
|
||||||
VkImageUsageFlags _usage;
|
VkImageUsageFlags _usage;
|
||||||
MTLPixelFormat _mtlPixelFormat;
|
VkFormat _vkFormat;
|
||||||
MTLTextureType _mtlTextureType;
|
MTLTextureType _mtlTextureType;
|
||||||
id<MTLTexture> _mtlTexture;
|
|
||||||
std::mutex _lock;
|
std::mutex _lock;
|
||||||
IOSurfaceRef _ioSurface;
|
IOSurfaceRef _ioSurface;
|
||||||
VkDeviceSize _rowByteAlignment;
|
VkDeviceSize _rowByteAlignment;
|
||||||
bool _isDepthStencilAttachment;
|
bool _isDepthStencilAttachment;
|
||||||
bool _canSupportMTLTextureView;
|
bool _canSupportMTLTextureView;
|
||||||
bool _hasExpectedTexelSize;
|
bool _hasExpectedTexelSize;
|
||||||
bool _usesTexelBuffer;
|
bool _hasChromaSubsampling;
|
||||||
bool _isLinear;
|
bool _isLinear;
|
||||||
bool _is3DCompressed;
|
bool _is3DCompressed;
|
||||||
bool _isAliasable;
|
bool _isAliasable;
|
||||||
@ -284,12 +363,12 @@ class MVKSwapchainImage : public MVKImage {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** Binds this resource to the specified offset within the specified memory allocation. */
|
/** Binds this resource to the specified offset within the specified memory allocation. */
|
||||||
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
|
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex) override;
|
||||||
|
|
||||||
#pragma mark Metal
|
#pragma mark Metal
|
||||||
|
|
||||||
/** Returns the Metal texture used by the CAMetalDrawable underlying this image. */
|
/** Returns the Metal texture used by the CAMetalDrawable underlying this image. */
|
||||||
id<MTLTexture> getMTLTexture() override;
|
id<MTLTexture> getMTLTexture(uint8_t planeIndex) override;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
@ -401,6 +480,34 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKImageViewPlane
|
||||||
|
|
||||||
|
class MVKImageViewPlane {
|
||||||
|
|
||||||
|
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 -
|
||||||
#pragma mark MVKImageView
|
#pragma mark MVKImageView
|
||||||
|
|
||||||
@ -418,17 +525,20 @@ public:
|
|||||||
#pragma mark Metal
|
#pragma mark Metal
|
||||||
|
|
||||||
/** Returns the Metal texture underlying this image view. */
|
/** Returns the Metal texture underlying this image view. */
|
||||||
id<MTLTexture> getMTLTexture();
|
id<MTLTexture> getMTLTexture(uint8_t planeIndex) { return _planes[planeIndex]->getMTLTexture(); }
|
||||||
|
|
||||||
/** Returns the Metal pixel format of this image view. */
|
/** Returns the Metal pixel format of this image view. */
|
||||||
inline MTLPixelFormat getMTLPixelFormat() { return _mtlPixelFormat; }
|
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. */
|
/** Returns the Metal texture type of this image view. */
|
||||||
inline MTLTextureType getMTLTextureType() { return _mtlTextureType; }
|
inline MTLTextureType getMTLTextureType() { return _mtlTextureType; }
|
||||||
|
|
||||||
/** Returns the packed component swizzle of this image view. */
|
|
||||||
inline uint32_t getPackedSwizzle() { return _packedSwizzle; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the texture of the specified render pass descriptor
|
* Populates the texture of the specified render pass descriptor
|
||||||
* with the Metal texture underlying this image.
|
* with the Metal texture underlying this image.
|
||||||
@ -458,7 +568,6 @@ public:
|
|||||||
* This is a static function that can be used to validate image view formats prior to creating one.
|
* This is a static function that can be used to validate image view formats prior to creating one.
|
||||||
*/
|
*/
|
||||||
static VkResult validateSwizzledMTLPixelFormat(const VkImageViewCreateInfo* pCreateInfo,
|
static VkResult validateSwizzledMTLPixelFormat(const VkImageViewCreateInfo* pCreateInfo,
|
||||||
MVKPixelFormats* mvkPixFmts,
|
|
||||||
MVKVulkanAPIObject* apiObject,
|
MVKVulkanAPIObject* apiObject,
|
||||||
bool hasNativeSwizzleSupport,
|
bool hasNativeSwizzleSupport,
|
||||||
bool hasShaderSwizzleSupport,
|
bool hasShaderSwizzleSupport,
|
||||||
@ -472,23 +581,54 @@ public:
|
|||||||
const VkImageViewCreateInfo* pCreateInfo,
|
const VkImageViewCreateInfo* pCreateInfo,
|
||||||
const MVKConfiguration* pAltMVKConfig = nullptr);
|
const MVKConfiguration* pAltMVKConfig = nullptr);
|
||||||
|
|
||||||
~MVKImageView() override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend MVKImageViewPlane;
|
||||||
|
|
||||||
void propagateDebugName() override;
|
void propagateDebugName() override;
|
||||||
id<MTLTexture> newMTLTexture();
|
|
||||||
void initMTLTextureViewSupport();
|
|
||||||
void validateImageViewConfig(const VkImageViewCreateInfo* pCreateInfo);
|
|
||||||
|
|
||||||
MVKImage* _image;
|
MVKImage* _image;
|
||||||
|
MVKSmallVector<std::unique_ptr<MVKImageViewPlane>, 3> _planes;
|
||||||
VkImageSubresourceRange _subresourceRange;
|
VkImageSubresourceRange _subresourceRange;
|
||||||
VkImageUsageFlags _usage;
|
VkImageUsageFlags _usage;
|
||||||
id<MTLTexture> _mtlTexture;
|
|
||||||
std::mutex _lock;
|
std::mutex _lock;
|
||||||
MTLPixelFormat _mtlPixelFormat;
|
|
||||||
MTLTextureType _mtlTextureType;
|
MTLTextureType _mtlTextureType;
|
||||||
uint32_t _packedSwizzle;
|
};
|
||||||
bool _useMTLTextureView;
|
|
||||||
|
|
||||||
|
#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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -508,6 +648,10 @@ public:
|
|||||||
|
|
||||||
/** Returns the Metal sampler state. */
|
/** Returns the Metal sampler state. */
|
||||||
inline id<MTLSamplerState> getMTLSamplerState() { return _mtlSamplerState; }
|
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.
|
* If this sampler requires hardcoding in MSL, populates the hardcoded sampler in the resource binding.
|
||||||
@ -529,5 +673,6 @@ protected:
|
|||||||
|
|
||||||
id<MTLSamplerState> _mtlSamplerState;
|
id<MTLSamplerState> _mtlSamplerState;
|
||||||
SPIRV_CROSS_NAMESPACE::MSLConstexprSampler _constExprSampler;
|
SPIRV_CROSS_NAMESPACE::MSLConstexprSampler _constExprSampler;
|
||||||
|
MVKSamplerYcbcrConversion* _ycbcrConversion;
|
||||||
bool _requiresConstExprSampler;
|
bool _requiresConstExprSampler;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -622,6 +622,8 @@ void MVKInstance::initProcAddrs() {
|
|||||||
ADD_DVC_EXT_ENTRY_POINT(vkGetDescriptorSetLayoutSupportKHR, KHR_MAINTENANCE3);
|
ADD_DVC_EXT_ENTRY_POINT(vkGetDescriptorSetLayoutSupportKHR, KHR_MAINTENANCE3);
|
||||||
ADD_DVC_EXT_ENTRY_POINT(vkCmdPushDescriptorSetKHR, KHR_PUSH_DESCRIPTOR);
|
ADD_DVC_EXT_ENTRY_POINT(vkCmdPushDescriptorSetKHR, KHR_PUSH_DESCRIPTOR);
|
||||||
ADD_DVC_EXT2_ENTRY_POINT(vkCmdPushDescriptorSetWithTemplateKHR, KHR_PUSH_DESCRIPTOR, KHR_DESCRIPTOR_UPDATE_TEMPLATE);
|
ADD_DVC_EXT2_ENTRY_POINT(vkCmdPushDescriptorSetWithTemplateKHR, KHR_PUSH_DESCRIPTOR, KHR_DESCRIPTOR_UPDATE_TEMPLATE);
|
||||||
|
ADD_DVC_EXT_ENTRY_POINT(vkCreateSamplerYcbcrConversionKHR, KHR_SAMPLER_YCBCR_CONVERSION);
|
||||||
|
ADD_DVC_EXT_ENTRY_POINT(vkDestroySamplerYcbcrConversionKHR, KHR_SAMPLER_YCBCR_CONVERSION);
|
||||||
ADD_DVC_EXT_ENTRY_POINT(vkCreateSwapchainKHR, KHR_SWAPCHAIN);
|
ADD_DVC_EXT_ENTRY_POINT(vkCreateSwapchainKHR, KHR_SWAPCHAIN);
|
||||||
ADD_DVC_EXT_ENTRY_POINT(vkDestroySwapchainKHR, KHR_SWAPCHAIN);
|
ADD_DVC_EXT_ENTRY_POINT(vkDestroySwapchainKHR, KHR_SWAPCHAIN);
|
||||||
ADD_DVC_EXT_ENTRY_POINT(vkGetSwapchainImagesKHR, KHR_SWAPCHAIN);
|
ADD_DVC_EXT_ENTRY_POINT(vkGetSwapchainImagesKHR, KHR_SWAPCHAIN);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.h"
|
||||||
#include "MVKEnvironment.h"
|
#include "MVKEnvironment.h"
|
||||||
#include "MVKBaseObject.h"
|
#include "MVKBaseObject.h"
|
||||||
|
#include <SPIRV-Cross/spirv_msl.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
@ -70,6 +71,8 @@ typedef enum : uint16_t {
|
|||||||
kMVKMTLFmtCapsDRMR = (kMVKMTLFmtCapsDRM | kMVKMTLFmtCapsResolve),
|
kMVKMTLFmtCapsDRMR = (kMVKMTLFmtCapsDRM | kMVKMTLFmtCapsResolve),
|
||||||
kMVKMTLFmtCapsDRFMR = (kMVKMTLFmtCapsDRMR | kMVKMTLFmtCapsFilter),
|
kMVKMTLFmtCapsDRFMR = (kMVKMTLFmtCapsDRMR | kMVKMTLFmtCapsFilter),
|
||||||
|
|
||||||
|
kMVKMTLFmtCapsChromaSubsampling = kMVKMTLFmtCapsRF,
|
||||||
|
kMVKMTLFmtCapsMultiPlanar = kMVKMTLFmtCapsChromaSubsampling,
|
||||||
} MVKMTLFmtCaps;
|
} MVKMTLFmtCaps;
|
||||||
|
|
||||||
|
|
||||||
@ -83,16 +86,18 @@ typedef struct {
|
|||||||
MTLPixelFormat mtlPixelFormatSubstitute;
|
MTLPixelFormat mtlPixelFormatSubstitute;
|
||||||
MTLVertexFormat mtlVertexFormat;
|
MTLVertexFormat mtlVertexFormat;
|
||||||
MTLVertexFormat mtlVertexFormatSubstitute;
|
MTLVertexFormat mtlVertexFormatSubstitute;
|
||||||
|
uint8_t chromaSubsamplingPlaneCount;
|
||||||
|
uint8_t chromaSubsamplingComponentBits;
|
||||||
VkExtent2D blockTexelSize;
|
VkExtent2D blockTexelSize;
|
||||||
uint32_t bytesPerBlock;
|
uint32_t bytesPerBlock;
|
||||||
MVKFormatType formatType;
|
MVKFormatType formatType;
|
||||||
VkFormatProperties properties;
|
VkFormatProperties properties;
|
||||||
const char* name;
|
const char* name;
|
||||||
bool hasReportedSubstitution;
|
bool hasReportedSubstitution;
|
||||||
|
|
||||||
|
inline double bytesPerTexel() const { return (double)bytesPerBlock / (double)(blockTexelSize.width * blockTexelSize.height); };
|
||||||
|
|
||||||
inline double bytesPerTexel() const { return (double)bytesPerBlock / (double)(blockTexelSize.width * blockTexelSize.height); };
|
inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid || chromaSubsamplingPlaneCount > 0); };
|
||||||
|
|
||||||
inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid); };
|
|
||||||
inline bool isSupportedOrSubstitutable() const { return isSupported() || (mtlPixelFormatSubstitute != MTLPixelFormatInvalid); };
|
inline bool isSupportedOrSubstitutable() const { return isSupported() || (mtlPixelFormatSubstitute != MTLPixelFormatInvalid); };
|
||||||
|
|
||||||
inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid); };
|
inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid); };
|
||||||
@ -174,16 +179,28 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of the compression block, measured in texels for a Vulkan format.
|
* Returns the size of the compression block, measured in texels for a Vulkan format.
|
||||||
* The returned value will be {1, 1} for non-compressed formats.
|
* The returned value will be {1, 1} for non-compressed formats without chroma-subsampling.
|
||||||
*/
|
*/
|
||||||
VkExtent2D getBlockTexelSize(VkFormat vkFormat);
|
VkExtent2D getBlockTexelSize(VkFormat vkFormat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of the compression block, measured in texels for a Metal format.
|
* Returns the size of the compression block, measured in texels for a Metal format.
|
||||||
* The returned value will be {1, 1} for non-compressed formats.
|
* The returned value will be {1, 1} for non-compressed formats without chroma-subsampling.
|
||||||
*/
|
*/
|
||||||
VkExtent2D getBlockTexelSize(MTLPixelFormat mtlFormat);
|
VkExtent2D getBlockTexelSize(MTLPixelFormat mtlFormat);
|
||||||
|
|
||||||
|
/** Returns the number of planes of the specified chroma-subsampling (YCbCr) VkFormat */
|
||||||
|
uint8_t getChromaSubsamplingPlaneCount(VkFormat vkFormat);
|
||||||
|
|
||||||
|
/** Returns the number of bits per channel of the specified chroma-subsampling (YCbCr) VkFormat */
|
||||||
|
uint8_t getChromaSubsamplingComponentBits(VkFormat vkFormat);
|
||||||
|
|
||||||
|
/** Returns the MSLFormatResolution of the specified chroma-subsampling (YCbCr) VkFormat */
|
||||||
|
SPIRV_CROSS_NAMESPACE::MSLFormatResolution getChromaSubsamplingResolution(VkFormat vkFormat);
|
||||||
|
|
||||||
|
/** Returns the number of planes, blockTexelSize, bytesPerBlock and mtlPixFmt of each plane of the specified chroma-subsampling (YCbCr) VkFormat into the given arrays */
|
||||||
|
uint8_t getChromaSubsamplingPlanes(VkFormat vkFormat, VkExtent2D blockTexelSize[3], uint32_t bytesPerBlock[3], MTLPixelFormat mtlPixFmt[3]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size, in bytes, of a texel of the specified Vulkan format.
|
* Returns the size, in bytes, of a texel of the specified Vulkan format.
|
||||||
* The returned value may be fractional for certain compressed formats.
|
* The returned value may be fractional for certain compressed formats.
|
||||||
|
@ -236,6 +236,61 @@ VkExtent2D MVKPixelFormats::getBlockTexelSize(MTLPixelFormat mtlFormat) {
|
|||||||
return getVkFormatDesc(mtlFormat).blockTexelSize;
|
return getVkFormatDesc(mtlFormat).blockTexelSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t MVKPixelFormats::getChromaSubsamplingPlaneCount(VkFormat vkFormat) {
|
||||||
|
return getVkFormatDesc(vkFormat).chromaSubsamplingPlaneCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MVKPixelFormats::getChromaSubsamplingComponentBits(VkFormat vkFormat) {
|
||||||
|
return getVkFormatDesc(vkFormat).chromaSubsamplingComponentBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRV_CROSS_NAMESPACE::MSLFormatResolution MVKPixelFormats::getChromaSubsamplingResolution(VkFormat vkFormat) {
|
||||||
|
VkExtent2D blockTexelSize = getVkFormatDesc(vkFormat).blockTexelSize;
|
||||||
|
return (blockTexelSize.width != 2) ? SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_444
|
||||||
|
: (blockTexelSize.height != 2) ? SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_422
|
||||||
|
: SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_420;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MVKPixelFormats::getChromaSubsamplingPlanes(VkFormat vkFormat, VkExtent2D blockTexelSize[3], uint32_t bytesPerBlock[3], MTLPixelFormat mtlPixFmt[3]) {
|
||||||
|
uint8_t planes = getChromaSubsamplingPlaneCount(vkFormat);
|
||||||
|
uint8_t bits = getChromaSubsamplingComponentBits(vkFormat);
|
||||||
|
SPIRV_CROSS_NAMESPACE::MSLFormatResolution resolution = getChromaSubsamplingResolution(vkFormat);
|
||||||
|
bytesPerBlock[0] = mvkCeilingDivide((uint32_t)bits/8U, 1U);
|
||||||
|
switch(resolution) {
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
case SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_444:
|
||||||
|
blockTexelSize[0] = blockTexelSize[1] = blockTexelSize[2] = VkExtent2D{1, 1};
|
||||||
|
break;
|
||||||
|
case SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_422:
|
||||||
|
blockTexelSize[0] = blockTexelSize[1] = blockTexelSize[2] = VkExtent2D{2, 1};
|
||||||
|
break;
|
||||||
|
case SPIRV_CROSS_NAMESPACE::MSL_FORMAT_RESOLUTION_420:
|
||||||
|
blockTexelSize[0] = blockTexelSize[1] = blockTexelSize[2] = VkExtent2D{2, 2};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch(planes) {
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
bytesPerBlock[0] *= 4;
|
||||||
|
mtlPixFmt[0] = (bits == 8) ? MTLPixelFormatRGBA8Unorm : MTLPixelFormatRGBA16Unorm;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
blockTexelSize[0] = VkExtent2D{1, 1};
|
||||||
|
bytesPerBlock[1] = bytesPerBlock[0]*2;
|
||||||
|
mtlPixFmt[0] = (bits == 8) ? MTLPixelFormatR8Unorm : MTLPixelFormatR16Unorm;
|
||||||
|
mtlPixFmt[1] = (bits == 8) ? MTLPixelFormatRG8Unorm : MTLPixelFormatRG16Unorm;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
blockTexelSize[0] = VkExtent2D{1, 1};
|
||||||
|
bytesPerBlock[1] = bytesPerBlock[2] = bytesPerBlock[0];
|
||||||
|
mtlPixFmt[0] = mtlPixFmt[1] = mtlPixFmt[2] = (bits == 8) ? MTLPixelFormatR8Unorm : MTLPixelFormatR16Unorm;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return planes;
|
||||||
|
}
|
||||||
|
|
||||||
float MVKPixelFormats::getBytesPerTexel(VkFormat vkFormat) {
|
float MVKPixelFormats::getBytesPerTexel(VkFormat vkFormat) {
|
||||||
return getVkFormatDesc(vkFormat).bytesPerTexel();
|
return getVkFormatDesc(vkFormat).bytesPerTexel();
|
||||||
}
|
}
|
||||||
@ -492,10 +547,16 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalD
|
|||||||
// test();
|
// test();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define addVkFormatDesc(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) \
|
#define addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) \
|
||||||
MVKAssert(fmtIdx < _vkFormatCount, "Attempting to describe %d VkFormats, but only have space for %d. Increase the value of _vkFormatCount", fmtIdx + 1, _vkFormatCount); \
|
MVKAssert(fmtIdx < _vkFormatCount, "Attempting to describe %d VkFormats, but only have space for %d. Increase the value of _vkFormatCount", fmtIdx + 1, _vkFormatCount); \
|
||||||
_vkFormatDescriptions[fmtIdx++] = { VK_FORMAT_ ##VK_FMT, MTLPixelFormat ##MTL_FMT, MTLPixelFormat ##MTL_FMT_ALT, MTLVertexFormat ##MTL_VTX_FMT, MTLVertexFormat ##MTL_VTX_FMT_ALT, \
|
_vkFormatDescriptions[fmtIdx++] = { VK_FORMAT_ ##VK_FMT, MTLPixelFormat ##MTL_FMT, MTLPixelFormat ##MTL_FMT_ALT, MTLVertexFormat ##MTL_VTX_FMT, MTLVertexFormat ##MTL_VTX_FMT_ALT, \
|
||||||
{ BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, "VK_FORMAT_" #VK_FMT, false }
|
CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, "VK_FORMAT_" #VK_FMT, false }
|
||||||
|
|
||||||
|
#define addVkFormatDesc(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) \
|
||||||
|
addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, 0, 0, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE)
|
||||||
|
|
||||||
|
#define addVkFormatDescChromaSubsampling(VK_FMT, MTL_FMT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT) \
|
||||||
|
addVkFormatDescFull(VK_FMT, MTL_FMT, Invalid, Invalid, Invalid, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, ColorFloat)
|
||||||
|
|
||||||
void MVKPixelFormats::initVkFormatCapabilities() {
|
void MVKPixelFormats::initVkFormatCapabilities() {
|
||||||
|
|
||||||
@ -742,9 +803,41 @@ void MVKPixelFormats::initVkFormatCapabilities() {
|
|||||||
addVkFormatDesc( PVRTC2_2BPP_SRGB_BLOCK_IMG, Invalid, Invalid, Invalid, Invalid, 8, 4, 8, Compressed );
|
addVkFormatDesc( PVRTC2_2BPP_SRGB_BLOCK_IMG, Invalid, Invalid, Invalid, Invalid, 8, 4, 8, Compressed );
|
||||||
addVkFormatDesc( PVRTC2_4BPP_SRGB_BLOCK_IMG, Invalid, Invalid, Invalid, Invalid, 4, 4, 8, Compressed );
|
addVkFormatDesc( PVRTC2_4BPP_SRGB_BLOCK_IMG, Invalid, Invalid, Invalid, Invalid, 4, 4, 8, Compressed );
|
||||||
|
|
||||||
// Future extension VK_KHX_color_conversion and Vulkan 1.1.
|
// Extension VK_KHR_sampler_ycbcr_conversion
|
||||||
addVkFormatDesc( UNDEFINED, GBGR422, Invalid, Invalid, Invalid, 2, 1, 4, ColorFloat );
|
addVkFormatDescChromaSubsampling( G8B8G8R8_422_UNORM, GBGR422, 1, 8, 2, 1, 4 );
|
||||||
addVkFormatDesc( UNDEFINED, BGRG422, Invalid, Invalid, Invalid, 2, 1, 4, ColorFloat );
|
addVkFormatDescChromaSubsampling( B8G8R8G8_422_UNORM, BGRG422, 1, 8, 2, 1, 4 );
|
||||||
|
addVkFormatDescChromaSubsampling( G8_B8_R8_3PLANE_420_UNORM, Invalid, 3, 8, 2, 2, 6 );
|
||||||
|
addVkFormatDescChromaSubsampling( G8_B8R8_2PLANE_420_UNORM, Invalid, 2, 8, 2, 2, 6 );
|
||||||
|
addVkFormatDescChromaSubsampling( G8_B8_R8_3PLANE_422_UNORM, Invalid, 3, 8, 2, 1, 4 );
|
||||||
|
addVkFormatDescChromaSubsampling( G8_B8R8_2PLANE_422_UNORM, Invalid, 2, 8, 2, 1, 4 );
|
||||||
|
addVkFormatDescChromaSubsampling( G8_B8_R8_3PLANE_444_UNORM, Invalid, 3, 8, 1, 1, 3 );
|
||||||
|
addVkFormatDescChromaSubsampling( R10X6_UNORM_PACK16, Invalid, 0, 10, 1, 1, 2 );
|
||||||
|
addVkFormatDescChromaSubsampling( R10X6G10X6_UNORM_2PACK16, Invalid, 0, 10, 1, 1, 4 );
|
||||||
|
addVkFormatDescChromaSubsampling( R10X6G10X6B10X6A10X6_UNORM_4PACK16, Invalid, 0, 10, 1, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, Invalid, 1, 10, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, Invalid, 1, 10, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, Invalid, 3, 10, 2, 2, 12 );
|
||||||
|
addVkFormatDescChromaSubsampling( G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, Invalid, 2, 10, 2, 2, 12 );
|
||||||
|
addVkFormatDescChromaSubsampling( G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, Invalid, 3, 10, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, Invalid, 2, 10, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, Invalid, 3, 10, 1, 1, 6 );
|
||||||
|
addVkFormatDescChromaSubsampling( R12X4_UNORM_PACK16, Invalid, 0, 12, 1, 1, 2 );
|
||||||
|
addVkFormatDescChromaSubsampling( R12X4G12X4_UNORM_2PACK16, Invalid, 0, 12, 1, 1, 4 );
|
||||||
|
addVkFormatDescChromaSubsampling( R12X4G12X4B12X4A12X4_UNORM_4PACK16, Invalid, 0, 12, 1, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, Invalid, 1, 12, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, Invalid, 1, 12, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, Invalid, 3, 12, 2, 2, 12 );
|
||||||
|
addVkFormatDescChromaSubsampling( G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, Invalid, 2, 12, 2, 2, 12 );
|
||||||
|
addVkFormatDescChromaSubsampling( G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, Invalid, 3, 12, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, Invalid, 2, 12, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, Invalid, 3, 12, 1, 1, 6 );
|
||||||
|
addVkFormatDescChromaSubsampling( G16B16G16R16_422_UNORM, Invalid, 1, 16, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( B16G16R16G16_422_UNORM, Invalid, 1, 16, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G16_B16_R16_3PLANE_420_UNORM, Invalid, 3, 16, 2, 2, 12 );
|
||||||
|
addVkFormatDescChromaSubsampling( G16_B16R16_2PLANE_420_UNORM, Invalid, 2, 16, 2, 2, 12 );
|
||||||
|
addVkFormatDescChromaSubsampling( G16_B16_R16_3PLANE_422_UNORM, Invalid, 3, 16, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G16_B16R16_2PLANE_422_UNORM, Invalid, 2, 16, 2, 1, 8 );
|
||||||
|
addVkFormatDescChromaSubsampling( G16_B16_R16_3PLANE_444_UNORM, Invalid, 3, 16, 1, 1, 6 );
|
||||||
|
|
||||||
// When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count
|
// When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count
|
||||||
}
|
}
|
||||||
@ -1139,44 +1232,44 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id<MTLDevice> mtlDevice) {
|
|||||||
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, RGBA32Sint, RWC );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, RGBA32Sint, RWC );
|
||||||
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, RGBA32Float, RWC );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, RGBA32Float, RWC );
|
||||||
|
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_4x4_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_4x4_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_4x4_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_4x4_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x4_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x4_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x4_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x4_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x5_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x5_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x5_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x5_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x5_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x5_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x5_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x5_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x6_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x6_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x6_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x6_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x5_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x5_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x5_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x5_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x6_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x6_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x6_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x6_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x8_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x8_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x8_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x8_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x5_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x5_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x5_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x5_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x6_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x6_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x6_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x6_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x8_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x8_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x8_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x8_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x10_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x10_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x10_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x10_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x10_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x10_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x10_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x10_sRGB, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x12_LDR, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x12_LDR, RF );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x12_sRGB, RF );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x12_sRGB, RF );
|
||||||
|
|
||||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v1, Depth32Float, DRMR );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v1, Depth32Float, DRMR );
|
||||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v1, Depth32Float_Stencil8, DRMR );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v1, Depth32Float_Stencil8, DRMR );
|
||||||
|
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGRA10_XR, All );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGRA10_XR, All );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGRA10_XR_sRGB, All );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGRA10_XR_sRGB, All );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGR10_XR, All );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGR10_XR, All );
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGR10_XR_sRGB, All );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGR10_XR_sRGB, All );
|
||||||
|
|
||||||
addMTLPixelFormatCapabilities(iOS_GPUFamily1_v4, BGR10A2Unorm, All );
|
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v4, BGR10A2Unorm, All );
|
||||||
|
|
||||||
addMTLVertexFormatCapabilities( iOS_GPUFamily1_v4, UCharNormalized, Vertex );
|
addMTLVertexFormatCapabilities( iOS_GPUFamily1_v4, UCharNormalized, Vertex );
|
||||||
addMTLVertexFormatCapabilities( iOS_GPUFamily1_v4, CharNormalized, Vertex );
|
addMTLVertexFormatCapabilities( iOS_GPUFamily1_v4, CharNormalized, Vertex );
|
||||||
@ -1256,6 +1349,17 @@ typedef enum : VkFormatFeatureFlags {
|
|||||||
VK_FORMAT_FEATURE_BLIT_DST_BIT),
|
VK_FORMAT_FEATURE_BLIT_DST_BIT),
|
||||||
kMVKVkFormatFeatureFlagsTexDSAtt = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT),
|
kMVKVkFormatFeatureFlagsTexDSAtt = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT),
|
||||||
kMVKVkFormatFeatureFlagsTexBlend = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
|
kMVKVkFormatFeatureFlagsTexBlend = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
|
||||||
|
kMVKVkFormatFeatureFlagsTexTransfer = (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
|
||||||
|
VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
|
||||||
|
VK_FORMAT_FEATURE_BLIT_SRC_BIT |
|
||||||
|
VK_FORMAT_FEATURE_BLIT_DST_BIT),
|
||||||
|
kMVKVkFormatFeatureFlagsTexChromaSubsampling = (VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR |
|
||||||
|
VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR |
|
||||||
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR |
|
||||||
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR |
|
||||||
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR |
|
||||||
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR),
|
||||||
|
kMVKVkFormatFeatureFlagsTexMultiPlanar = (VK_FORMAT_FEATURE_DISJOINT_BIT_KHR),
|
||||||
kMVKVkFormatFeatureFlagsBufRead = (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT),
|
kMVKVkFormatFeatureFlagsBufRead = (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT),
|
||||||
kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT),
|
kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT),
|
||||||
kMVKVkFormatFeatureFlagsBufAtomic = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
|
kMVKVkFormatFeatureFlagsBufAtomic = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
|
||||||
@ -1272,9 +1376,23 @@ void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc) {
|
|||||||
|
|
||||||
VkFormatProperties& vkProps = vkDesc.properties;
|
VkFormatProperties& vkProps = vkDesc.properties;
|
||||||
MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkDesc.mtlPixelFormat).mtlFmtCaps;
|
MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkDesc.mtlPixelFormat).mtlFmtCaps;
|
||||||
|
vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
||||||
|
vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
||||||
|
|
||||||
// Set optimal tiling features first
|
// Chroma subsampling and multi planar features
|
||||||
vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
if (getChromaSubsamplingComponentBits(vkDesc.vkFormat) > 0) {
|
||||||
|
vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexTransfer;
|
||||||
|
}
|
||||||
|
uint8_t chromaSubsamplingPlaneCount = getChromaSubsamplingPlaneCount(vkDesc.vkFormat);
|
||||||
|
if (chromaSubsamplingPlaneCount > 0) {
|
||||||
|
mtlPixFmtCaps = kMVKMTLFmtCapsRF;
|
||||||
|
enableFormatFeatures(ChromaSubsampling, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
||||||
|
}
|
||||||
|
if (chromaSubsamplingPlaneCount > 1) {
|
||||||
|
enableFormatFeatures(MultiPlanar, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimal tiling features
|
||||||
enableFormatFeatures(Read, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
enableFormatFeatures(Read, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
||||||
enableFormatFeatures(Filter, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
enableFormatFeatures(Filter, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
||||||
enableFormatFeatures(Write, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
enableFormatFeatures(Write, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
||||||
@ -1283,9 +1401,7 @@ void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc) {
|
|||||||
enableFormatFeatures(Blend, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
enableFormatFeatures(Blend, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
|
||||||
|
|
||||||
// Linear tiling is not available to depth/stencil or compressed formats.
|
// Linear tiling is not available to depth/stencil or compressed formats.
|
||||||
vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
|
||||||
if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) {
|
if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) {
|
||||||
|
|
||||||
// Start with optimal tiling features, and modify.
|
// Start with optimal tiling features, and modify.
|
||||||
vkProps.linearTilingFeatures = vkProps.optimalTilingFeatures;
|
vkProps.linearTilingFeatures = vkProps.optimalTilingFeatures;
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
|
|||||||
if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) {
|
if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) {
|
||||||
MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx];
|
MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx];
|
||||||
MVKImageView* dsImage = framebuffer->getAttachment(dsRPAttIdx);
|
MVKImageView* dsImage = framebuffer->getAttachment(dsRPAttIdx);
|
||||||
MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat();
|
MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat(0);
|
||||||
|
|
||||||
if (pixFmts->isDepthFormat(mtlDSFormat)) {
|
if (pixFmts->isDepthFormat(mtlDSFormat)) {
|
||||||
MTLRenderPassDepthAttachmentDescriptor* mtlDepthAttDesc = mtlRPDesc.depthAttachment;
|
MTLRenderPassDepthAttachmentDescriptor* mtlDepthAttDesc = mtlRPDesc.depthAttachment;
|
||||||
|
@ -39,14 +39,8 @@ public:
|
|||||||
/** Returns the byte offset in the bound device memory. */
|
/** Returns the byte offset in the bound device memory. */
|
||||||
inline VkDeviceSize getDeviceMemoryOffset() { return _deviceMemoryOffset; }
|
inline VkDeviceSize getDeviceMemoryOffset() { return _deviceMemoryOffset; }
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
|
||||||
virtual VkResult getMemoryRequirements(VkMemoryRequirements* pMemoryRequirements) = 0;
|
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
|
||||||
virtual VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements) = 0;
|
|
||||||
|
|
||||||
/** Binds this resource to the specified offset within the specified memory allocation. */
|
/** Binds this resource to the specified offset within the specified memory allocation. */
|
||||||
virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
|
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
|
||||||
|
|
||||||
/** Returns the device memory underlying this resource. */
|
/** Returns the device memory underlying this resource. */
|
||||||
inline MVKDeviceMemory* getDeviceMemory() { return _deviceMemory; }
|
inline MVKDeviceMemory* getDeviceMemory() { return _deviceMemory; }
|
||||||
|
@ -58,6 +58,7 @@ MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE)
|
|||||||
MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE)
|
MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE)
|
||||||
MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE)
|
MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE)
|
||||||
MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE)
|
MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE)
|
||||||
|
MVK_EXTENSION(KHR_sampler_ycbcr_conversion, KHR_SAMPLER_YCBCR_CONVERSION, DEVICE)
|
||||||
MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE)
|
MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE)
|
||||||
MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE)
|
MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE)
|
||||||
MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE)
|
MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE)
|
||||||
|
@ -115,7 +115,7 @@ MVK_PUBLIC_SYMBOL VkResult vkSetMTLTextureMVK(
|
|||||||
id<MTLTexture> mtlTexture) {
|
id<MTLTexture> mtlTexture) {
|
||||||
|
|
||||||
MVKImage* mvkImg = (MVKImage*)image;
|
MVKImage* mvkImg = (MVKImage*)image;
|
||||||
return mvkImg->setMTLTexture(mtlTexture);
|
return mvkImg->setMTLTexture(0, mtlTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
MVK_PUBLIC_SYMBOL void vkGetMTLTextureMVK(
|
MVK_PUBLIC_SYMBOL void vkGetMTLTextureMVK(
|
||||||
@ -123,7 +123,7 @@ MVK_PUBLIC_SYMBOL void vkGetMTLTextureMVK(
|
|||||||
id<MTLTexture>* pMTLTexture) {
|
id<MTLTexture>* pMTLTexture) {
|
||||||
|
|
||||||
MVKImage* mvkImg = (MVKImage*)image;
|
MVKImage* mvkImg = (MVKImage*)image;
|
||||||
*pMTLTexture = mvkImg->getMTLTexture();
|
*pMTLTexture = mvkImg->getMTLTexture(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MVK_PUBLIC_SYMBOL void vkGetMTLBufferMVK(
|
MVK_PUBLIC_SYMBOL void vkGetMTLBufferMVK(
|
||||||
|
@ -526,7 +526,7 @@ MVK_PUBLIC_SYMBOL VkResult vkBindImageMemory(
|
|||||||
MVKTraceVulkanCallStart();
|
MVKTraceVulkanCallStart();
|
||||||
MVKImage* mvkImg = (MVKImage*)image;
|
MVKImage* mvkImg = (MVKImage*)image;
|
||||||
MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)mem;
|
MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)mem;
|
||||||
VkResult rslt = mvkImg->bindDeviceMemory(mvkMem, memOffset);
|
VkResult rslt = mvkImg->bindDeviceMemory(mvkMem, memOffset, 0);
|
||||||
MVKTraceVulkanCallEnd();
|
MVKTraceVulkanCallEnd();
|
||||||
return rslt;
|
return rslt;
|
||||||
}
|
}
|
||||||
@ -549,7 +549,7 @@ MVK_PUBLIC_SYMBOL void vkGetImageMemoryRequirements(
|
|||||||
|
|
||||||
MVKTraceVulkanCallStart();
|
MVKTraceVulkanCallStart();
|
||||||
MVKImage* mvkImg = (MVKImage*)image;
|
MVKImage* mvkImg = (MVKImage*)image;
|
||||||
mvkImg->getMemoryRequirements(pMemoryRequirements);
|
mvkImg->getMemoryRequirements(pMemoryRequirements, 0);
|
||||||
MVKTraceVulkanCallEnd();
|
MVKTraceVulkanCallEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2218,6 +2218,37 @@ MVK_PUBLIC_SYMBOL void vkCmdPushDescriptorSetWithTemplateKHR(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark VK_KHR_sampler_ycbcr_conversion extension
|
||||||
|
|
||||||
|
MVK_PUBLIC_SYMBOL VkResult vkCreateSamplerYcbcrConversionKHR(
|
||||||
|
VkDevice device,
|
||||||
|
const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
|
||||||
|
const VkAllocationCallbacks* pAllocator,
|
||||||
|
VkSamplerYcbcrConversion* pYcbcrConversion) {
|
||||||
|
|
||||||
|
MVKTraceVulkanCallStart();
|
||||||
|
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
|
||||||
|
MVKSamplerYcbcrConversion* mvkSampConv = mvkDev->createSamplerYcbcrConversion(pCreateInfo, pAllocator);
|
||||||
|
*pYcbcrConversion = (VkSamplerYcbcrConversion)mvkSampConv;
|
||||||
|
VkResult rslt = mvkSampConv->getConfigurationResult();
|
||||||
|
MVKTraceVulkanCallEnd();
|
||||||
|
return rslt;
|
||||||
|
}
|
||||||
|
|
||||||
|
MVK_PUBLIC_SYMBOL void vkDestroySamplerYcbcrConversionKHR(
|
||||||
|
VkDevice device,
|
||||||
|
VkSamplerYcbcrConversion ycbcrConversion,
|
||||||
|
const VkAllocationCallbacks* pAllocator) {
|
||||||
|
|
||||||
|
MVKTraceVulkanCallStart();
|
||||||
|
if ( !ycbcrConversion ) { return; }
|
||||||
|
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
|
||||||
|
mvkDev->destroySamplerYcbcrConversion((MVKSamplerYcbcrConversion*)ycbcrConversion, pAllocator);
|
||||||
|
MVKTraceVulkanCallEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark VK_KHR_swapchain extension
|
#pragma mark VK_KHR_swapchain extension
|
||||||
|
|
||||||
|
@ -133,9 +133,22 @@ MVK_PUBLIC_SYMBOL bool mvk::MSLResourceBinding::matches(const MSLResourceBinding
|
|||||||
if (constExprSampler.lod_clamp_min != other.constExprSampler.lod_clamp_min) { return false; }
|
if (constExprSampler.lod_clamp_min != other.constExprSampler.lod_clamp_min) { return false; }
|
||||||
if (constExprSampler.lod_clamp_max != other.constExprSampler.lod_clamp_max) { return false; }
|
if (constExprSampler.lod_clamp_max != other.constExprSampler.lod_clamp_max) { return false; }
|
||||||
if (constExprSampler.max_anisotropy != other.constExprSampler.max_anisotropy) { return false; }
|
if (constExprSampler.max_anisotropy != other.constExprSampler.max_anisotropy) { return false; }
|
||||||
|
|
||||||
|
if (constExprSampler.planes != other.constExprSampler.planes) { return false; }
|
||||||
|
if (constExprSampler.resolution != other.constExprSampler.resolution) { return false; }
|
||||||
|
if (constExprSampler.chroma_filter != other.constExprSampler.chroma_filter) { return false; }
|
||||||
|
if (constExprSampler.x_chroma_offset != other.constExprSampler.x_chroma_offset) { return false; }
|
||||||
|
if (constExprSampler.y_chroma_offset != other.constExprSampler.y_chroma_offset) { return false; }
|
||||||
|
for(uint32_t i = 0; i < 4; ++i)
|
||||||
|
if (constExprSampler.swizzle[i] != other.constExprSampler.swizzle[i]) { return false; }
|
||||||
|
if (constExprSampler.ycbcr_model != other.constExprSampler.ycbcr_model) { return false; }
|
||||||
|
if (constExprSampler.ycbcr_range != other.constExprSampler.ycbcr_range) { return false; }
|
||||||
|
if (constExprSampler.bpc != other.constExprSampler.bpc) { return false; }
|
||||||
|
|
||||||
if (constExprSampler.compare_enable != other.constExprSampler.compare_enable) { return false; }
|
if (constExprSampler.compare_enable != other.constExprSampler.compare_enable) { return false; }
|
||||||
if (constExprSampler.lod_clamp_enable != other.constExprSampler.lod_clamp_enable) { return false; }
|
if (constExprSampler.lod_clamp_enable != other.constExprSampler.lod_clamp_enable) { return false; }
|
||||||
if (constExprSampler.anisotropy_enable != other.constExprSampler.anisotropy_enable) { return false; }
|
if (constExprSampler.anisotropy_enable != other.constExprSampler.anisotropy_enable) { return false; }
|
||||||
|
if (constExprSampler.ycbcr_conversion_enable != other.constExprSampler.ycbcr_conversion_enable) { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user