diff options
Diffstat (limited to 'src/gui/rhi')
| -rw-r--r-- | src/gui/rhi/qrhimetal.mm | 22 | ||||
| -rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 104 | ||||
| -rw-r--r-- | src/gui/rhi/qrhivulkan_p.h | 6 |
3 files changed, 122 insertions, 10 deletions
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 7fa05f69232..0d4ce909daa 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -26,6 +26,8 @@ #include <Metal/Metal.h> +#include <utility> // for std::pair + QT_BEGIN_NAMESPACE /* @@ -1674,12 +1676,12 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind if (needsBufferSizeBuffer) { QMetalBuffer *bufD = nullptr; - QVarLengthArray<QPair<QMetalShader *, QRhiShaderResourceBinding::StageFlag>, 4> shaders; + QVarLengthArray<std::pair<QMetalShader *, QRhiShaderResourceBinding::StageFlag>, 4> shaders; if (compPsD) { bufD = compPsD->d->bufferSizeBuffer; Q_ASSERT(compPsD->d->cs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)); - shaders.append(qMakePair(&compPsD->d->cs, QRhiShaderResourceBinding::StageFlag::ComputeStage)); + shaders.append({&compPsD->d->cs, QRhiShaderResourceBinding::StageFlag::ComputeStage}); } else { bufD = gfxPsD->d->bufferSizeBuffer; if (gfxPsD->d->tess.enabled) { @@ -1706,24 +1708,24 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind == gfxPsD->d->tess.compVs[2].nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]); if (gfxPsD->d->tess.compVs[0].nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) - shaders.append(qMakePair(&gfxPsD->d->tess.compVs[0], QRhiShaderResourceBinding::StageFlag::VertexStage)); + shaders.append({&gfxPsD->d->tess.compVs[0], QRhiShaderResourceBinding::StageFlag::VertexStage}); if (gfxPsD->d->tess.compTesc.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) - shaders.append(qMakePair(&gfxPsD->d->tess.compTesc, QRhiShaderResourceBinding::StageFlag::TessellationControlStage)); + shaders.append({&gfxPsD->d->tess.compTesc, QRhiShaderResourceBinding::StageFlag::TessellationControlStage}); if (gfxPsD->d->tess.vertTese.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) - shaders.append(qMakePair(&gfxPsD->d->tess.vertTese, QRhiShaderResourceBinding::StageFlag::TessellationEvaluationStage)); + shaders.append({&gfxPsD->d->tess.vertTese, QRhiShaderResourceBinding::StageFlag::TessellationEvaluationStage}); } else { if (gfxPsD->d->vs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) - shaders.append(qMakePair(&gfxPsD->d->vs, QRhiShaderResourceBinding::StageFlag::VertexStage)); + shaders.append({&gfxPsD->d->vs, QRhiShaderResourceBinding::StageFlag::VertexStage}); } if (gfxPsD->d->fs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) - shaders.append(qMakePair(&gfxPsD->d->fs, QRhiShaderResourceBinding::StageFlag::FragmentStage)); + shaders.append({&gfxPsD->d->fs, QRhiShaderResourceBinding::StageFlag::FragmentStage}); } quint32 offset = 0; - for (const QPair<QMetalShader *, QRhiShaderResourceBinding::StageFlag> &shader : shaders) { + for (const auto &shader : shaders) { const int binding = shader.first->nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]; @@ -6030,7 +6032,7 @@ bool QMetalGraphicsPipeline::create() for (QMetalShader *shader : shaders) { if (shader->nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) { const int binding = shader->nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]; - shader->nativeResourceBindingMap[binding] = qMakePair(binding, -1); + shader->nativeResourceBindingMap[binding] = {binding, -1}; int maxNativeBinding = 0; for (const QShaderDescription::StorageBlock &block : shader->desc.storageBlocks()) maxNativeBinding = qMax(maxNativeBinding, shader->nativeResourceBindingMap[block.binding].first); @@ -6148,7 +6150,7 @@ bool QMetalComputePipeline::create() // SPIRV-Cross buffer size buffers if (d->cs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) { const int binding = d->cs.nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]; - d->cs.nativeResourceBindingMap[binding] = qMakePair(binding, -1); + d->cs.nativeResourceBindingMap[binding] = {binding, -1}; } if (rhiD->d->shaderCache.count() >= QRhiMetal::MAX_SHADER_CACHE_ENTRIES) { diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 33e35ba6694..202e28263c2 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -682,6 +682,12 @@ bool QRhiVulkan::create(QRhi::Flags flags) if (devExts.contains("VK_KHR_fragment_shading_rate")) addToChain(&physDevFeaturesChainable, &fragmentShadingRateFeatures); #endif +#ifdef VK_EXT_device_fault + VkPhysicalDeviceFaultFeaturesEXT deviceFaultFeatures = {}; + deviceFaultFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT; + if (devExts.contains(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) + addToChain(&physDevFeaturesChainable, &deviceFaultFeatures); +#endif #endif // Vulkan >=1.2 headers at build time, >=1.2 implementation at run time @@ -825,6 +831,13 @@ bool QRhiVulkan::create(QRhi::Flags flags) requestedDevExts.append(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME); #endif +#ifdef VK_EXT_device_fault + if (devExts.contains(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) { + requestedDevExts.append(VK_EXT_DEVICE_FAULT_EXTENSION_NAME); + caps.deviceFault = true; + } +#endif + for (const QByteArray &ext : requestedDeviceExtensions) { if (!ext.isEmpty() && !requestedDevExts.contains(ext)) { if (devExts.contains(ext)) { @@ -910,6 +923,7 @@ bool QRhiVulkan::create(QRhi::Flags flags) // Here we have no way to tell if the extensions got enabled or not. // Pretend it's all there and supported. If getProcAddress fails, we'll // handle that gracefully. + caps.deviceFault = true; caps.vertexAttribDivisor = true; caps.renderPass2KHR = true; caps.depthStencilResolveKHR = true; @@ -1126,6 +1140,12 @@ bool QRhiVulkan::create(QRhi::Flags flags) } #endif +#ifdef VK_EXT_device_fault + if (caps.deviceFault) { + vkGetDeviceFaultInfoEXT = reinterpret_cast<PFN_vkGetDeviceFaultInfoEXT>(f->vkGetDeviceProcAddr(dev, "vkGetDeviceFaultInfoEXT")); + } +#endif + deviceLost = false; nativeHandlesStruct.physDev = physDev; @@ -2643,6 +2663,7 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin } else { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkAcquireNextImageKHR()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -2803,6 +2824,7 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram } else if (err != VK_SUBOPTIMAL_KHR) { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkQueuePresentKHR()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -2862,6 +2884,7 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb) if (err != VK_SUCCESS) { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkAllocateCommandBuffers()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -2877,6 +2900,7 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb) if (err != VK_SUCCESS) { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkBeginCommandBuffer()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -2894,6 +2918,7 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer if (err != VK_SUCCESS) { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkEndCommandBuffer()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -2930,6 +2955,7 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer if (err != VK_SUCCESS) { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkQueueSubmit()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -2951,6 +2977,7 @@ QRhi::FrameOpResult QRhiVulkan::waitCommandCompletion(int frameSlot) if (err != VK_SUCCESS) { if (err == VK_ERROR_DEVICE_LOST) { qWarning("Device loss detected in vkWaitForFences()"); + printExtraErrorInfo(err); deviceLost = true; return QRhi::FrameOpDeviceLost; } @@ -4079,10 +4106,87 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level, void QRhiVulkan::printExtraErrorInfo(VkResult err) { + if (err == VK_ERROR_DEVICE_LOST) + printDeviceLossErrorInfo(); if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY) qWarning() << "Out of device memory, current allocator statistics are" << statistics(); } +void QRhiVulkan::printDeviceLossErrorInfo() const +{ +#ifdef VK_EXT_device_fault + if (!dev || !caps.deviceFault || !vkGetDeviceFaultInfoEXT) + return; + + VkDeviceFaultCountsEXT faultCounts{}; + faultCounts.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT; + faultCounts.pNext = nullptr; + + VkResult result = vkGetDeviceFaultInfoEXT(dev, &faultCounts, nullptr); + if (result != VK_SUCCESS && result != VK_INCOMPLETE) { + qWarning("vkGetDeviceFaultInfoEXT failed with %d", result); + return; + } + faultCounts.vendorBinarySize = 0; + + QVarLengthArray<VkDeviceFaultAddressInfoEXT> addressInfos; + addressInfos.resize(faultCounts.addressInfoCount); + + QVarLengthArray<VkDeviceFaultVendorInfoEXT> vendorInfos; + vendorInfos.resize(faultCounts.vendorInfoCount); + + VkDeviceFaultInfoEXT info{}; + info.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT; + info.pNext = nullptr; + info.pAddressInfos = addressInfos.isEmpty() ? nullptr : addressInfos.data(); + info.pVendorInfos = vendorInfos.isEmpty() ? nullptr : vendorInfos.data(); + info.pVendorBinaryData = nullptr; + + result = vkGetDeviceFaultInfoEXT(dev, &faultCounts, &info); + if (result != VK_SUCCESS && result != VK_INCOMPLETE) { + qWarning("vkGetDeviceFaultInfoEXT failed with %d", result); + return; + } + + const char *desc = info.description[0] ? info.description : "n/a"; + qWarning("VK_ERROR_DEVICE_LOST (VK_EXT_device_fault): %u address infos, %u vendor infos, %llu bytes vendor binary: %s", + faultCounts.addressInfoCount, + faultCounts.vendorInfoCount, + (unsigned long long)faultCounts.vendorBinarySize, + desc); + + for (uint32_t i = 0; i < faultCounts.addressInfoCount; ++i) { + const auto &a = addressInfos[i]; + auto addressTypeString = [](const VkDeviceFaultAddressTypeEXT type) { + switch (type) { + case VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT: return "NONE"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT: return "READ_INVALID"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT: return "WRITE_INVALID"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT: return "EXECUTE_INVALID"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT: return "INSTRUCTION_POINTER_UNKNOWN"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT: return "INSTRUCTION_POINTER_INVALID"; + case VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT: return "INSTRUCTION_POINTER_FAULT"; + default: return "UNKNOWN"; + }; + }; + qWarning(" AddressInfo[%02u]: type=%s addr=0x%llx precision=%llu", + i, + addressTypeString(a.addressType), + (unsigned long long)a.reportedAddress, + (unsigned long long)a.addressPrecision); + } + + for (uint32_t i = 0; i < faultCounts.vendorInfoCount; ++i) { + const auto &v = vendorInfos[i]; + qWarning(" VendorInfo[%02u]: code=%llu data=%llu desc=%s", + i, + (unsigned long long)v.vendorFaultCode, + (unsigned long long)v.vendorFaultData, + v.description); + } +#endif // VK_EXT_device_fault +} + void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates) { QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates); diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h index 21044545ad2..eb07d8be448 100644 --- a/src/gui/rhi/qrhivulkan_p.h +++ b/src/gui/rhi/qrhivulkan_p.h @@ -882,6 +882,7 @@ public: void ensureCommandPoolForNewFrame(); double elapsedSecondsFromTimestamp(quint64 timestamp[2], bool *ok); void printExtraErrorInfo(VkResult err); + void printDeviceLossErrorInfo() const; QVulkanInstance *inst = nullptr; QWindow *maybeWindow = nullptr; @@ -942,11 +943,16 @@ public: PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = nullptr; #endif +#ifdef VK_EXT_device_fault + PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT = nullptr; +#endif + struct { bool compute = false; bool depthClamp = false; bool wideLines = false; bool debugUtils = false; + bool deviceFault = false; bool vertexAttribDivisor = false; bool texture3DSliceAs2D = false; bool tessellation = false; |
