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:
Laszlo Agocs 2020-04-28 18:15:03 +02:00
parent f2347077f5
commit 1c0a7a87e9
13 changed files with 339 additions and 257 deletions

View File

@ -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);
}
/*!

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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,

View File

@ -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();

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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)
{
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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,