Commit cbb16855 authored by Laszlo Agocs's avatar Laszlo Agocs

Improve resource binding logic

Esp. for Metal where we now avoid superfluous set* for shader
resources.
parent 211520f0
......@@ -105,6 +105,7 @@ bool QRhiImgui::prepareFrame(QRhiRenderTarget *rt, QRhiRenderPassDescriptor *rp,
if (!d->ubuf) {
d->ubuf = d->rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4);
d->ubuf->setName(QByteArrayLiteral("imgui uniform buffer"));
d->releasePool << d->ubuf;
if (!d->ubuf->build())
return false;
......@@ -124,14 +125,17 @@ bool QRhiImgui::prepareFrame(QRhiRenderTarget *rt, QRhiRenderPassDescriptor *rp,
if (!d->sampler) {
d->sampler = d->rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
QRhiSampler::Repeat, QRhiSampler::Repeat);
d->sampler->setName(QByteArrayLiteral("imgui sampler"));
d->releasePool << d->sampler;
if (!d->sampler->build())
return false;
}
for (QRhiImguiPrivate::Texture &t : d->textures) {
for (int i = 0; i < d->textures.count(); ++i) {
QRhiImguiPrivate::Texture &t(d->textures[i]);
if (!t.tex) {
t.tex = d->rhi->newTexture(QRhiTexture::RGBA8, t.image.size());
t.tex->setName(QByteArrayLiteral("imgui texture ") + QByteArray::number(i));
if (!t.tex->build())
return false;
dstResourceUpdates->uploadTexture(t.tex, t.image);
......@@ -212,6 +216,7 @@ bool QRhiImgui::prepareFrame(QRhiRenderTarget *rt, QRhiRenderPassDescriptor *rp,
if (!d->vbuf) {
d->vbuf = d->rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, totalVbufSize);
d->vbuf->setName(QByteArrayLiteral("imgui vertex buffer"));
d->releasePool << d->vbuf;
if (!d->vbuf->build())
return false;
......@@ -224,6 +229,7 @@ bool QRhiImgui::prepareFrame(QRhiRenderTarget *rt, QRhiRenderPassDescriptor *rp,
}
if (!d->ibuf) {
d->ibuf = d->rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::IndexBuffer, totalIbufSize);
d->ibuf->setName(QByteArrayLiteral("imgui index buffer"));
d->releasePool << d->ibuf;
if (!d->ibuf->build())
return false;
......
......@@ -116,7 +116,7 @@ QString graphicsApiName()
return QString();
}
QRhi::Flags rhiFlags = 0;
QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers;
int sampleCount = 1;
QRhiSwapChain::Flags scFlags = 0;
......
......@@ -84,8 +84,6 @@ struct {
void preInit()
{
rhiFlags |= QRhi::EnableDebugMarkers;
#ifdef PROFILE_TO_FILE
rhiFlags |= QRhi::EnableProfiling;
const QString profFn = QFileInfo(QLatin1String("rhiprof.txt")).absoluteFilePath();
......
......@@ -367,9 +367,9 @@ public:
// This has two uses: to get names visible in graphics debugging tools and
// in the profiling output. Regarding the former, the name is ignored when
// DebugMarkers are not supported or EnableDebugMarkers is not set. May
// also be ignored for objects other than buffers, renderbuffers, and
// textures, depending on the backend.
// DebugMarkers are not supported, and may be ignored when
// EnableDebugMarkers is not set. May also be ignored for objects other
// than buffers, renderbuffers, and textures, depending on the backend.
QByteArray name() const;
void setName(const QByteArray &name);
......
......@@ -372,6 +372,7 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
break;
}
}
if (srbUpdate)
updateShaderResourceBindings(srbD);
......@@ -1258,18 +1259,22 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
// A sampler with binding N is mapped to a HLSL sampler and texture
// with registers sN and tN by SPIRV-Cross.
bd.stex.texGeneration = QRHI_RES(QD3D11Texture, b.stex.tex)->generation;
bd.stex.samplerGeneration = QRHI_RES(QD3D11Sampler, b.stex.sampler)->generation;
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b.stex.sampler);
bd.stex.texGeneration = texD->generation;
bd.stex.samplerGeneration = samplerD->generation;
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vssamplers.feed(b.binding, QRHI_RES(QD3D11Sampler, b.stex.sampler)->samplerState);
srbD->vsshaderresources.feed(b.binding, QRHI_RES(QD3D11Texture, b.stex.tex)->srv);
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, QRHI_RES(QD3D11Sampler, b.stex.sampler)->samplerState);
srbD->fsshaderresources.feed(b.binding, QRHI_RES(QD3D11Texture, b.stex.tex)->srv);
srbD->fssamplers.feed(b.binding, samplerD->samplerState);
srbD->fsshaderresources.feed(b.binding, texD->srv);
}
}
break;
default:
Q_UNREACHABLE();
......
......@@ -426,6 +426,41 @@ QRhiShaderResourceBindings *QRhiMetal::createShaderResourceBindings()
return new QMetalShaderResourceBindings(this);
}
void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, QMetalCommandBuffer *cbD)
{
for (const QRhiShaderResourceBinding &b : qAsConst(srbD->sortedBindings)) {
switch (b.type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b.ubuf.buf);
id<MTLBuffer> mtlbuf = bufD->d->buf[bufD->m_type == QRhiBuffer::Immutable ? 0 : currentFrameSlot];
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage))
[cbD->d->currentPassEncoder setVertexBuffer: mtlbuf offset: b.ubuf.offset atIndex: b.binding];
if (b.stage.testFlag(QRhiShaderResourceBinding::FragmentStage))
[cbD->d->currentPassEncoder setFragmentBuffer: mtlbuf offset: b.ubuf.offset atIndex: b.binding];
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QMetalTexture *texD = QRHI_RES(QMetalTexture, b.stex.tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b.stex.sampler);
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
[cbD->d->currentPassEncoder setVertexTexture: texD->d->tex atIndex: b.binding];
[cbD->d->currentPassEncoder setVertexSamplerState: samplerD->d->samplerState atIndex: b.binding];
}
if (b.stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
[cbD->d->currentPassEncoder setFragmentTexture: texD->d->tex atIndex: b.binding];
[cbD->d->currentPassEncoder setFragmentSamplerState: samplerD->d->samplerState atIndex: b.binding];
}
}
break;
default:
Q_UNREACHABLE();
break;
}
}
}
void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps, QRhiShaderResourceBindings *srb)
{
Q_ASSERT(inPass);
......@@ -435,37 +470,43 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
srb = psD->m_shaderResourceBindings;
QMetalShaderResourceBindings *srbD = QRHI_RES(QMetalShaderResourceBindings, srb);
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
for (const QRhiShaderResourceBinding &b : qAsConst(srbD->sortedBindings)) {
bool hasSlottedResourceInSrb = false;
const int resSlot = hasSlottedResourceInSrb ? currentFrameSlot : 0;
bool resNeedsRebind = false;
// do host writes, figure out if we need to rebind, and mark as in-use
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->sortedBindings[i]);
QMetalShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b.type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b.ubuf.buf);
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
if (bufD->m_type != QRhiBuffer::Immutable) { // static and dynamic are both slotted
hasSlottedResourceInSrb = true;
executeBufferHostWritesForCurrentFrame(bufD);
}
if (bufD->generation != bd.ubuf.generation) {
resNeedsRebind = true;
bd.ubuf.generation = bufD->generation;
}
bufD->lastActiveFrameSlot = currentFrameSlot;
executeBufferHostWritesForCurrentFrame(bufD);
id<MTLBuffer> mtlbuf = bufD->d->buf[bufD->m_type == QRhiBuffer::Immutable ? 0 : currentFrameSlot];
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage))
[cbD->d->currentPassEncoder setVertexBuffer: mtlbuf offset: b.ubuf.offset atIndex: b.binding];
if (b.stage.testFlag(QRhiShaderResourceBinding::FragmentStage))
[cbD->d->currentPassEncoder setFragmentBuffer: mtlbuf offset: b.ubuf.offset atIndex: b.binding];
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QMetalTexture *tex = QRHI_RES(QMetalTexture, b.stex.tex);
tex->lastActiveFrameSlot = currentFrameSlot;
QMetalSampler *samp = QRHI_RES(QMetalSampler, b.stex.sampler);
samp->lastActiveFrameSlot = currentFrameSlot;
if (b.stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
[cbD->d->currentPassEncoder setVertexTexture: tex->d->tex atIndex: b.binding];
[cbD->d->currentPassEncoder setVertexSamplerState: samp->d->samplerState atIndex: b.binding];
}
if (b.stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
[cbD->d->currentPassEncoder setFragmentTexture: tex->d->tex atIndex: b.binding];
[cbD->d->currentPassEncoder setFragmentSamplerState: samp->d->samplerState atIndex: b.binding];
QMetalTexture *texD = QRHI_RES(QMetalTexture, b.stex.tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b.stex.sampler);
if (texD->generation != bd.stex.texGeneration
|| samplerD->generation != bd.stex.samplerGeneration)
{
resNeedsRebind = true;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerGeneration = samplerD->generation;
}
texD->lastActiveFrameSlot = currentFrameSlot;
samplerD->lastActiveFrameSlot = currentFrameSlot;
}
break;
default:
......@@ -474,18 +515,27 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
if (cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation
|| cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
// make sure the resources for the correct slot get bound
if (hasSlottedResourceInSrb && cbD->currentResSlot != resSlot)
resNeedsRebind = true;
if (cbD->currentPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
cbD->currentPipeline = ps;
cbD->currentPipelineGeneration = psD->generation;
cbD->currentSrb = srb;
cbD->currentSrbGeneration = srbD->generation;
[cbD->d->currentPassEncoder setRenderPipelineState: psD->d->ps];
[cbD->d->currentPassEncoder setDepthStencilState: psD->d->ds];
[cbD->d->currentPassEncoder setCullMode: psD->d->cullMode];
[cbD->d->currentPassEncoder setFrontFacingWinding: psD->d->winding];
}
if (resNeedsRebind || cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation) {
cbD->currentSrb = srb;
cbD->currentSrbGeneration = srbD->generation;
cbD->currentResSlot = resSlot;
enqueueShaderResourceBindings(srbD, cbD);
}
psD->lastActiveFrameSlot = currentFrameSlot;
}
......@@ -1341,8 +1391,14 @@ bool QMetalBuffer::build()
if (i == 0 || m_type != Immutable) {
d->buf[i] = [rhiD->d->dev newBufferWithLength: roundedSize options: opts];
d->pendingUpdates[i].reserve(16);
if (!objectName.isEmpty())
d->buf[i].label = [NSString stringWithUTF8String: objectName.constData()];
if (!objectName.isEmpty()) {
if (m_type == Immutable) {
d->buf[i].label = [NSString stringWithUTF8String: objectName.constData()];
} else {
const QByteArray name = objectName + '/' + QByteArray::number(i);
d->buf[i].label = [NSString stringWithUTF8String: name.constData()];
}
}
}
}
......@@ -1973,6 +2029,25 @@ bool QMetalShaderResourceBindings::build()
else
maxBinding = -1;
boundResourceData.resize(sortedBindings.count());
for (int i = 0, ie = sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(sortedBindings[i]);
QMetalShaderResourceBindings::BoundResourceData &bd(boundResourceData[i]);
switch (b.type) {
case QRhiShaderResourceBinding::UniformBuffer:
bd.ubuf.generation = QRHI_RES(QMetalBuffer, b.ubuf.buf)->generation;
break;
case QRhiShaderResourceBinding::SampledTexture:
bd.stex.texGeneration = QRHI_RES(QMetalTexture, b.stex.tex)->generation;
bd.stex.samplerGeneration = QRHI_RES(QMetalSampler, b.stex.sampler)->generation;
break;
default:
Q_UNREACHABLE();
break;
}
}
generation += 1;
return true;
}
......@@ -2440,6 +2515,7 @@ void QMetalCommandBuffer::resetState()
currentPipelineGeneration = 0;
currentSrb = nullptr;
currentSrbGeneration = 0;
currentResSlot = -1;
currentIndexBuffer = nullptr;
d->currentPassEncoder = nil;
d->currentPassRpDesc = nil;
......
......@@ -178,6 +178,22 @@ struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
QVector<QRhiShaderResourceBinding> sortedBindings;
int maxBinding = -1;
struct BoundUniformBufferData {
uint generation;
};
struct BoundSampledTextureData {
uint texGeneration;
uint samplerGeneration;
};
struct BoundResourceData {
union {
BoundUniformBufferData ubuf;
BoundSampledTextureData stex;
};
};
QVector<BoundResourceData> boundResourceData;
uint generation = 0;
friend class QRhiMetal;
};
......@@ -213,6 +229,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer
uint currentPipelineGeneration;
QRhiShaderResourceBindings *currentSrb;
uint currentSrbGeneration;
int currentResSlot;
QRhiBuffer *currentIndexBuffer;
quint32 currentIndexOffset;
QRhiCommandBuffer::IndexFormat currentIndexFormat;
......@@ -334,6 +351,7 @@ public:
void finishActiveReadbacks(bool forced = false);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, QMetalCommandBuffer *cbD);
int effectiveSampleCount(int sampleCount) const;
bool importedDevice = false;
......
......@@ -1903,12 +1903,14 @@ 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);
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bd.stex.texGeneration = QRHI_RES(QVkTexture, b.stex.tex)->generation;
bd.stex.samplerGeneration = QRHI_RES(QVkSampler, b.stex.sampler)->generation;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerGeneration = samplerD->generation;
VkDescriptorImageInfo imageInfo;
imageInfo.sampler = QRHI_RES(QVkSampler, b.stex.sampler)->sampler;
imageInfo.imageView = QRHI_RES(QVkTexture, b.stex.tex)->imageView;
imageInfo.sampler = samplerD->sampler;
imageInfo.imageView = texD->imageView;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfos.append(imageInfo);
writeInfo.pImageInfo = &imageInfos.last();
......@@ -2847,10 +2849,16 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
if (!srb)
srb = psD->m_shaderResourceBindings;
// do host writes and mark referenced shader resources as in-use
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
bool hasSlottedResourceInSrb = false;
for (const QRhiShaderResourceBinding &b : qAsConst(srbD->m_bindings)) {
const int descSetIdx = hasSlottedResourceInSrb ? currentFrameSlot : 0;
bool rewriteDescSet = false;
// Do host writes and mark referenced shader resources as in-use.
// Also prepare to ensure the descriptor set we are going to bind refers to up-to-date Vk objects.
for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->m_bindings[i]);
QVkShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[descSetIdx][i]);
switch (b.type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
......@@ -2861,46 +2869,35 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
hasSlottedResourceInSrb = true;
executeBufferHostWritesForCurrentFrame(bufD);
}
}
break;
case QRhiShaderResourceBinding::SampledTexture:
QRHI_RES(QVkTexture, b.stex.tex)->lastActiveFrameSlot = currentFrameSlot;
QRHI_RES(QVkSampler, b.stex.sampler)->lastActiveFrameSlot = currentFrameSlot;
break;
default:
Q_UNREACHABLE();
break;
}
}
// ensure the descriptor set we are going to bind refers to up-to-date Vk objects
const int descSetIdx = hasSlottedResourceInSrb ? currentFrameSlot : 0;
bool srbUpdate = false;
for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding &b(srbD->m_bindings[i]);
QVkShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[descSetIdx][i]);
switch (b.type) {
case QRhiShaderResourceBinding::UniformBuffer:
if (QRHI_RES(QVkBuffer, b.ubuf.buf)->generation != bd.ubuf.generation) {
srbUpdate = true;
bd.ubuf.generation = QRHI_RES(QVkBuffer, b.ubuf.buf)->generation;
if (bufD->generation != bd.ubuf.generation) {
rewriteDescSet = true;
bd.ubuf.generation = bufD->generation;
}
}
break;
case QRhiShaderResourceBinding::SampledTexture:
if (QRHI_RES(QVkTexture, b.stex.tex)->generation != bd.stex.texGeneration
|| QRHI_RES(QVkSampler, b.stex.sampler)->generation != bd.stex.samplerGeneration)
{
QVkTexture *texD = QRHI_RES(QVkTexture, b.stex.tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, b.stex.sampler);
texD->lastActiveFrameSlot = currentFrameSlot;
samplerD->lastActiveFrameSlot = currentFrameSlot;
if (texD->generation != bd.stex.texGeneration
|| samplerD->generation != bd.stex.samplerGeneration)
{
srbUpdate = true;
bd.stex.texGeneration = QRHI_RES(QVkTexture, b.stex.tex)->generation;
bd.stex.samplerGeneration = QRHI_RES(QVkSampler, b.stex.sampler)->generation;
rewriteDescSet = true;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerGeneration = samplerD->generation;
}
}
break;
default:
Q_UNREACHABLE();
break;
}
}
if (srbUpdate)
// write descriptor sets, if needed
if (rewriteDescSet)
updateShaderResourceBindings(srb, descSetIdx);
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
......@@ -2912,10 +2909,9 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
psD->lastActiveFrameSlot = currentFrameSlot;
// make sure the descriptors for the correct slot will get bound
if (hasSlottedResourceInSrb && cbD->currentDescSetSlot != descSetIdx)
srbUpdate = true;
const bool forceRebind = hasSlottedResourceInSrb && cbD->currentDescSetSlot != descSetIdx;
if (srbUpdate || cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation) {
if (forceRebind || rewriteDescSet || cbD->currentSrb != srb || cbD->currentSrbGeneration != srbD->generation) {
df->vkCmdBindDescriptorSets(cbD->cb, VK_PIPELINE_BIND_POINT_GRAPHICS, psD->layout, 0, 1,
&srbD->descSets[descSetIdx], 0, nullptr);
cbD->currentSrb = srb;
......@@ -3070,7 +3066,7 @@ void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
vkCmdDebugMarkerInsert(QRHI_RES(QVkCommandBuffer, cb)->cb, &marker);
}
void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name)
void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot)
{
if (!debugMarkers || !debugMarkersAvailable || name.isEmpty())
return;
......@@ -3080,7 +3076,12 @@ void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type,
nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
nameInfo.objectType = type;
nameInfo.object = object;
nameInfo.pObjectName = name.constData();
QByteArray decoratedName = name;
if (slot >= 0) {
decoratedName += '/';
decoratedName += QByteArray::number(slot);
}
nameInfo.pObjectName = decoratedName.constData();
vkDebugMarkerSetObjectName(dev, &nameInfo);
}
......@@ -3476,7 +3477,8 @@ bool QVkBuffer::build()
if (m_type == Dynamic)
pendingDynamicUpdates[i].reserve(16);
rhiD->setObjectName(reinterpret_cast<uint64_t>(buffers[i]), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, objectName);
rhiD->setObjectName(reinterpret_cast<uint64_t>(buffers[i]), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, objectName,
m_type == Dynamic ? i : -1);
}
}
......
......@@ -453,7 +453,7 @@ public:
void executeDeferredReleases(bool forced = false);
void finishActiveReadbacks(bool forced = false);
void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name);
void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot = -1);
void bufferBarrier(QRhiCommandBuffer *cb, QRhiBuffer *buf);
void imageSubResBarrier(QRhiCommandBuffer *cb, QRhiTexture *tex,
VkImageLayout oldLayout, VkImageLayout newLayout,
......
multiwindow_threaded should demo pulling out the device and importing to another rhi
mtl: reduce set*
advanced blend modes
gl: tex formats (texture, readback)
gl: srgb
......@@ -47,6 +46,7 @@ dxc for d3d as an alternative to fxc?
hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done
mtl: reduce set*
mtl: report readback temp buf
vk: support instanceStepRate via VK_EXT_vertex_attribute_divisor
resize to 0 width or height fails (vk, d3d)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment