Retrieve linear image memory alignment requirements from Metal device.
Add mvkMTLPixelFormatLinearTextureAlignment() function. Add MVKDevice::getVkFormatTexelBufferAlignment() and use for Linear image memory alignment. For non-linear image memory alignment, use mvkVkFormatBytesPerBlock(). Rename MVKDevice::mtlPixelFormatFromVkFormat() to getMTLPixelFormatFromVkFormat().
This commit is contained in:
parent
231e39bd7f
commit
f459bf34e3
@ -839,13 +839,13 @@ void MVKCmdClearAttachments::encode(MVKCommandEncoder* cmdEncoder) {
|
|||||||
uint32_t caCnt = subpass->getColorAttachmentCount();
|
uint32_t caCnt = subpass->getColorAttachmentCount();
|
||||||
for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
|
for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
|
||||||
VkFormat vkAttFmt = subpass->getColorAttachmentFormat(caIdx);
|
VkFormat vkAttFmt = subpass->getColorAttachmentFormat(caIdx);
|
||||||
_rpsKey.attachmentMTLPixelFormats[caIdx] = cmdPool->mtlPixelFormatFromVkFormat(vkAttFmt);
|
_rpsKey.attachmentMTLPixelFormats[caIdx] = cmdPool->getMTLPixelFormatFromVkFormat(vkAttFmt);
|
||||||
MTLClearColor mtlCC = mvkMTLClearColorFromVkClearValue(_vkClearValues[caIdx], vkAttFmt);
|
MTLClearColor mtlCC = mvkMTLClearColorFromVkClearValue(_vkClearValues[caIdx], vkAttFmt);
|
||||||
_clearColors[caIdx] = { (float)mtlCC.red, (float)mtlCC.green, (float)mtlCC.blue, (float)mtlCC.alpha};
|
_clearColors[caIdx] = { (float)mtlCC.red, (float)mtlCC.green, (float)mtlCC.blue, (float)mtlCC.alpha};
|
||||||
}
|
}
|
||||||
|
|
||||||
VkFormat vkAttFmt = subpass->getDepthStencilFormat();
|
VkFormat vkAttFmt = subpass->getDepthStencilFormat();
|
||||||
MTLPixelFormat mtlAttFmt = cmdPool->mtlPixelFormatFromVkFormat(vkAttFmt);
|
MTLPixelFormat mtlAttFmt = cmdPool->getMTLPixelFormatFromVkFormat(vkAttFmt);
|
||||||
_rpsKey.attachmentMTLPixelFormats[kMVKAttachmentFormatDepthStencilIndex] = mtlAttFmt;
|
_rpsKey.attachmentMTLPixelFormats[kMVKAttachmentFormatDepthStencilIndex] = mtlAttFmt;
|
||||||
bool isClearingDepth = _isClearingDepth && mvkMTLPixelFormatIsDepthFormat(mtlAttFmt);
|
bool isClearingDepth = _isClearingDepth && mvkMTLPixelFormatIsDepthFormat(mtlAttFmt);
|
||||||
bool isClearingStencil = _isClearingStencil && mvkMTLPixelFormatIsStencilFormat(mtlAttFmt);
|
bool isClearingStencil = _isClearingStencil && mvkMTLPixelFormatIsStencilFormat(mtlAttFmt);
|
||||||
|
@ -155,7 +155,7 @@ id<MTLTexture> MVKBufferView::getMTLTexture() {
|
|||||||
MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
|
MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
|
||||||
_buffer = (MVKBuffer*)pCreateInfo->buffer;
|
_buffer = (MVKBuffer*)pCreateInfo->buffer;
|
||||||
_mtlBufferOffset = _buffer->getMTLBufferOffset() + pCreateInfo->offset;
|
_mtlBufferOffset = _buffer->getMTLBufferOffset() + pCreateInfo->offset;
|
||||||
_mtlPixelFormat = mtlPixelFormatFromVkFormat(pCreateInfo->format);
|
_mtlPixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->format);
|
||||||
VkExtent2D fmtBlockSize = mvkVkFormatBlockTexelSize(pCreateInfo->format); // Pixel size of format
|
VkExtent2D fmtBlockSize = mvkVkFormatBlockTexelSize(pCreateInfo->format); // Pixel size of format
|
||||||
size_t bytesPerBlock = mvkVkFormatBytesPerBlock(pCreateInfo->format);
|
size_t bytesPerBlock = mvkVkFormatBytesPerBlock(pCreateInfo->format);
|
||||||
_mtlTexture = nil;
|
_mtlTexture = nil;
|
||||||
@ -166,9 +166,10 @@ MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pC
|
|||||||
size_t blockCount = byteCount / bytesPerBlock;
|
size_t blockCount = byteCount / bytesPerBlock;
|
||||||
|
|
||||||
// But Metal requires the texture to be a 2D texture. Determine the number of 2D rows we need and their width.
|
// But Metal requires the texture to be a 2D texture. Determine the number of 2D rows we need and their width.
|
||||||
|
// Multiple rows will automatically align with PoT max texture dimension, but need to align upwards if less than full single row.
|
||||||
size_t maxBlocksPerRow = _device->_pMetalFeatures->maxTextureDimension / fmtBlockSize.width;
|
size_t maxBlocksPerRow = _device->_pMetalFeatures->maxTextureDimension / fmtBlockSize.width;
|
||||||
size_t blocksPerRow = min(blockCount, maxBlocksPerRow);
|
size_t blocksPerRow = min(blockCount, maxBlocksPerRow);
|
||||||
_mtlBytesPerRow = mvkAlignByteOffset(blocksPerRow * bytesPerBlock, _device->_pProperties->limits.minTexelBufferOffsetAlignment);
|
_mtlBytesPerRow = mvkAlignByteOffset(blocksPerRow * bytesPerBlock, _device->getVkFormatTexelBufferAlignment(pCreateInfo->format));
|
||||||
|
|
||||||
size_t rowCount = blockCount / blocksPerRow;
|
size_t rowCount = blockCount / blocksPerRow;
|
||||||
if (blockCount % blocksPerRow) { rowCount++; }
|
if (blockCount % blocksPerRow) { rowCount++; }
|
||||||
|
@ -502,7 +502,10 @@ public:
|
|||||||
*
|
*
|
||||||
* All other pixel formats are returned unchanged.
|
* All other pixel formats are returned unchanged.
|
||||||
*/
|
*/
|
||||||
MTLPixelFormat mtlPixelFormatFromVkFormat(VkFormat vkFormat);
|
MTLPixelFormat getMTLPixelFormatFromVkFormat(VkFormat vkFormat);
|
||||||
|
|
||||||
|
/** Returns the memory alignment required for the format when used in a texel buffer. */
|
||||||
|
VkDeviceSize getVkFormatTexelBufferAlignment(VkFormat format);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MTLBuffer used to hold occlusion query results,
|
* Returns the MTLBuffer used to hold occlusion query results,
|
||||||
@ -608,12 +611,12 @@ public:
|
|||||||
* Returns the Metal MTLPixelFormat corresponding to the specified Vulkan VkFormat,
|
* Returns the Metal MTLPixelFormat corresponding to the specified Vulkan VkFormat,
|
||||||
* or returns MTLPixelFormatInvalid if no corresponding MTLPixelFormat exists.
|
* or returns MTLPixelFormatInvalid if no corresponding MTLPixelFormat exists.
|
||||||
*
|
*
|
||||||
* This function delegates to the MVKDevice::mtlPixelFormatFromVkFormat() function.
|
* This function delegates to the MVKDevice::getMTLPixelFormatFromVkFormat() function.
|
||||||
* See the notes for that function for more information about how MTLPixelFormats
|
* See the notes for that function for more information about how MTLPixelFormats
|
||||||
* are managed for each platform device.
|
* are managed for each platform device.
|
||||||
*/
|
*/
|
||||||
inline MTLPixelFormat mtlPixelFormatFromVkFormat(VkFormat vkFormat) {
|
inline MTLPixelFormat getMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
|
||||||
return _device->mtlPixelFormatFromVkFormat(vkFormat);
|
return _device->getMTLPixelFormatFromVkFormat(vkFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs an instance for the specified device. */
|
/** Constructs an instance for the specified device. */
|
||||||
|
@ -1635,7 +1635,7 @@ uint32_t MVKDevice::getMetalBufferIndexForVertexAttributeBinding(uint32_t bindin
|
|||||||
return ((_pMetalFeatures->maxPerStageBufferCount - 1) - binding);
|
return ((_pMetalFeatures->maxPerStageBufferCount - 1) - binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLPixelFormat MVKDevice::mtlPixelFormatFromVkFormat(VkFormat vkFormat) {
|
MTLPixelFormat MVKDevice::getMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
|
||||||
MTLPixelFormat mtlPixFmt = mvkMTLPixelFormatFromVkFormat(vkFormat);
|
MTLPixelFormat mtlPixFmt = mvkMTLPixelFormatFromVkFormat(vkFormat);
|
||||||
#if MVK_MACOS
|
#if MVK_MACOS
|
||||||
if (mtlPixFmt == MTLPixelFormatDepth24Unorm_Stencil8 &&
|
if (mtlPixFmt == MTLPixelFormatDepth24Unorm_Stencil8 &&
|
||||||
@ -1646,6 +1646,11 @@ MTLPixelFormat MVKDevice::mtlPixelFormatFromVkFormat(VkFormat vkFormat) {
|
|||||||
return mtlPixFmt;
|
return mtlPixFmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkDeviceSize MVKDevice::getVkFormatTexelBufferAlignment(VkFormat format) {
|
||||||
|
VkDeviceSize deviceAlignment = mvkMTLPixelFormatLinearTextureAlignment(getMTLPixelFormatFromVkFormat(format), getMTLDevice());
|
||||||
|
return deviceAlignment ? deviceAlignment : _pProperties->limits.minTexelBufferOffsetAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
id<MTLBuffer> MVKDevice::getGlobalVisibilityResultMTLBuffer() {
|
id<MTLBuffer> MVKDevice::getGlobalVisibilityResultMTLBuffer() {
|
||||||
lock_guard<mutex> lock(_vizLock);
|
lock_guard<mutex> lock(_vizLock);
|
||||||
return _globalVisibilityResultMTLBuffer;
|
return _globalVisibilityResultMTLBuffer;
|
||||||
|
@ -480,8 +480,6 @@ void MVKImage::getMTLTextureContent(MVKImageSubresource& subresource,
|
|||||||
|
|
||||||
MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MVKResource(device) {
|
MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MVKResource(device) {
|
||||||
|
|
||||||
_byteAlignment = _device->_pProperties->limits.minTexelBufferOffsetAlignment;
|
|
||||||
|
|
||||||
if (pCreateInfo->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) {
|
if (pCreateInfo->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) {
|
||||||
mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal may not allow uncompressed views of compressed images.");
|
mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal may not allow uncompressed views of compressed images.");
|
||||||
}
|
}
|
||||||
@ -508,7 +506,7 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
|||||||
|
|
||||||
_mtlTexture = nil;
|
_mtlTexture = nil;
|
||||||
_ioSurface = nil;
|
_ioSurface = nil;
|
||||||
_mtlPixelFormat = mtlPixelFormatFromVkFormat(pCreateInfo->format);
|
_mtlPixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->format);
|
||||||
_mtlTextureType = mvkMTLTextureTypeFromVkImageType(pCreateInfo->imageType,
|
_mtlTextureType = mvkMTLTextureTypeFromVkImageType(pCreateInfo->imageType,
|
||||||
_arrayLayers,
|
_arrayLayers,
|
||||||
(pCreateInfo->samples > 1));
|
(pCreateInfo->samples > 1));
|
||||||
@ -529,6 +527,8 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
|||||||
_isLinear = validateLinear(pCreateInfo);
|
_isLinear = validateLinear(pCreateInfo);
|
||||||
_usesTexelBuffer = false;
|
_usesTexelBuffer = false;
|
||||||
|
|
||||||
|
_byteAlignment = _isLinear ? _device->getVkFormatTexelBufferAlignment(pCreateInfo->format) : mvkVkFormatBytesPerBlock(pCreateInfo->format);
|
||||||
|
|
||||||
// Calc _byteCount after _mtlTexture & _byteAlignment
|
// Calc _byteCount after _mtlTexture & _byteAlignment
|
||||||
for (uint32_t mipLvl = 0; mipLvl < _mipLevels; mipLvl++) {
|
for (uint32_t mipLvl = 0; mipLvl < _mipLevels; mipLvl++) {
|
||||||
_byteCount += getBytesPerLayer(mipLvl) * _extent.depth * _arrayLayers;
|
_byteCount += getBytesPerLayer(mipLvl) * _extent.depth * _arrayLayers;
|
||||||
@ -754,7 +754,7 @@ void MVKImageView::validateImageViewConfig(const VkImageViewCreateInfo* pCreateI
|
|||||||
// alignments of existing MTLPixelFormats of the same structure. If swizzling is not possible for a
|
// alignments of existing MTLPixelFormats of the same structure. If swizzling is not possible for a
|
||||||
// particular combination of format and swizzle spec, the original MTLPixelFormat is returned.
|
// particular combination of format and swizzle spec, the original MTLPixelFormat is returned.
|
||||||
MTLPixelFormat MVKImageView::getSwizzledMTLPixelFormat(VkFormat format, VkComponentMapping components, bool& useSwizzle) {
|
MTLPixelFormat MVKImageView::getSwizzledMTLPixelFormat(VkFormat format, VkComponentMapping components, bool& useSwizzle) {
|
||||||
MTLPixelFormat mtlPF = mtlPixelFormatFromVkFormat(format);
|
MTLPixelFormat mtlPF = getMTLPixelFormatFromVkFormat(format);
|
||||||
|
|
||||||
useSwizzle = false;
|
useSwizzle = false;
|
||||||
switch (mtlPF) {
|
switch (mtlPF) {
|
||||||
|
@ -412,7 +412,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
|
|||||||
const VkPipelineColorBlendAttachmentState* pCA = &pCreateInfo->pColorBlendState->pAttachments[caIdx];
|
const VkPipelineColorBlendAttachmentState* pCA = &pCreateInfo->pColorBlendState->pAttachments[caIdx];
|
||||||
|
|
||||||
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];
|
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];
|
||||||
colorDesc.pixelFormat = mtlPixelFormatFromVkFormat(mvkRenderSubpass->getColorAttachmentFormat(caIdx));
|
colorDesc.pixelFormat = getMTLPixelFormatFromVkFormat(mvkRenderSubpass->getColorAttachmentFormat(caIdx));
|
||||||
colorDesc.writeMask = mvkMTLColorWriteMaskFromVkChannelFlags(pCA->colorWriteMask);
|
colorDesc.writeMask = mvkMTLColorWriteMaskFromVkChannelFlags(pCA->colorWriteMask);
|
||||||
// Don't set the blend state if we're not using this attachment.
|
// Don't set the blend state if we're not using this attachment.
|
||||||
// The pixel format will be MTLPixelFormatInvalid in that case, and
|
// The pixel format will be MTLPixelFormatInvalid in that case, and
|
||||||
@ -431,7 +431,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Depth & stencil attachments
|
// Depth & stencil attachments
|
||||||
MTLPixelFormat mtlDSFormat = mtlPixelFormatFromVkFormat(mvkRenderSubpass->getDepthStencilFormat());
|
MTLPixelFormat mtlDSFormat = getMTLPixelFormatFromVkFormat(mvkRenderSubpass->getDepthStencilFormat());
|
||||||
if (mvkMTLPixelFormatIsDepthFormat(mtlDSFormat)) { plDesc.depthAttachmentPixelFormat = mtlDSFormat; }
|
if (mvkMTLPixelFormatIsDepthFormat(mtlDSFormat)) { plDesc.depthAttachmentPixelFormat = mtlDSFormat; }
|
||||||
if (mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) { plDesc.stencilAttachmentPixelFormat = mtlDSFormat; }
|
if (mvkMTLPixelFormatIsStencilFormat(mtlDSFormat)) { plDesc.stencilAttachmentPixelFormat = mtlDSFormat; }
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ void MVKRenderSubpass::populateClearAttachments(vector<VkClearAttachment>& clear
|
|||||||
cAtt.colorAttachment = 0;
|
cAtt.colorAttachment = 0;
|
||||||
cAtt.clearValue = clearValues[attIdx];
|
cAtt.clearValue = clearValues[attIdx];
|
||||||
|
|
||||||
MTLPixelFormat mtlDSFmt = _renderPass->mtlPixelFormatFromVkFormat(getDepthStencilFormat());
|
MTLPixelFormat mtlDSFmt = _renderPass->getMTLPixelFormatFromVkFormat(getDepthStencilFormat());
|
||||||
if (mvkMTLPixelFormatIsDepthFormat(mtlDSFmt)) { cAtt.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; }
|
if (mvkMTLPixelFormatIsDepthFormat(mtlDSFmt)) { cAtt.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; }
|
||||||
if (mvkMTLPixelFormatIsStencilFormat(mtlDSFmt)) { cAtt.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; }
|
if (mvkMTLPixelFormatIsStencilFormat(mtlDSFmt)) { cAtt.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; }
|
||||||
if (cAtt.aspectMask) { clearAtts.push_back(cAtt); }
|
if (cAtt.aspectMask) { clearAtts.push_back(cAtt); }
|
||||||
|
@ -192,7 +192,7 @@ void MVKSwapchain::initCAMetalLayer(const VkSwapchainCreateInfoKHR* pCreateInfo)
|
|||||||
MVKSurface* mvkSrfc = (MVKSurface*)pCreateInfo->surface;
|
MVKSurface* mvkSrfc = (MVKSurface*)pCreateInfo->surface;
|
||||||
_mtlLayer = mvkSrfc->getCAMetalLayer();
|
_mtlLayer = mvkSrfc->getCAMetalLayer();
|
||||||
_mtlLayer.device = getMTLDevice();
|
_mtlLayer.device = getMTLDevice();
|
||||||
_mtlLayer.pixelFormat = mtlPixelFormatFromVkFormat(pCreateInfo->imageFormat);
|
_mtlLayer.pixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->imageFormat);
|
||||||
_mtlLayer.displaySyncEnabledMVK = (pCreateInfo->presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR);
|
_mtlLayer.displaySyncEnabledMVK = (pCreateInfo->presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR);
|
||||||
_mtlLayer.magnificationFilter = _device->_pMVKConfig->swapchainMagFilterUseNearest ? kCAFilterNearest : kCAFilterLinear;
|
_mtlLayer.magnificationFilter = _device->_pMVKConfig->swapchainMagFilterUseNearest ? kCAFilterNearest : kCAFilterLinear;
|
||||||
_mtlLayer.framebufferOnly = !mvkIsAnyFlagEnabled(pCreateInfo->imageUsage, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
_mtlLayer.framebufferOnly = !mvkIsAnyFlagEnabled(pCreateInfo->imageUsage, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||||
|
@ -57,6 +57,15 @@ double mvkGetTimestampPeriod();
|
|||||||
*/
|
*/
|
||||||
double mvkGetElapsedMilliseconds(uint64_t startTimestamp = 0, uint64_t endTimestamp = 0);
|
double mvkGetElapsedMilliseconds(uint64_t startTimestamp = 0, uint64_t endTimestamp = 0);
|
||||||
|
|
||||||
|
/** Ensures the block is executed on the main thread. */
|
||||||
|
inline void mvkDispatchToMainAndWait(dispatch_block_t block) {
|
||||||
|
if (NSThread.isMainThread) {
|
||||||
|
block();
|
||||||
|
} else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MTLDevice
|
#pragma mark MTLDevice
|
||||||
@ -67,11 +76,9 @@ uint64_t mvkRecommendedMaxWorkingSetSize(id<MTLDevice> mtlDevice);
|
|||||||
/** Populate the propertes with info about the GPU represented by the MTLDevice. */
|
/** Populate the propertes with info about the GPU represented by the MTLDevice. */
|
||||||
void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id<MTLDevice> mtlDevice);
|
void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id<MTLDevice> mtlDevice);
|
||||||
|
|
||||||
/** Ensures the block is executed on the main thread. */
|
/**
|
||||||
inline void mvkDispatchToMainAndWait(dispatch_block_t block) {
|
* If the MTLDevice defines a texture memory alignment for the format, it is retrieved from
|
||||||
if (NSThread.isMainThread) {
|
* the MTLDevice and returned, or returns zero if the MTLDevice does not define an alignment.
|
||||||
block();
|
* The format must support linear texture memory (must not be depth, stencil, or compressed).
|
||||||
} else {
|
*/
|
||||||
dispatch_sync(dispatch_get_main_queue(), block);
|
VkDeviceSize mvkMTLPixelFormatLinearTextureAlignment(MTLPixelFormat mtlPixelFormat, id<MTLDevice> mtlDevice);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -188,4 +188,11 @@ void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id<MTLDevice> mtlD
|
|||||||
}
|
}
|
||||||
#endif //MVK_IOS
|
#endif //MVK_IOS
|
||||||
|
|
||||||
|
VkDeviceSize mvkMTLPixelFormatLinearTextureAlignment(MTLPixelFormat mtlPixelFormat,
|
||||||
|
id<MTLDevice> mtlDevice) {
|
||||||
|
if ([mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)]) {
|
||||||
|
return [mtlDevice minimumLinearTextureAlignmentForPixelFormat: mtlPixelFormat];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user