rhi: Add backing format hint to QRhiRenderBuffer
Task-number: QTBUG-83707 Change-Id: I63548f4ace70af614a2aa082663bb3ae9fbedc25 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
parent
f2347077f5
commit
1c0a7a87e9
@ -2123,9 +2123,11 @@ QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
|
||||
\internal
|
||||
*/
|
||||
QRhiRenderBuffer::QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
|
||||
int sampleCount_, Flags flags_)
|
||||
int sampleCount_, Flags flags_,
|
||||
QRhiTexture::Format backingFormatHint_)
|
||||
: QRhiResource(rhi),
|
||||
m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_)
|
||||
m_type(type_), m_pixelSize(pixelSize_), m_sampleCount(sampleCount_), m_flags(flags_),
|
||||
m_backingFormatHint(backingFormatHint_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -5488,14 +5490,29 @@ QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
|
||||
\return a new renderbuffer with the specified \a type, \a pixelSize, \a
|
||||
sampleCount, and \a flags.
|
||||
|
||||
When \a backingFormatHint is set to a texture format other than
|
||||
QRhiTexture::UnknownFormat, it may be used by the backend to decide what
|
||||
format to use for the storage backing the renderbuffer.
|
||||
|
||||
\note \a backingFormatHint becomes relevant typically when multisampling
|
||||
and floating point texture formats are involved: rendering into a
|
||||
multisample QRhiRenderBuffer and then resolving into a non-RGBA8
|
||||
QRhiTexture implies (with some graphics APIs) that the storage backing the
|
||||
QRhiRenderBuffer uses the matching non-RGBA8 format. That means that
|
||||
passing a format like QRhiTexture::RGBA32F is important, because backends
|
||||
will typically opt for QRhiTexture::RGBA8 by default, which would then
|
||||
break later on due to attempting to set up RGBA8->RGBA32F multisample
|
||||
resolve in the color attachment(s) of the QRhiTextureRenderTarget.
|
||||
|
||||
\sa QRhiResource::release()
|
||||
*/
|
||||
QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags)
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
{
|
||||
return d->createRenderBuffer(type, pixelSize, sampleCount, flags);
|
||||
return d->createRenderBuffer(type, pixelSize, sampleCount, flags, backingFormatHint);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -908,11 +908,12 @@ public:
|
||||
|
||||
protected:
|
||||
QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
|
||||
int sampleCount_, Flags flags_);
|
||||
int sampleCount_, Flags flags_, QRhiTexture::Format backingFormatHint_);
|
||||
Type m_type;
|
||||
QSize m_pixelSize;
|
||||
int m_sampleCount;
|
||||
Flags m_flags;
|
||||
QRhiTexture::Format m_backingFormatHint;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
|
||||
@ -1493,7 +1494,8 @@ public:
|
||||
QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount = 1,
|
||||
QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags());
|
||||
QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags(),
|
||||
QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat);
|
||||
|
||||
QRhiTexture *newTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
|
@ -80,7 +80,8 @@ public:
|
||||
virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags) = 0;
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) = 0;
|
||||
virtual QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
|
@ -528,9 +528,10 @@ bool QRhiD3D11::isDeviceLost() const
|
||||
}
|
||||
|
||||
QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
{
|
||||
return new QD3D11RenderBuffer(this, type, pixelSize, sampleCount, flags);
|
||||
return new QD3D11RenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
|
||||
}
|
||||
|
||||
QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
|
||||
@ -2613,8 +2614,9 @@ ID3D11UnorderedAccessView *QD3D11Buffer::unorderedAccessView()
|
||||
}
|
||||
|
||||
QD3D11RenderBuffer::QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags, backingFormatHint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -2668,7 +2670,8 @@ bool QD3D11RenderBuffer::build()
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
if (m_type == Color) {
|
||||
dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
dxgiFormat = m_backingFormatHint == QRhiTexture::UnknownFormat ? DXGI_FORMAT_R8G8B8A8_UNORM
|
||||
: toD3DTextureFormat(m_backingFormatHint, {});
|
||||
desc.Format = dxgiFormat;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
|
||||
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
|
||||
@ -2721,6 +2724,9 @@ bool QD3D11RenderBuffer::build()
|
||||
|
||||
QRhiTexture::Format QD3D11RenderBuffer::backingFormat() const
|
||||
{
|
||||
if (m_backingFormatHint != QRhiTexture::UnknownFormat)
|
||||
return m_backingFormatHint;
|
||||
else
|
||||
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,8 @@ struct QD3D11Buffer : public QRhiBuffer
|
||||
struct QD3D11RenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags);
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QD3D11RenderBuffer();
|
||||
void release() override;
|
||||
bool build() override;
|
||||
@ -567,7 +568,8 @@ public:
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags) override;
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
|
@ -690,6 +690,87 @@ static inline GLenum toGlCompressedTextureFormat(QRhiTexture::Format format, QRh
|
||||
}
|
||||
}
|
||||
|
||||
static inline void toGlTextureFormat(QRhiTexture::Format format, const QRhiGles2::Caps &caps,
|
||||
GLenum *glintformat, GLenum *glsizedintformat,
|
||||
GLenum *glformat, GLenum *gltype)
|
||||
{
|
||||
switch (format) {
|
||||
case QRhiTexture::RGBA8:
|
||||
*glintformat = GL_RGBA;
|
||||
*glsizedintformat = caps.rgba8Format ? GL_RGBA8 : GL_RGBA;
|
||||
*glformat = GL_RGBA;
|
||||
*gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case QRhiTexture::BGRA8:
|
||||
*glintformat = caps.bgraInternalFormat ? GL_BGRA : GL_RGBA;
|
||||
*glsizedintformat = caps.rgba8Format ? GL_RGBA8 : GL_RGBA;
|
||||
*glformat = GL_BGRA;
|
||||
*gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case QRhiTexture::R16:
|
||||
*glintformat = GL_R16;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_RED;
|
||||
*gltype = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case QRhiTexture::R8:
|
||||
*glintformat = GL_R8;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_RED;
|
||||
*gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case QRhiTexture::RED_OR_ALPHA8:
|
||||
*glintformat = caps.coreProfile ? GL_R8 : GL_ALPHA;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = caps.coreProfile ? GL_RED : GL_ALPHA;
|
||||
*gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case QRhiTexture::RGBA16F:
|
||||
*glintformat = GL_RGBA16F;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_RGBA;
|
||||
*gltype = GL_HALF_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::RGBA32F:
|
||||
*glintformat = GL_RGBA32F;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_RGBA;
|
||||
*gltype = GL_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::R16F:
|
||||
*glintformat = GL_R16F;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_RED;
|
||||
*gltype = GL_HALF_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::R32F:
|
||||
*glintformat = GL_R32F;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_RED;
|
||||
*gltype = GL_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::D16:
|
||||
*glintformat = GL_DEPTH_COMPONENT16;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_DEPTH_COMPONENT;
|
||||
*gltype = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case QRhiTexture::D32F:
|
||||
*glintformat = GL_DEPTH_COMPONENT32F;
|
||||
*glsizedintformat = *glintformat;
|
||||
*glformat = GL_DEPTH_COMPONENT;
|
||||
*gltype = GL_FLOAT;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
*glintformat = GL_RGBA;
|
||||
*glsizedintformat = caps.rgba8Format ? GL_RGBA8 : GL_RGBA;
|
||||
*glformat = GL_RGBA;
|
||||
*gltype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool QRhiGles2::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
|
||||
{
|
||||
if (isCompressedFormat(format))
|
||||
@ -833,9 +914,10 @@ bool QRhiGles2::isDeviceLost() const
|
||||
}
|
||||
|
||||
QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
{
|
||||
return new QGles2RenderBuffer(this, type, pixelSize, sampleCount, flags);
|
||||
return new QGles2RenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
|
||||
}
|
||||
|
||||
QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
|
||||
@ -3435,8 +3517,9 @@ QRhiBuffer::NativeBuffer QGles2Buffer::nativeBuffer()
|
||||
}
|
||||
|
||||
QGles2RenderBuffer::QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags, backingFormatHint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -3522,13 +3605,26 @@ bool QGles2RenderBuffer::build()
|
||||
QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
|
||||
break;
|
||||
case QRhiRenderBuffer::Color:
|
||||
if (rhiD->caps.msaaRenderBuffer && samples > 1)
|
||||
rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8,
|
||||
{
|
||||
GLenum internalFormat = GL_RGBA4; // ES 2.0
|
||||
if (rhiD->caps.rgba8Format) {
|
||||
internalFormat = GL_RGBA8;
|
||||
if (m_backingFormatHint != QRhiTexture::UnknownFormat) {
|
||||
GLenum glintformat, glformat, gltype;
|
||||
// only care about the sized internal format, the rest is not used here
|
||||
toGlTextureFormat(m_backingFormatHint, rhiD->caps,
|
||||
&glintformat, &internalFormat, &glformat, &gltype);
|
||||
}
|
||||
}
|
||||
if (rhiD->caps.msaaRenderBuffer && samples > 1) {
|
||||
rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalFormat,
|
||||
size.width(), size.height());
|
||||
else
|
||||
rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA4,
|
||||
} else {
|
||||
rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, internalFormat,
|
||||
size.width(), size.height());
|
||||
}
|
||||
QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
@ -3541,6 +3637,9 @@ bool QGles2RenderBuffer::build()
|
||||
|
||||
QRhiTexture::Format QGles2RenderBuffer::backingFormat() const
|
||||
{
|
||||
if (m_backingFormatHint != QRhiTexture::UnknownFormat)
|
||||
return m_backingFormatHint;
|
||||
else
|
||||
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
|
||||
}
|
||||
|
||||
@ -3608,76 +3707,8 @@ bool QGles2Texture::prepareBuild(QSize *adjustedSize)
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RGBA;
|
||||
} else {
|
||||
switch (m_format) {
|
||||
case QRhiTexture::RGBA8:
|
||||
glintformat = GL_RGBA;
|
||||
glsizedintformat = rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
break;
|
||||
case QRhiTexture::BGRA8:
|
||||
glintformat = rhiD->caps.bgraInternalFormat ? GL_BGRA : GL_RGBA;
|
||||
glsizedintformat = rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA;
|
||||
glformat = GL_BGRA;
|
||||
break;
|
||||
case QRhiTexture::R16:
|
||||
glintformat = GL_R16;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RED;
|
||||
gltype = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case QRhiTexture::R8:
|
||||
glintformat = GL_R8;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RED;
|
||||
break;
|
||||
case QRhiTexture::RED_OR_ALPHA8:
|
||||
glintformat = rhiD->caps.coreProfile ? GL_R8 : GL_ALPHA;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = rhiD->caps.coreProfile ? GL_RED : GL_ALPHA;
|
||||
break;
|
||||
case QRhiTexture::RGBA16F:
|
||||
glintformat = GL_RGBA16F;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_HALF_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::RGBA32F:
|
||||
glintformat = GL_RGBA32F;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::R16F:
|
||||
glintformat = GL_R16F;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RED;
|
||||
gltype = GL_HALF_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::R32F:
|
||||
glintformat = GL_R32F;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_RED;
|
||||
gltype = GL_FLOAT;
|
||||
break;
|
||||
case QRhiTexture::D16:
|
||||
glintformat = GL_DEPTH_COMPONENT16;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_DEPTH_COMPONENT;
|
||||
gltype = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
case QRhiTexture::D32F:
|
||||
glintformat = GL_DEPTH_COMPONENT32F;
|
||||
glsizedintformat = glintformat;
|
||||
glformat = GL_DEPTH_COMPONENT;
|
||||
gltype = GL_FLOAT;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
glintformat = GL_RGBA;
|
||||
glsizedintformat = rhiD->caps.rgba8Format ? GL_RGBA8 : GL_RGBA;
|
||||
glformat = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
toGlTextureFormat(m_format, rhiD->caps,
|
||||
&glintformat, &glsizedintformat, &glformat, &gltype);
|
||||
}
|
||||
|
||||
samplerState = QGles2SamplerData();
|
||||
|
@ -89,7 +89,8 @@ struct QGles2Buffer : public QRhiBuffer
|
||||
struct QGles2RenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags);
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QGles2RenderBuffer();
|
||||
void release() override;
|
||||
bool build() override;
|
||||
@ -694,7 +695,8 @@ public:
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags) override;
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
|
@ -621,9 +621,10 @@ bool QRhiMetal::isDeviceLost() const
|
||||
}
|
||||
|
||||
QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
{
|
||||
return new QMetalRenderBuffer(this, type, pixelSize, sampleCount, flags);
|
||||
return new QMetalRenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
|
||||
}
|
||||
|
||||
QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
|
||||
@ -2232,149 +2233,6 @@ QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer()
|
||||
return { { &d->buf[0] }, 1 };
|
||||
}
|
||||
|
||||
QMetalRenderBuffer::QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags),
|
||||
d(new QMetalRenderBufferData)
|
||||
{
|
||||
}
|
||||
|
||||
QMetalRenderBuffer::~QMetalRenderBuffer()
|
||||
{
|
||||
release();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void QMetalRenderBuffer::release()
|
||||
{
|
||||
if (!d->tex)
|
||||
return;
|
||||
|
||||
QRhiMetalData::DeferredReleaseEntry e;
|
||||
e.type = QRhiMetalData::DeferredReleaseEntry::RenderBuffer;
|
||||
e.lastActiveFrameSlot = lastActiveFrameSlot;
|
||||
|
||||
e.renderbuffer.texture = d->tex;
|
||||
d->tex = nil;
|
||||
|
||||
QRHI_RES_RHI(QRhiMetal);
|
||||
rhiD->d->releaseQueue.append(e);
|
||||
QRHI_PROF;
|
||||
QRHI_PROF_F(releaseRenderBuffer(this));
|
||||
rhiD->unregisterResource(this);
|
||||
}
|
||||
|
||||
bool QMetalRenderBuffer::build()
|
||||
{
|
||||
if (d->tex)
|
||||
release();
|
||||
|
||||
if (m_pixelSize.isEmpty())
|
||||
return false;
|
||||
|
||||
QRHI_RES_RHI(QRhiMetal);
|
||||
samples = rhiD->effectiveSampleCount(m_sampleCount);
|
||||
|
||||
MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
|
||||
desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
|
||||
desc.width = NSUInteger(m_pixelSize.width());
|
||||
desc.height = NSUInteger(m_pixelSize.height());
|
||||
if (samples > 1)
|
||||
desc.sampleCount = NSUInteger(samples);
|
||||
desc.resourceOptions = MTLResourceStorageModePrivate;
|
||||
desc.usage = MTLTextureUsageRenderTarget;
|
||||
|
||||
bool transientBacking = false;
|
||||
switch (m_type) {
|
||||
case DepthStencil:
|
||||
#ifdef Q_OS_MACOS
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
d->format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
|
||||
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
|
||||
#else
|
||||
desc.storageMode = MTLStorageModeMemoryless;
|
||||
transientBacking = true;
|
||||
d->format = MTLPixelFormatDepth32Float_Stencil8;
|
||||
#endif
|
||||
desc.pixelFormat = d->format;
|
||||
break;
|
||||
case Color:
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
d->format = MTLPixelFormatRGBA8Unorm;
|
||||
desc.pixelFormat = d->format;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
d->tex = [rhiD->d->dev newTextureWithDescriptor: desc];
|
||||
[desc release];
|
||||
|
||||
if (!m_objectName.isEmpty())
|
||||
d->tex.label = [NSString stringWithUTF8String: m_objectName.constData()];
|
||||
|
||||
QRHI_PROF;
|
||||
QRHI_PROF_F(newRenderBuffer(this, transientBacking, false, samples));
|
||||
|
||||
lastActiveFrameSlot = -1;
|
||||
generation += 1;
|
||||
rhiD->registerResource(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
QRhiTexture::Format QMetalRenderBuffer::backingFormat() const
|
||||
{
|
||||
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
|
||||
}
|
||||
|
||||
QMetalTexture::QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
|
||||
int sampleCount, Flags flags)
|
||||
: QRhiTexture(rhi, format, pixelSize, sampleCount, flags),
|
||||
d(new QMetalTextureData(this))
|
||||
{
|
||||
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
|
||||
d->stagingBuf[i] = nil;
|
||||
|
||||
for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
|
||||
d->perLevelViews[i] = nil;
|
||||
}
|
||||
|
||||
QMetalTexture::~QMetalTexture()
|
||||
{
|
||||
release();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void QMetalTexture::release()
|
||||
{
|
||||
if (!d->tex)
|
||||
return;
|
||||
|
||||
QRhiMetalData::DeferredReleaseEntry e;
|
||||
e.type = QRhiMetalData::DeferredReleaseEntry::Texture;
|
||||
e.lastActiveFrameSlot = lastActiveFrameSlot;
|
||||
|
||||
e.texture.texture = d->owns ? d->tex : nil;
|
||||
d->tex = nil;
|
||||
|
||||
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
|
||||
e.texture.stagingBuffers[i] = d->stagingBuf[i];
|
||||
d->stagingBuf[i] = nil;
|
||||
}
|
||||
|
||||
for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
|
||||
e.texture.views[i] = d->perLevelViews[i];
|
||||
d->perLevelViews[i] = nil;
|
||||
}
|
||||
|
||||
QRHI_RES_RHI(QRhiMetal);
|
||||
rhiD->d->releaseQueue.append(e);
|
||||
QRHI_PROF;
|
||||
QRHI_PROF_F(releaseTexture(this));
|
||||
rhiD->unregisterResource(this);
|
||||
}
|
||||
|
||||
static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
|
||||
{
|
||||
const bool srgb = flags.testFlag(QRhiTexture::sRGB);
|
||||
@ -2507,6 +2365,156 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR
|
||||
}
|
||||
}
|
||||
|
||||
QMetalRenderBuffer::QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags, backingFormatHint),
|
||||
d(new QMetalRenderBufferData)
|
||||
{
|
||||
}
|
||||
|
||||
QMetalRenderBuffer::~QMetalRenderBuffer()
|
||||
{
|
||||
release();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void QMetalRenderBuffer::release()
|
||||
{
|
||||
if (!d->tex)
|
||||
return;
|
||||
|
||||
QRhiMetalData::DeferredReleaseEntry e;
|
||||
e.type = QRhiMetalData::DeferredReleaseEntry::RenderBuffer;
|
||||
e.lastActiveFrameSlot = lastActiveFrameSlot;
|
||||
|
||||
e.renderbuffer.texture = d->tex;
|
||||
d->tex = nil;
|
||||
|
||||
QRHI_RES_RHI(QRhiMetal);
|
||||
rhiD->d->releaseQueue.append(e);
|
||||
QRHI_PROF;
|
||||
QRHI_PROF_F(releaseRenderBuffer(this));
|
||||
rhiD->unregisterResource(this);
|
||||
}
|
||||
|
||||
bool QMetalRenderBuffer::build()
|
||||
{
|
||||
if (d->tex)
|
||||
release();
|
||||
|
||||
if (m_pixelSize.isEmpty())
|
||||
return false;
|
||||
|
||||
QRHI_RES_RHI(QRhiMetal);
|
||||
samples = rhiD->effectiveSampleCount(m_sampleCount);
|
||||
|
||||
MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
|
||||
desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
|
||||
desc.width = NSUInteger(m_pixelSize.width());
|
||||
desc.height = NSUInteger(m_pixelSize.height());
|
||||
if (samples > 1)
|
||||
desc.sampleCount = NSUInteger(samples);
|
||||
desc.resourceOptions = MTLResourceStorageModePrivate;
|
||||
desc.usage = MTLTextureUsageRenderTarget;
|
||||
|
||||
bool transientBacking = false;
|
||||
switch (m_type) {
|
||||
case DepthStencil:
|
||||
#ifdef Q_OS_MACOS
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
d->format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
|
||||
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
|
||||
#else
|
||||
desc.storageMode = MTLStorageModeMemoryless;
|
||||
transientBacking = true;
|
||||
d->format = MTLPixelFormatDepth32Float_Stencil8;
|
||||
#endif
|
||||
desc.pixelFormat = d->format;
|
||||
break;
|
||||
case Color:
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
if (m_backingFormatHint != QRhiTexture::UnknownFormat)
|
||||
d->format = toMetalTextureFormat(m_backingFormatHint, {});
|
||||
else
|
||||
d->format = MTLPixelFormatRGBA8Unorm;
|
||||
desc.pixelFormat = d->format;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
d->tex = [rhiD->d->dev newTextureWithDescriptor: desc];
|
||||
[desc release];
|
||||
|
||||
if (!m_objectName.isEmpty())
|
||||
d->tex.label = [NSString stringWithUTF8String: m_objectName.constData()];
|
||||
|
||||
QRHI_PROF;
|
||||
QRHI_PROF_F(newRenderBuffer(this, transientBacking, false, samples));
|
||||
|
||||
lastActiveFrameSlot = -1;
|
||||
generation += 1;
|
||||
rhiD->registerResource(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
QRhiTexture::Format QMetalRenderBuffer::backingFormat() const
|
||||
{
|
||||
if (m_backingFormatHint != QRhiTexture::UnknownFormat)
|
||||
return m_backingFormatHint;
|
||||
else
|
||||
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
|
||||
}
|
||||
|
||||
QMetalTexture::QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
|
||||
int sampleCount, Flags flags)
|
||||
: QRhiTexture(rhi, format, pixelSize, sampleCount, flags),
|
||||
d(new QMetalTextureData(this))
|
||||
{
|
||||
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
|
||||
d->stagingBuf[i] = nil;
|
||||
|
||||
for (int i = 0; i < QRhi::MAX_LEVELS; ++i)
|
||||
d->perLevelViews[i] = nil;
|
||||
}
|
||||
|
||||
QMetalTexture::~QMetalTexture()
|
||||
{
|
||||
release();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void QMetalTexture::release()
|
||||
{
|
||||
if (!d->tex)
|
||||
return;
|
||||
|
||||
QRhiMetalData::DeferredReleaseEntry e;
|
||||
e.type = QRhiMetalData::DeferredReleaseEntry::Texture;
|
||||
e.lastActiveFrameSlot = lastActiveFrameSlot;
|
||||
|
||||
e.texture.texture = d->owns ? d->tex : nil;
|
||||
d->tex = nil;
|
||||
|
||||
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
|
||||
e.texture.stagingBuffers[i] = d->stagingBuf[i];
|
||||
d->stagingBuf[i] = nil;
|
||||
}
|
||||
|
||||
for (int i = 0; i < QRhi::MAX_LEVELS; ++i) {
|
||||
e.texture.views[i] = d->perLevelViews[i];
|
||||
d->perLevelViews[i] = nil;
|
||||
}
|
||||
|
||||
QRHI_RES_RHI(QRhiMetal);
|
||||
rhiD->d->releaseQueue.append(e);
|
||||
QRHI_PROF;
|
||||
QRHI_PROF_F(releaseTexture(this));
|
||||
rhiD->unregisterResource(this);
|
||||
}
|
||||
|
||||
bool QMetalTexture::prepareBuild(QSize *adjustedSize)
|
||||
{
|
||||
if (d->tex)
|
||||
|
@ -79,7 +79,8 @@ struct QMetalRenderBufferData;
|
||||
struct QMetalRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags);
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QMetalRenderBuffer();
|
||||
void release() override;
|
||||
bool build() override;
|
||||
@ -349,7 +350,8 @@ public:
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags) override;
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
|
@ -182,9 +182,10 @@ bool QRhiNull::isDeviceLost() const
|
||||
}
|
||||
|
||||
QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
{
|
||||
return new QNullRenderBuffer(this, type, pixelSize, sampleCount, flags);
|
||||
return new QNullRenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
|
||||
}
|
||||
|
||||
QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
|
||||
@ -564,8 +565,9 @@ bool QNullBuffer::build()
|
||||
}
|
||||
|
||||
QNullRenderBuffer::QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags, backingFormatHint)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,8 @@ struct QNullBuffer : public QRhiBuffer
|
||||
struct QNullRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags);
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QNullRenderBuffer();
|
||||
void release() override;
|
||||
bool build() override;
|
||||
@ -207,7 +208,8 @@ public:
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags) override;
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
|
@ -4084,9 +4084,10 @@ bool QRhiVulkan::isDeviceLost() const
|
||||
}
|
||||
|
||||
QRhiRenderBuffer *QRhiVulkan::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags)
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
{
|
||||
return new QVkRenderBuffer(this, type, pixelSize, sampleCount, flags);
|
||||
return new QVkRenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
|
||||
}
|
||||
|
||||
QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
|
||||
@ -5241,8 +5242,9 @@ QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer()
|
||||
}
|
||||
|
||||
QVkRenderBuffer::QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, Flags flags)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
|
||||
int sampleCount, Flags flags,
|
||||
QRhiTexture::Format backingFormatHint)
|
||||
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags, backingFormatHint)
|
||||
{
|
||||
}
|
||||
|
||||
@ -5300,7 +5302,7 @@ bool QVkRenderBuffer::build()
|
||||
case QRhiRenderBuffer::Color:
|
||||
{
|
||||
if (!backingTexture) {
|
||||
backingTexture = QRHI_RES(QVkTexture, rhiD->createTexture(QRhiTexture::RGBA8,
|
||||
backingTexture = QRHI_RES(QVkTexture, rhiD->createTexture(backingFormat(),
|
||||
m_pixelSize,
|
||||
m_sampleCount,
|
||||
QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
|
||||
@ -5344,6 +5346,9 @@ bool QVkRenderBuffer::build()
|
||||
|
||||
QRhiTexture::Format QVkRenderBuffer::backingFormat() const
|
||||
{
|
||||
if (m_backingFormatHint != QRhiTexture::UnknownFormat)
|
||||
return m_backingFormatHint;
|
||||
else
|
||||
return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,8 @@ struct QVkTexture;
|
||||
struct QVkRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, Flags flags);
|
||||
int sampleCount, Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QVkRenderBuffer();
|
||||
void release() override;
|
||||
bool build() override;
|
||||
@ -658,7 +659,8 @@ public:
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags) override;
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
|
Loading…
Reference in New Issue
Block a user