Commit 70435b7a authored by Laszlo Agocs's avatar Laszlo Agocs

More robust backend create/destroy

parent dcbff92d
......@@ -356,54 +356,51 @@ QRhi::QRhi()
QRhi::~QRhi()
{
delete d;
if (d) {
d->destroy();
delete d;
}
}
QRhi *QRhi::create(Implementation impl, QRhiInitParams *params)
{
QScopedPointer<QRhi> r(new QRhi);
switch (impl) {
case Vulkan:
{
#if QT_CONFIG(vulkan)
QRhi *r = new QRhi;
r->d = new QRhiVulkan(params);
return r;
break;
#else
qWarning("This build of Qt has no Vulkan support");
break;
#endif
}
case OpenGLES2:
{
QRhi *r = new QRhi;
r->d = new QRhiGles2(params);
return r;
}
break;
case D3D11:
{
#ifdef Q_OS_WIN
QRhi *r = new QRhi;
r->d = new QRhiD3D11(params);
return r;
break;
#else
qWarning("This platform has no Direct3D 11 support");
break;
#endif
}
case Metal:
{
#ifdef Q_OS_DARWIN
QRhi *r = new QRhi;
r->d = new QRhiMetal(params);
return r;
break;
#else
qWarning("This platform has no Metal support");
break;
#endif
}
default:
break;
}
if (r->d && r->d->create())
return r.take();
return nullptr;
}
......
......@@ -1049,6 +1049,8 @@ struct Q_RHI_EXPORT QRhiInitParams
{
};
// A QRhi instance can be created and used on any thread but all usage must be
// limited to that one single thread.
class Q_RHI_EXPORT QRhi
{
public:
......
......@@ -61,6 +61,9 @@ class QRhiImplementation
public:
virtual ~QRhiImplementation();
virtual bool create() = 0;
virtual void destroy() = 0;
virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
......
......@@ -75,11 +75,6 @@ QRhiD3D11::QRhiD3D11(QRhiInitParams *params)
create();
}
QRhiD3D11::~QRhiD3D11()
{
destroy();
}
static QString comErrorMessage(HRESULT hr)
{
#ifndef Q_OS_WINRT
......@@ -98,7 +93,7 @@ static inline uint aligned(uint v, uint byteAlign)
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
void QRhiD3D11::create()
bool QRhiD3D11::create()
{
uint flags = 0;
if (debugLayer)
......@@ -107,7 +102,7 @@ void QRhiD3D11::create()
HRESULT hr = CreateDXGIFactory2(0, IID_IDXGIFactory2, reinterpret_cast<void **>(&dxgiFactory));
if (FAILED(hr)) {
qWarning("Failed to create DXGI factory: %s", qPrintable(comErrorMessage(hr)));
return;
return false;
}
if (!importedDevice) {
......@@ -130,7 +125,7 @@ void QRhiD3D11::create()
}
if (!adapterToUse) {
qWarning("No adapter");
return;
return false;
}
ID3D11DeviceContext *ctx = nullptr;
......@@ -140,18 +135,20 @@ void QRhiD3D11::create()
adapterToUse->Release();
if (FAILED(hr)) {
qWarning("Failed to create D3D11 device and context: %s", qPrintable(comErrorMessage(hr)));
return;
return false;
}
if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
ctx->Release();
} else {
qWarning("ID3D11DeviceContext1 not supported");
return;
return false;
}
} else {
Q_ASSERT(dev && context);
featureLevel = dev->GetFeatureLevel();
}
return true;
}
void QRhiD3D11::destroy()
......
......@@ -415,7 +415,9 @@ class QRhiD3D11 : public QRhiImplementation
{
public:
QRhiD3D11(QRhiInitParams *params);
~QRhiD3D11();
bool create() override;
void destroy() override;
QRhiGraphicsPipeline *createGraphicsPipeline() override;
QRhiShaderResourceBindings *createShaderResourceBindings() override;
......@@ -481,8 +483,6 @@ public:
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
bool isFeatureSupported(QRhi::Feature feature) const override;
void create();
void destroy();
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD);
void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD);
......
......@@ -69,11 +69,6 @@ QRhiGles2::QRhiGles2(QRhiInitParams *params)
create();
}
QRhiGles2::~QRhiGles2()
{
destroy();
}
bool QRhiGles2::ensureContext(QSurface *surface) const
{
bool nativeWindowGone = false;
......@@ -98,13 +93,13 @@ bool QRhiGles2::ensureContext(QSurface *surface) const
return true;
}
void QRhiGles2::create()
bool QRhiGles2::create()
{
Q_ASSERT(ctx);
Q_ASSERT(fallbackSurface);
if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface)) // see 'window' discussion in QRhiGles2InitParams comments
return;
return false;
f = static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
......@@ -122,6 +117,8 @@ void QRhiGles2::create()
caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
&& f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
return true;
}
void QRhiGles2::destroy()
......
......@@ -430,7 +430,9 @@ class QRhiGles2 : public QRhiImplementation
{
public:
QRhiGles2(QRhiInitParams *params);
~QRhiGles2();
bool create() override;
void destroy() override;
QRhiGraphicsPipeline *createGraphicsPipeline() override;
QRhiShaderResourceBindings *createShaderResourceBindings() override;
......@@ -497,8 +499,6 @@ public:
bool isFeatureSupported(QRhi::Feature feature) const override;
bool ensureContext(QSurface *surface = nullptr) const;
void create();
void destroy();
void executeDeferredReleases();
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void executeCommandBuffer(QRhiCommandBuffer *cb);
......
......@@ -221,7 +221,6 @@ QRhiMetal::QRhiMetal(QRhiInitParams *params)
QRhiMetal::~QRhiMetal()
{
destroy();
delete d;
}
......@@ -230,7 +229,7 @@ static inline uint aligned(uint v, uint byteAlign)
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
void QRhiMetal::create()
bool QRhiMetal::create()
{
if (!importedDevice)
d->dev = MTLCreateSystemDefaultDevice();
......@@ -238,6 +237,8 @@ void QRhiMetal::create()
qDebug("Metal device: %s", qPrintable(QString::fromNSString([d->dev name])));
d->cmdQueue = [d->dev newCommandQueue];
return true;
}
void QRhiMetal::destroy()
......
......@@ -249,6 +249,9 @@ public:
QRhiMetal(QRhiInitParams *params);
~QRhiMetal();
bool create() override;
void destroy() override;
QRhiGraphicsPipeline *createGraphicsPipeline() override;
QRhiShaderResourceBindings *createShaderResourceBindings() override;
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
......@@ -313,8 +316,6 @@ public:
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
bool isFeatureSupported(QRhi::Feature feature) const override;
void create();
void destroy();
void executeDeferredReleases(bool forced = false);
void finishActiveReadbacks(bool forced = false);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
......
......@@ -169,16 +169,9 @@ QRhiVulkan::QRhiVulkan(QRhiInitParams *params)
cmdPool = vkparams->cmdPool;
}
maybeWindow = vkparams->window; // may be null
create();
}
QRhiVulkan::~QRhiVulkan()
{
destroy();
}
void QRhiVulkan::create()
bool QRhiVulkan::create()
{
Q_ASSERT(inst);
......@@ -190,14 +183,18 @@ void QRhiVulkan::create()
uint32_t devCount = 0;
f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr);
qDebug("%d physical devices", devCount);
if (!devCount)
qFatal("No physical devices");
if (!devCount) {
qWarning("No physical devices");
return false;
}
// Just pick the first physical device for now.
devCount = 1;
VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, &physDev);
if (err != VK_SUCCESS)
qFatal("Failed to enumerate physical devices: %d", err);
if (err != VK_SUCCESS) {
qWarning("Failed to enumerate physical devices: %d", err);
return false;
}
uint32_t queueCount = 0;
f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
......@@ -222,10 +219,14 @@ void QRhiVulkan::create()
// ###
qWarning("No graphics queue that can present. This is not supported atm.");
}
if (gfxQueueFamilyIdx == -1)
qFatal("No graphics queue family found");
if (presQueueFamilyIdx == -1)
qFatal("No present queue family found");
if (gfxQueueFamilyIdx == -1) {
qWarning("No graphics queue family found");
return false;
}
if (presQueueFamilyIdx == -1) {
qWarning("No present queue family found");
return false;
}
VkDeviceQueueCreateInfo queueInfo[2];
const float prio[] = { 0 };
......@@ -259,8 +260,10 @@ void QRhiVulkan::create()
devInfo.ppEnabledExtensionNames = devExts.constData();
err = f->vkCreateDevice(physDev, &devInfo, nullptr, &dev);
if (err != VK_SUCCESS)
qFatal("Failed to create device: %d", err);
if (err != VK_SUCCESS) {
qWarning("Failed to create device: %d", err);
return false;
}
}
df = inst->deviceFunctions(dev);
......@@ -270,8 +273,10 @@ void QRhiVulkan::create()
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
VkResult err = df->vkCreateCommandPool(dev, &poolInfo, nullptr, &cmdPool);
if (err != VK_SUCCESS)
qFatal("Failed to create command pool: %d", err);
if (err != VK_SUCCESS) {
qWarning("Failed to create command pool: %d", err);
return false;
}
}
if (gfxQueueFamilyIdx != -1 && !gfxQueue)
df->vkGetDeviceQueue(dev, gfxQueueFamilyIdx, 0, &gfxQueue);
......@@ -312,7 +317,7 @@ void QRhiVulkan::create()
VkResult err = vmaCreateAllocator(&allocatorInfo, &vmaallocator);
if (err != VK_SUCCESS) {
qWarning("Failed to create allocator: %d", err);
return;
return false;
}
allocator = vmaallocator;
......@@ -322,6 +327,8 @@ void QRhiVulkan::create()
descriptorPools.append(pool);
else
qWarning("Failed to create initial descriptor pool: %d", err);
return true;
}
void QRhiVulkan::destroy()
......
......@@ -316,7 +316,9 @@ class QRhiVulkan : public QRhiImplementation
{
public:
QRhiVulkan(QRhiInitParams *params);
~QRhiVulkan();
bool create() override;
void destroy() override;
QRhiGraphicsPipeline *createGraphicsPipeline() override;
QRhiShaderResourceBindings *createShaderResourceBindings() override;
......@@ -382,8 +384,6 @@ public:
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
bool isFeatureSupported(QRhi::Feature feature) const override;
void create();
void destroy();
VkResult createDescriptorPool(VkDescriptorPool *pool);
bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex);
uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
......
resource import/export, what's the interop story
vk: shouldn't just qFatal
multiwindow_threaded should demo pulling out the device and importing to another rhi
advanced blend modes
gl: tex formats (texture, readback)
gl: srgb
......@@ -32,6 +32,7 @@ copy/transfer queue?
d3d: support DxcCompiler (in addition to d3dcompiler?) when runtime compiling hlsl?
tessellation?
indirect draw?
vk: msaa texture or msaa color renderbuffer could be lazy/transient when only used with resolve
vk: subpasses?
more tex: 3d, array?
vk compressed tex: could it consume a complete ktx without any memcpys?
......@@ -45,6 +46,7 @@ dxc for d3d as an alternative to fxc?
hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done
vk: shouldn't just qFatal
mtl: multiwindow
multi window? (multi swapchain) -> trouble
test cubemap
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment