Commit 3cee5983 authored by Laszlo Agocs's avatar Laszlo Agocs

Make QRhiShaderResourceBinding a proper class

Here we choose to go the heavy weight route and turn it into a
d-pointered (implicitly shared, even) class since the data a binding
description needs may grow in yet-unknown ways when introducing support
for other resource types.
parent c9911761
......@@ -215,7 +215,7 @@ void Window::customRender()
// Now replace d.tex with d.newTex as the shader resource.
auto bindings = d.srb->bindings();
bindings[1].stex.tex = d.newTex; // see customInit, this was d.tex originally
bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.newTex, d.sampler);
d.srb->setBindings(bindings);
// "rebuild", whatever that means for a given backend. This srb is
// already live as the ps in the setGraphicsPipeline references it,
......@@ -264,7 +264,7 @@ void Window::customRender()
// switch to showing d.importedTex
auto bindings = d.srb->bindings();
bindings[1].stex.tex = d.importedTex;
bindings[1] = QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.importedTex, d.sampler);
d.srb->setBindings(bindings);
d.srb->build();
} else {
......
......@@ -1516,7 +1516,7 @@ void QRhiResource::releaseAndDestroy()
}
/*!
Returns the currently set object name. By default the name is empty.
\return the currently set object name. By default the name is empty.
*/
QByteArray QRhiResource::name() const
{
......@@ -1782,58 +1782,117 @@ QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
}
/*!
Returns a shader resource binding for the given binding number, pipeline
stage, and buffer specified by \a binding_, \a stage_, and \a buf_.
\internal
*/
QRhiShaderResourceBinding::QRhiShaderResourceBinding()
: d(new QRhiShaderResourceBindingPrivate)
{
}
/*!
\internal
*/
void QRhiShaderResourceBinding::detach()
{
if (d->ref.load() != 1) {
QRhiShaderResourceBindingPrivate *newd = new QRhiShaderResourceBindingPrivate(d);
if (!d->ref.deref())
delete d;
d = newd;
}
}
/*!
\internal
*/
QRhiShaderResourceBinding::QRhiShaderResourceBinding(const QRhiShaderResourceBinding &other)
{
d = other.d;
d->ref.ref();
}
/*!
\internal
*/
QRhiShaderResourceBinding &QRhiShaderResourceBinding::operator=(const QRhiShaderResourceBinding &other)
{
if (d != other.d) {
other.d->ref.ref();
if (!d->ref.deref())
delete d;
d = other.d;
}
return *this;
}
/*!
Destructor.
*/
QRhiShaderResourceBinding::~QRhiShaderResourceBinding()
{
if (!d->ref.deref())
delete d;
}
/*!
\return a shader resource binding for the given binding number, pipeline
stage, and buffer specified by \a binding, \a stage, and \a buf.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
int binding_, StageFlags stage_, QRhiBuffer *buf_)
int binding, StageFlags stage, QRhiBuffer *buf)
{
QRhiShaderResourceBinding b;
b.binding = binding_;
b.stage = stage_;
b.type = UniformBuffer;
b.ubuf.buf = buf_;
b.ubuf.offset = 0;
b.ubuf.maybeSize = 0; // entire buffer
QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
Q_ASSERT(d->ref.load() == 1);
d->binding = binding;
d->stage = stage;
d->type = UniformBuffer;
d->u.ubuf.buf = buf;
d->u.ubuf.offset = 0;
d->u.ubuf.maybeSize = 0; // entire buffer
return b;
}
/*!
Returns a shader resource binding for the given binding number, pipeline
stage, and buffer specified by \a binding_, \a stage_, and \a buf_. This
overload binds a region only, as specified by \a offset_ and \a size_.
\return a shader resource binding for the given binding number, pipeline
stage, and buffer specified by \a binding, \a stage, and \a buf. This
overload binds a region only, as specified by \a offset and \a size.
\note It is up to the user to ensure the offset is aligned to
QRhi::ubufAlignment().
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
int binding_, StageFlags stage_, QRhiBuffer *buf_, int offset_, int size_)
int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
{
Q_ASSERT(size_ > 0);
Q_ASSERT(size > 0);
QRhiShaderResourceBinding b;
b.binding = binding_;
b.stage = stage_;
b.type = UniformBuffer;
b.ubuf.buf = buf_;
b.ubuf.offset = offset_;
b.ubuf.maybeSize = size_;
QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
Q_ASSERT(d->ref.load() == 1);
d->binding = binding;
d->stage = stage;
d->type = UniformBuffer;
d->u.ubuf.buf = buf;
d->u.ubuf.offset = offset;
d->u.ubuf.maybeSize = size;
return b;
}
/*!
Returns a shader resource binding for the given binding number, pipeline
stage, texture, and sampler specified by \a binding_, \a stage_, \a tex_,
\a sampler_.
\return a shader resource binding for the given binding number, pipeline
stage, texture, and sampler specified by \a binding, \a stage, \a tex,
\a sampler.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
int binding_, StageFlags stage_, QRhiTexture *tex_, QRhiSampler *sampler_)
int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
{
QRhiShaderResourceBinding b;
b.binding = binding_;
b.stage = stage_;
b.type = SampledTexture;
b.stex.tex = tex_;
b.stex.sampler = sampler_;
QRhiShaderResourceBindingPrivate *d = QRhiShaderResourceBindingPrivate::get(&b);
Q_ASSERT(d->ref.load() == 1);
d->binding = binding;
d->stage = stage;
d->type = SampledTexture;
d->u.stex.tex = tex;
d->u.stex.sampler = sampler;
return b;
}
......@@ -2851,7 +2910,7 @@ bool QRhi::isYUpInFramebuffer() const
}
/*!
Returns a matrix that can be used allow applications keep using
\return a matrix that can be used allow applications keep using
OpenGL-targeted vertex data and projection matrices (for example, the ones
generated by QMatrix4x4::perspective()) regardless of the backed. Once
\c{this_matrix * mvp} is used instead of just \c mvp, vertex data with Y up
......
......@@ -59,6 +59,7 @@ class QRhiCommandBuffer;
class QRhiResourceUpdateBatch;
class QRhiResourceUpdateBatchPrivate;
class QRhiProfiler;
class QRhiShaderResourceBindingPrivate;
class Q_RHI_EXPORT QRhiColorClearValue
{
......@@ -165,6 +166,7 @@ private:
quint32 m_stride;
Classification m_classification;
int m_instanceStepRate;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_MOVABLE_TYPE);
......@@ -204,6 +206,7 @@ private:
int m_location;
Format m_format;
quint32 m_offset;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_MOVABLE_TYPE);
......@@ -220,6 +223,7 @@ public:
private:
QVector<QRhiVertexInputBinding> m_bindings;
QVector<QRhiVertexInputAttribute> m_attributes;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiVertexInputLayout, Q_MOVABLE_TYPE);
......@@ -248,12 +252,14 @@ public:
private:
Type m_type;
QBakedShader m_shader;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiGraphicsShaderStage, Q_MOVABLE_TYPE);
struct Q_RHI_EXPORT QRhiShaderResourceBinding
class Q_RHI_EXPORT QRhiShaderResourceBinding
{
public:
enum Type {
UniformBuffer,
SampledTexture
......@@ -267,26 +273,19 @@ struct Q_RHI_EXPORT QRhiShaderResourceBinding
};
Q_DECLARE_FLAGS(StageFlags, StageFlag)
static QRhiShaderResourceBinding uniformBuffer(int binding_, StageFlags stage_, QRhiBuffer *buf_);
static QRhiShaderResourceBinding uniformBuffer(int binding_, StageFlags stage_, QRhiBuffer *buf_, int offset_, int size_);
static QRhiShaderResourceBinding sampledTexture(int binding_, StageFlags stage_, QRhiTexture *tex_, QRhiSampler *sampler_);
int binding;
StageFlags stage;
Type type;
struct UniformBufferData {
QRhiBuffer *buf;
int offset;
int maybeSize;
};
struct SampledTextureData {
QRhiTexture *tex;
QRhiSampler *sampler;
};
union {
UniformBufferData ubuf;
SampledTextureData stex;
};
QRhiShaderResourceBinding();
QRhiShaderResourceBinding(const QRhiShaderResourceBinding &other);
QRhiShaderResourceBinding &operator=(const QRhiShaderResourceBinding &other);
~QRhiShaderResourceBinding();
void detach();
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf);
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
private:
QRhiShaderResourceBindingPrivate *d;
friend class QRhiShaderResourceBindingPrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags)
......@@ -323,13 +322,12 @@ public:
private:
QRhiTexture *m_texture = nullptr;
QRhiRenderBuffer *m_renderBuffer = nullptr;
int m_layer = 0;
int m_level = 0;
QRhiTexture *m_resolveTexture = nullptr;
int m_resolveLayer = 0;
int m_resolveLevel = 0;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_MOVABLE_TYPE);
......@@ -361,6 +359,7 @@ private:
QVector<QRhiColorAttachment> m_colorAttachments;
QRhiRenderBuffer *m_depthStencilBuffer = nullptr;
QRhiTexture *m_depthTexture = nullptr;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiTextureRenderTargetDescription, Q_MOVABLE_TYPE);
......@@ -393,6 +392,7 @@ private:
QPoint m_destinationTopLeft;
QSize m_sourceSize;
QPoint m_sourceTopLeft;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiTextureMipLevel, Q_MOVABLE_TYPE);
......@@ -408,6 +408,7 @@ public:
private:
QVector<QRhiTextureMipLevel> m_mipImages;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiTextureLayer, Q_MOVABLE_TYPE);
......@@ -423,6 +424,7 @@ public:
private:
QVector<QRhiTextureLayer> m_layers;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE);
......@@ -455,14 +457,13 @@ public:
private:
QSize m_pixelSize;
int m_sourceLayer = 0;
int m_sourceLevel = 0;
QPoint m_sourceTopLeft;
int m_destinationLayer = 0;
int m_destinationLevel = 0;
QPoint m_destinationTopLeft;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_MOVABLE_TYPE);
......@@ -486,6 +487,7 @@ private:
QRhiTexture *m_texture = nullptr;
int m_layer = 0;
int m_level = 0;
void *m_reserved;
};
Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_MOVABLE_TYPE);
......
......@@ -45,6 +45,7 @@
#include "qrhi.h"
#include "qrhiprofiler_p.h"
#include <QBitArray>
#include <QAtomicInt>
QT_BEGIN_NAMESPACE
......@@ -263,6 +264,45 @@ Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureRead, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureMipGen, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TexturePrepare, Q_MOVABLE_TYPE);
class Q_RHI_PRIVATE_EXPORT QRhiShaderResourceBindingPrivate
{
public:
QRhiShaderResourceBindingPrivate()
: ref(1)
{
}
QRhiShaderResourceBindingPrivate(const QRhiShaderResourceBindingPrivate *other)
: ref(1),
binding(other->binding),
stage(other->stage),
type(other->type),
u(other->u)
{
}
static QRhiShaderResourceBindingPrivate *get(QRhiShaderResourceBinding *s) { return s->d; }
static const QRhiShaderResourceBindingPrivate *get(const QRhiShaderResourceBinding *s) { return s->d; }
QAtomicInt ref;
int binding;
QRhiShaderResourceBinding::StageFlags stage;
QRhiShaderResourceBinding::Type type;
struct UniformBufferData {
QRhiBuffer *buf;
int offset;
int maybeSize;
};
struct SampledTextureData {
QRhiTexture *tex;
QRhiSampler *sampler;
};
union {
UniformBufferData ubuf;
SampledTextureData stex;
} u;
};
template<typename T>
struct QRhiBatchedBindings
{
......
......@@ -394,12 +394,12 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
bool srbUpdate = false;
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->sortedBindings[i]);
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b.type) {
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b.ubuf.buf);
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD);
......@@ -411,8 +411,8 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b.stex.sampler);
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
if (texD->generation != bd.stex.texGeneration
|| samplerD->generation != bd.stex.samplerGeneration)
{
......@@ -1314,28 +1314,28 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->fsshaderresources.clear();
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->sortedBindings[i]);
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->sortedBindings[i]);
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b.type) {
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b.ubuf.buf);
Q_ASSERT(aligned(b.ubuf.offset, 256) == b.ubuf.offset);
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
Q_ASSERT(aligned(b->u.ubuf.offset, 256) == b->u.ubuf.offset);
bd.ubuf.generation = bufD->generation;
const uint offsetInConstants = b.ubuf.offset / 16;
const uint offsetInConstants = b->u.ubuf.offset / 16;
// size must be 16 mult. (in constants, i.e. multiple of 256 bytes).
// We can round up if needed since the buffers's actual size
// (ByteWidth) is always a multiple of 256.
const uint sizeInConstants = aligned(b.ubuf.maybeSize ? b.ubuf.maybeSize : bufD->m_size, 256) / 16;
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vsubufs.feed(b.binding, bufD->buffer);
srbD->vsubufoffsets.feed(b.binding, offsetInConstants);
srbD->vsubufsizes.feed(b.binding, sizeInConstants);
const uint sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vsubufs.feed(b->binding, bufD->buffer);
srbD->vsubufoffsets.feed(b->binding, offsetInConstants);
srbD->vsubufsizes.feed(b->binding, sizeInConstants);
}
if (b.stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fsubufs.feed(b.binding, bufD->buffer);
srbD->fsubufoffsets.feed(b.binding, offsetInConstants);
srbD->fsubufsizes.feed(b.binding, sizeInConstants);
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fsubufs.feed(b->binding, bufD->buffer);
srbD->fsubufoffsets.feed(b->binding, offsetInConstants);
srbD->fsubufsizes.feed(b->binding, sizeInConstants);
}
}
break;
......@@ -1343,17 +1343,17 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
{
// A sampler with binding N is mapped to a HLSL sampler and texture
// with registers sN and tN by SPIRV-Cross.
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b.stex.sampler);
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
bd.stex.texGeneration = texD->generation;
bd.stex.samplerGeneration = samplerD->generation;
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vssamplers.feed(b.binding, samplerD->samplerState);
srbD->vsshaderresources.feed(b.binding, texD->srv);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vssamplers.feed(b->binding, samplerD->samplerState);
srbD->vsshaderresources.feed(b->binding, texD->srv);
}
if (b.stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fssamplers.feed(b.binding, samplerD->samplerState);
srbD->fsshaderresources.feed(b.binding, texD->srv);
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fssamplers.feed(b->binding, samplerD->samplerState);
srbD->fsshaderresources.feed(b->binding, texD->srv);
}
}
break;
......@@ -2269,7 +2269,7 @@ bool QD3D11ShaderResourceBindings::build()
std::sort(sortedBindings.begin(), sortedBindings.end(),
[](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
{
return a.binding < b.binding;
return QRhiShaderResourceBindingPrivate::get(&a)->binding < QRhiShaderResourceBindingPrivate::get(&b)->binding;
});
boundResourceData.resize(sortedBindings.count());
......
......@@ -1378,19 +1378,19 @@ void QRhiGles2::setChangedUniforms(QGles2GraphicsPipeline *psD, QRhiShaderResour
QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb);
for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->m_bindings[i]);
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->m_bindings[i]);
QGles2ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b.type) {
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b.ubuf.buf);
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.ubuf.buf);
if (changedOnly && bufD->ubufChangeRange.isNull()) // do not set again when nothing changed
break;
const QByteArray bufView = QByteArray::fromRawData(bufD->ubuf.constData() + b.ubuf.offset,
b.ubuf.maybeSize ? b.ubuf.maybeSize : bufD->m_size);
const QByteArray bufView = QByteArray::fromRawData(bufD->ubuf.constData() + b->u.ubuf.offset,
b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
for (QGles2GraphicsPipeline::Uniform &uniform : psD->uniforms) {
if (uniform.binding == b.binding
if (uniform.binding == b->binding
&& (!changedOnly ||
(uniform.offset >= uint(bufD->ubufChangeRange.changeBegin)
&& uniform.offset < uint(bufD->ubufChangeRange.changeEnd))))
......@@ -1443,19 +1443,19 @@ void QRhiGles2::setChangedUniforms(QGles2GraphicsPipeline *psD, QRhiShaderResour
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QGles2Texture *texD = QRHI_RES(QGles2Texture, b.stex.tex);
QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b.stex.sampler);
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.tex);
QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.sampler);
const bool textureChanged = QRHI_RES(QGles2Texture, b.stex.tex)->generation != bd.stex.texGeneration;
const bool textureChanged = QRHI_RES(QGles2Texture, b->u.stex.tex)->generation != bd.stex.texGeneration;
if (textureChanged)
bd.stex.texGeneration = QRHI_RES(QGles2Texture, b.stex.tex)->generation;
const bool samplerChanged = QRHI_RES(QGles2Sampler, b.stex.sampler)->generation != bd.stex.samplerGeneration;
bd.stex.texGeneration = QRHI_RES(QGles2Texture, b->u.stex.tex)->generation;
const bool samplerChanged = QRHI_RES(QGles2Sampler, b->u.stex.sampler)->generation != bd.stex.samplerGeneration;
if (samplerChanged)
bd.stex.samplerGeneration = QRHI_RES(QGles2Sampler, b.stex.sampler)->generation;
bd.stex.samplerGeneration = QRHI_RES(QGles2Sampler, b->u.stex.sampler)->generation;
int texUnit = 0;
for (QGles2GraphicsPipeline::Sampler &sampler : psD->samplers) {
if (sampler.binding == b.binding) {
if (sampler.binding == b->binding) {
f->glActiveTexture(GL_TEXTURE0 + texUnit);
f->glBindTexture(texD->target, texD->texture);
......@@ -2053,9 +2053,9 @@ bool QGles2ShaderResourceBindings::build()
boundResourceData.resize(m_bindings.count());
for (int i = 0, ie = m_bindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(m_bindings[i]);
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&m_bindings[i]);
BoundResourceData &bd(boundResourceData[i]);
switch (b.type) {
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
// nothing, we do not track buffer generations
break;
......
......@@ -2209,7 +2209,7 @@ bool QMetalShaderResourceBindings::build()
std::sort(sortedBindings.begin(), sortedBindings.end(),
[](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
{
return a.binding < b.binding;
return QRhiShaderResourceBindingPrivate::get(&a)->binding < QRhiShaderResourceBindingPrivate::get(&b)->binding;
});
if (!sortedBindings.isEmpty())
maxBinding = sortedBindings.last().binding;
......
......@@ -1971,27 +1971,27 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
while (frameSlot < (updateAll ? QVK_FRAMES_IN_FLIGHT : descSetIdx + 1)) {
srbD->boundResourceData[frameSlot].resize(srbD->m_bindings.count());
for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->m_bindings[i]);
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&srbD->m_bindings[i]);
QVkShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[frameSlot][i]);
VkWriteDescriptorSet writeInfo;
memset(&writeInfo, 0, sizeof(writeInfo));
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.dstSet = srbD->descSets[frameSlot];
writeInfo.dstBinding = b.binding;
writeInfo.dstBinding = b->binding;
writeInfo.descriptorCount = 1;
switch (b.type) {
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
QRhiBuffer *buf = b.ubuf.buf;
QRhiBuffer *buf = b->u.ubuf.buf;
QVkBuffer *bufD = QRHI_RES(QVkBuffer, buf);
bd.ubuf.generation = bufD->generation;
VkDescriptorBufferInfo bufInfo;
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
bufInfo.offset = b.ubuf.offset;
bufInfo.range = b.ubuf.maybeSize ? b.ubuf.maybeSize : bufD->m_size;
bufInfo.offset = b->u.ubuf.offset;
bufInfo.range = b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size;
// be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads
Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset);
bufferInfos.append(bufInfo);
......@@ -2000,8 +2000,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QVkTexture *texD = QRHI_RES(QVkTexture, b.stex.tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, b.stex.sampler);
QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler);
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerGeneration = samplerD->generation;
......@@ -2949,10 +2949,11 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
bool hasSlottedResourceInSrb = false;
for (const QRhiShaderResourceBinding &b : qAsConst(srbD->m_bindings)) {
switch (b.type) {
for (const QRhiShaderResourceBinding &binding : qAsConst(srbD->m_bindings)) {
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&binding);
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
if (QRHI_RES(QVkBuffer, b.ubuf.buf)->m_type == QRhiBuffer::Dynamic)
if (QRHI_RES(QVkBuffer, b->u.ubuf.buf)->m_type == QRhiBuffer::Dynamic)