6#include <QGuiApplication>
10#include <QTemporaryFile>
13#include <QOperatingSystemVersion>
15#include <QtCore/private/qcore_mac_p.h>
20#include <UIKit/UIKit.h>
23#include <Metal/Metal.h>
24#include <QuartzCore/CAMetalLayer.h>
39#if __has_feature(objc_arc)
40#error ARC not supported
164 const
QColor &colorClearValue,
403 return vertexOrIndexCount *
instanceCount *
sizeof(float) * 60;
412 return patchCount *
sizeof(float) * 128;
446 MTLRenderPassDescriptor *
rp =
nullptr;
451 bool liveResizeObserverSet =
false;
465 if (importDevice->dev) {
471 qWarning(
"No MTLDevice given, cannot import");
485 return (
v + byteAlign - 1) & ~(byteAlign - 1);
501 if (@available(macOS 11.0,
iOS 14.0, *)) {
503 MTLBinaryArchiveDescriptor *binArchDesc = [MTLBinaryArchiveDescriptor
new];
504 binArchDesc.url = sourceFileUrl;
506 binArch = [
dev newBinaryArchiveWithDescriptor: binArchDesc
error: &err];
509 const QString msg = QString::fromNSString(err.localizedDescription);
526 d->
dev = MTLCreateSystemDefaultDevice();
544 if (@available(macOS 10.15, *)) {
545 const MTLDeviceLocation deviceLocation = [
d->
dev location];
546 switch (deviceLocation) {
547 case MTLDeviceLocationBuiltIn:
550 case MTLDeviceLocationSlot:
553 case MTLDeviceLocationExternal:
571 d->
captureMgr = [MTLCaptureManager sharedCaptureManager];
579#if defined(Q_OS_MACOS)
580 caps.maxTextureSize = 16384;
581 caps.baseVertexAndInstance =
true;
582 if (@available(macOS 10.15, *))
583 caps.isAppleGPU = [
d->
dev supportsFamily:MTLGPUFamilyApple7];
584 caps.maxThreadGroupSize = 1024;
585 caps.multiView =
true;
586#elif defined(Q_OS_TVOS)
587 if ([
d->
dev supportsFeatureSet: MTLFeatureSet(30003)])
588 caps.maxTextureSize = 16384;
590 caps.maxTextureSize = 8192;
591 caps.baseVertexAndInstance =
false;
592 caps.isAppleGPU =
true;
593#elif defined(Q_OS_IOS)
595 if ([
d->
dev supportsFeatureSet: MTLFeatureSet(16)]
596 || [
d->
dev supportsFeatureSet: MTLFeatureSet(11)]
597 || [
d->
dev supportsFeatureSet: MTLFeatureSet(4)])
599 caps.maxTextureSize = 16384;
600 caps.baseVertexAndInstance =
true;
601 }
else if ([
d->
dev supportsFeatureSet: MTLFeatureSet(3)]
602 || [
d->
dev supportsFeatureSet: MTLFeatureSet(2)])
604 caps.maxTextureSize = 8192;
605 caps.baseVertexAndInstance =
false;
607 caps.maxTextureSize = 4096;
608 caps.baseVertexAndInstance =
false;
610 caps.isAppleGPU =
true;
611 if (@available(
iOS 13, *)) {
612 if ([
d->
dev supportsFamily: MTLGPUFamilyApple4])
613 caps.maxThreadGroupSize = 1024;
614 if ([
d->
dev supportsFamily: MTLGPUFamilyApple5])
615 caps.multiView =
true;
619 caps.supportedSampleCounts = { 1 };
620 for (
int sampleCount : { 2, 4, 8 }) {
621 if ([
d->
dev supportsTextureSampleCount: sampleCount])
622 caps.supportedSampleCounts.append(sampleCount);
646 if (@available(macOS 11.0,
iOS 14.0, *)) {
662 return caps.supportedSampleCounts;
668 const int s =
qBound(1, sampleCount, 64);
670 qWarning(
"Attempted to set unsupported sample count %d", sampleCount);
710 if (
m.isIdentity()) {
713 0.0f, 1.0f, 0.0f, 0.0f,
714 0.0f, 0.0f, 0.5f, 0.5f,
715 0.0f, 0.0f, 0.0f, 1.0f);
724 bool supportsFamilyMac2 =
false;
725 bool supportsFamilyApple3 =
false;
728 supportsFamilyMac2 =
true;
730 supportsFamilyApple3 =
true;
732 supportsFamilyApple3 =
true;
739 if (!supportsFamilyApple3) {
746 if (!supportsFamilyMac2)
787 return caps.baseVertexAndInstance;
789 return caps.baseVertexAndInstance;
808 if (@available(macOS 11.0,
iOS 14.0, *))
842 return caps.multiView;
855 return caps.maxTextureSize;
871 return caps.maxThreadGroupSize;
936 if (@available(macOS 11.0,
iOS 14.0, *)) {
942 qCDebug(QRHI_LOG_INFO,
"pipelineCacheData: Failed to create temporary file for Metal");
950 if (![
d->binArch serializeToURL:
url error: &err]) {
951 const QString msg = QString::fromNSString(err.localizedDescription);
953 qCDebug(QRHI_LOG_INFO,
"Failed to serialize MTLBinaryArchive: %s",
qPrintable(msg));
959 qCDebug(QRHI_LOG_INFO,
"pipelineCacheData: Failed to reopen temporary file");
979 header.driver[driverStrLen] =
'\0';
994 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (header incomplete)");
1003 if (
header.rhiId != rhiId) {
1004 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
1010 if (
header.arch != arch) {
1011 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Architecture does not match (%u, %u)",
1017 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: OS version does not match (%u.%u, %u.%u)",
1024 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Metal device name does not match");
1029 qCDebug(QRHI_LOG_INFO,
"setPipelineCacheData: Invalid blob size (data incomplete)");
1033 if (@available(macOS 11.0,
iOS 14.0, *)) {
1034 const char *
p =
data.constData() + dataOffset;
1038 qCDebug(QRHI_LOG_INFO,
"pipelineCacheData: Failed to create temporary file for Metal");
1047 qCDebug(QRHI_LOG_INFO,
"Created MTLBinaryArchive with initial data of %u bytes",
header.dataSize);
1052 int sampleCount, QRhiRenderBuffer::Flags
flags,
1059 const QSize &pixelSize,
int depth,
int arraySize,
1060 int sampleCount, QRhiTexture::Flags
flags)
1069 return new QMetalSampler(
this, magFilter, minFilter, mipmapMode, u,
v,
w);
1073 QRhiTextureRenderTarget::Flags
flags)
1127 withRange: NSMakeRange(bufferBatch.startBinding,
NSUInteger(bufferBatch.resources.count()))];
1132 withRange: NSMakeRange(bufferBatch.startBinding,
NSUInteger(bufferBatch.resources.count()))];
1137 withRange: NSMakeRange(bufferBatch.startBinding,
NSUInteger(bufferBatch.resources.count()))];
1156 withRange: NSMakeRange(textureBatch.startBinding,
NSUInteger(textureBatch.resources.count()))];
1160 withRange: NSMakeRange(textureBatch.startBinding,
NSUInteger(textureBatch.resources.count()))];
1164 withRange: NSMakeRange(textureBatch.startBinding,
NSUInteger(textureBatch.resources.count()))];
1180 switch (encoderStage) {
1183 withRange: NSMakeRange(samplerBatch.startBinding,
NSUInteger(samplerBatch.resources.count()))];
1187 withRange: NSMakeRange(samplerBatch.startBinding,
NSUInteger(samplerBatch.resources.count()))];
1191 withRange: NSMakeRange(samplerBatch.startBinding,
NSUInteger(samplerBatch.resources.count()))];
1250 int dynamicOffsetCount,
1252 bool offsetOnlyChange,
1265 for (
int i = 0;
i < dynamicOffsetCount; ++
i) {
1267 if (dynOfs.first ==
b->binding) {
1276 if (nativeBinding >= 0)
1287 for (
int elem = 0; elem <
data->count; ++elem) {
1300 if (textureBinding >= 0 && texD)
1301 bindingData.
res[stage].
textures.append({ textureBinding + elem, texD->
d->
tex });
1302 if (samplerBinding >= 0)
1319 if (nativeBinding >= 0)
1320 bindingData.
res[stage].
textures.append({ nativeBinding,
t });
1335 if (nativeBinding >= 0)
1360 return a.nativeBinding < b.nativeBinding;
1385 if (offsetOnlyChange)
1389 return a.nativeBinding < b.nativeBinding;
1393 return a.nativeBinding < b.nativeBinding;
1481 workBuf->lastActiveFrameSlot = -1;
1485 workBuf->lastActiveFrameSlot = -1;
1493 int dynamicOffsetCount,
1509 bool hasSlottedResourceInSrb =
false;
1510 bool hasDynamicOffsetInSrb =
false;
1511 bool resNeedsRebind =
false;
1530 hasSlottedResourceInSrb =
true;
1531 if (
b->u.ubuf.hasDynamicOffset)
1532 hasDynamicOffsetInSrb =
true;
1534 resNeedsRebind =
true;
1548 resNeedsRebind =
true;
1550 for (
int elem = 0; elem <
data->count; ++elem) {
1556 const quint64 samplerId = samplerD ? samplerD->
m_id : 0;
1563 resNeedsRebind =
true;
1582 resNeedsRebind =
true;
1596 if (needsBufferSizeBuffer) {
1597 for (
int i = 0;
i < 6; ++
i) {
1600 if (
b->stage.testFlag(stage)) {
1601 storageBufferSizes[stage][
b->binding] =
b->u.sbuf.maybeSize ?
b->u.sbuf.maybeSize : bufD->
size();
1608 resNeedsRebind =
true;
1621 if (needsBufferSizeBuffer) {
1679 int maxNativeBinding = 0;
1681 maxNativeBinding =
qMax(maxNativeBinding,
shader.first->nativeResourceBindingMap[block.binding].first);
1683 const int size = (maxNativeBinding + 1) *
sizeof(
int);
1699 const int index =
shader.first->nativeResourceBindingMap[block.binding].first;
1705 if (bufferSizeBufferData.
size() <=
index)
1709 bufferSizeBufferData[
index] =
sizes[block.binding];
1714 data.assign(
reinterpret_cast<const char *
>(bufferSizeBufferData.
constData()),
size);
1729 resNeedsRebind =
true;
1735 if (hasDynamicOffsetInSrb || resNeedsRebind || srbChanged || srbRebuilt) {
1760 const bool offsetOnlyChange = hasDynamicOffsetInSrb && !resNeedsRebind && !srbChanged && !srbRebuilt;
1774 for (
int i = 0;
i < bindingCount; ++
i) {
1779 buffers.feed(startBinding +
i, mtlbuf);
1780 offsets.feed(startBinding +
i, bindings[
i].second);
1792 const int firstVertexBinding = srbD->
maxBinding + 1;
1802 for (
int i = 0, ie =
buffers.batches.count();
i != ie; ++
i) {
1803 const auto &bufferBatch(
buffers.batches[
i]);
1804 const auto &offsetBatch(
offsets.batches[
i]);
1806 bufferBatch.resources.constData()
1807 offsets: offsetBatch.resources.constData()
1808 withRange: NSMakeRange(
uint(firstVertexBinding) + bufferBatch.startBinding,
NSUInteger(bufferBatch.resources.count()))];
1832 if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize,
viewport.viewport(), &
x, &
y, &
w, &
h))
1836 vp.originX = double(
x);
1837 vp.originY = double(
y);
1838 vp.width = double(
w);
1839 vp.height = double(
h);
1840 vp.znear = double(
viewport.minDepth());
1841 vp.zfar = double(
viewport.maxDepth());
1848 qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize,
viewport.viewport(), &
x, &
y, &
w, &
h);
1866 if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.
scissor(), &
x, &
y, &
w, &
h))
1937 MTLLoadAction oldDepthLoad;
1938 MTLLoadAction oldStencilLoad;
1945 if (cbD->
d->
currentPassRpDesc.stencilAttachment.storeAction != MTLStoreActionDontCare)
1972 const quint32 vertexOrIndexCount = indexed ?
args.drawIndexed.indexCount :
args.draw.vertexCount;
1994 [computeEncoder setComputePipelineState: computePipelineState];
2007 if (outputBufferBinding >= 0) {
2012 [computeEncoder setBuffer: vertOutBuf->
d->
buf[0]
offset: 0 atIndex: outputBufferBinding];
2015 if (indexBufferBinding >= 0)
2016 [computeEncoder setBuffer: (
id<MTLBuffer>)
args.drawIndexed.indexBuffer
offset: 0 atIndex: indexBufferBinding];
2021 [computeEncoder setBuffers: bufferBatch.resources.constData()
2022 offsets: offsetBatch.resources.constData()
2027 [computeEncoder setStageInRegion: MTLRegionMake2D(
args.drawIndexed.vertexOffset,
args.drawIndexed.firstInstance,
2028 args.drawIndexed.indexCount,
args.drawIndexed.instanceCount)];
2030 [computeEncoder setStageInRegion: MTLRegionMake2D(
args.draw.firstVertex,
args.draw.firstInstance,
2031 args.draw.vertexCount,
args.draw.instanceCount)];
2034 [computeEncoder dispatchThreads: MTLSizeMake(vertexOrIndexCount,
instanceCount, 1)
2035 threadsPerThreadgroup: MTLSizeMake(computePipelineState.threadExecutionWidth, 1, 1)];
2042 [computeEncoder setComputePipelineState: computePipelineState];
2055 if (outputBufferBinding >= 0) {
2060 [computeEncoder setBuffer: tescOutBuf->
d->
buf[0]
offset: 0 atIndex: outputBufferBinding];
2063 if (patchOutputBufferBinding >= 0) {
2066 if (!tescPatchOutBuf)
2068 [computeEncoder setBuffer: tescPatchOutBuf->
d->
buf[0]
offset: 0 atIndex: patchOutputBufferBinding];
2071 if (tessFactorBufferBinding >= 0) {
2072 tescFactorBuf = extraBufMgr.
acquireWorkBuffer(
this, patchCount *
sizeof(MTLQuadTessellationFactorsHalf));
2073 [computeEncoder setBuffer: tescFactorBuf->
d->
buf[0]
offset: 0 atIndex: tessFactorBufferBinding];
2076 if (paramsBufferBinding >= 0) {
2085 params.patchCount = patchCount;
2087 char *
p =
reinterpret_cast<char *
>([paramsBuf
contents]);
2089 [computeEncoder setBuffer: paramsBuf
offset: 0 atIndex: paramsBufferBinding];
2092 if (vertOutBuf && inputBufferBinding >= 0)
2093 [computeEncoder setBuffer: vertOutBuf->
d->
buf[0]
offset: 0 atIndex: inputBufferBinding];
2095 int sgSize = int(computePipelineState.threadExecutionWidth);
2097 while (wgSize >
caps.maxThreadGroupSize) {
2102 threadsPerThreadgroup: MTLSizeMake(wgSize, 1, 1)];
2129 if (outputBufferBinding >= 0 && tescOutBuf)
2130 [renderEncoder setVertexBuffer: tescOutBuf->
d->
buf[0]
offset: 0 atIndex: outputBufferBinding];
2132 if (patchOutputBufferBinding >= 0 && tescPatchOutBuf)
2133 [renderEncoder setVertexBuffer: tescPatchOutBuf->
d->
buf[0]
offset: 0 atIndex: patchOutputBufferBinding];
2135 if (tessFactorBufferBinding >= 0 && tescFactorBuf) {
2136 [renderEncoder setTessellationFactorBuffer: tescFactorBuf->
d->
buf[0]
offset: 0 instanceStride: 0];
2137 [renderEncoder setVertexBuffer: tescFactorBuf->
d->
buf[0]
offset: 0 atIndex: tessFactorBufferBinding];
2142 patchCount: patchCount
2143 patchIndexBuffer: nil
2144 patchIndexBufferOffset: 0
2154 if (multiViewCount <= 1)
2159 if (viewMaskBufBinding == -1) {
2160 qWarning(
"No extra buffer for multiview in the vertex shader; was it built with --view-count specified?");
2167 multiViewInfo.viewOffset = 0;
2168 multiViewInfo.viewCount =
quint32(multiViewCount);
2173 char *
p =
reinterpret_cast<char *
>([mtlbuf
contents]);
2174 memcpy(
p, &multiViewInfo,
sizeof(multiViewInfo));
2193 a.draw.vertexCount = vertexCount;
2195 a.draw.firstVertex = firstVertex;
2196 a.draw.firstInstance = firstInstance;
2203 if (
caps.baseVertexAndInstance) {
2231 a.drawIndexed.indexCount = indexCount;
2233 a.drawIndexed.firstIndex = firstIndex;
2234 a.drawIndexed.vertexOffset = vertexOffset;
2235 a.drawIndexed.firstInstance = firstInstance;
2236 a.drawIndexed.indexBuffer = mtlibuf;
2243 if (
caps.baseVertexAndInstance) {
2245 indexCount: indexCount
2247 indexBuffer: mtlibuf
2248 indexBufferOffset: indexOffset
2250 baseVertex: vertexOffset
2251 baseInstance: firstInstance];
2254 indexCount: indexCount
2256 indexBuffer: mtlibuf
2257 indexBufferOffset: indexOffset
2267 NSString *
str = [NSString stringWithUTF8String:
name.constData()];
2272 [cbD->
d->
cb pushDebugGroup:
str];
2284 [cbD->
d->
cb popDebugGroup];
2339 if (sc != swapChainD)
2351 if (swapChainD->
samples > 1) {
2381 swapChainD->
d->
lastGpuTime[thisFrameSlot] +=
cb.GPUEndTime -
cb.GPUStartTime;
2382 dispatch_semaphore_signal(swapChainD->
d->
sem[thisFrameSlot]);
2386 const bool presentsWithTransaction = swapChainD->
d->
layer.presentsWithTransaction;
2387 if (!presentsWithTransaction && needsPresent) {
2390 [swapChainD->
cbWrapper.
d->
cb presentDrawable: drawable];
2395 if (presentsWithTransaction && needsPresent) {
2451 [
cb waitUntilCompleted];
2484 sc->waitUntilCompleted(
i);
2490 [
cb waitUntilCompleted];
2511 const QColor &colorClearValue,
2515 MTLRenderPassDescriptor *rp = [MTLRenderPassDescriptor renderPassDescriptor];
2516 MTLClearColor
c = MTLClearColorMake(colorClearValue.
redF(), colorClearValue.
greenF(), colorClearValue.
blueF(),
2517 colorClearValue.
alphaF());
2520 rp.colorAttachments[
i].loadAction = MTLLoadActionClear;
2521 rp.colorAttachments[
i].storeAction = MTLStoreActionStore;
2522 rp.colorAttachments[
i].clearColor =
c;
2525 if (hasDepthStencil) {
2526 rp.depthAttachment.loadAction = MTLLoadActionClear;
2527 rp.depthAttachment.storeAction = MTLStoreActionDontCare;
2528 rp.stencilAttachment.loadAction = MTLLoadActionClear;
2529 rp.stencilAttachment.storeAction = MTLStoreActionDontCare;
2530 rp.depthAttachment.clearDepth = double(depthStencilClearValue.
depthClearValue());
2542 if (imageSizeBytes > 0)
2557 if (!
img.isNull()) {
2558 const qsizetype fullImageSizeBytes =
img.sizeInBytes();
2559 int w =
img.width();
2560 int h =
img.height();
2561 int bpl =
img.bytesPerLine();
2571 if (
img.depth() == 32) {
2572 memcpy(
reinterpret_cast<char *
>(mp) + *curOfs,
img.constBits(),
size_t(fullImageSizeBytes));
2573 srcOffset = sy * bpl + sx * 4;
2577 bpl =
img.bytesPerLine();
2578 Q_ASSERT(
img.sizeInBytes() <= fullImageSizeBytes);
2579 memcpy(
reinterpret_cast<char *
>(mp) + *curOfs,
img.constBits(),
size_t(
img.sizeInBytes()));
2582 memcpy(
reinterpret_cast<char *
>(mp) + *curOfs,
img.constBits(),
size_t(fullImageSizeBytes));
2586 sourceOffset:
NSUInteger(*curOfs + srcOffset)
2588 sourceBytesPerImage: 0
2590 toTexture: texD->
d->
tex
2594 options: MTLBlitOptionNone];
2599 const int subresw = subresSize.
width();
2600 const int subresh = subresSize.
height();
2616 if (dx +
w != subresw)
2618 if (dy +
h != subresh)
2621 memcpy(
reinterpret_cast<char *
>(mp) + *curOfs, rawData.
constData(),
size_t(rawData.
size()));
2625 sourceBytesPerRow: bpl
2626 sourceBytesPerImage: 0
2628 toTexture: texD->
d->
tex
2632 options: MTLBlitOptionNone];
2635 }
else if (!rawData.
isEmpty()) {
2637 const int subresw = subresSize.
width();
2638 const int subresh = subresSize.
height();
2654 memcpy(
reinterpret_cast<char *
>(mp) + *curOfs, rawData.
constData(),
size_t(rawData.
size()));
2658 sourceBytesPerRow: bpl
2659 sourceBytesPerImage: 0
2661 toTexture: texD->
d->
tex
2665 options: MTLBlitOptionNone];
2701 char *
p =
reinterpret_cast<char *
>([bufD->
d->
buf[idx]
contents]);
2703 u.result->data.resize(u.readSize);
2704 memcpy(u.result->data.data(),
p + u.offset,
size_t(u.readSize));
2706 if (u.result->completed)
2707 u.result->completed();
2711 readback.
buf = bufD->
d->
buf[idx];
2712 readback.
offset = u.offset;
2714 readback.
result = u.result;
2721 auto ensureBlit = [&blitEnc, cbD,
this] {
2723 blitEnc = [cbD->d->cb blitCommandEncoder];
2725 [blitEnc pushDebugGroup:
@"Texture upload/copy"];
2729 for (
int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
2734 for (
int layer = 0, maxLayer = u.subresDesc.count();
layer < maxLayer; ++
layer) {
2737 stagingSize += subresUploadByteSize(subresDesc);
2744 options: MTLResourceStorageModeShared];
2748 for (
int layer = 0, maxLayer = u.subresDesc.count();
layer < maxLayer; ++
layer) {
2751 enqueueSubresUpload(utexD, mp, blitEnc,
layer,
level, subresDesc, &curOfs);
2759 e.lastActiveFrameSlot = currentFrameSlot;
2760 e.stagingBuffer.buffer = utexD->
d->
stagingBuf[currentFrameSlot];
2762 d->releaseQueue.append(
e);
2769 const QPoint dp = u.desc.destinationTopLeft();
2770 const QSize mipSize =
q->sizeForMipLevel(u.desc.sourceLevel(), srcD->
m_pixelSize);
2771 const QSize copySize = u.desc.pixelSize().
isEmpty() ? mipSize : u.desc.pixelSize();
2772 const QPoint sp = u.desc.sourceTopLeft();
2775 [blitEnc copyFromTexture: srcD->
d->
tex
2780 toTexture: dstD->
d->tex
2781 destinationSlice:
NSUInteger(dstIs3D ? 0 : u.
desc.destinationLayer())
2789 readback.
desc = u.rb;
2790 readback.
result = u.result;
2799 qWarning(
"Multisample texture cannot be read back");
2816 src = colorAtt.resolveTex ? colorAtt.resolveTex : colorAtt.tex;
2822 readback.
buf = [
d->dev newBufferWithLength: readback.
bufSize options: MTLResourceStorageModeShared];
2825 [blitEnc copyFromTexture:
src
2828 sourceOrigin: MTLOriginMake(0, 0, is3D ? u.rb.
layer() : 0)
2830 toBuffer: readback.
buf
2831 destinationOffset: 0
2832 destinationBytesPerRow: bpl
2833 destinationBytesPerImage: 0
2834 options: MTLBlitOptionNone];
2836 d->activeTextureReadbacks.append(readback);
2840 [blitEnc generateMipmapsForTexture: utexD->
d->
tex];
2847 [blitEnc popDebugGroup];
2848 [blitEnc endEncoding];
2861 quint32 changeBegin = UINT32_MAX;
2864 memcpy(
static_cast<char *
>(
p) + u.offset, u.data.constData(),
size_t(u.data.size()));
2865 if (u.offset < changeBegin)
2866 changeBegin = u.offset;
2867 if (u.offset + u.data.size() > changeEnd)
2868 changeEnd = u.offset + u.data.size();
2871 if (changeBegin < UINT32_MAX && changeBegin < changeEnd && bufD->
d->managed)
2892 const QColor &colorClearValue,
2895 QRhiCommandBuffer::BeginPassFlags)
2900 if (resourceUpdates)
2910 if (color0.needsDrawableForTex || color0.needsDrawableForResolveTex) {
2922 if (color0.needsDrawableForTex) {
2924 color0.needsDrawableForTex =
false;
2926 color0.resolveTex = scTex;
2927 color0.needsDrawableForResolveTex =
false;
2936 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QMetalTexture, QMetalRenderBuffer>(rtTex->
description(), rtD->
currentResIdList))
2950 if (
it->texture()) {
2952 if (
it->multiViewCount() >= 2)
2954 }
else if (
it->renderBuffer()) {
2957 if (
it->resolveTexture())
2977 cbD->
d->
currentPassRpDesc.colorAttachments[
i].storeAction = MTLStoreActionMultisampleResolve;
3010 if (resourceUpdates)
3016 QRhiCommandBuffer::BeginPassFlags)
3021 if (resourceUpdates)
3037 if (resourceUpdates)
3097 if (forced ||
currentFrameSlot ==
e.lastActiveFrameSlot ||
e.lastActiveFrameSlot < 0) {
3115 [
e.graphicsPipeline.pipelineState
release];
3116 [
e.graphicsPipeline.depthStencilState
release];
3117 [
e.graphicsPipeline.tessVertexComputeState[0]
release];
3118 [
e.graphicsPipeline.tessVertexComputeState[1]
release];
3119 [
e.graphicsPipeline.tessVertexComputeState[2]
release];
3120 [
e.graphicsPipeline.tessTessControlComputeState
release];
3123 [
e.computePipeline.pipelineState
release];
3159 char *
p =
reinterpret_cast<char *
>([readback.
buf contents]);
3170 for (
auto f : completedCallbacks)
3198 e.buffer.buffers[
i] =
d->
buf[
i];
3205 rhiD->d->releaseQueue.append(
e);
3206 rhiD->unregisterResource(
this);
3216 qWarning(
"StorageBuffer cannot be combined with Dynamic");
3224 MTLResourceOptions opts = MTLResourceStorageModeShared;
3229 opts = MTLResourceStorageModeManaged;
3245 d->
buf[
i] = [rhiD->d->dev newBufferWithLength: roundedSize options: opts];
3251 d->
buf[
i].label = [NSString stringWithUTF8String:
name.constData()];
3259 rhiD->registerResource(
this);
3270 rhiD->executeBufferHostWritesForSlot(
this,
i);
3276 return { { &
d->
buf[0] }, 1 };
3289 const int slot = rhiD->currentFrameSlot;
3291 return static_cast<char *
>(
p);
3299 const int slot = rhiD->currentFrameSlot;
3314 return srgb ? MTLPixelFormatRGBA8Unorm_sRGB : MTLPixelFormatRGBA8Unorm;
3316 return srgb ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
3319 return MTLPixelFormatR8Unorm;
3321 return srgb ? MTLPixelFormatR8Unorm_sRGB : MTLPixelFormatR8Unorm;
3325 return MTLPixelFormatRG8Unorm;
3327 return srgb ? MTLPixelFormatRG8Unorm_sRGB : MTLPixelFormatRG8Unorm;
3330 return MTLPixelFormatR16Unorm;
3332 return MTLPixelFormatRG16Unorm;
3334 return MTLPixelFormatR8Unorm;
3337 return MTLPixelFormatRGBA16Float;
3339 return MTLPixelFormatRGBA32Float;
3341 return MTLPixelFormatR16Float;
3343 return MTLPixelFormatR32Float;
3346 return MTLPixelFormatRGB10A2Unorm;
3350 return MTLPixelFormatDepth16Unorm;
3352 return [
d->d->dev isDepth24Stencil8PixelFormatSupported] ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float;
3354 return [
d->d->dev isDepth24Stencil8PixelFormatSupported] ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
3357 return MTLPixelFormatDepth32Float;
3359 return MTLPixelFormatDepth32Float;
3361 return MTLPixelFormatDepth32Float_Stencil8;
3364 return MTLPixelFormatDepth32Float;
3368 return srgb ? MTLPixelFormatBC1_RGBA_sRGB : MTLPixelFormatBC1_RGBA;
3370 return srgb ? MTLPixelFormatBC2_RGBA_sRGB : MTLPixelFormatBC2_RGBA;
3372 return srgb ? MTLPixelFormatBC3_RGBA_sRGB : MTLPixelFormatBC3_RGBA;
3374 return MTLPixelFormatBC4_RUnorm;
3376 qWarning(
"QRhiMetal does not support BC5");
3377 return MTLPixelFormatInvalid;
3379 return MTLPixelFormatBC6H_RGBUfloat;
3381 return srgb ? MTLPixelFormatBC7_RGBAUnorm_sRGB : MTLPixelFormatBC7_RGBAUnorm;
3390 qWarning(
"QRhiMetal: BCx compression not supported on this platform");
3391 return MTLPixelFormatInvalid;
3396 return srgb ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
3398 return srgb ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1;
3400 return srgb ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8;
3403 return srgb ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR;
3405 return srgb ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR;
3407 return srgb ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR;
3409 return srgb ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR;
3411 return srgb ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR;
3413 return srgb ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR;
3415 return srgb ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR;
3417 return srgb ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR;
3419 return srgb ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR;
3421 return srgb ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR;
3423 return srgb ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR;
3425 return srgb ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR;
3427 return srgb ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR;
3429 return srgb ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
3432 if (
d->caps.isAppleGPU) {
3433 if (@available(macOS 11.0, *))
3434 return srgb ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
3436 qWarning(
"QRhiMetal: ETC2 compression not supported on this platform");
3437 return MTLPixelFormatInvalid;
3439 if (
d->caps.isAppleGPU) {
3440 if (@available(macOS 11.0, *))
3441 return srgb ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1;
3443 qWarning(
"QRhiMetal: ETC2 compression not supported on this platform");
3444 return MTLPixelFormatInvalid;
3446 if (
d->caps.isAppleGPU) {
3447 if (@available(macOS 11.0, *))
3448 return srgb ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8;
3450 qWarning(
"QRhiMetal: ETC2 compression not supported on this platform");
3451 return MTLPixelFormatInvalid;
3453 if (
d->caps.isAppleGPU) {
3454 if (@available(macOS 11.0, *))
3455 return srgb ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR;
3457 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3458 return MTLPixelFormatInvalid;
3460 if (
d->caps.isAppleGPU) {
3461 if (@available(macOS 11.0, *))
3462 return srgb ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR;
3464 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3465 return MTLPixelFormatInvalid;
3467 if (
d->caps.isAppleGPU) {
3468 if (@available(macOS 11.0, *))
3469 return srgb ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR;
3471 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3472 return MTLPixelFormatInvalid;
3474 if (
d->caps.isAppleGPU) {
3475 if (@available(macOS 11.0, *))
3476 return srgb ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR;
3478 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3479 return MTLPixelFormatInvalid;
3481 if (
d->caps.isAppleGPU) {
3482 if (@available(macOS 11.0, *))
3483 return srgb ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR;
3485 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3486 return MTLPixelFormatInvalid;
3488 if (
d->caps.isAppleGPU) {
3489 if (@available(macOS 11.0, *))
3490 return srgb ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR;
3492 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3493 return MTLPixelFormatInvalid;
3495 if (
d->caps.isAppleGPU) {
3496 if (@available(macOS 11.0, *))
3497 return srgb ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR;
3499 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3500 return MTLPixelFormatInvalid;
3502 if (
d->caps.isAppleGPU) {
3503 if (@available(macOS 11.0, *))
3504 return srgb ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR;
3506 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3507 return MTLPixelFormatInvalid;
3509 if (
d->caps.isAppleGPU) {
3510 if (@available(macOS 11.0, *))
3511 return srgb ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR;
3513 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3514 return MTLPixelFormatInvalid;
3516 if (
d->caps.isAppleGPU) {
3517 if (@available(macOS 11.0, *))
3518 return srgb ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR;
3520 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3521 return MTLPixelFormatInvalid;
3523 if (
d->caps.isAppleGPU) {
3524 if (@available(macOS 11.0, *))
3525 return srgb ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR;
3527 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3528 return MTLPixelFormatInvalid;
3530 if (
d->caps.isAppleGPU) {
3531 if (@available(macOS 11.0, *))
3532 return srgb ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR;
3534 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3535 return MTLPixelFormatInvalid;
3537 if (
d->caps.isAppleGPU) {
3538 if (@available(macOS 11.0, *))
3539 return srgb ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR;
3541 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3542 return MTLPixelFormatInvalid;
3544 if (
d->caps.isAppleGPU) {
3545 if (@available(macOS 11.0, *))
3546 return srgb ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
3548 qWarning(
"QRhiMetal: ASTC compression not supported on this platform");
3549 return MTLPixelFormatInvalid;
3554 return MTLPixelFormatInvalid;
3559 int sampleCount, QRhiRenderBuffer::Flags
flags,
3581 e.renderbuffer.texture =
d->
tex;
3586 rhiD->d->releaseQueue.append(
e);
3587 rhiD->unregisterResource(
this);
3602 MTLTextureDescriptor *
desc = [[MTLTextureDescriptor alloc]
init];
3603 desc.textureType =
samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
3608 desc.resourceOptions = MTLResourceStorageModePrivate;
3609 desc.usage = MTLTextureUsageRenderTarget;
3614 if (rhiD->caps.isAppleGPU) {
3615 if (@available(macOS 11.0, *)) {
3616 desc.storageMode = MTLStorageModeMemoryless;
3617 d->
format = MTLPixelFormatDepth32Float_Stencil8;
3622 desc.storageMode = MTLStorageModePrivate;
3623 d->
format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
3624 ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
3627 desc.storageMode = MTLStorageModeMemoryless;
3628 d->
format = MTLPixelFormatDepth32Float_Stencil8;
3633 desc.storageMode = MTLStorageModePrivate;
3637 d->
format = MTLPixelFormatRGBA8Unorm;
3645 d->
tex = [rhiD->d->dev newTextureWithDescriptor:
desc];
3653 rhiD->registerResource(
this);
3707 rhiD->d->releaseQueue.append(
e);
3708 rhiD->unregisterResource(
this);
3732 qWarning(
"Cubemap texture cannot be multisample");
3736 qWarning(
"3D texture cannot be multisample");
3740 qWarning(
"Multisample texture cannot have mipmaps");
3744 if (isCube && is3D) {
3745 qWarning(
"Texture cannot be both cube and 3D");
3748 if (isArray && is3D) {
3749 qWarning(
"Texture cannot be both array and 3D");
3753 qWarning(
"Texture cannot be both 1D and 3D");
3756 if (is1D && isCube) {
3757 qWarning(
"Texture cannot be both 1D and cube");
3761 qWarning(
"Texture cannot have a depth of %d when it is not 3D",
m_depth);
3774 *adjustedSize =
size;
3785 MTLTextureDescriptor *
desc = [[MTLTextureDescriptor alloc]
init];
3792 desc.textureType = MTLTextureTypeCube;
3794 desc.textureType = MTLTextureType3D;
3796 desc.textureType = isArray ? MTLTextureType1DArray : MTLTextureType1D;
3797 }
else if (isArray) {
3799 if (@available(
iOS 14, *)) {
3800 desc.textureType =
samples > 1 ? MTLTextureType2DMultisampleArray : MTLTextureType2DArray;
3802 desc.textureType = MTLTextureType2DArray;
3805 desc.textureType =
samples > 1 ? MTLTextureType2DMultisampleArray : MTLTextureType2DArray;
3808 desc.textureType =
samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
3819 desc.resourceOptions = MTLResourceStorageModePrivate;
3820 desc.storageMode = MTLStorageModePrivate;
3821 desc.usage = MTLTextureUsageShaderRead;
3823 desc.usage |= MTLTextureUsageRenderTarget;
3825 desc.usage |= MTLTextureUsageShaderWrite;
3828 d->
tex = [rhiD->d->dev newTextureWithDescriptor:
desc];
3838 rhiD->registerResource(
this);
3858 rhiD->registerResource(
this);
3873 const MTLTextureType
type = [
tex textureType];
3878 slices: NSMakeRange(0, isCube ? 6 : (isArray ?
qMax(0,
q->m_arraySize) : 1))];
3886 :
QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u,
v,
w),
3911 rhiD->d->releaseQueue.append(
e);
3912 rhiD->unregisterResource(
this);
3920 return MTLSamplerMinMagFilterNearest;
3922 return MTLSamplerMinMagFilterLinear;
3925 return MTLSamplerMinMagFilterNearest;
3933 return MTLSamplerMipFilterNotMipmapped;
3935 return MTLSamplerMipFilterNearest;
3937 return MTLSamplerMipFilterLinear;
3940 return MTLSamplerMipFilterNotMipmapped;
3948 return MTLSamplerAddressModeRepeat;
3950 return MTLSamplerAddressModeClampToEdge;
3952 return MTLSamplerAddressModeMirrorRepeat;
3955 return MTLSamplerAddressModeClampToEdge;
3963 return MTLCompareFunctionNever;
3965 return MTLCompareFunctionLess;
3967 return MTLCompareFunctionEqual;
3969 return MTLCompareFunctionLessEqual;
3971 return MTLCompareFunctionGreater;
3973 return MTLCompareFunctionNotEqual;
3975 return MTLCompareFunctionGreaterEqual;
3977 return MTLCompareFunctionAlways;
3980 return MTLCompareFunctionNever;
3989 MTLSamplerDescriptor *
desc = [[MTLSamplerDescriptor alloc]
init];
4004 rhiD->registerResource(
this);
4025 rhiD->unregisterResource(
this);
4077 rhiD->registerResource(rpD,
false);
4136 rhiD->unregisterResource(
this);
4146 for (
int i = 0;
i < colorAttachmentCount; ++
i) {
4161 rhiD->registerResource(rpD,
false);
4183 if (attIndex == 0) {
4190 if (attIndex == 0) {
4198 colorAtt.
slice = is3D ?
it->layer() : 0;
4208 if (hasDepthStencil) {
4233 QRhiRenderTargetAttachmentTracker::updateResIdList<QMetalTexture, QMetalRenderBuffer>(
m_desc, &
d->
currentResIdList);
4235 rhiD->registerResource(
this,
false);
4241 if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QMetalTexture, QMetalRenderBuffer>(
m_desc,
d->
currentResIdList))
4274 rhiD->unregisterResource(
this);
4283 if (!rhiD->sanityCheckShaderResourceBindings(
this))
4286 rhiD->updateLayoutDesc(
this);
4301 rhiD->registerResource(
this,
false);
4362 e.graphicsPipeline.pipelineState =
d->
ps;
4363 e.graphicsPipeline.depthStencilState =
d->
ds;
4373 rhiD->d->releaseQueue.append(
e);
4374 rhiD->unregisterResource(
this);
4382 return MTLVertexFormatFloat4;
4384 return MTLVertexFormatFloat3;
4386 return MTLVertexFormatFloat2;
4388 return MTLVertexFormatFloat;
4390 return MTLVertexFormatUChar4Normalized;
4392 return MTLVertexFormatUChar2Normalized;
4394 return MTLVertexFormatUCharNormalized;
4396 return MTLVertexFormatUInt4;
4398 return MTLVertexFormatUInt3;
4400 return MTLVertexFormatUInt2;
4402 return MTLVertexFormatUInt;
4404 return MTLVertexFormatInt4;
4406 return MTLVertexFormatInt3;
4408 return MTLVertexFormatInt2;
4410 return MTLVertexFormatInt;
4412 return MTLVertexFormatHalf4;
4414 return MTLVertexFormatHalf3;
4416 return MTLVertexFormatHalf2;
4418 return MTLVertexFormatHalf;
4421 return MTLVertexFormatFloat4;
4429 return MTLBlendFactorZero;
4431 return MTLBlendFactorOne;
4433 return MTLBlendFactorSourceColor;
4435 return MTLBlendFactorOneMinusSourceColor;
4437 return MTLBlendFactorDestinationColor;
4439 return MTLBlendFactorOneMinusDestinationColor;
4441 return MTLBlendFactorSourceAlpha;
4443 return MTLBlendFactorOneMinusSourceAlpha;
4445 return MTLBlendFactorDestinationAlpha;
4447 return MTLBlendFactorOneMinusDestinationAlpha;
4449 return MTLBlendFactorBlendColor;
4451 return MTLBlendFactorBlendAlpha;
4453 return MTLBlendFactorOneMinusBlendColor;
4455 return MTLBlendFactorOneMinusBlendAlpha;
4457 return MTLBlendFactorSourceAlphaSaturated;
4459 return MTLBlendFactorSource1Color;
4461 return MTLBlendFactorOneMinusSource1Color;
4463 return MTLBlendFactorSource1Alpha;
4465 return MTLBlendFactorOneMinusSource1Alpha;
4468 return MTLBlendFactorZero;
4476 return MTLBlendOperationAdd;
4478 return MTLBlendOperationSubtract;
4480 return MTLBlendOperationReverseSubtract;
4482 return MTLBlendOperationMin;
4484 return MTLBlendOperationMax;
4487 return MTLBlendOperationAdd;
4495 f |= MTLColorWriteMaskRed;
4497 f |= MTLColorWriteMaskGreen;
4499 f |= MTLColorWriteMaskBlue;
4501 f |= MTLColorWriteMaskAlpha;
4509 return MTLCompareFunctionNever;
4511 return MTLCompareFunctionLess;
4513 return MTLCompareFunctionEqual;
4515 return MTLCompareFunctionLessEqual;
4517 return MTLCompareFunctionGreater;
4519 return MTLCompareFunctionNotEqual;
4521 return MTLCompareFunctionGreaterEqual;
4523 return MTLCompareFunctionAlways;
4526 return MTLCompareFunctionAlways;
4534 return MTLStencilOperationZero;
4536 return MTLStencilOperationKeep;
4538 return MTLStencilOperationReplace;
4540 return MTLStencilOperationIncrementClamp;
4542 return MTLStencilOperationDecrementClamp;
4544 return MTLStencilOperationInvert;
4546 return MTLStencilOperationIncrementWrap;
4548 return MTLStencilOperationDecrementWrap;
4551 return MTLStencilOperationKeep;
4559 return MTLPrimitiveTypeTriangle;
4561 return MTLPrimitiveTypeTriangleStrip;
4563 return MTLPrimitiveTypeLine;
4565 return MTLPrimitiveTypeLineStrip;
4567 return MTLPrimitiveTypePoint;
4570 return MTLPrimitiveTypeTriangle;
4580 return MTLPrimitiveTopologyClassTriangle;
4583 return MTLPrimitiveTopologyClassLine;
4585 return MTLPrimitiveTopologyClassPoint;
4588 return MTLPrimitiveTopologyClassTriangle;
4596 return MTLCullModeNone;
4598 return MTLCullModeFront;
4600 return MTLCullModeBack;
4603 return MTLCullModeNone;
4611 return MTLTriangleFillModeFill;
4613 return MTLTriangleFillModeLines;
4616 return MTLTriangleFillModeFill;
4624 return MTLWindingClockwise;
4626 return MTLWindingCounterClockwise;
4629 return MTLWindingCounterClockwise;
4637 return MTLTessellationPartitionModePow2;
4639 return MTLTessellationPartitionModeFractionalEven;
4641 return MTLTessellationPartitionModeFractionalOdd;
4644 return MTLTessellationPartitionModePow2;
4651 return MTLLanguageVersion(((
v / 10) << 16) + (
v % 10));
4658 if (@available(macOS 13,
iOS 16, *))
4660 if (@available(macOS 12,
iOS 15, *))
4662 if (@available(macOS 11,
iOS 14, *))
4664 if (@available(macOS 10.15,
iOS 13, *))
4666 if (@available(macOS 10.14,
iOS 12, *))
4668 versions << 20 << 12;
4674 for (
const int &version : versions) {
4684 dispatch_get_global_queue(0, 0),
4685 DISPATCH_DATA_DESTRUCTOR_DEFAULT);
4688 dispatch_release(
data);
4694 const QString msg = QString::fromNSString(err.localizedDescription);
4699 for (
const int &version : versions) {
4707 qWarning() <<
"No MSL 2.0 or 1.2 code found in baked shader" <<
shader;
4712 MTLCompileOptions *opts = [[MTLCompileOptions alloc]
init];
4723 const QString msg = QString::fromNSString(err.localizedDescription);
4735 return [lib newFunctionWithName:[NSString stringWithUTF8String:entryPoint.
constData()]];
4740 MTLRenderPipelineDescriptor *rpDesc =
reinterpret_cast<MTLRenderPipelineDescriptor *
>(metalRpDesc);
4744 rpDesc.colorAttachments[0].pixelFormat = MTLPixelFormat(rpD->
colorFormat[0]);
4745 rpDesc.colorAttachments[0].writeMask = MTLColorWriteMaskAll;
4746 rpDesc.colorAttachments[0].blendingEnabled =
false;
4753 rpDesc.colorAttachments[
i].pixelFormat = MTLPixelFormat(rpD->
colorFormat[
i]);
4754 rpDesc.colorAttachments[
i].blendingEnabled =
b.enable;
4760 rpDesc.colorAttachments[
i].alphaBlendOperation =
toMetalBlendOp(
b.opAlpha);
4768 MTLPixelFormat
fmt = MTLPixelFormat(rpD->
dsFormat);
4769 rpDesc.depthAttachmentPixelFormat =
fmt;
4770#if defined(Q_OS_MACOS)
4771 if (
fmt != MTLPixelFormatDepth16Unorm &&
fmt != MTLPixelFormatDepth32Float)
4773 if (
fmt != MTLPixelFormatDepth32Float)
4775 rpDesc.stencilAttachmentPixelFormat =
fmt;
4784 MTLDepthStencilDescriptor *dsDesc =
reinterpret_cast<MTLDepthStencilDescriptor *
>(metalDsDesc);
4789 dsDesc.frontFaceStencil = [[MTLStencilDescriptor alloc]
init];
4797 dsDesc.backFaceStencil = [[MTLStencilDescriptor alloc]
init];
4829 desc.attributes[loc].bufferIndex =
NSUInteger(firstVertexBinding +
it->binding());
4832 const NSUInteger viewCount = qMax<NSUInteger>(1,
q->multiViewCount());
4837 desc.layouts[layoutIdx].stepFunction =
4839 ? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex;
4841 if (
desc.layouts[layoutIdx].stepFunction == MTLVertexStepFunctionPerInstance)
4842 desc.layouts[layoutIdx].stepRate *= viewCount;
4843 desc.layouts[layoutIdx].stride =
it->stride();
4860 desc.attributes[loc].bufferIndex =
NSUInteger(firstVertexBinding +
it->binding());
4867 if (
desc.indexBufferIndex) {
4868 desc.layouts[layoutIdx].stepFunction =
4870 ? MTLStepFunctionThreadPositionInGridY : MTLStepFunctionThreadPositionInGridXIndexed;
4872 desc.layouts[layoutIdx].stepFunction =
4874 ? MTLStepFunctionThreadPositionInGridY : MTLStepFunctionThreadPositionInGridX;
4877 desc.layouts[layoutIdx].stride =
it->stride();
4883 if (@available(macOS 11.0,
iOS 14.0, *)) {
4885 NSArray *binArchArray = [NSArray arrayWithObjects: binArch, nil];
4886 rpDesc.binaryArchives = binArchArray;
4893 if (@available(macOS 11.0,
iOS 14.0, *)) {
4898 if (!
d->binArchWasEmpty &&
d->q->osMajor >= 13) {
4899 static bool logPrinted =
false;
4902 qCDebug(QRHI_LOG_INFO,
"Skipping adding more pipelines to MTLBinaryArchive on this OS version (%d.%d) due to known issues.",
4903 d->q->osMajor,
d->q->osMinor);
4916 if (@available(macOS 11.0,
iOS 14.0, *)) {
4919 if (![binArch addRenderPipelineFunctionsWithDescriptor: rpDesc
error: &err]) {
4920 const QString msg = QString::fromNSString(err.localizedDescription);
4921 qWarning(
"Failed to collect render pipeline functions to binary archive: %s",
qPrintable(msg));
4931 MTLVertexDescriptor *vertexDesc = [MTLVertexDescriptor vertexDescriptor];
4934 MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc]
init];
4935 rpDesc.vertexDescriptor = vertexDesc;
4944 auto cacheIt = rhiD->d->shaderCache.constFind(shaderStage);
4945 if (cacheIt != rhiD->d->shaderCache.constEnd()) {
4946 switch (shaderStage.type()) {
4951 rpDesc.vertexFunction =
d->
vs.
func;
4957 rpDesc.fragmentFunction =
d->
fs.
func;
4968 &
error, &entryPoint, &activeKey);
4983 rhiD->d->shaderCache.clear();
4985 switch (shaderStage.type()) {
4992 rhiD->d->shaderCache.insert(shaderStage,
d->
vs);
4995 rpDesc.vertexFunction =
func;
5003 rhiD->d->shaderCache.insert(shaderStage,
d->
fs);
5006 rpDesc.fragmentFunction =
func;
5022 rhiD->d->trySeedingRenderPipelineFromBinaryArchive(rpDesc);
5025 rhiD->d->addRenderPipelineToBinaryArchive(rpDesc);
5028 d->
ps = [rhiD->d->dev newRenderPipelineStateWithDescriptor: rpDesc
error: &err];
5031 const QString msg = QString::fromNSString(err.localizedDescription);
5036 MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc]
init];
5038 d->
ds = [rhiD->d->dev newDepthStencilStateWithDescriptor: dsDesc];
5049 switch (vertexCompVariant) {
5064 const int varIndex = vsCompVariantToIndex(vertexCompVariant);
5065 if (varIndex >= 0 && vertexComputeState[varIndex])
5066 return vertexComputeState[varIndex];
5070 func = compVs[varIndex].func;
5073 qWarning(
"No compute function found for vertex shader translated for tessellation, this should not happen");
5077 const QMap<int, int> &ebb(compVs[varIndex].nativeShaderInfo.extraBufferBindings);
5080 MTLComputePipelineDescriptor *cpDesc = [MTLComputePipelineDescriptor
new];
5081 cpDesc.computeFunction =
func;
5082 cpDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = YES;
5083 cpDesc.stageInputDescriptor = [MTLStageInputOutputDescriptor stageInputOutputDescriptor];
5084 if (indexBufferBinding >= 0) {
5086 cpDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt32;
5087 cpDesc.stageInputDescriptor.indexBufferIndex = indexBufferBinding;
5089 cpDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt16;
5090 cpDesc.stageInputDescriptor.indexBufferIndex = indexBufferBinding;
5093 q->setupStageInputDescriptor(cpDesc.stageInputDescriptor);
5102 options: MTLPipelineOptionNone
5107 const QString msg = QString::fromNSString(err.localizedDescription);
5110 vertexComputeState[varIndex] =
ps;
5118 if (tessControlComputeState)
5119 return tessControlComputeState;
5121 MTLComputePipelineDescriptor *cpDesc = [MTLComputePipelineDescriptor
new];
5122 cpDesc.computeFunction = compTesc.func;
5131 options: MTLPipelineOptionNone
5136 const QString msg = QString::fromNSString(err.localizedDescription);
5139 tessControlComputeState =
ps;
5161 static const int maxVertexAttributes = 31;
5168 Q_UNREACHABLE_RETURN(-1);
5181 for (
const int dim :
variable.arrayDims)
5185 for (
int element = 0; element <
elements; ++element) {
5186 for (
const auto &member :
variable.structMembers) {
5196 vertexAlignment = std::max(vertexAlignment,
alignment);
5198 for (
int element = 0; element <
elements; ++element) {
5211 for (
const int dim :
variable.arrayDims)
5215 for (
int element = 0; element <
elements; ++element) {
5216 for (
const auto &member :
variable.structMembers) {
5226 vertexAlignment = std::max(vertexAlignment,
alignment);
5228 for (
int element = 0; element <
elements; ++element) {
5234 attributes[
index].bufferIndex = binding;
5250 if (
a.size() ==
b.size()) {
5252 for (
int i = 0;
i <
a.size() &&
match; ++
i) {
5254 &&
a[
i].arrayDims ==
b[
i].arrayDims
5255 &&
matches(
a[
i].structMembers,
b[
i].structMembers);
5265 return a.location ==
b.location
5267 &&
a.perPatch ==
b.perPatch
5268 &&
matches(
a.structMembers,
b.structMembers);
5317 if (pipeline->
d->
ps)
5318 return pipeline->
d->
ps;
5320 MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc]
init];
5321 MTLVertexDescriptor *vertexDesc = [MTLVertexDescriptor vertexDescriptor];
5324 const QMap<int, int> &ebb(compTesc.nativeShaderInfo.extraBufferBindings);
5328 quint32 offsetInTescOutput = 0;
5329 quint32 offsetInTescPatchOutput = 0;
5330 quint32 offsetInTessFactorBuffer = 0;
5331 quint32 tescOutputAlignment = 0;
5332 quint32 tescPatchOutputAlignment = 0;
5333 quint32 tessFactorAlignment = 0;
5338 for (
const auto &tescOutVar : compTesc.desc.outputVariables())
5339 tescOutVars[tescOutVar.location] = tescOutVar;
5343 for (
const auto &teseInVar : vertTese.desc.inputVariables())
5344 teseInVars[teseInVar.location] = teseInVar;
5351 int index = tescOutVar.location;
5356 if (tescOutVar.perPatch) {
5357 binding = tescPatchOutputBufferBinding;
5358 offset = &offsetInTescPatchOutput;
5361 tescOutVar.arrayDims.removeLast();
5362 binding = tescOutputBufferBinding;
5363 offset = &offsetInTescOutput;
5370 qWarning() <<
"mismatched tessellation control output -> tesssellation evaluation input at location" <<
index;
5371 qWarning() <<
" tesc out:" << tescOutVar;
5375 if (binding != -1) {
5377 usedBuffers << binding;
5379 qWarning() <<
"baked tessellation control shader missing output buffer binding information";
5384 qWarning() <<
"missing tessellation evaluation input for tessellation control output:" << tescOutVar;
5388 teseInVars.
remove(tescOutVar.location);
5392 qWarning() <<
"missing tessellation control output for tessellation evaluation input:" << teseInVar;
5396 for (
const auto &tescOutBuiltin : compTesc.desc.outputBuiltinVariables())
5397 tescOutBuiltins[tescOutBuiltin.type] = tescOutBuiltin;
5401 for (
const auto &teseInBuiltin : vertTese.desc.inputBuiltinVariables())
5402 teseInBuiltins[teseInBuiltin.type] = teseInBuiltin;
5405 bool tessLevelAdded =
false;
5414 switch (builtin.type) {
5417 binding = tescOutputBufferBinding;
5418 offset = &offsetInTescOutput;
5423 binding = tescOutputBufferBinding;
5424 offset = &offsetInTescOutput;
5429 variable.arrayDims = builtin.arrayDims;
5430 binding = tescOutputBufferBinding;
5431 offset = &offsetInTescOutput;
5436 binding = tessFactorBufferBinding;
5437 offset = &offsetInTessFactorBuffer;
5438 tessLevelAdded = trianglesMode;
5442 if (trianglesMode) {
5443 if (!tessLevelAdded) {
5445 binding = tessFactorBufferBinding;
5446 offsetInTessFactorBuffer = 0;
5447 offset = &offsetInTessFactorBuffer;
5449 tessLevelAdded =
true;
5451 teseInBuiltins.
remove(builtin.type);
5456 binding = tessFactorBufferBinding;
5457 offsetInTessFactorBuffer = 8;
5458 offset = &offsetInTessFactorBuffer;
5467 if (teseInBuiltins.
contains(builtin.type)) {
5468 if (binding != -1) {
5471 usedBuffers << binding;
5473 qWarning() <<
"baked tessellation control shader missing output buffer binding information";
5480 teseInBuiltins.
remove(builtin.type);
5484 switch (builtin.type) {
5488 qWarning() <<
"missing tessellation control output for tessellation evaluation builtin input:" << builtin;
5495 if (usedBuffers.
contains(tescOutputBufferBinding)) {
5496 vertexDesc.layouts[tescOutputBufferBinding].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
5497 vertexDesc.layouts[tescOutputBufferBinding].stride =
aligned(offsetInTescOutput, tescOutputAlignment);
5500 if (usedBuffers.
contains(tescPatchOutputBufferBinding)) {
5501 vertexDesc.layouts[tescPatchOutputBufferBinding].stepFunction = MTLVertexStepFunctionPerPatch;
5502 vertexDesc.layouts[tescPatchOutputBufferBinding].stride =
aligned(offsetInTescPatchOutput, tescPatchOutputAlignment);
5505 if (usedBuffers.
contains(tessFactorBufferBinding)) {
5506 vertexDesc.layouts[tessFactorBufferBinding].stepFunction = MTLVertexStepFunctionPerPatch;
5507 vertexDesc.layouts[tessFactorBufferBinding].stride = trianglesMode ?
sizeof(MTLTriangleTessellationFactorsHalf) :
sizeof(MTLQuadTessellationFactorsHalf);
5510 rpDesc.vertexDescriptor = vertexDesc;
5511 rpDesc.vertexFunction = vertTese.func;
5512 rpDesc.fragmentFunction = pipeline->
d->
fs.
func;
5534 const QString msg = QString::fromNSString(err.localizedDescription);
5535 qWarning(
"Failed to create render pipeline state for tessellation: %s",
qPrintable(msg));
5539 pipeline->
d->
ps =
ps;
5550 if (workBuf && workBuf->lastActiveFrameSlot == -1 && workBuf->size() >=
size) {
5560 if (workBuf && workBuf->lastActiveFrameSlot == -1) {
5561 workBuf->setSize(
size);
5562 if (workBuf->create()) {
5572 if (
type == WorkBufType::DeviceLocal) {
5579 if (
buf->create()) {
5585 qWarning(
"Failed to acquire work buffer of size %u",
size);
5598 d->tess.inControlPointCount =
uint(m_patchControlPointCount);
5600 if (!
d->tess.outControlPointCount)
5603 if (!
d->tess.outControlPointCount) {
5604 qWarning(
"Failed to determine output vertex count from the tessellation control or evaluation shader, cannot tessellate");
5605 d->tess.enabled =
false;
5606 d->tess.failed =
true;
5610 if (m_multiViewCount >= 2)
5611 qWarning(
"Multiview is not supported with tessellation");
5619 bool variantsPresent[3] = {};
5622 switch (k.sourceVariant()) {
5624 variantsPresent[0] =
true;
5627 variantsPresent[1] =
true;
5630 variantsPresent[2] =
true;
5636 if (!(variantsPresent[0] && variantsPresent[1] && variantsPresent[2])) {
5637 qWarning(
"Vertex shader is not prepared for Metal tessellation. Cannot tessellate. "
5638 "Perhaps the relevant variants (UInt32IndexedVertexAsComputeShader et al) were not generated? "
5639 "Try passing --msltess to qsb.");
5640 d->tess.enabled =
false;
5641 d->tess.failed =
true;
5654 d->tess.enabled =
false;
5655 d->tess.failed =
true;
5662 d->tess.enabled =
false;
5663 d->tess.failed =
true;
5674 if (!
d->tess.vsCompPipeline(rhiD,
variant)) {
5675 qWarning(
"Failed to pre-generate compute pipeline for vertex compute shader (tessellation variant %d)",
int(
variant));
5676 d->tess.enabled =
false;
5677 d->tess.failed =
true;
5686 if (!tessControlLib) {
5688 d->tess.enabled =
false;
5689 d->tess.failed =
true;
5692 id<MTLFunction> tessControlFunc = rhiD->d->createMSLShaderFunction(tessControlLib, entryPoint);
5693 if (!tessControlFunc) {
5696 d->tess.enabled =
false;
5697 d->tess.failed =
true;
5700 d->tess.compTesc.lib = tessControlLib;
5701 d->tess.compTesc.func = tessControlFunc;
5705 if (!
d->tess.tescCompPipeline(rhiD)) {
5706 qWarning(
"Failed to pre-generate compute pipeline for tessellation control shader");
5707 d->tess.enabled =
false;
5708 d->tess.failed =
true;
5716 d->tess.enabled =
false;
5717 d->tess.failed =
true;
5720 id<MTLFunction> tessEvalFunc = rhiD->d->createMSLShaderFunction(tessEvalLib, entryPoint);
5721 if (!tessEvalFunc) {
5724 d->tess.enabled =
false;
5725 d->tess.failed =
true;
5728 d->tess.vertTese.lib = tessEvalLib;
5729 d->tess.vertTese.func = tessEvalFunc;
5737 d->tess.enabled =
false;
5738 d->tess.failed =
true;
5741 id<MTLFunction> fragFunc = rhiD->d->createMSLShaderFunction(fragLib, entryPoint);
5745 d->tess.enabled =
false;
5746 d->tess.failed =
true;
5749 d->fs.lib = fragLib;
5750 d->fs.func = fragFunc;
5755 if (!
d->tess.teseFragRenderPipeline(rhiD,
this)) {
5756 qWarning(
"Failed to pre-generate render pipeline for tessellation evaluation + fragment shader");
5757 d->tess.enabled =
false;
5758 d->tess.failed =
true;
5762 MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc]
init];
5763 setupMetalDepthStencilDescriptor(dsDesc);
5764 d->ds = [rhiD->d->dev newDepthStencilStateWithDescriptor: dsDesc];
5778 rhiD->pipelineCreationStart();
5779 if (!rhiD->sanityCheckGraphicsPipeline(
this))
5787 for (
const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
5788 switch (shaderStage.type()) {
5790 tessVert = shaderStage.
shader();
5793 tesc = shaderStage.
shader();
5796 tese = shaderStage.
shader();
5799 tessFrag = shaderStage.
shader();
5805 d->tess.enabled = tesc.
isValid() && tese.
isValid() && m_topology == Patches && m_patchControlPointCount > 0;
5806 d->tess.failed =
false;
5808 bool ok =
d->tess.enabled ? createTessellationPipelines(tessVert, tesc, tese, tessFrag) : createVertexFragmentPipeline();
5815 if (
d->tess.enabled) {
5816 shaders.append(&
d->tess.compVs[0]);
5817 shaders.append(&
d->tess.compVs[1]);
5818 shaders.append(&
d->tess.compVs[2]);
5830 int maxNativeBinding = 0;
5832 maxNativeBinding =
qMax(maxNativeBinding,
shader->nativeResourceBindingMap[block.binding].first);
5836 buffers += ((maxNativeBinding + 1 + 7) / 8) * 8;
5841 if (!
d->bufferSizeBuffer)
5844 d->bufferSizeBuffer->setSize(
buffers *
sizeof(
int));
5845 d->bufferSizeBuffer->create();
5848 rhiD->pipelineCreationEnd();
5849 lastActiveFrameSlot = -1;
5851 rhiD->registerResource(
this);
5880 e.computePipeline.pipelineState =
d->
ps;
5885 rhiD->d->releaseQueue.append(
e);
5886 rhiD->unregisterResource(
this);
5892 if (@available(macOS 11.0,
iOS 14.0, *)) {
5894 NSArray *binArchArray = [NSArray arrayWithObjects: binArch, nil];
5895 cpDesc.binaryArchives = binArchArray;
5902 if (@available(macOS 11.0,
iOS 14.0, *)) {
5905 if (![binArch addComputePipelineFunctionsWithDescriptor: cpDesc
error: &err]) {
5906 const QString msg = QString::fromNSString(err.localizedDescription);
5907 qWarning(
"Failed to collect compute pipeline functions to binary archive: %s",
qPrintable(msg));
5919 rhiD->pipelineCreationStart();
5921 auto cacheIt = rhiD->d->shaderCache.constFind(
m_shaderStage);
5922 if (cacheIt != rhiD->d->shaderCache.constEnd()) {
5930 &
error, &entryPoint, &activeKey);
5957 rhiD->d->shaderCache.clear();
5967 MTLComputePipelineDescriptor *cpDesc = [MTLComputePipelineDescriptor
new];
5968 cpDesc.computeFunction =
d->
cs.
func;
5970 rhiD->d->trySeedingComputePipelineFromBinaryArchive(cpDesc);
5973 rhiD->d->addComputePipelineToBinaryArchive(cpDesc);
5976 d->
ps = [rhiD->d->dev newComputePipelineStateWithDescriptor: cpDesc
5977 options: MTLPipelineOptionNone
5982 const QString msg = QString::fromNSString(err.localizedDescription);
6002 rhiD->pipelineCreationEnd();
6005 rhiD->registerResource(
this);
6077 rtWrapper(rhi,
this),
6082 d->
sem[
i] =
nullptr;
6103 dispatch_release(
d->
sem[
i]);
6104 d->
sem[
i] =
nullptr;
6114 d->liveResizeStartObserver.remove();
6115 d->liveResizeEndObserver.remove();
6116 d->liveResizeObserverSet =
false;
6126 rhiD->swapchains.remove(
this);
6127 rhiD->unregisterResource(
this);
6148 NSView *
view =
reinterpret_cast<NSView *
>(
window->winId());
6150 UIView *
view =
reinterpret_cast<UIView *
>(
window->winId());
6153 return static_cast<CAMetalLayer *
>(
view.layer);
6184 if (@available(macOS 10.11,
iOS 16.0, *))
6206 rpD->
dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
6207 ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
6209 rpD->
dsFormat = MTLPixelFormatDepth32Float_Stencil8;
6214 rhiD->registerResource(rpD,
false);
6238 dispatch_semaphore_t
sem =
d->
sem[slot];
6239 dispatch_semaphore_wait(
sem, DISPATCH_TIME_FOREVER);
6240 dispatch_semaphore_signal(
sem);
6254 if (needsRegistration)
6255 rhiD->swapchains.insert(
this);
6260 qWarning(
"QMetalSwapChain only supports MetalSurface windows");
6272 if (@available(macOS 10.11,
iOS 16.0, *)) {
6273 d->
layer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearSRGB);
6274 d->
layer.wantsExtendedDynamicRangeContent = YES;
6279 d->
layer.framebufferOnly = NO;
6283 d->
layer.displaySyncEnabled = NO;
6304 const float scaleFactor =
d->
layer.contentsScale;
6305 layerSize.width *= scaleFactor;
6306 layerSize.height *= scaleFactor;
6307 d->
layer.drawableSize = layerSize;
6312 [
d->
layer setDevice: rhiD->d->dev];
6320 const bool canUsePresentsWithTransaction = NSThread.isMainThread;
6326 if (allowPresentsWithTransaction && canUsePresentsWithTransaction && !
d->liveResizeObserverSet) {
6327 d->liveResizeObserverSet =
true;
6328 NSView *
view =
reinterpret_cast<NSView *
>(
window->winId());
6331 qCDebug(QRHI_LOG_INFO,
"will set presentsWithTransaction during live resize");
6333 d->
layer.presentsWithTransaction =
true;
6336 d->
layer.presentsWithTransaction =
false;
6356 qWarning(
"Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
6363 qWarning(
"Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
6366 qWarning(
"Depth-stencil buffer's size (%dx%d) does not match the layer size (%dx%d). Expect problems.",
6379 qCDebug(QRHI_LOG_INFO,
"got CAMetalLayer, pixel size %dx%d (scale %.2f)",
6383 MTLTextureDescriptor *
desc = [[MTLTextureDescriptor alloc]
init];
6384 desc.textureType = MTLTextureType2DMultisample;
6389 desc.resourceOptions = MTLResourceStorageModePrivate;
6390 desc.storageMode = MTLStorageModePrivate;
6391 desc.usage = MTLTextureUsageRenderTarget;
6394 d->
msaaTex[
i] = [rhiD->d->dev newTextureWithDescriptor:
desc];
6399 if (needsRegistration)
6400 rhiD->registerResource(
this);
6409 info.limits.colorComponentValue.maxColorComponentValue = 1;
6410 info.isHardCodedDefaults =
true;
6415 NSView *
view =
reinterpret_cast<NSView *
>(
m_window->winId());
6417 info.limits.colorComponentValue.maxColorComponentValue =
screen.maximumExtendedDynamicRangeColorComponentValue;
6418 info.limits.colorComponentValue.maxPotentialColorComponentValue =
screen.maximumPotentialExtendedDynamicRangeColorComponentValue;
6419 info.isHardCodedDefaults =
false;
6421 if (@available(
iOS 16.0, *)) {
6422 UIView *
view =
reinterpret_cast<UIView *
>(
m_window->winId());
6423 UIScreen *
screen =
view.window.windowScene.screen;
6424 info.limits.colorComponentValue.maxColorComponentValue =
view.window.windowScene.screen.currentEDRHeadroom;
6425 info.limits.colorComponentValue.maxPotentialColorComponentValue =
screen.potentialEDRHeadroom;
6426 info.isHardCodedDefaults =
false;
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qsizetype length() const noexcept
Same as size().
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
The QColor class provides colors based on RGB, HSV or CMYK values.
float greenF() const noexcept
Returns the green color component of this color.
float redF() const noexcept
Returns the red color component of this color.
float alphaF() const noexcept
Returns the alpha color component of this color.
float blueF() const noexcept
Returns the blue color component of this color.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
QString absoluteFilePath() const
Returns an absolute path including the file name.
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qsizetype sizeInBytes() const
bool isNull() const
Returns true if it is a null image, otherwise returns false.
qsizetype count() const noexcept
void append(parameter_type t)
T value(const Key &key, const T &defaultValue=T()) const
bool contains(const Key &key) const
const_iterator cend() const
size_type remove(const Key &key)
const_iterator constFind(const Key &key) const
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
constexpr int majorVersion() const
Returns the major version number, that is, the first segment of the operating system's version number...
constexpr int minorVersion() const
Returns the minor version number, that is, the second segment of the operating system's version numbe...
static QOperatingSystemVersion current()
[0]
\inmodule QtCore\reentrant
constexpr bool isNull() const noexcept
Returns true if both the x and y coordinates are set to 0, otherwise returns false.
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
Type
Specifies storage type of buffer resource.
void setSize(quint32 sz)
Sets the size of the buffer in bytes.
QRhiRenderBuffer * renderBuffer() const
QRhiTexture * texture() const
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
QPair< int, quint32 > DynamicOffset
Synonym for QPair<int, quint32>.
IndexFormat
Specifies the index data type.
QRhiShaderStage m_shaderStage
QRhiShaderResourceBindings * m_shaderResourceBindings
float depthClearValue() const
quint32 stencilClearValue() const
QRhiRenderPassDescriptor * m_renderPassDesc
quint32 m_stencilReadMask
BlendOp
Specifies the blend operation.
void setCullMode(CullMode mode)
Sets the specified face culling mode.
PolygonMode
Specifies the polygon rasterization mode.
BlendFactor
Specifies the blend factor.
StencilOpState m_stencilFront
quint32 m_stencilWriteMask
QRhiShaderResourceBindings * shaderResourceBindings() const
CompareOp
Specifies the depth or stencil comparison function.
CullMode
Specifies the culling mode.
QVarLengthArray< QRhiShaderStage, 4 > m_shaderStages
QRhiRenderPassDescriptor * renderPassDescriptor() const
QVarLengthArray< TargetBlend, 8 > m_targetBlends
QRhiShaderResourceBindings * m_shaderResourceBindings
PolygonMode m_polygonMode
float m_slopeScaledDepthBias
Topology
Specifies the primitive topology.
StencilOpState m_stencilBack
void setDepthBias(int bias)
Sets the depth bias.
StencilOp
Specifies the stencil operation.
bool isCompressedFormat(QRhiTexture::Format format) const
static const QRhiShaderResourceBinding::Data * shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
quint32 pipelineCacheRhiId() const
void compressedFormatInfo(QRhiTexture::Format format, const QSize &size, quint32 *bpl, quint32 *byteSize, QSize *blockDim) const
static const int MAX_SHADER_CACHE_ENTRIES
static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
qint64 totalPipelineCreationTime() const
void textureFormatInfo(QRhiTexture::Format format, const QSize &size, quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const
void setPixelSize(const QSize &sz)
Sets the size (in pixels) to sz.
QRhiTexture::Format m_backingFormatHint
Type
Specifies the type of the renderbuffer.
virtual bool create()=0
Creates the corresponding native graphics resources.
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Sets the QRhiRenderPassDescriptor desc for use with this render target.
virtual QSize pixelSize() const =0
QVarLengthArray< BufferOp, BUFFER_OPS_STATIC_ALLOC > bufferOps
static QRhiResourceUpdateBatchPrivate * get(QRhiResourceUpdateBatch *b)
virtual Type resourceType() const =0
QRhiImplementation * m_rhi
Filter
Specifies the minification, magnification, or mipmap filtering.
AddressMode
Specifies the addressing mode.
CompareOp
Specifies the texture comparison function.
std::array< int, 4 > scissor() const
static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf)
StageFlag
Flag values to indicate which stages the shader resource is visible in.
@ TessellationEvaluationStage
@ TessellationControlStage
QVarLengthArray< QRhiShaderResourceBinding, BINDING_PREALLOC > m_bindings
QShader::Variant shaderVariant() const
QRhiSwapChainProxyData m_proxyData
@ SurfaceHasNonPreMulAlpha
QRhiRenderPassDescriptor * m_renderPassDesc
Format
Describes the swapchain format.
QRhiRenderBuffer * m_depthStencil
const QRhiColorAttachment * cbeginColorAttachments() const
QRhiTexture * depthTexture() const
const QRhiColorAttachment * cendColorAttachments() const
QRhiRenderBuffer * depthStencilBuffer() const
const QRhiColorAttachment * colorAttachmentAt(qsizetype index) const
qsizetype colorAttachmentCount() const
QRhiTextureRenderTargetDescription m_desc
@ PreserveDepthStencilContents
QRhiTextureRenderTargetDescription description() const
quint32 dataStride() const
QPoint sourceTopLeft() const
QPoint destinationTopLeft() const
Format
Specifies the texture format.
ResourceLimit
Describes the resource limit to query.
@ MaxThreadsPerThreadGroup
@ MaxThreadGroupsPerDimension
Feature
Flag values to indicate what features are supported by the backend currently in use.
@ NonDynamicUniformBuffers
@ RenderToNonBaseMipLevel
@ MultisampleRenderBuffer
@ PipelineCacheDataLoadSave
@ ReadBackNonUniformBuffer
@ RenderToOneDimensionalTexture
@ OneDimensionalTextureMipmaps
@ ReadBackNonBaseMipLevel
@ ThreeDimensionalTextureMipmaps
@ NonFourAlignedEffectiveIndexBufferOffset
@ ThreeDimensionalTextures
@ ReadBackAnyTextureFormat
static const int MAX_MIP_LEVELS
FrameOpResult
Describes the result of operations that can have a soft failure.
@ EnablePipelineCacheDataSave
bool contains(const T &value) const
QByteArray shader() const
QByteArray entryPoint() const
TessellationWindingOrder
\value UnknownTessellationWindingOrder \value CwTessellationWindingOrder \value CcwTessellationWindin...
@ CwTessellationWindingOrder
@ CcwTessellationWindingOrder
QList< StorageBlock > storageBlocks() const
@ TrianglesTessellationMode
TessellationPartitioning
\value UnknownTessellationPartitioning \value EqualTessellationPartitioning \value FractionalEvenTess...
@ EqualTessellationPartitioning
@ FractionalEvenTessellationPartitioning
@ FractionalOddTessellationPartitioning
uint tessellationOutputVertexCount() const
QShaderCode shader(const QShaderKey &key) const
QList< QShaderKey > availableShaders() const
NativeResourceBindingMap nativeResourceBindingMap(const QShaderKey &key) const
NativeShaderInfo nativeShaderInfo(const QShaderKey &key) const
\variable QShader::NativeShaderInfo::flags
Variant
Describes what kind of shader code an entry contains.
@ UInt32IndexedVertexAsComputeShader
@ NonIndexedVertexAsComputeShader
@ UInt16IndexedVertexAsComputeShader
QShaderDescription description() const
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
const QChar * constData() const
Returns a pointer to the data stored in the QString.
QByteArray toUtf8() const &
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
\inmodule QtCore \reentrant
QString fileName() const override
Returns the complete unique filename backing the QTemporaryFile object.
bool open()
A QTemporaryFile will always be opened in QIODevice::ReadWrite mode, this allows easy access to the d...
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
constexpr size_type size() const noexcept
const T & at(qsizetype idx) const
void resize(qsizetype sz)
const_iterator cbegin() const noexcept
const_iterator cend() const noexcept
const T * constData() const
iterator begin() noexcept
SurfaceType surfaceType() const override
Returns the surface type of the window.
QMap< QString, QString > map
[6]
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define Q_STATIC_ASSERT(Condition)
std::pair< T1, T2 > QPair
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
static QString header(const QString &name)
static const qint64 headerSize
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr const T & qMax(const T &a, const T &b)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLuint const GLuint * buffers
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLint GLint GLint GLsizei GLsizei GLsizei GLboolean commit
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint GLsizei const GLchar * label
[43]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLsizei GLenum const void * indices
GLfloat GLfloat GLfloat GLfloat h
GLuint GLsizei const GLuint const GLintptr * offsets
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLdouble GLdouble GLdouble GLdouble q
GLsizei GLsizei GLuint * shaders
GLfloat GLfloat GLfloat alpha
GLenum GLenum colorFormat
GLsizeiptr const void GLenum usage
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
static QPair< int, int > mapBinding(int binding, int stageIndex, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
Int aligned(Int v, Int byteAlign)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
static const QTextHtmlElement elements[Html_NumElements]
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
unsigned long long quint64
QVideoFrameFormat::PixelFormat fmt
QFileInfo info(fileName)
[8]
QUrl url("example.com")
[constructor-url-reference]
view viewport() -> scroll(dx, dy, deviceRect)
struct QMetalShaderResourceBindings::BoundSampledTextureData::@235 d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE]
id< MTLTexture > viewForLevel(int level)
QMetalTextureData(QMetalTexture *t)
id< MTLBuffer > stagingBuf[QMTL_FRAMES_IN_FLIGHT]
id< MTLTexture > perLevelViews[QRhi::MAX_MIP_LEVELS]
~QMetalTextureRenderTarget()
float devicePixelRatio() const override
QMetalRenderTargetData * d
QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags)
bool create() override
Creates the corresponding native graphics resources.
QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() override
int sampleCount() const override
QSize pixelSize() const override
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, int arraySize, int sampleCount, Flags flags)
bool prepareCreate(QSize *adjustedSize=nullptr)
NativeTexture nativeTexture() override
bool create() override
Creates the corresponding native graphics resources.
void destroy() override
Releases (or requests deferred releasing of) the underlying native graphics resources.
bool createFrom(NativeTexture src) override
Similar to create(), except that no new native textures are created.
QVarLengthArray< T, 4 > resources
void feed(int binding, T resource)
QVarLengthArray< Batch, 4 > batches
id< MTLComputePipelineState > pipelineState
id< MTLDepthStencilState > depthStencilState
std::array< id< MTLComputePipelineState >, 3 > tessVertexComputeState
id< MTLSamplerState > samplerState
id< MTLComputePipelineState > tessTessControlComputeState
id< MTLRenderPipelineState > pipelineState
QRhiReadbackResult * result
QRhiReadbackDescription desc
QRhiTexture::Format format
\variable QRhiReadbackResult::completed
QRhiTexture::Format format
std::function< void()> completed
float maxPotentialColorComponentValue
union QRhiSwapChainHdrInfo::@398 limits
struct QRhiSwapChainHdrInfo::@398::@400 colorComponentValue
\variable QShaderDescription::StorageBlock::blockName
\variable QShaderDescription::PushConstantBlock::name
@ MslTessTescTessLevelBufferBinding
@ MslMultiViewMaskBufferBinding
@ MslTessTescInputBufferBinding
@ MslTessTescPatchOutputBufferBinding
@ MslBufferSizeBufferBinding
@ MslTessVertTescOutputBufferBinding
@ MslTessTescParamsBufferBinding
@ MslTessVertIndicesBufferBinding
QMap< int, int > extraBufferBindings