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_relaxed_block_layout`
|
||||
- `VK_KHR_sampler_mirror_clamp_to_edge` *(macOS)*
|
||||
- `VK_KHR_sampler_ycbcr_conversion`
|
||||
- `VK_KHR_shader_draw_parameters`
|
||||
- `VK_KHR_shader_float16_int8`
|
||||
- `VK_KHR_storage_buffer_storage_class`
|
||||
|
@ -90,7 +90,9 @@ void MVKCmdPipelineBarrier<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
|
@ -103,7 +103,7 @@ public:
|
||||
|
||||
protected:
|
||||
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
|
||||
bool canCopyFormats();
|
||||
bool canCopyFormats(const VkImageBlit& region);
|
||||
bool canCopy(const VkImageBlit& region);
|
||||
void populateVertices(MVKVertexPosTex* vertices, const VkImageBlit& region);
|
||||
|
||||
@ -125,8 +125,9 @@ typedef MVKCmdBlitImage<4> MVKCmdBlitImageMulti;
|
||||
|
||||
/** Describes Metal texture resolve parameters. */
|
||||
typedef struct {
|
||||
uint32_t level;
|
||||
uint32_t slice;
|
||||
VkImageCopy* copyRegion;
|
||||
uint32_t level;
|
||||
uint32_t slice;
|
||||
} MVKMetalResolveSlice;
|
||||
|
||||
/**
|
||||
|
@ -62,129 +62,138 @@ VkResult MVKCmdCopyImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
||||
_dstLayout = dstImageLayout;
|
||||
|
||||
_vkImageCopies.clear(); // Clear for reuse
|
||||
for (uint32_t i = 0; i < regionCount; i++) {
|
||||
_vkImageCopies.push_back(pRegions[i]);
|
||||
}
|
||||
|
||||
// Validate
|
||||
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
||||
if ((_dstImage->getSampleCount() != _srcImage->getSampleCount()) ||
|
||||
(pixFmts->getBytesPerBlock(_dstImage->getMTLPixelFormat()) != pixFmts->getBytesPerBlock(_srcImage->getMTLPixelFormat()))) {
|
||||
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.");
|
||||
for (uint32_t regionIdx = 0; regionIdx < regionCount; regionIdx++) {
|
||||
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();
|
||||
if ((_dstImage->getSampleCount() != _srcImage->getSampleCount()) ||
|
||||
(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.");
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
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();
|
||||
bool isSrcCompressed = _srcImage->getIsCompressed();
|
||||
for (uint32_t copyIdx = 0; copyIdx < copyCnt; copyIdx++) {
|
||||
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();
|
||||
bool isDstCompressed = _dstImage->getIsCompressed();
|
||||
MTLPixelFormat dstMTLPixFmt = _dstImage->getMTLPixelFormat(dstPlaneIndex);
|
||||
bool isDstCompressed = _dstImage->getIsCompressed();
|
||||
|
||||
// If source and destination have different formats and at least one is compressed, use a temporary intermediary buffer
|
||||
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];
|
||||
// If source and destination have different formats and at least one is compressed, use a temporary intermediary buffer
|
||||
bool useTempBuffer = (srcMTLPixFmt != dstMTLPixFmt) && (isSrcCompressed || isDstCompressed);
|
||||
|
||||
// Add copy from source image to temp buffer.
|
||||
auto& srcCpy = vkSrcCopies[copyIdx];
|
||||
srcCpy.bufferOffset = tmpBuffSize;
|
||||
srcCpy.bufferRowLength = 0;
|
||||
srcCpy.bufferImageHeight = 0;
|
||||
srcCpy.imageSubresource = vkIC.srcSubresource;
|
||||
srcCpy.imageOffset = vkIC.srcOffset;
|
||||
srcCpy.imageExtent = vkIC.extent;
|
||||
if (useTempBuffer) {
|
||||
// Add copy from source image to temp buffer.
|
||||
auto& srcCpy = vkSrcCopies[copyIdx];
|
||||
srcCpy.bufferOffset = tmpBuffSize;
|
||||
srcCpy.bufferRowLength = 0;
|
||||
srcCpy.bufferImageHeight = 0;
|
||||
srcCpy.imageSubresource = vkIC.srcSubresource;
|
||||
srcCpy.imageOffset = vkIC.srcOffset;
|
||||
srcCpy.imageExtent = vkIC.extent;
|
||||
|
||||
// Add copy from temp buffer to destination image.
|
||||
// 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,
|
||||
// so we must downscale the destination extent by the size of the source block.
|
||||
VkExtent3D dstExtent = vkIC.extent;
|
||||
if (isSrcCompressed && !isDstCompressed) {
|
||||
VkExtent2D srcBlockExtent = pixFmts->getBlockTexelSize(srcMTLPixFmt);
|
||||
dstExtent.width /= srcBlockExtent.width;
|
||||
dstExtent.height /= srcBlockExtent.height;
|
||||
}
|
||||
auto& dstCpy = vkDstCopies[copyIdx];
|
||||
dstCpy.bufferOffset = tmpBuffSize;
|
||||
dstCpy.bufferRowLength = 0;
|
||||
dstCpy.bufferImageHeight = 0;
|
||||
dstCpy.imageSubresource = vkIC.dstSubresource;
|
||||
dstCpy.imageOffset = vkIC.dstOffset;
|
||||
dstCpy.imageExtent = dstExtent;
|
||||
// Add copy from temp buffer to destination image.
|
||||
// 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,
|
||||
// so we must downscale the destination extent by the size of the source block.
|
||||
VkExtent3D dstExtent = vkIC.extent;
|
||||
if (isSrcCompressed && !isDstCompressed) {
|
||||
VkExtent2D srcBlockExtent = pixFmts->getBlockTexelSize(srcMTLPixFmt);
|
||||
dstExtent.width /= srcBlockExtent.width;
|
||||
dstExtent.height /= srcBlockExtent.height;
|
||||
}
|
||||
auto& dstCpy = vkDstCopies[copyIdx];
|
||||
dstCpy.bufferOffset = tmpBuffSize;
|
||||
dstCpy.bufferRowLength = 0;
|
||||
dstCpy.bufferImageHeight = 0;
|
||||
dstCpy.imageSubresource = vkIC.dstSubresource;
|
||||
dstCpy.imageOffset = vkIC.dstOffset;
|
||||
dstCpy.imageExtent = dstExtent;
|
||||
|
||||
size_t bytesPerRow = pixFmts->getBytesPerRow(srcMTLPixFmt, vkIC.extent.width);
|
||||
size_t bytesPerRegion = pixFmts->getBytesPerLayer(srcMTLPixFmt, bytesPerRow, vkIC.extent.height);
|
||||
tmpBuffSize += bytesPerRegion;
|
||||
}
|
||||
size_t bytesPerRow = pixFmts->getBytesPerRow(srcMTLPixFmt, vkIC.extent.width);
|
||||
size_t bytesPerRegion = pixFmts->getBytesPerLayer(srcMTLPixFmt, bytesPerRow, vkIC.extent.height);
|
||||
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;
|
||||
tempBuffData.size = tmpBuffSize;
|
||||
tempBuffData.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
VkBuffer tempBuff = (VkBuffer)cmdEncoder->getCommandEncodingPool()->getTransferMVKBuffer(tempBuffData);
|
||||
id<MTLBlitCommandEncoder> mtlBlitEnc = cmdEncoder->getMTLBlitEncoder(commandUse);
|
||||
|
||||
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
|
||||
// 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);
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy from buffer to destination image
|
||||
// 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)_dstImage, _dstLayout, copyCnt, vkDstCopies, true);
|
||||
cpyCmd.encode(cmdEncoder);
|
||||
if (tmpBuffSize > 0) {
|
||||
MVKBufferDescriptorData tempBuffData;
|
||||
tempBuffData.size = tmpBuffSize;
|
||||
tempBuffData.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
VkBuffer tempBuff = (VkBuffer)cmdEncoder->getCommandEncodingPool()->getTransferMVKBuffer(tempBuffData);
|
||||
|
||||
} 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(_dstImage->getMTLPixelFormat());
|
||||
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture();
|
||||
if ( !srcMTLTex || !dstMTLTex ) { return; }
|
||||
MVKCmdBufferImageCopy<N> cpyCmd;
|
||||
|
||||
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
|
||||
for (auto& cpyRgn : _vkImageCopies) {
|
||||
uint32_t srcLevel = cpyRgn.srcSubresource.mipLevel;
|
||||
MTLOrigin srcOrigin = mvkMTLOriginFromVkOffset3D(cpyRgn.srcOffset);
|
||||
MTLSize srcSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(cpyRgn.extent),
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copy from buffer to destination image
|
||||
// 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)_dstImage, _dstLayout, copyCnt, vkDstCopies, true);
|
||||
cpyCmd.encode(cmdEncoder);
|
||||
}
|
||||
}
|
||||
|
||||
template class MVKCmdCopyImage<1>;
|
||||
@ -208,33 +217,37 @@ VkResult MVKCmdBlitImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
||||
|
||||
_srcImage = (MVKImage*)srcImage;
|
||||
_srcLayout = srcImageLayout;
|
||||
|
||||
_dstImage = (MVKImage*)dstImage;
|
||||
_dstLayout = dstImageLayout;
|
||||
|
||||
_filter = filter;
|
||||
|
||||
_vkImageBlits.clear(); // Clear for reuse
|
||||
for (uint32_t i = 0; i < regionCount; i++) {
|
||||
_vkImageBlits.push_back(pRegions[i]);
|
||||
for (uint32_t regionIdx = 0; regionIdx < regionCount; regionIdx++) {
|
||||
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;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool MVKCmdBlitImage<N>::canCopyFormats() {
|
||||
return ((_srcImage->getMTLPixelFormat() == _dstImage->getMTLPixelFormat()) &&
|
||||
bool MVKCmdBlitImage<N>::canCopyFormats(const VkImageBlit& region) {
|
||||
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()));
|
||||
}
|
||||
|
||||
@ -255,8 +268,10 @@ void MVKCmdBlitImage<N>::populateVertices(MVKVertexPosTex* vertices, const VkIma
|
||||
const VkOffset3D& do1 = region.dstOffsets[1];
|
||||
|
||||
// Get the extents of the source and destination textures.
|
||||
VkExtent3D srcExtent = _srcImage->getExtent3D(region.srcSubresource.mipLevel);
|
||||
VkExtent3D dstExtent = _dstImage->getExtent3D(region.dstSubresource.mipLevel);
|
||||
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.srcSubresource.aspectMask);
|
||||
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
|
||||
// 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,
|
||||
// and those that require rendering
|
||||
bool canCopyFmts = canCopyFormats();
|
||||
for (auto& vkIB : _vkImageBlits) {
|
||||
if (canCopyFmts && canCopy(vkIB)) {
|
||||
if (canCopyFormats(vkIB) && canCopy(vkIB)) {
|
||||
|
||||
const VkOffset3D& so0 = vkIB.srcOffsets[0];
|
||||
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.
|
||||
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture();
|
||||
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture();
|
||||
if (blitCnt && srcMTLTex && dstMTLTex) {
|
||||
for (uint32_t blitIdx = 0; blitIdx < blitCnt; blitIdx++) {
|
||||
auto& mvkIBR = mvkBlitRenders[blitIdx];
|
||||
|
||||
cmdEncoder->endCurrentMetalEncoding();
|
||||
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(mvkIBR.region.srcSubresource.aspectMask);
|
||||
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(mvkIBR.region.dstSubresource.aspectMask);
|
||||
|
||||
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
||||
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
||||
mtlColorAttDesc.storeAction = MTLStoreActionStore;
|
||||
mtlColorAttDesc.texture = dstMTLTex;
|
||||
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture(srcPlaneIndex);
|
||||
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture(dstPlaneIndex);
|
||||
if (blitCnt && srcMTLTex && dstMTLTex) {
|
||||
cmdEncoder->endCurrentMetalEncoding();
|
||||
|
||||
MVKRPSKeyBlitImg blitKey;
|
||||
blitKey.srcMTLPixelFormat = _srcImage->getMTLPixelFormat();
|
||||
blitKey.srcMTLTextureType = _srcImage->getMTLTextureType();
|
||||
blitKey.dstMTLPixelFormat = _dstImage->getMTLPixelFormat();
|
||||
blitKey.srcFilter = mvkMTLSamplerMinMagFilterFromVkFilter(_filter);
|
||||
blitKey.dstSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_dstImage->getSampleCount());
|
||||
id<MTLRenderPipelineState> mtlRPS = cmdEncoder->getCommandEncodingPool()->getCmdBlitImageMTLRenderPipelineState(blitKey);
|
||||
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
||||
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
||||
mtlColorAttDesc.storeAction = MTLStoreActionStore;
|
||||
mtlColorAttDesc.texture = dstMTLTex;
|
||||
|
||||
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++) {
|
||||
auto& mvkIBR = mvkBlitRenders[blitIdx];
|
||||
uint32_t vtxBuffIdx = cmdEncoder->getDevice()->getMetalBufferIndexForVertexAttributeBinding(kMVKVertexContentBufferIndex);
|
||||
|
||||
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;
|
||||
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));
|
||||
[mtlRendEnc pushDebugGroup: @"vkCmdBlitImage"];
|
||||
[mtlRendEnc setRenderPipelineState: mtlRPS];
|
||||
cmdEncoder->setVertexBytes(mtlRendEnc, mvkIBR.vertices, sizeof(mvkIBR.vertices), vtxBuffIdx);
|
||||
[mtlRendEnc setFragmentTexture: srcMTLTex atIndex: 0];
|
||||
|
||||
[mtlRendEnc pushDebugGroup: @"vkCmdBlitImage"];
|
||||
[mtlRendEnc setRenderPipelineState: mtlRPS];
|
||||
cmdEncoder->setVertexBytes(mtlRendEnc, mvkIBR.vertices, sizeof(mvkIBR.vertices), vtxBuffIdx);
|
||||
[mtlRendEnc setFragmentTexture: srcMTLTex atIndex: 0];
|
||||
struct {
|
||||
uint slice;
|
||||
float lod;
|
||||
} texSubRez;
|
||||
texSubRez.slice = mvkIBR.region.srcSubresource.baseArrayLayer + layIdx;
|
||||
texSubRez.lod = mvkIBR.region.srcSubresource.mipLevel;
|
||||
cmdEncoder->setFragmentBytes(mtlRendEnc, &texSubRez, sizeof(texSubRez), 0);
|
||||
|
||||
struct {
|
||||
uint slice;
|
||||
float lod;
|
||||
} 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: kMVKBlitVertexCount];
|
||||
[mtlRendEnc popDebugGroup];
|
||||
[mtlRendEnc endEncoding];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template class MVKCmdBlitImage<1>;
|
||||
@ -428,15 +444,18 @@ VkResult MVKCmdResolveImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
||||
|
||||
_vkImageResolves.clear(); // Clear for reuse
|
||||
_vkImageResolves.reserve(regionCount);
|
||||
for (uint32_t i = 0; i < regionCount; i++) {
|
||||
_vkImageResolves.push_back(pRegions[i]);
|
||||
}
|
||||
for (uint32_t regionIdx = 0; regionIdx < regionCount; regionIdx++) {
|
||||
auto& vkIR = pRegions[regionIdx];
|
||||
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.dstSubresource.aspectMask);
|
||||
|
||||
// Validate
|
||||
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
||||
if ( !mvkAreAllFlagsEnabled(pixFmts->getCapabilities(_dstImage->getMTLPixelFormat()), kMVKMTLFmtCapsResolve) ) {
|
||||
return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdResolveImage(): %s cannot be used as a resolve destination on this device.", pixFmts->getName(_dstImage->getVkFormat()));
|
||||
}
|
||||
// Validate
|
||||
MVKPixelFormats* pixFmts = cmdBuff->getPixelFormats();
|
||||
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()));
|
||||
}
|
||||
|
||||
_vkImageResolves.push_back(vkIR);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
@ -457,10 +476,12 @@ void MVKCmdResolveImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
uint32_t sliceCnt = 0;
|
||||
|
||||
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;
|
||||
VkExtent3D srcImgExt = _srcImage->getExtent3D(mipLvl);
|
||||
VkExtent3D dstImgExt = _dstImage->getExtent3D(mipLvl);
|
||||
VkExtent3D srcImgExt = _srcImage->getExtent3D(srcPlaneIndex, mipLvl);
|
||||
VkExtent3D dstImgExt = _dstImage->getExtent3D(dstPlaneIndex, mipLvl);
|
||||
|
||||
// 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
|
||||
@ -496,25 +517,23 @@ void MVKCmdResolveImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
uint32_t layCnt = vkIR.dstSubresource.layerCount;
|
||||
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
||||
MVKMetalResolveSlice& rslvSlice = mtlResolveSlices[sliceCnt++];
|
||||
rslvSlice.copyRegion = &cpyRgn;
|
||||
rslvSlice.level = vkIR.dstSubresource.mipLevel;
|
||||
rslvSlice.slice = baseLayer + layIdx;
|
||||
}
|
||||
}
|
||||
|
||||
id<MTLTexture> srcMTLTex;
|
||||
if (expCnt == 0) {
|
||||
// Expansion and copying is not required. Each mip level of the source image
|
||||
// is being resolved entirely. Resolve directly from the source image.
|
||||
srcMTLTex = _srcImage->getMTLTexture();
|
||||
|
||||
} else {
|
||||
// Expansion and copying is not required. Each mip level of the source image
|
||||
// is being resolved entirely. Resolve directly from the source image.
|
||||
MVKImage* xfrImage = _srcImage;
|
||||
if (expCnt) {
|
||||
// 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,
|
||||
// and then resolve from the temporary image to the destination image.
|
||||
MVKImageDescriptorData xferImageData;
|
||||
_dstImage->getTransferDescriptorData(xferImageData);
|
||||
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.
|
||||
MVKCmdBlitImage<N> expCmd;
|
||||
@ -530,23 +549,24 @@ void MVKCmdResolveImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
(VkImage)xfrImage, _dstLayout,
|
||||
copyCnt, copyRegions);
|
||||
copyCmd.encode(cmdEncoder, kMVKCommandUseResolveCopyImage);
|
||||
|
||||
srcMTLTex = xfrImage->getMTLTexture();
|
||||
}
|
||||
|
||||
cmdEncoder->endCurrentMetalEncoding();
|
||||
|
||||
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
||||
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
||||
mtlColorAttDesc.storeAction = MTLStoreActionMultisampleResolve;
|
||||
mtlColorAttDesc.texture = srcMTLTex;
|
||||
mtlColorAttDesc.resolveTexture = _dstImage->getMTLTexture();
|
||||
MTLRenderPassColorAttachmentDescriptor* mtlColorAttDesc = mtlRPD.colorAttachments[0];
|
||||
mtlColorAttDesc.loadAction = MTLLoadActionLoad;
|
||||
mtlColorAttDesc.storeAction = MTLStoreActionMultisampleResolve;
|
||||
|
||||
// For each resolve slice, update the render pass descriptor for
|
||||
// the texture level and slice and create a render encoder.
|
||||
for (uint32_t sIdx = 0; sIdx < sliceCnt; 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.slice = rslvSlice.slice;
|
||||
mtlColorAttDesc.resolveLevel = rslvSlice.level;
|
||||
@ -675,12 +695,13 @@ VkResult MVKCmdBufferImageCopy<N>::setContent(MVKCommandBuffer* cmdBuff,
|
||||
_bufferImageCopyRegions.reserve(regionCount);
|
||||
for (uint32_t i = 0; i < regionCount; i++) {
|
||||
_bufferImageCopyRegions.push_back(pRegions[i]);
|
||||
}
|
||||
|
||||
// Validate
|
||||
if ( !_image->hasExpectedTexelSize() ) {
|
||||
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()));
|
||||
|
||||
// Validate
|
||||
if ( !_image->hasExpectedTexelSize() ) {
|
||||
MTLPixelFormat mtlPixFmt = _image->getMTLPixelFormat(MVKImage::getPlaneFromVkImageAspectFlags(pRegions[i].imageSubresource.aspectMask));
|
||||
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(mtlPixFmt), cmdBuff->getPixelFormats()->getName(_image->getVkFormat()));
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
@ -689,21 +710,23 @@ VkResult MVKCmdBufferImageCopy<N>::setContent(MVKCommandBuffer* cmdBuff,
|
||||
template <size_t N>
|
||||
void MVKCmdBufferImageCopy<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
id<MTLBuffer> mtlBuffer = _buffer->getMTLBuffer();
|
||||
id<MTLTexture> mtlTexture = _image->getMTLTexture();
|
||||
if ( !mtlBuffer || !mtlTexture ) { return; }
|
||||
if ( !mtlBuffer ) { return; }
|
||||
|
||||
NSUInteger mtlBuffOffsetBase = _buffer->getMTLBufferOffset();
|
||||
MTLPixelFormat mtlPixFmt = _image->getMTLPixelFormat();
|
||||
MVKCommandUse cmdUse = _toImage ? kMVKCommandUseCopyBufferToImage : kMVKCommandUseCopyImageToBuffer;
|
||||
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
||||
|
||||
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;
|
||||
MTLOrigin mtlTxtOrigin = mvkMTLOriginFromVkOffset3D(cpyRgn.imageOffset);
|
||||
MTLSize mtlTxtSize = mvkClampMTLSize(mvkMTLSizeFromVkExtent3D(cpyRgn.imageExtent),
|
||||
mtlTxtOrigin,
|
||||
mvkMTLSizeFromVkExtent3D(_image->getExtent3D(mipLevel)));
|
||||
mvkMTLSizeFromVkExtent3D(_image->getExtent3D(planeIndex, mipLevel)));
|
||||
NSUInteger mtlBuffOffset = mtlBuffOffsetBase + cpyRgn.bufferOffset;
|
||||
|
||||
uint32_t buffImgWd = cpyRgn.bufferRowLength;
|
||||
@ -1075,29 +1098,31 @@ VkResult MVKCmdClearImage<N>::setContent(MVKCommandBuffer* cmdBuff,
|
||||
// Add subresource ranges
|
||||
_subresourceRanges.clear(); // Clear for reuse
|
||||
_subresourceRanges.reserve(rangeCount);
|
||||
for (uint32_t i = 0; i < rangeCount; i++) {
|
||||
_subresourceRanges.push_back(pRanges[i]);
|
||||
}
|
||||
bool isDS = isDepthStencilClear();
|
||||
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) {
|
||||
auto& vkIR = pRanges[rangeIdx];
|
||||
uint8_t planeIndex = MVKImage::getPlaneFromVkImageAspectFlags(vkIR.aspectMask);
|
||||
|
||||
// Validate
|
||||
bool isDS = isDepthStencilClear();
|
||||
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"));
|
||||
}
|
||||
MVKMTLFmtCaps mtlFmtCaps = cmdBuff->getPixelFormats()->getCapabilities(_image->getMTLPixelFormat());
|
||||
if ((isDS && !mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCapsDSAtt)) ||
|
||||
( !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()));
|
||||
}
|
||||
// Validate
|
||||
MVKMTLFmtCaps mtlFmtCaps = cmdBuff->getPixelFormats()->getCapabilities(_image->getMTLPixelFormat(planeIndex));
|
||||
if ((isDS && !mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCapsDSAtt)) ||
|
||||
( !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()));
|
||||
}
|
||||
|
||||
_subresourceRanges.push_back(vkIR);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void MVKCmdClearImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
id<MTLTexture> imgMTLTex = _image->getMTLTexture();
|
||||
if ( !imgMTLTex ) { return; }
|
||||
|
||||
bool isDS = isDepthStencilClear();
|
||||
NSString* mtlRendEncName = (isDS
|
||||
? mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearDepthStencilImage)
|
||||
@ -1107,6 +1132,8 @@ void MVKCmdClearImage<N>::encode(MVKCommandEncoder* cmdEncoder) {
|
||||
|
||||
MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();
|
||||
for (auto& srRange : _subresourceRanges) {
|
||||
id<MTLTexture> imgMTLTex = _image->getMTLTexture(MVKImage::getPlaneFromVkImageAspectFlags(srRange.aspectMask));
|
||||
if ( !imgMTLTex ) { continue; }
|
||||
|
||||
MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassColorAttachmentDescriptor* mtlRPCADesc = nil;
|
||||
|
@ -369,7 +369,7 @@ MVKImage* MVKCommandResourceFactory::newMVKImage(MVKImageDescriptorData& imgData
|
||||
.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
|
||||
};
|
||||
MVKImage* mvkImg = _device->createImage(&createInfo, nullptr);
|
||||
mvkImg->bindDeviceMemory(_transferImageMemory, 0);
|
||||
mvkImg->bindDeviceMemory(_transferImageMemory, 0, 0);
|
||||
return mvkImg;
|
||||
}
|
||||
|
||||
|
@ -40,13 +40,13 @@ public:
|
||||
#pragma mark Resource memory
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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. */
|
||||
VkResult bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo);
|
||||
|
@ -189,33 +189,32 @@ void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder,
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||
const auto& imageInfo = get<VkDescriptorImageInfo>(pData, stride, rezIdx - dstArrayElement);
|
||||
MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
|
||||
tb.mtlTexture = imageView->getMTLTexture();
|
||||
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) {
|
||||
tb.swizzle = imageView->getPackedSwizzle();
|
||||
} else {
|
||||
tb.swizzle = 0;
|
||||
}
|
||||
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
||||
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 (_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;
|
||||
uint8_t planeCount = (imageView) ? imageView->getPlaneCount() : 1;
|
||||
for (uint8_t planeIndex = 0; planeIndex < planeCount; planeIndex++) {
|
||||
tb.mtlTexture = imageView->getMTLTexture(planeIndex);
|
||||
tb.swizzle = (_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ? imageView->getPackedSwizzle() : 0;
|
||||
if (_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
||||
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 (_applyToStage[i]) {
|
||||
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx + planeIndex;
|
||||
if (i == kMVKShaderStageCompute) {
|
||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindBuffer(bb); }
|
||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
||||
} 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: {
|
||||
const auto& imageInfo = get<VkDescriptorImageInfo>(pData, stride, rezIdx - dstArrayElement);
|
||||
MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
|
||||
tb.mtlTexture = imageView->getMTLTexture();
|
||||
if (imageView) {
|
||||
tb.swizzle = imageView->getPackedSwizzle();
|
||||
} else {
|
||||
tb.swizzle = 0;
|
||||
}
|
||||
MVKSampler* sampler;
|
||||
if (_immutableSamplers.empty()) {
|
||||
sampler = (MVKSampler*)imageInfo.sampler;
|
||||
validate(sampler);
|
||||
} else {
|
||||
sampler = _immutableSamplers[rezIdx];
|
||||
}
|
||||
sb.mtlSamplerState = sampler->getMTLSamplerState();
|
||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||
if (_applyToStage[i]) {
|
||||
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx;
|
||||
sb.index = mtlIdxs.stages[i].samplerIndex + rezIdx;
|
||||
if (i == kMVKShaderStageCompute) {
|
||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); }
|
||||
} else {
|
||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindTexture(MVKShaderStage(i), tb); }
|
||||
if (cmdEncoder) { cmdEncoder->_graphicsResourcesState.bindSamplerState(MVKShaderStage(i), sb); }
|
||||
uint8_t planeCount = (imageView) ? imageView->getPlaneCount() : 1;
|
||||
for (uint8_t planeIndex = 0; planeIndex < planeCount; planeIndex++) {
|
||||
tb.mtlTexture = imageView->getMTLTexture(planeIndex);
|
||||
tb.swizzle = (imageView) ? imageView->getPackedSwizzle() : 0;
|
||||
MVKSampler* sampler;
|
||||
if (_immutableSamplers.empty()) {
|
||||
sampler = (MVKSampler*)imageInfo.sampler;
|
||||
validate(sampler);
|
||||
} else {
|
||||
sampler = _immutableSamplers[rezIdx];
|
||||
}
|
||||
sb.mtlSamplerState = sampler->getMTLSamplerState();
|
||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||
if (_applyToStage[i]) {
|
||||
tb.index = mtlIdxs.stages[i].textureIndex + rezIdx + planeIndex;
|
||||
sb.index = mtlIdxs.stages[i].samplerIndex + rezIdx;
|
||||
if (i == kMVKShaderStageCompute) {
|
||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindTexture(tb); }
|
||||
if (cmdEncoder) { cmdEncoder->_computeResourcesState.bindSamplerState(sb); }
|
||||
} else {
|
||||
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
|
||||
bool MVKDescriptorSetLayoutBinding::validate(MVKSampler* mvkSampler) {
|
||||
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 true;
|
||||
@ -437,7 +435,19 @@ void MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStage
|
||||
if ( !_device->_pMetalFeatures->arrayOfSamplers ) {
|
||||
_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;
|
||||
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
@ -688,53 +698,54 @@ void MVKImageDescriptor::bind(MVKCommandEncoder* cmdEncoder,
|
||||
MVKShaderResourceBinding& mtlIndexes,
|
||||
MVKArrayRef<uint32_t> dynamicOffsets,
|
||||
uint32_t* pDynamicOffsetIndex) {
|
||||
MVKMTLTextureBinding tb;
|
||||
MVKMTLBufferBinding bb;
|
||||
switch (descriptorType) {
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||
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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
break;
|
||||
}
|
||||
|
||||
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,
|
||||
@ -845,7 +856,7 @@ void MVKSamplerDescriptorMixin::write(MVKDescriptorSet* mvkDescSet,
|
||||
const auto* pImgInfo = &get<VkDescriptorImageInfo>(pData, stride, srcIndex);
|
||||
_mvkSampler = (MVKSampler*)pImgInfo->sampler;
|
||||
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(); }
|
||||
|
@ -57,6 +57,7 @@ class MVKPipelineCache;
|
||||
class MVKPipelineLayout;
|
||||
class MVKPipeline;
|
||||
class MVKSampler;
|
||||
class MVKSamplerYcbcrConversion;
|
||||
class MVKDescriptorSetLayout;
|
||||
class MVKDescriptorPool;
|
||||
class MVKDescriptorUpdateTemplate;
|
||||
@ -521,6 +522,11 @@ public:
|
||||
void destroySampler(MVKSampler* mvkSamp,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
MVKSamplerYcbcrConversion* createSamplerYcbcrConversion(const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
void destroySamplerYcbcrConversion(MVKSamplerYcbcrConversion* mvkSampConv,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
MVKDescriptorSetLayout* createDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
void destroyDescriptorSetLayout(MVKDescriptorSetLayout* mvkDSL,
|
||||
@ -652,6 +658,7 @@ public:
|
||||
const VkPhysicalDeviceVariablePointerFeatures _enabledVarPtrFeatures;
|
||||
const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT _enabledInterlockFeatures;
|
||||
const VkPhysicalDeviceHostQueryResetFeaturesEXT _enabledHostQryResetFeatures;
|
||||
const VkPhysicalDeviceSamplerYcbcrConversionFeatures _enabledSamplerYcbcrConversionFeatures;
|
||||
const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT _enabledScalarLayoutFeatures;
|
||||
const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT _enabledTexelBuffAlignFeatures;
|
||||
const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT _enabledVtxAttrDivFeatures;
|
||||
|
@ -139,6 +139,11 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
|
||||
portabilityFeatures->samplerMipLodBias = false;
|
||||
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: {
|
||||
auto* shaderIntFuncsFeatures = (VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*)next;
|
||||
shaderIntFuncsFeatures->shaderIntegerFunctions2 = true;
|
||||
@ -204,6 +209,11 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
|
||||
portabilityProps->minVertexInputBindingStrideAlignment = 4;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES: {
|
||||
auto* samplerYcbcrConvProps = (VkSamplerYcbcrConversionImageFormatProperties*)next;
|
||||
samplerYcbcrConvProps->combinedImageSamplerDescriptorCount = 3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -462,9 +472,9 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1},
|
||||
};
|
||||
MTLPixelFormat mtlPixFmt;
|
||||
MTLPixelFormat mtlPixFmt = _pixelFormats.getMTLPixelFormat(viewInfo.format);
|
||||
bool useSwizzle;
|
||||
return (MVKImageView::validateSwizzledMTLPixelFormat(&viewInfo, &_pixelFormats, this,
|
||||
return (MVKImageView::validateSwizzledMTLPixelFormat(&viewInfo, this,
|
||||
_metalFeatures.nativeTextureSwizzle,
|
||||
_mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle,
|
||||
mtlPixFmt, useSwizzle) == VK_SUCCESS);
|
||||
@ -1300,6 +1310,7 @@ void MVKPhysicalDevice::initProperties() {
|
||||
uint32_t maxStorage = 0, maxUniform = 0;
|
||||
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) {
|
||||
if ( _pixelFormats.getChromaSubsamplingComponentBits(vk) > 0 ) { return false; } // Skip chroma subsampling formats
|
||||
MTLPixelFormat mtlFmt = _pixelFormats.getMTLPixelFormat(vk);
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (swapchainInfo) {
|
||||
return (MVKImage*)addResource(new MVKPeerSwapchainImage(this, pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1)));
|
||||
}
|
||||
return (MVKImage*)addResource(new MVKImage(this, pCreateInfo));
|
||||
MVKImage* mvkImg = (swapchainInfo)
|
||||
? new MVKPeerSwapchainImage(this, pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1))
|
||||
: new MVKImage(this, pCreateInfo);
|
||||
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||
addResource(memoryBinding.get());
|
||||
}
|
||||
return mvkImg;
|
||||
}
|
||||
|
||||
void MVKDevice::destroyImage(MVKImage* mvkImg,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
if (mvkImg) {
|
||||
removeResource(mvkImg);
|
||||
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||
removeResource(memoryBinding.get());
|
||||
}
|
||||
mvkImg->destroy();
|
||||
}
|
||||
}
|
||||
@ -2268,13 +2284,19 @@ MVKPresentableSwapchainImage* MVKDevice::createPresentableSwapchainImage(const V
|
||||
MVKSwapchain* swapchain,
|
||||
uint32_t swapchainIndex,
|
||||
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,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
if (mvkImg) {
|
||||
removeResource(mvkImg);
|
||||
for (auto& memoryBinding : mvkImg->_memoryBindings) {
|
||||
removeResource(memoryBinding.get());
|
||||
}
|
||||
mvkImg->destroy();
|
||||
}
|
||||
}
|
||||
@ -2438,6 +2460,16 @@ void MVKDevice::destroySampler(MVKSampler* mvkSamp,
|
||||
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,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
return new MVKDescriptorSetLayout(this, pCreateInfo);
|
||||
@ -2689,6 +2721,7 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
||||
_enabledVarPtrFeatures(),
|
||||
_enabledInterlockFeatures(),
|
||||
_enabledHostQryResetFeatures(),
|
||||
_enabledSamplerYcbcrConversionFeatures(),
|
||||
_enabledScalarLayoutFeatures(),
|
||||
_enabledTexelBuffAlignFeatures(),
|
||||
_enabledVtxAttrDivFeatures(),
|
||||
@ -2850,6 +2883,7 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
||||
mvkClear(&_enabledVarPtrFeatures);
|
||||
mvkClear(&_enabledInterlockFeatures);
|
||||
mvkClear(&_enabledHostQryResetFeatures);
|
||||
mvkClear(&_enabledSamplerYcbcrConversionFeatures);
|
||||
mvkClear(&_enabledScalarLayoutFeatures);
|
||||
mvkClear(&_enabledTexelBuffAlignFeatures);
|
||||
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.pNext = &pdTexelBuffAlignFeatures;
|
||||
|
||||
VkPhysicalDeviceSamplerYcbcrConversionFeatures pdSamplerYcbcrConversionFeatures;
|
||||
pdSamplerYcbcrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
|
||||
pdSamplerYcbcrConversionFeatures.pNext = &pdScalarLayoutFeatures;
|
||||
|
||||
VkPhysicalDeviceHostQueryResetFeaturesEXT pdHostQryResetFeatures;
|
||||
pdHostQryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT;
|
||||
pdHostQryResetFeatures.pNext = &pdScalarLayoutFeatures;
|
||||
pdHostQryResetFeatures.pNext = &pdSamplerYcbcrConversionFeatures;
|
||||
|
||||
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT pdInterlockFeatures;
|
||||
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);
|
||||
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: {
|
||||
auto* requestedFeatures = (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT*)next;
|
||||
enableFeatures(&_enabledScalarLayoutFeatures.scalarBlockLayout,
|
||||
|
@ -24,8 +24,7 @@
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
class MVKBuffer;
|
||||
class MVKImage;
|
||||
class MVKImageMemoryBinding;
|
||||
|
||||
// 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;
|
||||
@ -131,15 +130,15 @@ public:
|
||||
~MVKDeviceMemory() override;
|
||||
|
||||
protected:
|
||||
friend MVKBuffer;
|
||||
friend MVKImage;
|
||||
friend class MVKBuffer;
|
||||
friend class MVKImageMemoryBinding;
|
||||
|
||||
void propagateDebugName() override;
|
||||
VkDeviceSize adjustMemorySize(VkDeviceSize size, VkDeviceSize offset);
|
||||
VkResult addBuffer(MVKBuffer* mvkBuff);
|
||||
void removeBuffer(MVKBuffer* mvkBuff);
|
||||
VkResult addImage(MVKImage* mvkImg);
|
||||
void removeImage(MVKImage* mvkImg);
|
||||
VkResult addImageMemoryBinding(MVKImageMemoryBinding* mvkImg);
|
||||
void removeImageMemoryBinding(MVKImageMemoryBinding* mvkImg);
|
||||
bool ensureMTLHeap();
|
||||
bool ensureMTLBuffer();
|
||||
bool ensureHostMemory();
|
||||
@ -148,7 +147,7 @@ protected:
|
||||
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||
|
||||
MVKSmallVector<MVKBuffer*, 4> _buffers;
|
||||
MVKSmallVector<MVKImage*, 4> _images;
|
||||
MVKSmallVector<MVKImageMemoryBinding*, 4> _imageMemoryBindings;
|
||||
std::mutex _rezLock;
|
||||
VkDeviceSize _allocationSize = 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 (!_mtlHeap) {
|
||||
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); }
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,7 @@ VkResult MVKDeviceMemory::pullFromDevice(VkDeviceSize offset,
|
||||
VkDeviceSize memSize = adjustMemorySize(size, offset);
|
||||
if (memSize > 0 && isMemoryHostAccessible() && (evenIfCoherent || !isMemoryHostCoherent()) && !_mtlHeap) {
|
||||
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); }
|
||||
|
||||
#if MVK_MACOS
|
||||
@ -152,23 +152,23 @@ void MVKDeviceMemory::removeBuffer(MVKBuffer* mvkBuff) {
|
||||
mvkRemoveAllOccurances(_buffers, mvkBuff);
|
||||
}
|
||||
|
||||
VkResult MVKDeviceMemory::addImage(MVKImage* mvkImg) {
|
||||
VkResult MVKDeviceMemory::addImageMemoryBinding(MVKImageMemoryBinding* mvkImg) {
|
||||
lock_guard<mutex> lock(_rezLock);
|
||||
|
||||
// If a dedicated alloc, ensure this image is the one and only image
|
||||
// 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() );
|
||||
}
|
||||
|
||||
if (!_isDedicated) { _images.push_back(mvkImg); }
|
||||
if (!_isDedicated) { _imageMemoryBindings.push_back(mvkImg); }
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void MVKDeviceMemory::removeImage(MVKImage* mvkImg) {
|
||||
void MVKDeviceMemory::removeImageMemoryBinding(MVKImageMemoryBinding* mvkImg) {
|
||||
lock_guard<mutex> lock(_rezLock);
|
||||
mvkRemoveAllOccurances(_images, mvkImg);
|
||||
mvkRemoveAllOccurances(_imageMemoryBindings, mvkImg);
|
||||
}
|
||||
|
||||
// Ensures that this instance is backed by a MTLHeap object,
|
||||
@ -266,7 +266,7 @@ void MVKDeviceMemory::freeHostMemory() {
|
||||
|
||||
MVKResource* MVKDeviceMemory::getDedicatedResource() {
|
||||
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,
|
||||
@ -319,7 +319,9 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_images.push_back((MVKImage*)dedicatedImage);
|
||||
for (auto& memoryBinding : ((MVKImage*)dedicatedImage)->_memoryBindings) {
|
||||
_imageMemoryBindings.push_back(memoryBinding.get());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -367,7 +369,7 @@ MVKDeviceMemory::~MVKDeviceMemory() {
|
||||
// to allow the resource to callback to remove itself from the collection.
|
||||
auto buffCopies = _buffers;
|
||||
for (auto& buf : buffCopies) { buf->bindDeviceMemory(nullptr, 0); }
|
||||
auto imgCopies = _images;
|
||||
auto imgCopies = _imageMemoryBindings;
|
||||
for (auto& img : imgCopies) { img->bindDeviceMemory(nullptr, 0); }
|
||||
|
||||
[_mtlBuffer release];
|
||||
|
@ -33,19 +33,112 @@ class MVKSwapchain;
|
||||
class MVKCommandEncoder;
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKImagePlane
|
||||
|
||||
/** Tracks the state of an image subresource. */
|
||||
typedef struct {
|
||||
VkImageSubresource subresource;
|
||||
VkSubresourceLayout layout;
|
||||
VkImageLayout layoutState;
|
||||
VkImageSubresource subresource;
|
||||
VkSubresourceLayout layout;
|
||||
VkImageLayout layoutState;
|
||||
} 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 MVKImage
|
||||
|
||||
/** Represents a Vulkan image. */
|
||||
class MVKImage : public MVKResource {
|
||||
class MVKImage : public MVKVulkanAPIDeviceObject {
|
||||
|
||||
public:
|
||||
|
||||
@ -55,6 +148,9 @@ public:
|
||||
/** Returns the debug report object type of this object. */
|
||||
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; }
|
||||
|
||||
/** Returns the plane index of VkImageAspectFlags. */
|
||||
static uint8_t getPlaneFromVkImageAspectFlags(VkImageAspectFlags aspectMask);
|
||||
|
||||
/**
|
||||
* Returns the Vulkan image type of this image.
|
||||
* This may be different than the value originally specified for the image
|
||||
@ -63,7 +159,7 @@ public:
|
||||
VkImageType getImageType();
|
||||
|
||||
/** Returns the Vulkan image format of this image. */
|
||||
VkFormat getVkFormat();
|
||||
VkFormat getVkFormat() { return _vkFormat; };
|
||||
|
||||
/** Returns whether this image has a depth or stencil format. */
|
||||
bool getIsDepthStencil();
|
||||
@ -81,7 +177,7 @@ public:
|
||||
* Returns the 3D extent of this image at the specified mipmap level.
|
||||
* For 2D or cube images, the Z component will be 1.
|
||||
*/
|
||||
VkExtent3D getExtent3D(uint32_t mipLevel);
|
||||
VkExtent3D getExtent3D(uint8_t planeIndex, uint32_t mipLevel);
|
||||
|
||||
/** Returns the number of mipmap levels in this image. */
|
||||
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
|
||||
* 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)
|
||||
@ -109,7 +205,10 @@ public:
|
||||
* of bytes per row (as returned by the getBytesPerRow() function, multiplied by
|
||||
* 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. */
|
||||
VkResult getSubresourceLayout(const VkImageSubresource* pSubresource,
|
||||
@ -122,24 +221,17 @@ public:
|
||||
#pragma mark Resource memory
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
void applyImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
@ -150,10 +242,10 @@ public:
|
||||
#pragma mark Metal
|
||||
|
||||
/** 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. */
|
||||
id<MTLTexture> getMTLTexture(MTLPixelFormat mtlPixFmt);
|
||||
id<MTLTexture> getMTLTexture(uint8_t planeIndex, MTLPixelFormat mtlPixFmt);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
@ -189,7 +281,7 @@ public:
|
||||
IOSurfaceRef getIOSurface();
|
||||
|
||||
/** 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. */
|
||||
inline MTLTextureType getMTLTextureType() { return _mtlTextureType; }
|
||||
@ -225,50 +317,37 @@ public:
|
||||
~MVKImage() override;
|
||||
|
||||
protected:
|
||||
friend class MVKDeviceMemory;
|
||||
friend class MVKImageView;
|
||||
using MVKResource::needsHostReadSync;
|
||||
friend MVKDeviceMemory;
|
||||
friend MVKDevice;
|
||||
friend MVKImageMemoryBinding;
|
||||
friend MVKImagePlane;
|
||||
friend class MVKImageViewPlane;
|
||||
friend MVKImageView;
|
||||
|
||||
void propagateDebugName() override;
|
||||
MVKImageSubresource* getSubresource(uint32_t mipLevel, uint32_t arrayLayer);
|
||||
void validateConfig(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||
VkSampleCountFlagBits validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||
uint32_t validateMipLevels(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||
bool validateLinear(const VkImageCreateInfo* pCreateInfo, bool isAttachment);
|
||||
bool validateUseTexelBuffer();
|
||||
void initSubresources(const VkImageCreateInfo* pCreateInfo);
|
||||
void initSubresourceLayout(MVKImageSubresource& imgSubRez);
|
||||
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||
id<MTLTexture> newMTLTexture();
|
||||
void releaseMTLTexture();
|
||||
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;
|
||||
std::unordered_map<NSUInteger, id<MTLTexture>> _mtlTextureViews;
|
||||
MVKSmallVector<std::unique_ptr<MVKImageMemoryBinding>, 3> _memoryBindings;
|
||||
MVKSmallVector<std::unique_ptr<MVKImagePlane>, 3> _planes;
|
||||
VkExtent3D _extent;
|
||||
uint32_t _mipLevels;
|
||||
uint32_t _arrayLayers;
|
||||
VkSampleCountFlagBits _samples;
|
||||
VkImageUsageFlags _usage;
|
||||
MTLPixelFormat _mtlPixelFormat;
|
||||
VkFormat _vkFormat;
|
||||
MTLTextureType _mtlTextureType;
|
||||
id<MTLTexture> _mtlTexture;
|
||||
std::mutex _lock;
|
||||
IOSurfaceRef _ioSurface;
|
||||
VkDeviceSize _rowByteAlignment;
|
||||
bool _isDepthStencilAttachment;
|
||||
bool _canSupportMTLTextureView;
|
||||
bool _hasExpectedTexelSize;
|
||||
bool _usesTexelBuffer;
|
||||
bool _hasChromaSubsampling;
|
||||
bool _isLinear;
|
||||
bool _is3DCompressed;
|
||||
bool _isAliasable;
|
||||
@ -284,12 +363,12 @@ class MVKSwapchainImage : public MVKImage {
|
||||
public:
|
||||
|
||||
/** 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
|
||||
|
||||
/** 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
|
||||
@ -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 MVKImageView
|
||||
|
||||
@ -418,17 +525,20 @@ public:
|
||||
#pragma mark Metal
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
static VkResult validateSwizzledMTLPixelFormat(const VkImageViewCreateInfo* pCreateInfo,
|
||||
MVKPixelFormats* mvkPixFmts,
|
||||
MVKVulkanAPIObject* apiObject,
|
||||
bool hasNativeSwizzleSupport,
|
||||
bool hasShaderSwizzleSupport,
|
||||
@ -472,23 +581,54 @@ public:
|
||||
const VkImageViewCreateInfo* pCreateInfo,
|
||||
const MVKConfiguration* pAltMVKConfig = nullptr);
|
||||
|
||||
~MVKImageView() override;
|
||||
|
||||
protected:
|
||||
friend MVKImageViewPlane;
|
||||
|
||||
void propagateDebugName() override;
|
||||
id<MTLTexture> newMTLTexture();
|
||||
void initMTLTextureViewSupport();
|
||||
void validateImageViewConfig(const VkImageViewCreateInfo* pCreateInfo);
|
||||
|
||||
MVKImage* _image;
|
||||
MVKSmallVector<std::unique_ptr<MVKImageViewPlane>, 3> _planes;
|
||||
VkImageSubresourceRange _subresourceRange;
|
||||
VkImageUsageFlags _usage;
|
||||
id<MTLTexture> _mtlTexture;
|
||||
std::mutex _lock;
|
||||
MTLPixelFormat _mtlPixelFormat;
|
||||
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. */
|
||||
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.
|
||||
@ -529,5 +673,6 @@ protected:
|
||||
|
||||
id<MTLSamplerState> _mtlSamplerState;
|
||||
SPIRV_CROSS_NAMESPACE::MSLConstexprSampler _constExprSampler;
|
||||
MVKSamplerYcbcrConversion* _ycbcrConversion;
|
||||
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(vkCmdPushDescriptorSetKHR, KHR_PUSH_DESCRIPTOR);
|
||||
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(vkDestroySwapchainKHR, KHR_SWAPCHAIN);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkGetSwapchainImagesKHR, KHR_SWAPCHAIN);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "mvk_datatypes.h"
|
||||
#include "MVKEnvironment.h"
|
||||
#include "MVKBaseObject.h"
|
||||
#include <SPIRV-Cross/spirv_msl.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
@ -70,6 +71,8 @@ typedef enum : uint16_t {
|
||||
kMVKMTLFmtCapsDRMR = (kMVKMTLFmtCapsDRM | kMVKMTLFmtCapsResolve),
|
||||
kMVKMTLFmtCapsDRFMR = (kMVKMTLFmtCapsDRMR | kMVKMTLFmtCapsFilter),
|
||||
|
||||
kMVKMTLFmtCapsChromaSubsampling = kMVKMTLFmtCapsRF,
|
||||
kMVKMTLFmtCapsMultiPlanar = kMVKMTLFmtCapsChromaSubsampling,
|
||||
} MVKMTLFmtCaps;
|
||||
|
||||
|
||||
@ -83,16 +86,18 @@ typedef struct {
|
||||
MTLPixelFormat mtlPixelFormatSubstitute;
|
||||
MTLVertexFormat mtlVertexFormat;
|
||||
MTLVertexFormat mtlVertexFormatSubstitute;
|
||||
uint8_t chromaSubsamplingPlaneCount;
|
||||
uint8_t chromaSubsamplingComponentBits;
|
||||
VkExtent2D blockTexelSize;
|
||||
uint32_t bytesPerBlock;
|
||||
MVKFormatType formatType;
|
||||
VkFormatProperties properties;
|
||||
const char* name;
|
||||
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); };
|
||||
inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid || chromaSubsamplingPlaneCount > 0); };
|
||||
inline bool isSupportedOrSubstitutable() const { return isSupported() || (mtlPixelFormatSubstitute != MTLPixelFormatInvalid); };
|
||||
|
||||
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.
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/** 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.
|
||||
* The returned value may be fractional for certain compressed formats.
|
||||
|
@ -236,6 +236,61 @@ VkExtent2D MVKPixelFormats::getBlockTexelSize(MTLPixelFormat mtlFormat) {
|
||||
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) {
|
||||
return getVkFormatDesc(vkFormat).bytesPerTexel();
|
||||
}
|
||||
@ -492,10 +547,16 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalD
|
||||
// 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); \
|
||||
_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() {
|
||||
|
||||
@ -742,9 +803,41 @@ void MVKPixelFormats::initVkFormatCapabilities() {
|
||||
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 );
|
||||
|
||||
// Future extension VK_KHX_color_conversion and Vulkan 1.1.
|
||||
addVkFormatDesc( UNDEFINED, GBGR422, Invalid, Invalid, Invalid, 2, 1, 4, ColorFloat );
|
||||
addVkFormatDesc( UNDEFINED, BGRG422, Invalid, Invalid, Invalid, 2, 1, 4, ColorFloat );
|
||||
// Extension VK_KHR_sampler_ycbcr_conversion
|
||||
addVkFormatDescChromaSubsampling( G8B8G8R8_422_UNORM, GBGR422, 1, 8, 2, 1, 4 );
|
||||
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
|
||||
}
|
||||
@ -1139,44 +1232,44 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id<MTLDevice> mtlDevice) {
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, RGBA32Sint, RWC );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, RGBA32Float, RWC );
|
||||
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_4x4_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_4x4_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x4_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x4_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_5x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x6_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_6x6_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x6_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x6_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x8_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_8x8_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x6_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x6_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x8_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x8_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x10_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_10x10_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x10_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x10_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x12_LDR, RF );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily2_v1, ASTC_12x12_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_4x4_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_4x4_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x4_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x4_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_5x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x6_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_6x6_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x6_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x6_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x8_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_8x8_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x5_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x5_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x6_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x6_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x8_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x8_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x10_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_10x10_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x10_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x10_sRGB, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x12_LDR, RF );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, ASTC_12x12_sRGB, RF );
|
||||
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v1, Depth32Float, DRMR );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v1, Depth32Float_Stencil8, DRMR );
|
||||
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGRA10_XR, All );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGRA10_XR_sRGB, All );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGR10_XR, All );
|
||||
addMTLPixelFormatCapabilities(iOS_GPUFamily3_v2, BGR10_XR_sRGB, All );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGRA10_XR, All );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGRA10_XR_sRGB, All );
|
||||
addMTLPixelFormatCapabilities( iOS_GPUFamily3_v2, BGR10_XR, 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, CharNormalized, Vertex );
|
||||
@ -1256,6 +1349,17 @@ typedef enum : VkFormatFeatureFlags {
|
||||
VK_FORMAT_FEATURE_BLIT_DST_BIT),
|
||||
kMVKVkFormatFeatureFlagsTexDSAtt = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_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),
|
||||
kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT),
|
||||
kMVKVkFormatFeatureFlagsBufAtomic = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
|
||||
@ -1272,9 +1376,23 @@ void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc) {
|
||||
|
||||
VkFormatProperties& vkProps = vkDesc.properties;
|
||||
MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkDesc.mtlPixelFormat).mtlFmtCaps;
|
||||
vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
||||
vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
||||
|
||||
// Set optimal tiling features first
|
||||
vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
||||
// Chroma subsampling and multi planar features
|
||||
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(Filter, 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);
|
||||
|
||||
// Linear tiling is not available to depth/stencil or compressed formats.
|
||||
vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
|
||||
if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) {
|
||||
|
||||
// Start with optimal tiling features, and modify.
|
||||
vkProps.linearTilingFeatures = vkProps.optimalTilingFeatures;
|
||||
|
||||
|
@ -110,7 +110,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
|
||||
if (dsRPAttIdx != VK_ATTACHMENT_UNUSED) {
|
||||
MVKRenderPassAttachment* dsMVKRPAtt = &_renderPass->_attachments[dsRPAttIdx];
|
||||
MVKImageView* dsImage = framebuffer->getAttachment(dsRPAttIdx);
|
||||
MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat();
|
||||
MTLPixelFormat mtlDSFormat = dsImage->getMTLPixelFormat(0);
|
||||
|
||||
if (pixFmts->isDepthFormat(mtlDSFormat)) {
|
||||
MTLRenderPassDepthAttachmentDescriptor* mtlDepthAttDesc = mtlRPDesc.depthAttachment;
|
||||
|
@ -39,14 +39,8 @@ public:
|
||||
/** Returns the byte offset in the bound device memory. */
|
||||
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. */
|
||||
virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
|
||||
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
|
||||
|
||||
/** Returns the device memory underlying this resource. */
|
||||
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_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_ycbcr_conversion, KHR_SAMPLER_YCBCR_CONVERSION, 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_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE)
|
||||
|
@ -115,7 +115,7 @@ MVK_PUBLIC_SYMBOL VkResult vkSetMTLTextureMVK(
|
||||
id<MTLTexture> mtlTexture) {
|
||||
|
||||
MVKImage* mvkImg = (MVKImage*)image;
|
||||
return mvkImg->setMTLTexture(mtlTexture);
|
||||
return mvkImg->setMTLTexture(0, mtlTexture);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void vkGetMTLTextureMVK(
|
||||
@ -123,7 +123,7 @@ MVK_PUBLIC_SYMBOL void vkGetMTLTextureMVK(
|
||||
id<MTLTexture>* pMTLTexture) {
|
||||
|
||||
MVKImage* mvkImg = (MVKImage*)image;
|
||||
*pMTLTexture = mvkImg->getMTLTexture();
|
||||
*pMTLTexture = mvkImg->getMTLTexture(0);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void vkGetMTLBufferMVK(
|
||||
|
@ -526,7 +526,7 @@ MVK_PUBLIC_SYMBOL VkResult vkBindImageMemory(
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKImage* mvkImg = (MVKImage*)image;
|
||||
MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)mem;
|
||||
VkResult rslt = mvkImg->bindDeviceMemory(mvkMem, memOffset);
|
||||
VkResult rslt = mvkImg->bindDeviceMemory(mvkMem, memOffset, 0);
|
||||
MVKTraceVulkanCallEnd();
|
||||
return rslt;
|
||||
}
|
||||
@ -549,7 +549,7 @@ MVK_PUBLIC_SYMBOL void vkGetImageMemoryRequirements(
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKImage* mvkImg = (MVKImage*)image;
|
||||
mvkImg->getMemoryRequirements(pMemoryRequirements);
|
||||
mvkImg->getMemoryRequirements(pMemoryRequirements, 0);
|
||||
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 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_max != other.constExprSampler.lod_clamp_max) { 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.lod_clamp_enable != other.constExprSampler.lod_clamp_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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user