diff options
Diffstat (limited to 'src/gui/rhi')
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 17 | ||||
-rw-r--r-- | src/gui/rhi/qrhi_p.h | 2 | ||||
-rw-r--r-- | src/gui/rhi/qrhi_p_p.h | 3 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 116 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11_p_p.h | 10 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 63 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 3 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 229 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal_p_p.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhinull.cpp | 5 | ||||
-rw-r--r-- | src/gui/rhi/qrhinull_p_p.h | 1 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 5 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan_p_p.h | 1 |
13 files changed, 315 insertions, 141 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 4414b61d55..88d2f73541 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -5020,6 +5020,23 @@ QRhiProfiler *QRhi::profiler() } /*! + Attempts to release resources in the backend's caches. This can include both + CPU and GPU resources. Only memory and resources that can be recreated + automatically are in scope. As an example, if the backend's + QRhiGraphicsPipeline implementation maintains a cache of shader compilation + results, calling this function leads to emptying that cache, thus + potentially freeing up memory and graphics resources. + + Calling this function makes sense in resource constrained environments, + where at a certain point there is a need to ensure minimal resource usage, + at the expense of performance. + */ +void QRhi::releaseCachedResources() +{ + d->releaseCachedResources(); +} + +/*! \return a new graphics pipeline resource. \sa QRhiResource::release() diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 2d36c19e99..928d1f8fa7 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1420,6 +1420,8 @@ public: static const int MAX_LAYERS = 6; // cubemaps only static const int MAX_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone + void releaseCachedResources(); + protected: QRhi(); diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index 0914cf268b..b69757ae6d 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -157,6 +157,7 @@ public: virtual const QRhiNativeHandles *nativeHandles() = 0; virtual void sendVMemStatsToProfiler() = 0; virtual void makeThreadLocalNativeContextCurrent() = 0; + virtual void releaseCachedResources() = 0; bool isCompressedFormat(QRhiTexture::Format format) const; void compressedFormatInfo(QRhiTexture::Format format, const QSize &size, @@ -205,6 +206,8 @@ public: QRhi *q; + static const int MAX_SHADER_CACHE_ENTRIES = 128; + protected: bool debugMarkers = false; int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11. diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 9e8533be23..93eadc047d 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -267,10 +267,20 @@ bool QRhiD3D11::create(QRhi::Flags flags) return true; } +void QRhiD3D11::clearShaderCache() +{ + for (Shader &s : m_shaderCache) + s.s->Release(); + + m_shaderCache.clear(); +} + void QRhiD3D11::destroy() { finishActiveReadbacks(); + clearShaderCache(); + if (annotations) { annotations->Release(); annotations = nullptr; @@ -461,6 +471,11 @@ void QRhiD3D11::makeThreadLocalNativeContextCurrent() // nothing to do here } +void QRhiD3D11::releaseCachedResources() +{ + clearShaderCache(); +} + QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags) { @@ -3408,30 +3423,57 @@ bool QD3D11GraphicsPipeline::build() QByteArray vsByteCode; for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) { - QString error; - QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error); - if (bytecode.isEmpty()) { - qWarning("HLSL shader compilation failed: %s", qPrintable(error)); - return false; - } - switch (shaderStage.type()) { - case QRhiShaderStage::Vertex: - hr = rhiD->dev->CreateVertexShader(bytecode.constData(), bytecode.size(), nullptr, &vs); - if (FAILED(hr)) { - qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr))); - return false; + auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage); + if (cacheIt != rhiD->m_shaderCache.constEnd()) { + switch (shaderStage.type()) { + case QRhiShaderStage::Vertex: + vs = static_cast<ID3D11VertexShader *>(cacheIt->s); + vs->AddRef(); + vsByteCode = cacheIt->bytecode; + break; + case QRhiShaderStage::Fragment: + fs = static_cast<ID3D11PixelShader *>(cacheIt->s); + fs->AddRef(); + break; + default: + break; } - vsByteCode = bytecode; - break; - case QRhiShaderStage::Fragment: - hr = rhiD->dev->CreatePixelShader(bytecode.constData(), bytecode.size(), nullptr, &fs); - if (FAILED(hr)) { - qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr))); + } else { + QString error; + const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error); + if (bytecode.isEmpty()) { + qWarning("HLSL shader compilation failed: %s", qPrintable(error)); return false; } - break; - default: - break; + + if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) { + // Use the simplest strategy: too many cached shaders -> drop them all. + rhiD->clearShaderCache(); + } + + switch (shaderStage.type()) { + case QRhiShaderStage::Vertex: + hr = rhiD->dev->CreateVertexShader(bytecode.constData(), bytecode.size(), nullptr, &vs); + if (FAILED(hr)) { + qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr))); + return false; + } + vsByteCode = bytecode; + rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode)); + vs->AddRef(); + break; + case QRhiShaderStage::Fragment: + hr = rhiD->dev->CreatePixelShader(bytecode.constData(), bytecode.size(), nullptr, &fs); + if (FAILED(hr)) { + qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr))); + return false; + } + rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode)); + fs->AddRef(); + break; + default: + break; + } } } @@ -3501,19 +3543,31 @@ bool QD3D11ComputePipeline::build() QRHI_RES_RHI(QRhiD3D11); - QString error; - QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error); - if (bytecode.isEmpty()) { - qWarning("HLSL compute shader compilation failed: %s", qPrintable(error)); - return false; - } + auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage); + if (cacheIt != rhiD->m_shaderCache.constEnd()) { + cs = static_cast<ID3D11ComputeShader *>(cacheIt->s); + } else { + QString error; + const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error); + if (bytecode.isEmpty()) { + qWarning("HLSL compute shader compilation failed: %s", qPrintable(error)); + return false; + } - HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), bytecode.size(), nullptr, &cs); - if (FAILED(hr)) { - qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr))); - return false; + HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), bytecode.size(), nullptr, &cs); + if (FAILED(hr)) { + qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr))); + return false; + } + + if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) + rhiD->clearShaderCache(); + + rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode)); } + cs->AddRef(); + generation += 1; rhiD->registerResource(this); return true; diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 582146315d..cd44519aaa 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -632,6 +632,7 @@ public: const QRhiNativeHandles *nativeHandles() override; void sendVMemStatsToProfiler() override; void makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); @@ -646,6 +647,7 @@ public: DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const; void finishActiveReadbacks(); void reportLiveObjects(ID3D11Device *device); + void clearShaderCache(); bool debugLayer = false; bool importedDevice = false; @@ -684,6 +686,14 @@ public: QRhiTexture::Format format; }; QVector<ActiveReadback> activeReadbacks; + + struct Shader { + Shader() = default; + Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { } + IUnknown *s; + QByteArray bytecode; + }; + QHash<QRhiShaderStage, Shader> m_shaderCache; }; Q_DECLARE_TYPEINFO(QRhiD3D11::ActiveReadback, Q_MOVABLE_TYPE); diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index f4e711e33e..9ad591a17a 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -502,6 +502,10 @@ void QRhiGles2::destroy() ensureContext(); executeDeferredReleases(); + for (uint shader : m_shaderCache) + f->glDeleteShader(shader); + m_shaderCache.clear(); + if (!importedContext) { delete ctx; ctx = nullptr; @@ -757,6 +761,17 @@ void QRhiGles2::makeThreadLocalNativeContextCurrent() ensureContext(); } +void QRhiGles2::releaseCachedResources() +{ + if (!ensureContext()) + return; + + for (uint shader : m_shaderCache) + f->glDeleteShader(shader); + + m_shaderCache.clear(); +} + QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags) { @@ -2673,7 +2688,6 @@ static inline GLenum toGlShaderType(QRhiShaderStage::Type type) bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderDescription *desc, int *glslVersionUsed) { - GLuint shader = f->glCreateShader(toGlShaderType(shaderStage.type())); const QShader bakedShader = shaderStage.shader(); QVector<int> versionsToTry; QByteArray source; @@ -2733,27 +2747,40 @@ bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage return false; } - const char *srcStr = source.constData(); - const GLint srcLength = source.count(); - f->glShaderSource(shader, 1, &srcStr, &srcLength); - f->glCompileShader(shader); - GLint compiled = 0; - f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - GLint infoLogLength = 0; - f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); - QByteArray log; - if (infoLogLength > 1) { - GLsizei length = 0; - log.resize(infoLogLength); - f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data()); + GLuint shader; + auto cacheIt = m_shaderCache.constFind(shaderStage); + if (cacheIt != m_shaderCache.constEnd()) { + shader = *cacheIt; + } else { + shader = f->glCreateShader(toGlShaderType(shaderStage.type())); + const char *srcStr = source.constData(); + const GLint srcLength = source.count(); + f->glShaderSource(shader, 1, &srcStr, &srcLength); + f->glCompileShader(shader); + GLint compiled = 0; + f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + GLint infoLogLength = 0; + f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); + QByteArray log; + if (infoLogLength > 1) { + GLsizei length = 0; + log.resize(infoLogLength); + f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data()); + } + qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData()); + return false; } - qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData()); - return false; + if (m_shaderCache.count() >= MAX_SHADER_CACHE_ENTRIES) { + // Use the simplest strategy: too many cached shaders -> drop them all. + for (uint shader : m_shaderCache) + f->glDeleteShader(shader); // does not actually get released yet when attached to a not-yet-released program + m_shaderCache.clear(); + } + m_shaderCache.insert(shaderStage, shader); } f->glAttachShader(program, shader); - f->glDeleteShader(shader); *desc = bakedShader.description(); return true; diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 6da529be92..877eb88d27 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -665,6 +665,7 @@ public: const QRhiNativeHandles *nativeHandles() override; void sendVMemStatsToProfiler() override; void makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; bool ensureContext(QSurface *surface = nullptr) const; void executeDeferredReleases(); @@ -804,6 +805,8 @@ public: bool active = false; QGles2CommandBuffer cbWrapper; } ofr; + + QHash<QRhiShaderStage, uint> m_shaderCache; }; Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_MOVABLE_TYPE); diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index dfa79edb00..a14ffa7173 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -138,6 +138,20 @@ QT_BEGIN_NAMESPACE \l{QRhiCommandBuffer::endPass()}. */ +struct QMetalShader +{ + id<MTLLibrary> lib = nil; + id<MTLFunction> func = nil; + std::array<uint, 3> localSize; + + void release() { + [lib release]; + lib = nil; + [func release]; + func = nil; + } +}; + struct QRhiMetalData { QRhiMetalData(QRhiImplementation *rhi) : ofr(rhi) { } @@ -206,6 +220,8 @@ struct QRhiMetalData API_AVAILABLE(macos(10.13), ios(11.0)) id<MTLCaptureScope> captureScope = nil; static const int TEXBUF_ALIGN = 256; // probably not accurate + + QHash<QRhiShaderStage, QMetalShader> shaderCache; }; Q_DECLARE_TYPEINFO(QRhiMetalData::DeferredReleaseEntry, Q_MOVABLE_TYPE); @@ -289,17 +305,14 @@ struct QMetalGraphicsPipelineData MTLPrimitiveType primitiveType; MTLWinding winding; MTLCullMode cullMode; - id<MTLLibrary> vsLib = nil; - id<MTLFunction> vsFunc = nil; - id<MTLLibrary> fsLib = nil; - id<MTLFunction> fsFunc = nil; + QMetalShader vs; + QMetalShader fs; }; struct QMetalComputePipelineData { id<MTLComputePipelineState> ps = nil; - id<MTLLibrary> csLib = nil; - id<MTLFunction> csFunc = nil; + QMetalShader cs; MTLSize localSize; }; @@ -404,6 +417,10 @@ void QRhiMetal::destroy() executeDeferredReleases(true); finishActiveReadbacks(true); + for (QMetalShader &s : d->shaderCache) + s.release(); + d->shaderCache.clear(); + if (@available(macOS 10.13, iOS 11.0, *)) { [d->captureScope release]; d->captureScope = nil; @@ -570,6 +587,14 @@ void QRhiMetal::makeThreadLocalNativeContextCurrent() // nothing to do here } +void QRhiMetal::releaseCachedResources() +{ + for (QMetalShader &s : d->shaderCache) + s.release(); + + d->shaderCache.clear(); +} + QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags) { @@ -2843,36 +2868,17 @@ void QMetalGraphicsPipeline::release() { QRHI_RES_RHI(QRhiMetal); - if (!d->ps) - return; - - if (d->ps) { - [d->ps release]; - d->ps = nil; - } + d->vs.release(); + d->fs.release(); - if (d->ds) { - [d->ds release]; - d->ds = nil; - } + [d->ds release]; + d->ds = nil; - if (d->vsFunc) { - [d->vsFunc release]; - d->vsFunc = nil; - } - if (d->vsLib) { - [d->vsLib release]; - d->vsLib = nil; - } + if (!d->ps) + return; - if (d->fsFunc) { - [d->fsFunc release]; - d->fsFunc = nil; - } - if (d->fsLib) { - [d->fsLib release]; - d->fsLib = nil; - } + [d->ps release]; + d->ps = nil; rhiD->unregisterResource(this); } @@ -3159,34 +3165,66 @@ bool QMetalGraphicsPipeline::build() // buffers not just the resource binding layout) so leave it at the default for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) { - QString error; - QByteArray entryPoint; - id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), shaderStage.shaderVariant(), &error, &entryPoint); - if (!lib) { - qWarning("MSL shader compilation failed: %s", qPrintable(error)); - return false; - } - id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint); - if (!func) { - qWarning("MSL function for entry point %s not found", entryPoint.constData()); - [lib release]; - return false; - } - switch (shaderStage.type()) { - case QRhiShaderStage::Vertex: - rpDesc.vertexFunction = func; - d->vsLib = lib; - d->vsFunc = func; - break; - case QRhiShaderStage::Fragment: - rpDesc.fragmentFunction = func; - d->fsLib = lib; - d->fsFunc = func; - break; - default: - [func release]; - [lib release]; - break; + auto cacheIt = rhiD->d->shaderCache.constFind(shaderStage); + if (cacheIt != rhiD->d->shaderCache.constEnd()) { + switch (shaderStage.type()) { + case QRhiShaderStage::Vertex: + d->vs = *cacheIt; + [d->vs.lib retain]; + [d->vs.func retain]; + rpDesc.vertexFunction = d->vs.func; + break; + case QRhiShaderStage::Fragment: + d->fs = *cacheIt; + [d->fs.lib retain]; + [d->fs.func retain]; + rpDesc.fragmentFunction = d->fs.func; + break; + default: + break; + } + } else { + QString error; + QByteArray entryPoint; + id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), shaderStage.shaderVariant(), &error, &entryPoint); + if (!lib) { + qWarning("MSL shader compilation failed: %s", qPrintable(error)); + return false; + } + id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint); + if (!func) { + qWarning("MSL function for entry point %s not found", entryPoint.constData()); + [lib release]; + return false; + } + if (rhiD->d->shaderCache.count() >= QRhiMetal::MAX_SHADER_CACHE_ENTRIES) { + // Use the simplest strategy: too many cached shaders -> drop them all. + for (QMetalShader &s : rhiD->d->shaderCache) + s.release(); + rhiD->d->shaderCache.clear(); + } + switch (shaderStage.type()) { + case QRhiShaderStage::Vertex: + d->vs.lib = lib; + d->vs.func = func; + rhiD->d->shaderCache.insert(shaderStage, d->vs); + [d->vs.lib retain]; + [d->vs.func retain]; + rpDesc.vertexFunction = func; + break; + case QRhiShaderStage::Fragment: + d->fs.lib = lib; + d->fs.func = func; + rhiD->d->shaderCache.insert(shaderStage, d->fs); + [d->fs.lib retain]; + [d->fs.func retain]; + rpDesc.fragmentFunction = func; + break; + default: + [func release]; + [lib release]; + break; + } } } @@ -3286,22 +3324,13 @@ void QMetalComputePipeline::release() { QRHI_RES_RHI(QRhiMetal); - if (d->csFunc) { - [d->csFunc release]; - d->csFunc = nil; - } - if (d->csLib) { - [d->csLib release]; - d->csLib = nil; - } + d->cs.release(); if (!d->ps) return; - if (d->ps) { - [d->ps release]; - d->ps = nil; - } + [d->ps release]; + d->ps = nil; rhiD->unregisterResource(this); } @@ -3313,28 +3342,44 @@ bool QMetalComputePipeline::build() QRHI_RES_RHI(QRhiMetal); - const QShader shader = m_shaderStage.shader(); - QString error; - QByteArray entryPoint; - id<MTLLibrary> lib = rhiD->d->createMetalLib(shader, m_shaderStage.shaderVariant(), - &error, &entryPoint); - if (!lib) { - qWarning("MSL shader compilation failed: %s", qPrintable(error)); - return false; - } - id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint); - if (!func) { - qWarning("MSL function for entry point %s not found", entryPoint.constData()); - [lib release]; - return false; + auto cacheIt = rhiD->d->shaderCache.constFind(m_shaderStage); + if (cacheIt != rhiD->d->shaderCache.constEnd()) { + d->cs = *cacheIt; + } else { + const QShader shader = m_shaderStage.shader(); + QString error; + QByteArray entryPoint; + id<MTLLibrary> lib = rhiD->d->createMetalLib(shader, m_shaderStage.shaderVariant(), + &error, &entryPoint); + if (!lib) { + qWarning("MSL shader compilation failed: %s", qPrintable(error)); + return false; + } + id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint); + if (!func) { + qWarning("MSL function for entry point %s not found", entryPoint.constData()); + [lib release]; + return false; + } + d->cs.lib = lib; + d->cs.func = func; + d->cs.localSize = shader.description().computeShaderLocalSize(); + + if (rhiD->d->shaderCache.count() >= QRhiMetal::MAX_SHADER_CACHE_ENTRIES) { + for (QMetalShader &s : rhiD->d->shaderCache) + s.release(); + rhiD->d->shaderCache.clear(); + } + rhiD->d->shaderCache.insert(m_shaderStage, d->cs); } - d->csLib = lib; - d->csFunc = func; - std::array<uint, 3> localSize = shader.description().computeShaderLocalSize(); - d->localSize = MTLSizeMake(localSize[0], localSize[1], localSize[2]); + + [d->cs.lib retain]; + [d->cs.func retain]; + + d->localSize = MTLSizeMake(d->cs.localSize[0], d->cs.localSize[1], d->cs.localSize[2]); NSError *err = nil; - d->ps = [rhiD->d->dev newComputePipelineStateWithFunction: d->csFunc error: &err]; + d->ps = [rhiD->d->dev newComputePipelineStateWithFunction: d->cs.func error: &err]; if (!d->ps) { const QString msg = QString::fromNSString(err.localizedDescription); qWarning("Failed to create render pipeline state: %s", qPrintable(msg)); diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h index c448865f4d..01b0bf4f56 100644 --- a/src/gui/rhi/qrhimetal_p_p.h +++ b/src/gui/rhi/qrhimetal_p_p.h @@ -417,6 +417,7 @@ public: const QRhiNativeHandles *nativeHandles() override; void sendVMemStatsToProfiler() override; void makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; void executeDeferredReleases(bool forced = false); void finishActiveReadbacks(bool forced = false); diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index dff6e05268..29a3968bfc 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -174,6 +174,11 @@ void QRhiNull::makeThreadLocalNativeContextCurrent() // nothing to do here } +void QRhiNull::releaseCachedResources() +{ + // nothing to do here +} + QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags) { diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h index bdf0d59724..b43f830d5e 100644 --- a/src/gui/rhi/qrhinull_p_p.h +++ b/src/gui/rhi/qrhinull_p_p.h @@ -283,6 +283,7 @@ public: const QRhiNativeHandles *nativeHandles() override; void sendVMemStatsToProfiler() override; void makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; QRhiNullNativeHandles nativeHandlesStruct; QRhiSwapChain *currentSwapChain = nullptr; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index dfc85fb853..4f550c6a90 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -3744,6 +3744,11 @@ void QRhiVulkan::makeThreadLocalNativeContextCurrent() // nothing to do here } +void QRhiVulkan::releaseCachedResources() +{ + // nothing to do here +} + QRhiRenderBuffer *QRhiVulkan::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount, QRhiRenderBuffer::Flags flags) { diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index 962a1b8eb7..23cc80b814 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -712,6 +712,7 @@ public: const QRhiNativeHandles *nativeHandles() override; void sendVMemStatsToProfiler() override; void makeThreadLocalNativeContextCurrent() override; + void releaseCachedResources() override; VkResult createDescriptorPool(VkDescriptorPool *pool); bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex); |