rhi: Speed up buffer and texture tracking
Task-number: QTBUG-78862 Change-Id: If278bd55530081cbbdbab8dd6e14d86e28da558e Reviewed-by: Christian Strømme <christian.stromme@qt.io>
This commit is contained in:
parent
7000b66f7e
commit
9e59024bf8
@ -5513,7 +5513,7 @@ static inline QRhiPassResourceTracker::BufferStage earlierStage(QRhiPassResource
|
||||
void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
|
||||
const UsageState &state)
|
||||
{
|
||||
auto it = std::find_if(m_buffers.begin(), m_buffers.end(), [buf](const Buffer &b) { return b.buf == buf; });
|
||||
auto it = m_buffers.find(buf);
|
||||
if (it != m_buffers.end()) {
|
||||
if (it->access != *access) {
|
||||
const QByteArray name = buf->name();
|
||||
@ -5529,12 +5529,11 @@ void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAc
|
||||
}
|
||||
|
||||
Buffer b;
|
||||
b.buf = buf;
|
||||
b.slot = slot;
|
||||
b.access = *access;
|
||||
b.stage = *stage;
|
||||
b.stateAtPassBegin = state; // first use -> initial state
|
||||
m_buffers.append(b);
|
||||
m_buffers.insert(buf, b);
|
||||
}
|
||||
|
||||
static inline QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a,
|
||||
@ -5553,7 +5552,7 @@ static inline bool isImageLoadStore(QRhiPassResourceTracker::TextureAccess acces
|
||||
void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
|
||||
const UsageState &state)
|
||||
{
|
||||
auto it = std::find_if(m_textures.begin(), m_textures.end(), [tex](const Texture &t) { return t.tex == tex; });
|
||||
auto it = m_textures.find(tex);
|
||||
if (it != m_textures.end()) {
|
||||
if (it->access != *access) {
|
||||
// Different subresources of a texture may be used for both load
|
||||
@ -5577,11 +5576,10 @@ void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *a
|
||||
}
|
||||
|
||||
Texture t;
|
||||
t.tex = tex;
|
||||
t.access = *access;
|
||||
t.stage = *stage;
|
||||
t.stateAtPassBegin = state; // first use -> initial state
|
||||
m_textures.append(t);
|
||||
m_textures.insert(tex, t);
|
||||
}
|
||||
|
||||
QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
|
||||
|
@ -503,28 +503,32 @@ public:
|
||||
const UsageState &state);
|
||||
|
||||
struct Buffer {
|
||||
QRhiBuffer *buf;
|
||||
int slot;
|
||||
BufferAccess access;
|
||||
BufferStage stage;
|
||||
UsageState stateAtPassBegin;
|
||||
};
|
||||
const QVector<Buffer> *buffers() const { return &m_buffers; }
|
||||
|
||||
using BufferIterator = QHash<QRhiBuffer *, Buffer>::const_iterator;
|
||||
BufferIterator cbeginBuffers() const { return m_buffers.cbegin(); }
|
||||
BufferIterator cendBuffers() const { return m_buffers.cend(); }
|
||||
|
||||
struct Texture {
|
||||
QRhiTexture *tex;
|
||||
TextureAccess access;
|
||||
TextureStage stage;
|
||||
UsageState stateAtPassBegin;
|
||||
};
|
||||
const QVector<Texture> *textures() const { return &m_textures; }
|
||||
|
||||
using TextureIterator = QHash<QRhiTexture *, Texture>::const_iterator;
|
||||
TextureIterator cbeginTextures() const { return m_textures.cbegin(); }
|
||||
TextureIterator cendTextures() const { return m_textures.cend(); }
|
||||
|
||||
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
|
||||
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
|
||||
|
||||
private:
|
||||
QVector<Buffer> m_buffers;
|
||||
QVector<Texture> m_textures;
|
||||
QHash<QRhiBuffer *, Buffer> m_buffers;
|
||||
QHash<QRhiTexture *, Texture> m_textures;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_MOVABLE_TYPE);
|
||||
|
@ -2186,7 +2186,6 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
|
||||
{
|
||||
GLbitfield barriers = 0;
|
||||
QRhiPassResourceTracker &tracker(cbD->passResTrackers[cmd.args.barriersForPass.trackerIndex]);
|
||||
const QVector<QRhiPassResourceTracker::Buffer> *buffers = tracker.buffers();
|
||||
// we only care about after-write, not any other accesses, and
|
||||
// cannot tell if something was written in a shader several passes
|
||||
// ago: now the previously written resource may be used with an
|
||||
@ -2194,17 +2193,16 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
|
||||
// barrier in theory. Hence setting all barrier bits whenever
|
||||
// something previously written is used for the first time in a
|
||||
// subsequent pass.
|
||||
for (const QRhiPassResourceTracker::Buffer &b : *buffers) {
|
||||
QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(b.stateAtPassBegin.access);
|
||||
for (auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers(); it != itEnd; ++it) {
|
||||
QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(it->stateAtPassBegin.access);
|
||||
if (accessBeforePass == QGles2Buffer::AccessStorageWrite
|
||||
|| accessBeforePass == QGles2Buffer::AccessStorageReadWrite)
|
||||
{
|
||||
barriers |= GL_ALL_BARRIER_BITS;
|
||||
}
|
||||
}
|
||||
const QVector<QRhiPassResourceTracker::Texture> *textures = tracker.textures();
|
||||
for (const QRhiPassResourceTracker::Texture &t : *textures) {
|
||||
QGles2Texture::Access accessBeforePass = QGles2Texture::Access(t.stateAtPassBegin.access);
|
||||
for (auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures(); it != itEnd; ++it) {
|
||||
QGles2Texture::Access accessBeforePass = QGles2Texture::Access(it->stateAtPassBegin.access);
|
||||
if (accessBeforePass == QGles2Texture::AccessStorageWrite
|
||||
|| accessBeforePass == QGles2Texture::AccessStorageReadWrite)
|
||||
{
|
||||
|
@ -3556,12 +3556,11 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
|
||||
if (tracker.isEmpty())
|
||||
return;
|
||||
|
||||
const QVector<QRhiPassResourceTracker::Buffer> *buffers = tracker.buffers();
|
||||
for (const QRhiPassResourceTracker::Buffer &b : *buffers) {
|
||||
QVkBuffer *bufD = QRHI_RES(QVkBuffer, b.buf);
|
||||
VkAccessFlags access = toVkAccess(b.access);
|
||||
VkPipelineStageFlags stage = toVkPipelineStage(b.stage);
|
||||
QVkBuffer::UsageState s = toVkBufferUsageState(b.stateAtPassBegin);
|
||||
for (auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers(); it != itEnd; ++it) {
|
||||
QVkBuffer *bufD = QRHI_RES(QVkBuffer, it.key());
|
||||
VkAccessFlags access = toVkAccess(it->access);
|
||||
VkPipelineStageFlags stage = toVkPipelineStage(it->stage);
|
||||
QVkBuffer::UsageState s = toVkBufferUsageState(it->stateAtPassBegin);
|
||||
if (!s.stage)
|
||||
continue;
|
||||
if (s.access == access && s.stage == stage) {
|
||||
@ -3575,7 +3574,7 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
|
||||
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
bufMemBarrier.srcAccessMask = s.access;
|
||||
bufMemBarrier.dstAccessMask = access;
|
||||
bufMemBarrier.buffer = bufD->buffers[b.slot];
|
||||
bufMemBarrier.buffer = bufD->buffers[it->slot];
|
||||
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||
df->vkCmdPipelineBarrier(cbD->cb, s.stage, stage, 0,
|
||||
0, nullptr,
|
||||
@ -3583,13 +3582,12 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
|
||||
0, nullptr);
|
||||
}
|
||||
|
||||
const QVector<QRhiPassResourceTracker::Texture> *textures = tracker.textures();
|
||||
for (const QRhiPassResourceTracker::Texture &t : *textures) {
|
||||
QVkTexture *texD = QRHI_RES(QVkTexture, t.tex);
|
||||
VkImageLayout layout = toVkLayout(t.access);
|
||||
VkAccessFlags access = toVkAccess(t.access);
|
||||
VkPipelineStageFlags stage = toVkPipelineStage(t.stage);
|
||||
QVkTexture::UsageState s = toVkTextureUsageState(t.stateAtPassBegin);
|
||||
for (auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures(); it != itEnd; ++it) {
|
||||
QVkTexture *texD = QRHI_RES(QVkTexture, it.key());
|
||||
VkImageLayout layout = toVkLayout(it->access);
|
||||
VkAccessFlags access = toVkAccess(it->access);
|
||||
VkPipelineStageFlags stage = toVkPipelineStage(it->stage);
|
||||
QVkTexture::UsageState s = toVkTextureUsageState(it->stateAtPassBegin);
|
||||
if (s.access == access && s.stage == stage && s.layout == layout) {
|
||||
if (!accessIsWrite(access))
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user