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,
|
void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
|
||||||
const UsageState &state)
|
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 != m_buffers.end()) {
|
||||||
if (it->access != *access) {
|
if (it->access != *access) {
|
||||||
const QByteArray name = buf->name();
|
const QByteArray name = buf->name();
|
||||||
@ -5529,12 +5529,11 @@ void QRhiPassResourceTracker::registerBuffer(QRhiBuffer *buf, int slot, BufferAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Buffer b;
|
Buffer b;
|
||||||
b.buf = buf;
|
|
||||||
b.slot = slot;
|
b.slot = slot;
|
||||||
b.access = *access;
|
b.access = *access;
|
||||||
b.stage = *stage;
|
b.stage = *stage;
|
||||||
b.stateAtPassBegin = state; // first use -> initial state
|
b.stateAtPassBegin = state; // first use -> initial state
|
||||||
m_buffers.append(b);
|
m_buffers.insert(buf, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QRhiPassResourceTracker::TextureStage earlierStage(QRhiPassResourceTracker::TextureStage a,
|
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,
|
void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
|
||||||
const UsageState &state)
|
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 != m_textures.end()) {
|
||||||
if (it->access != *access) {
|
if (it->access != *access) {
|
||||||
// Different subresources of a texture may be used for both load
|
// Different subresources of a texture may be used for both load
|
||||||
@ -5577,11 +5576,10 @@ void QRhiPassResourceTracker::registerTexture(QRhiTexture *tex, TextureAccess *a
|
|||||||
}
|
}
|
||||||
|
|
||||||
Texture t;
|
Texture t;
|
||||||
t.tex = tex;
|
|
||||||
t.access = *access;
|
t.access = *access;
|
||||||
t.stage = *stage;
|
t.stage = *stage;
|
||||||
t.stateAtPassBegin = state; // first use -> initial state
|
t.stateAtPassBegin = state; // first use -> initial state
|
||||||
m_textures.append(t);
|
m_textures.insert(tex, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
|
QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages)
|
||||||
|
@ -503,28 +503,32 @@ public:
|
|||||||
const UsageState &state);
|
const UsageState &state);
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
QRhiBuffer *buf;
|
|
||||||
int slot;
|
int slot;
|
||||||
BufferAccess access;
|
BufferAccess access;
|
||||||
BufferStage stage;
|
BufferStage stage;
|
||||||
UsageState stateAtPassBegin;
|
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 {
|
struct Texture {
|
||||||
QRhiTexture *tex;
|
|
||||||
TextureAccess access;
|
TextureAccess access;
|
||||||
TextureStage stage;
|
TextureStage stage;
|
||||||
UsageState stateAtPassBegin;
|
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 BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
|
||||||
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
|
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<Buffer> m_buffers;
|
QHash<QRhiBuffer *, Buffer> m_buffers;
|
||||||
QVector<Texture> m_textures;
|
QHash<QRhiTexture *, Texture> m_textures;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_MOVABLE_TYPE);
|
||||||
|
@ -2186,7 +2186,6 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
|
|||||||
{
|
{
|
||||||
GLbitfield barriers = 0;
|
GLbitfield barriers = 0;
|
||||||
QRhiPassResourceTracker &tracker(cbD->passResTrackers[cmd.args.barriersForPass.trackerIndex]);
|
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
|
// we only care about after-write, not any other accesses, and
|
||||||
// cannot tell if something was written in a shader several passes
|
// cannot tell if something was written in a shader several passes
|
||||||
// ago: now the previously written resource may be used with an
|
// 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
|
// barrier in theory. Hence setting all barrier bits whenever
|
||||||
// something previously written is used for the first time in a
|
// something previously written is used for the first time in a
|
||||||
// subsequent pass.
|
// subsequent pass.
|
||||||
for (const QRhiPassResourceTracker::Buffer &b : *buffers) {
|
for (auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers(); it != itEnd; ++it) {
|
||||||
QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(b.stateAtPassBegin.access);
|
QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(it->stateAtPassBegin.access);
|
||||||
if (accessBeforePass == QGles2Buffer::AccessStorageWrite
|
if (accessBeforePass == QGles2Buffer::AccessStorageWrite
|
||||||
|| accessBeforePass == QGles2Buffer::AccessStorageReadWrite)
|
|| accessBeforePass == QGles2Buffer::AccessStorageReadWrite)
|
||||||
{
|
{
|
||||||
barriers |= GL_ALL_BARRIER_BITS;
|
barriers |= GL_ALL_BARRIER_BITS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const QVector<QRhiPassResourceTracker::Texture> *textures = tracker.textures();
|
for (auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures(); it != itEnd; ++it) {
|
||||||
for (const QRhiPassResourceTracker::Texture &t : *textures) {
|
QGles2Texture::Access accessBeforePass = QGles2Texture::Access(it->stateAtPassBegin.access);
|
||||||
QGles2Texture::Access accessBeforePass = QGles2Texture::Access(t.stateAtPassBegin.access);
|
|
||||||
if (accessBeforePass == QGles2Texture::AccessStorageWrite
|
if (accessBeforePass == QGles2Texture::AccessStorageWrite
|
||||||
|| accessBeforePass == QGles2Texture::AccessStorageReadWrite)
|
|| accessBeforePass == QGles2Texture::AccessStorageReadWrite)
|
||||||
{
|
{
|
||||||
|
@ -3556,12 +3556,11 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
|
|||||||
if (tracker.isEmpty())
|
if (tracker.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QVector<QRhiPassResourceTracker::Buffer> *buffers = tracker.buffers();
|
for (auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers(); it != itEnd; ++it) {
|
||||||
for (const QRhiPassResourceTracker::Buffer &b : *buffers) {
|
QVkBuffer *bufD = QRHI_RES(QVkBuffer, it.key());
|
||||||
QVkBuffer *bufD = QRHI_RES(QVkBuffer, b.buf);
|
VkAccessFlags access = toVkAccess(it->access);
|
||||||
VkAccessFlags access = toVkAccess(b.access);
|
VkPipelineStageFlags stage = toVkPipelineStage(it->stage);
|
||||||
VkPipelineStageFlags stage = toVkPipelineStage(b.stage);
|
QVkBuffer::UsageState s = toVkBufferUsageState(it->stateAtPassBegin);
|
||||||
QVkBuffer::UsageState s = toVkBufferUsageState(b.stateAtPassBegin);
|
|
||||||
if (!s.stage)
|
if (!s.stage)
|
||||||
continue;
|
continue;
|
||||||
if (s.access == access && s.stage == stage) {
|
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.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
bufMemBarrier.srcAccessMask = s.access;
|
bufMemBarrier.srcAccessMask = s.access;
|
||||||
bufMemBarrier.dstAccessMask = access;
|
bufMemBarrier.dstAccessMask = access;
|
||||||
bufMemBarrier.buffer = bufD->buffers[b.slot];
|
bufMemBarrier.buffer = bufD->buffers[it->slot];
|
||||||
bufMemBarrier.size = VK_WHOLE_SIZE;
|
bufMemBarrier.size = VK_WHOLE_SIZE;
|
||||||
df->vkCmdPipelineBarrier(cbD->cb, s.stage, stage, 0,
|
df->vkCmdPipelineBarrier(cbD->cb, s.stage, stage, 0,
|
||||||
0, nullptr,
|
0, nullptr,
|
||||||
@ -3583,13 +3582,12 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
|
|||||||
0, nullptr);
|
0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<QRhiPassResourceTracker::Texture> *textures = tracker.textures();
|
for (auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures(); it != itEnd; ++it) {
|
||||||
for (const QRhiPassResourceTracker::Texture &t : *textures) {
|
QVkTexture *texD = QRHI_RES(QVkTexture, it.key());
|
||||||
QVkTexture *texD = QRHI_RES(QVkTexture, t.tex);
|
VkImageLayout layout = toVkLayout(it->access);
|
||||||
VkImageLayout layout = toVkLayout(t.access);
|
VkAccessFlags access = toVkAccess(it->access);
|
||||||
VkAccessFlags access = toVkAccess(t.access);
|
VkPipelineStageFlags stage = toVkPipelineStage(it->stage);
|
||||||
VkPipelineStageFlags stage = toVkPipelineStage(t.stage);
|
QVkTexture::UsageState s = toVkTextureUsageState(it->stateAtPassBegin);
|
||||||
QVkTexture::UsageState s = toVkTextureUsageState(t.stateAtPassBegin);
|
|
||||||
if (s.access == access && s.stage == stage && s.layout == layout) {
|
if (s.access == access && s.stage == stage && s.layout == layout) {
|
||||||
if (!accessIsWrite(access))
|
if (!accessIsWrite(access))
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user