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:
Laszlo Agocs 2019-09-30 15:23:32 +02:00
parent 7000b66f7e
commit 9e59024bf8
4 changed files with 30 additions and 32 deletions

View File

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

View File

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

View File

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

View File

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