Commit 64509cc5 authored by Laszlo Agocs's avatar Laszlo Agocs

d3d: Add compressed and sRGB texture support

...and related plumbing here and there.
parent cba06005
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../shared/examplefw.h"
#include "../shared/cube.h"
struct {
QRhiBuffer *vbuf = nullptr;
bool vbufReady = false;
QRhiBuffer *ubuf = nullptr;
QRhiTexture *tex = nullptr;
QRhiSampler *sampler = nullptr;
QRhiShaderResourceBindings *srb = nullptr;
QRhiGraphicsPipeline *ps = nullptr;
float rotation = 0;
QByteArrayList compressedData;
} d;
static const quint32 DDS_MAGIC = 0x20534444; // 'DDS '
static const quint32 DDS_FOURCC = 4;
#define FOURCC(c0, c1, c2, c3) ((c0) | ((c1) << 8) | ((c2) << 16) | ((c3 << 24)))
struct DDS_PIXELFORMAT {
quint32 size;
quint32 flags;
quint32 fourCC;
quint32 rgbBitCount;
quint32 rBitMask;
quint32 gBitMask;
quint32 bBitMask;
quint32 aBitMask;
};
struct DDS_HEADER {
quint32 size;
quint32 flags;
quint32 height;
quint32 width;
quint32 pitch;
quint32 depth;
quint32 mipMapCount;
quint32 reserved1[11];
DDS_PIXELFORMAT pixelFormat;
quint32 caps;
quint32 caps2;
quint32 caps3;
quint32 caps4;
quint32 reserved2;
};
static quint32 bc1size(const QSize &size)
{
static const quint32 blockSize = 8; // 8 bytes for BC1
const quint32 bytesPerLine = qMax<quint32>(1, (size.width() + 3) / 4) * blockSize;
const quint32 ySize = qMax<quint32>(1, (size.height() + 3) / 4);
return bytesPerLine * ySize;
}
static QByteArrayList loadBC1(const QString &filename, QSize *size, int *mipLevelCount)
{
QFile f(filename);
if (!f.open(QIODevice::ReadOnly)) {
qWarning("Failed to open %s", qPrintable(filename));
return QByteArrayList();
}
quint32 magic = 0;
f.read(reinterpret_cast<char *>(&magic), sizeof(magic));
if (magic != DDS_MAGIC) {
qWarning("%s is not a DDS file", qPrintable(filename));
return QByteArrayList();
}
DDS_HEADER header;
f.read(reinterpret_cast<char *>(&header), sizeof(header));
if (header.size != sizeof(DDS_HEADER)) {
qWarning("Invalid DDS header size");
return QByteArrayList();
}
if (header.pixelFormat.size != sizeof(DDS_PIXELFORMAT)) {
qWarning("Invalid DDS pixel format size");
return QByteArrayList();
}
if (!(header.pixelFormat.flags & DDS_FOURCC)) {
qWarning("Invalid DDS pixel format");
return QByteArrayList();
}
if (header.pixelFormat.fourCC != FOURCC('D', 'X', 'T', '1')) {
qWarning("Only DXT1 (BC1) is supported");
return QByteArrayList();
}
QByteArrayList data;
QSize sz(header.width, header.height);
for (quint32 level = 0; level < header.mipMapCount; ++level) {
data.append(f.read(bc1size(sz)));
sz.setWidth(qMax(1, sz.width() / 2));
sz.setHeight(qMax(1, sz.height() / 2));
}
*size = QSize(header.width, header.height);
*mipLevelCount = header.mipMapCount;
return data;
}
void Window::customInit()
{
if (!m_r->canTextureFormatBeSupported(QRhiTexture::BC1))
qFatal("This backend does not support BC1");
d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
d.vbuf->build();
d.vbufReady = false;
d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68);
d.ubuf->build();
QSize size;
int mipCount = 0;
d.compressedData = loadBC1(QLatin1String(":/qt.dds"), &size, &mipCount);
d.tex = m_r->newTexture(QRhiTexture::BC1, size, 0);
d.tex->build();
d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
d.sampler->build();
d.srb = m_r->newShaderResourceBindings();
d.srb->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler)
});
d.srb->build();
d.ps = m_r->newGraphicsPipeline();
d.ps->setDepthTest(true);
d.ps->setDepthWrite(true);
d.ps->setDepthOp(QRhiGraphicsPipeline::Less);
d.ps->setCullMode(QRhiGraphicsPipeline::Back);
d.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
const QBakedShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
if (!vs.isValid())
qFatal("Failed to load shader pack (vertex)");
const QBakedShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
if (!fs.isValid())
qFatal("Failed to load shader pack (fragment)");
d.ps->setShaderStages({
{ QRhiGraphicsShaderStage::Vertex, vs },
{ QRhiGraphicsShaderStage::Fragment, fs }
});
QRhiVertexInputLayout inputLayout;
inputLayout.bindings = {
{ 3 * sizeof(float) },
{ 2 * sizeof(float) }
};
inputLayout.attributes = {
{ 0, 0, QRhiVertexInputLayout::Attribute::Float3, 0 },
{ 1, 1, QRhiVertexInputLayout::Attribute::Float2, 0 }
};
d.ps->setVertexInputLayout(inputLayout);
d.ps->setShaderResourceBindings(d.srb);
d.ps->setRenderPassDescriptor(m_rp);
d.ps->build();
}
void Window::customRelease()
{
if (d.ps) {
d.ps->releaseAndDestroy();
d.ps = nullptr;
}
if (d.srb) {
d.srb->releaseAndDestroy();
d.srb = nullptr;
}
if (d.ubuf) {
d.ubuf->releaseAndDestroy();
d.ubuf = nullptr;
}
if (d.vbuf) {
d.vbuf->releaseAndDestroy();
d.vbuf = nullptr;
}
if (d.sampler) {
d.sampler->releaseAndDestroy();
d.sampler = nullptr;
}
if (d.tex) {
d.tex->releaseAndDestroy();
d.tex = nullptr;
}
}
void Window::customRender()
{
QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
if (!d.vbufReady) {
d.vbufReady = true;
u->uploadStaticBuffer(d.vbuf, cube);
qint32 flip = 0;
u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
}
if (!d.compressedData.isEmpty()) {
QRhiTextureUploadDescription::Layer::MipLevel image(d.compressedData[0]);
QRhiTextureUploadDescription desc;
desc.layers.append({ { image } });
u->uploadTexture(d.tex, desc);
d.compressedData.clear();
}
d.rotation += 1.0f;
QMatrix4x4 mvp = m_proj;
mvp.scale(0.5f);
mvp.rotate(d.rotation, 0, 1, 0);
u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData());
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
const QSize outputSizeInPixels = m_sc->effectivePixelSize();
m_r->beginPass(m_sc->currentFrameRenderTarget(), cb, { 0.4f, 0.7f, 0.0f, 1.0f }, { 1.0f, 0 }, u);
m_r->setGraphicsPipeline(cb, d.ps);
m_r->setViewport(cb, { 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
m_r->setVertexInput(cb, 0, { { d.vbuf, 0 }, { d.vbuf, 36 * 3 * sizeof(float) } });
m_r->draw(cb, 36);
m_r->endPass(cb);
}
TEMPLATE = app
QT += shadertools rhi
SOURCES = \
compressedtexture_bc1.cpp
RESOURCES = compressedtexture_bc1.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/rhi/compressedtexture_bc1
INSTALLS += target
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>qt.dds</file>
<file alias="texture.vert.qsb">../shared/texture.vert.qsb</file>
<file alias="texture.frag.qsb">../shared/texture.frag.qsb</file>
</qresource>
</RCC>
......@@ -2,6 +2,7 @@ TEMPLATE = subdirs
SUBDIRS += \
hellominimalcrossgfxtriangle \
compressedtexture_bc1 \
plainqwindow_gles2
qtConfig(vulkan) {
......
This diff is collapsed.
......@@ -50,6 +50,8 @@
#include "examplewindow.h"
//#define USE_SRGB_SWAPCHAIN
void ExampleWindow::exposeEvent(QExposeEvent *)
{
// You never know how Vulkan behaves today - at some point it started
......@@ -112,6 +114,9 @@ void ExampleWindow::init()
m_sc->setSampleCount(m_sampleCount);
m_scrp = m_sc->newCompatibleRenderPassDescriptor();
m_sc->setRenderPassDescriptor(m_scrp);
#ifdef USE_SRGB_SWAPCHAIN
m_sc->setFlags(QRhiSwapChain::sRGB);
#endif
m_triRenderer.setRhi(m_r);
m_triRenderer.setSampleCount(m_sampleCount);
......
......@@ -350,6 +350,11 @@ QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
return d->clipSpaceCorrMatrix();
}
bool QRhi::canTextureFormatBeSupported(QRhiTexture::Format format) const
{
return d->canTextureFormatBeSupported(format);
}
QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
{
return d->createGraphicsPipeline();
......
......@@ -262,7 +262,9 @@ struct Q_RHI_EXPORT QRhiTextureUploadDescription
struct Q_RHI_EXPORT MipLevel {
MipLevel() { }
MipLevel(const QImage &image_) : image(image_) { }
MipLevel(const QByteArray &compressedData_) : compressedData(compressedData_) { }
QImage image;
QByteArray compressedData;
};
Layer() { }
Layer(const QVector<MipLevel> &mipImages_) : mipImages(mipImages_) { }
......@@ -760,7 +762,8 @@ class Q_RHI_EXPORT QRhiSwapChain : public QRhiResource
public:
enum SurfaceImportFlag {
SurfaceHasPreMulAlpha = 1 << 0,
SurfaceHasNonPreMulAlpha = 1 << 1
SurfaceHasNonPreMulAlpha = 1 << 1,
sRGB = 1 << 2
};
Q_DECLARE_FLAGS(SurfaceImportFlags, SurfaceImportFlag)
......@@ -844,7 +847,7 @@ public:
void updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
void uploadTexture(QRhiTexture *tex, const QImage &image);
void uploadTexture(QRhiTexture *tex, const QImage &image); // shortcut
// This is not normally needed, textures that have an upload or are used
// with a TextureRenderTarget will be fine without it. May be more relevant later.
......@@ -1028,6 +1031,11 @@ public:
// instead of just mvp, to their vertex shaders)
QMatrix4x4 clipSpaceCorrMatrix() const;
// This is not isTextureFormatSupported: the result does not guarantee
// runtime availability, it only helps determining the guaranteed hopeless
// cases based on a static list from the backends.
bool canTextureFormatBeSupported(QRhiTexture::Format format) const;
protected:
QRhi();
......
......@@ -115,6 +115,7 @@ public:
virtual int ubufAlignment() const = 0;
virtual bool isYUpInFramebuffer() const = 0;
virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
virtual bool canTextureFormatBeSupported(QRhiTexture::Format format) const = 0;
QVector<QRhiResourceUpdateBatch *> resUpdPool;
QBitArray resUpdPoolMap;
......
......@@ -228,6 +228,14 @@ QMatrix4x4 QRhiD3D11::clipSpaceCorrMatrix() const
return m;
}
bool QRhiD3D11::canTextureFormatBeSupported(QRhiTexture::Format format) const
{
if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
return false;
return true;
}
QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Hints hints)
{
......@@ -487,6 +495,47 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
return QRhi::FrameOpSuccess;
}
static inline bool isCompressedFormat(QRhiTexture::Format format)
{
return format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7;
}
static void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
quint32 *bpl, quint32 *alignedHeight)
{
quint32 blockSize = 0;
switch (format) {
case QRhiTexture::BC1:
blockSize = 8;
break;
case QRhiTexture::BC2:
blockSize = 16;
break;
case QRhiTexture::BC3:
blockSize = 16;
break;
case QRhiTexture::BC4:
blockSize = 8;
break;
case QRhiTexture::BC5:
blockSize = 16;
break;
case QRhiTexture::BC6H:
blockSize = 16;
break;
case QRhiTexture::BC7:
blockSize = 16;
break;
default:
Q_UNREACHABLE();
break;
}
if (bpl)
*bpl = qMax<quint32>(1, (size.width() + 3) / 4) * blockSize;
if (alignedHeight)
*alignedHeight = qMax<quint32>(1, (size.height() + 3) / 4);
}
void QRhiD3D11::commitResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
{
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
......@@ -522,7 +571,15 @@ void QRhiD3D11::commitResourceUpdates(QRhiResourceUpdateBatch *resourceUpdates)
for (int level = 0, levelCount = layerDesc.mipImages.count(); level != levelCount; ++level) {
const QRhiTextureUploadDescription::Layer::MipLevel mipDesc(layerDesc.mipImages[level]);
UINT subres = D3D11CalcSubresource(level, layer, texD->mipLevelCount);
context->UpdateSubresource(texD->tex, subres, nullptr, mipDesc.image.constBits(), mipDesc.image.bytesPerLine(), 0);
if (!mipDesc.image.isNull()) {
context->UpdateSubresource(texD->tex, subres, nullptr,
mipDesc.image.constBits(), mipDesc.image.bytesPerLine(), 0);
} else if (!mipDesc.compressedData.isEmpty() && isCompressedFormat(texD->m_format)) {
quint32 bpl = 0;
compressedFormatInfo(texD->m_format, texD->m_pixelSize, &bpl, nullptr);
context->UpdateSubresource(texD->tex, subres, nullptr,
mipDesc.compressedData.constData(), bpl, 0);
}
}
}
}
......@@ -1005,13 +1062,14 @@ void QD3D11Texture::release()
tex = nullptr;
}
static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format)
static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
{
const bool srgb = flags.testFlag(QRhiTexture::sRGB);
switch (format) {
case QRhiTexture::RGBA8:
return DXGI_FORMAT_R8G8B8A8_UNORM;
return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
case QRhiTexture::BGRA8:
return DXGI_FORMAT_B8G8R8A8_UNORM;
return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
case QRhiTexture::R8:
return DXGI_FORMAT_R8_UNORM;
case QRhiTexture::R16:
......@@ -1022,6 +1080,59 @@ static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format)
case QRhiTexture::D32:
return DXGI_FORMAT_R32_TYPELESS;
case QRhiTexture::BC1:
return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
case QRhiTexture::BC2:
return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
case QRhiTexture::BC3:
return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
case QRhiTexture::BC4:
return DXGI_FORMAT_BC4_UNORM;
case QRhiTexture::BC5:
return DXGI_FORMAT_BC5_UNORM;
case QRhiTexture::BC6H:
return DXGI_FORMAT_BC6H_UF16;
case QRhiTexture::BC7:
return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
case QRhiTexture::ETC2_RGB8:
Q_FALLTHROUGH();
case QRhiTexture::ETC2_RGB8A1:
Q_FALLTHROUGH();
case QRhiTexture::ETC2_RGBA8:
qWarning("QRhiD3D11 does not support ETC2 textures");
return DXGI_FORMAT_R8G8B8A8_UNORM;
case QRhiTexture::ASTC_4x4:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_5x4:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_5x5:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_6x5:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_6x6:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_8x5:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_8x6:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_8x8:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_10x5:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_10x6:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_10x8:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_10x10:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_12x10:
Q_FALLTHROUGH();
case QRhiTexture::ASTC_12x12:
qWarning("QRhiD3D11 does not support ASTC textures");
return DXGI_FORMAT_R8G8B8A8_UNORM;
default:
Q_UNREACHABLE();
return DXGI_FORMAT_R8G8B8A8_UNORM;
......@@ -1098,7 +1209,7 @@ bool QD3D11Texture::build()
desc.Height = size.height();
desc.MipLevels = mipLevelCount;
desc.ArraySize = isCube ? 6 : 1;;
desc.Format = toD3DTextureFormat(m_format);
desc.Format = toD3DTextureFormat(m_format, m_flags);
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = bindFlags;
......@@ -1306,7 +1417,7 @@ bool QD3D11TextureRenderTarget::build()
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, texture);
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
memset(&rtvDesc, 0, sizeof(rtvDesc));
rtvDesc.Format = toD3DTextureFormat(texD->format());
rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.FirstArraySlice = m_desc.colorAttachments[i].layer;
......@@ -1916,7 +2027,11 @@ bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI
return false;
}
hr = rhiD->dev->CreateRenderTargetView(*tex, nullptr, rtv);
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
memset(&rtvDesc, 0, sizeof(rtvDesc));
rtvDesc.Format = format;
rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
if (FAILED(hr)) {
qWarning("Failed to create color buffer rtv: %s", qPrintable(comErrorMessage(hr)));
(*tex)->Release();
......@@ -1937,7 +2052,11 @@ bool QD3D11SwapChain::buildOrResize()
window = m_window;
pixelSize = m_requestedPixelSize;
colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
const DXGI_FORMAT srgbAdjustedFormat = m_flags.testFlag(sRGB) ?
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
const UINT swapChainFlags = 0;
QRHI_RES_RHI(QRhiD3D11);
......@@ -1986,13 +2105,17 @@ bool QD3D11SwapChain::buildOrResize()
qWarning("Failed to query swapchain buffer %d: %s", i, qPrintable(comErrorMessage(hr)));
return false;
}
hr = rhiD->dev->CreateRenderTargetView(tex[i], nullptr, &rtv[i]);
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
memset(&rtvDesc, 0, sizeof(rtvDesc));
rtvDesc.Format = srgbAdjustedFormat;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateRenderTargetView(tex[i], &rtvDesc, &rtv[i]);
if (FAILED(hr)) {
qWarning("Failed to create rtv for swapchain buffer %d: %s", i, qPrintable(comErrorMessage(hr)));
return false;
}
if (sampleDesc.Count > 1) {
if (!newColorBuffer(pixelSize, colorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
if (!newColorBuffer(pixelSize, srgbAdjustedFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
return false;
}
}
......
......@@ -407,6 +407,7 @@ public:
int ubufAlignment() const override;
bool isYUpInFramebuffer() const override;