5#include <QtQuick3DRuntimeRender/private/qssgrhieffectsystem_p.h>
6#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
7#include <QtQuick3DRuntimeRender/private/qssgrhiquadrenderer_p.h>
10#include <qtquick3d_tracepoints_p.h>
12#include <QtQuick3DUtils/private/qssgassert_p.h>
14#include <QtCore/qloggingcategory.h>
41 : m_sgContext(sgContext)
56 m_outSize = outputSize;
62 const auto foundIt = std::find_if(m_textures.cbegin(), m_textures.cend(), findTexture);
74 const bool gotMatch =
result !=
nullptr;
85 const auto found = std::find_if(m_textures.cbegin(), m_textures.cend(), findUnused);
86 if (found != m_textures.cend()) {
97 const auto &rhiCtx = m_sgContext->rhiContext();
98 QRhi *rhi = rhiCtx->rhi();
100 const bool needsRebuild =
result->texture && (
result->texture->pixelSize() !=
size || formatChanged);
107 if (rhiCtx->mainPassViewCount() >= 2)
112 }
else if (needsRebuild) {
116 result->texture->create();
119 if (!
result->renderTarget) {
121 colorAttachment.setMultiViewCount(rhiCtx->mainPassViewCount());
125 result->renderTarget->setRenderPassDescriptor(
result->renderPassDescriptor);
126 result->renderTarget->create();
128 }
else if (needsRebuild) {
130 delete result->renderPassDescriptor;
131 result->renderPassDescriptor =
result->renderTarget->newCompatibleRenderPassDescriptor();
132 result->renderTarget->setRenderPassDescriptor(
result->renderPassDescriptor);
134 result->renderTarget->create();
139 QByteArray rtName = inEffect->debugObjectName.toLatin1();
141 rtName += bufferName;
142 result->renderTarget->setName(rtName);
145 result->name = bufferName;
153 if (!
texture->flags.isSceneLifetime())
157void QSSGRhiEffectSystem::releaseTextures()
159 for (
auto *
t :
std::as_const(m_textures))
168 QSSG_ASSERT(m_sgContext !=
nullptr,
return inTexture);
169 const auto &rhiContext = m_sgContext->rhiContext();
170 const auto &
renderer = m_sgContext->renderer();
173 m_depthTexture = inDepthTexture;
174 m_cameraClipRange = cameraClipRange;
176 m_currentUbufIndex = 0;
177 auto *currentEffect = &firstEffect;
179 auto *latestOutput = doRenderEffect(currentEffect, &firstTex);
180 firstTex.texture =
nullptr;
182 while ((currentEffect = currentEffect->m_nextEffect)) {
183 auto *effectOut = doRenderEffect(currentEffect, latestOutput);
184 releaseTexture(latestOutput);
185 latestOutput = effectOut;
189 return latestOutput ? latestOutput->texture :
nullptr;
192void QSSGRhiEffectSystem::releaseResources()
197 m_shaderPipelines.
clear();
208 ? inEffect->outputFormat : targetCmd->m_outputFormat.
format;
218 qCDebug(lcEffectSystem) <<
"START effect " << inEffect->className;
224 qCDebug(lcEffectSystem).noquote() <<
" >" << theCommand->typeAsString() <<
"--" << theCommand->debugString();
226 switch (theCommand->m_type) {
228 allocateBufferCmd(
static_cast<QSSGAllocateBuffer *
>(theCommand), inTexture, inEffect);
246 if (applyCommand->m_samplerName.isEmpty())
249 addTextureToShaderPipeline(applyCommand->m_samplerName,
buffer->texture,
buffer->desc);
258 applyValueCmd(
static_cast<QSSGApplyValue *
>(theCommand), inEffect);
263 currentOutput = findTexture(bindCmd->m_bufferName);
268 bindShaderCmd(
static_cast<QSSGBindShader *
>(theCommand), inEffect);
275 inEffect->outputFormat : targetCmd->m_outputFormat.
format;
282 currentOutput = getTexture(tmpName, m_outSize, rhiFormat,
true, inEffect);
283 finalOutputTexture = currentOutput;
288 renderCmd(currentInput, currentOutput);
289 currentInput = inTexture;
293 qWarning() <<
"Effect command" << theCommand->typeAsString() <<
"not implemented";
298 qCDebug(lcEffectSystem) <<
"END effect " << inEffect->className;
299 return finalOutputTexture;
305 QSize bufferSize(m_outSize *
qreal(inCmd->m_sizeMultiplier));
315 buf->flags = inCmd->m_bufferFlags;
320 if (!m_currentShaderPipeline)
323 const bool setAll = inCmd->m_propertyName.isEmpty();
325 if (setAll ||
property.name == inCmd->m_propertyName) {
331 if (setAll || textureProperty.name == inCmd->m_propertyName) {
332 bool texAdded =
false;
335 const auto &theBufferManager(m_sgContext->bufferManager());
346 addTextureToShaderPipeline(textureProperty.name,
texture.m_texture, desc);
352 qCDebug(lcEffectSystem) <<
"Using dummy texture for property" << textureProperty.name;
353 addTextureToShaderPipeline(textureProperty.name,
nullptr, {});
361 if (!m_currentShaderPipeline)
364 const auto &
properties = inEffect->properties;
366 return (prop.name == inCmd->m_propertyName);
370 m_currentShaderPipeline->
setUniformValue(m_currentUBufData, inCmd->m_propertyName, inCmd->m_value, foundIt->shaderDataType);
372 qWarning() <<
"Could not find effect property" << inCmd->m_propertyName;
376 "vec2 qt_effectTextureMapUV(vec2 uv)\n"
382 "vec2 qt_effectTextureMapUV(vec2 uv)\n"
384 " return vec2(uv.x, 1.0 - uv.y);\n"
391 bool isYUpInFramebuffer,
394 const auto &
key = inCmd.m_shaderPathKey;
395 qCDebug(lcEffectSystem) <<
" generating new shader pipeline for: " <<
key;
427 m_currentTextures.
clear();
428 m_pendingClears.
clear();
429 m_currentShaderPipeline =
nullptr;
431 const auto &rhiCtx = m_sgContext->rhiContext();
432 QRhi *rhi = rhiCtx->rhi();
433 const auto &shaderLib = m_sgContext->shaderLibraryManager();
434 const auto &shaderCache = m_sgContext->shaderCache();
442 cacheKey.m_shaderPathKey = inCmd->m_shaderPathKey;
444 cacheKey.m_ubufIndex = m_currentUbufIndex;
449 if (
it != m_shaderPipelines.
cend())
450 m_currentShaderPipeline = (*it).get();
454 if (!m_currentShaderPipeline) {
460 if (!m_currentShaderPipeline && !shaderLib->m_preGeneratedShaderEntries.isEmpty()) {
463 if (foundIt != pregenEntries.cend()) {
467 const auto &
shader = shaderCache->newPipelineFromPregenerated(inCmd->m_shaderPathKey,
473 m_currentShaderPipeline =
shader.get();
477 if (!m_currentShaderPipeline) {
483 const auto &shaderPipeline = shaderCache->tryNewPipelineFromPersistentCache(qsbcKey,
484 inCmd->m_shaderPathKey,
487 if (shaderPipeline) {
489 m_currentShaderPipeline = shaderPipeline.get();
493 if (!m_currentShaderPipeline) {
497 const auto &
generator = m_sgContext->shaderProgramGenerator();
500 m_currentShaderPipeline =
stages.get();
505 const auto &rhiContext = m_sgContext->rhiContext();
507 if (m_currentShaderPipeline) {
508 const void *cacheKey1 =
reinterpret_cast<const void *
>(
this);
509 const void *cacheKey2 =
reinterpret_cast<const void *
>(
qintptr(m_currentUbufIndex));
512 m_currentUBufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
514 m_currentUBufData =
nullptr;
522 if (!m_currentShaderPipeline)
526 qWarning(
"No effect render target?");
531 addTextureToShaderPipeline(
QByteArrayLiteral(
"qt_inputTexture"), inTexture->texture, inTexture->desc);
532 addTextureToShaderPipeline(
QByteArrayLiteral(
"qt_inputTextureArray"), inTexture->texture, inTexture->desc);
534 const auto &rhiContext = m_sgContext->rhiContext();
535 const auto &
renderer = m_sgContext->renderer();
547 if (rt !=
target->renderTarget) {
548 cb->beginPass(rt,
Qt::transparent, { 1.0f, 0 },
nullptr, rhiContext->commonPassFlags());
554 m_pendingClears.
clear();
556 const QSize inputSize = inTexture->texture->pixelSize();
557 const QSize outputSize =
target->texture->pixelSize();
558 addCommonEffectUniforms(inputSize, outputSize);
562 const void *cacheKey1 =
reinterpret_cast<const void *
>(
this);
563 const void *cacheKey2 =
reinterpret_cast<const void *
>(
qintptr(m_currentUbufIndex));
566 m_currentUBufData =
nullptr;
569 renderer->rhiQuadRenderer()->prepareQuad(rhiContext.get(), rub);
579 qCDebug(lcEffectSystem) <<
" -> texture binding" << binding <<
"for" << rhiTex.name;
581 QRhiTexture *
texture = rhiTex.texture ? rhiTex.texture : rhiContext->dummyTexture({}, rub);
585 rhiContext->sampler(rhiTex.samplerDesc));
594 ps.
viewCount = rhiContext->mainPassViewCount();
598 m_currentUbufIndex++;
603void QSSGRhiEffectSystem::addCommonEffectUniforms(
const QSize &inputSize,
const QSize &outputSize)
605 const auto &rhiContext = m_sgContext->rhiContext();
606 QRhi *rhi = rhiContext->rhi();
610 mvp.
data()[5] = -1.0f;
619 float fc = float(m_sgContext->renderer()->frameCount());
633 if (m_depthTexture) {
639 addTextureToShaderPipeline(
"qt_depthTexture", m_depthTexture, depthSamplerDesc);
640 addTextureToShaderPipeline(
"qt_depthTextureArray", m_depthTexture, depthSamplerDesc);
644void QSSGRhiEffectSystem::addTextureToShaderPipeline(
const QByteArray &
name,
648 if (!m_currentShaderPipeline)
658 m_currentTextures.
insert(
name, {
name,
texture, validDescription ? samplerDescription : defaultDescription});
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
const_iterator constFind(const Key &key) const noexcept
const_iterator cend() const noexcept
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
float * data()
Returns a pointer to the raw data of this matrix.
static FeatureSet toFeatureSet(const T &ssgFeatureSet)
virtual void endFullDynamicBufferUpdateForCurrentFrame()
To be called when the entire contents of the buffer data has been updated in the memory block returne...
virtual QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const =0
QRhiRenderPassDescriptor * renderPassDescriptor() const
virtual bool create()=0
Creates the corresponding native graphics resources.
Format
Specifies the texture format.
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool isClipDepthZeroToOne() const
QRhiTexture * newTextureArray(QRhiTexture::Format format, int arraySize, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
bool isYUpInFramebuffer() const
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
static const char * toString(QSSGRenderTextureCubeFace value)
static QRhiTexture::Format toRhiFormat(const QSSGRenderTextureFormat format)
static QSSGRhiContextPrivate * get(QSSGRhiContext *q)
static QSSGRhiContextStats & get(QSSGRhiContext &rhiCtx)
QRhiTexture * process(const QSSGRenderEffect &firstEffect, QRhiTexture *inTexture, QRhiTexture *inDepthTexture, QVector2D cameraClipRange)
void setup(QSize outputSize)
static QSSGRhiShaderPipelinePtr buildShaderForEffect(const QSSGBindShader &inCmd, QSSGProgramGenerator &generator, QSSGShaderLibraryManager &shaderLib, QSSGShaderCache &shaderCache, bool isYUpInFramebuffer, int viewCount)
static QSSGRenderTextureFormat::Format overriddenOutputFormat(const QSSGRenderEffect *inEffect)
QSSGRhiEffectSystem(const std::shared_ptr< QSSGRenderContextInterface > &sgContext)
void setUniformValue(char *ubufData, const char *name, const QVariant &value, QSSGRenderShaderValue::Type type)
int bindingForTexture(const char *name, int hint=-1)
void ensureCombinedUniformBuffer(QRhiBuffer **ubuf)
void addUniformBuffer(int binding, QRhiShaderResourceBinding::StageFlags stage, QRhiBuffer *buf, int offset=0, int size=0)
void addTexture(int binding, QRhiShaderResourceBinding::StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
const_iterator constFind(const T &value) const
iterator insert(const T &value)
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
The QVector2D class represents a vector or vertex in 2D space.
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
QRhiSampler::Filter toRhi(QSSGRenderTextureFilterOp op)
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
static const QCssKnownValue properties[NumProperties - 1]
static QByteArray cacheKey(Args &&...args)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei const GLubyte * commands
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint GLsizei GLsizei GLenum format
#define Q_QUICK3D_PROFILE_START(Type)
#define Q_QUICK3D_PROFILE_END_WITH_ID(Type, Payload, POID)
#define Q_QUICK3D_PROFILE_END_WITH_STRING(Type, Payload, Str)
#define QSSG_ASSERT(cond, action)
#define QSSGRHICTX_STAT(ctx, f)
std::shared_ptr< QSSGRhiShaderPipeline > QSSGRhiShaderPipelinePtr
static const char * effect_builtin_textureMapUVFlipped
static const char * effect_builtin_textureMapUV
static QT_BEGIN_NAMESPACE const QRhiShaderResourceBinding::StageFlags VISIBILITY_ALL
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define Q_TRACE_SCOPE(x,...)
QRandomGenerator generator(sseq)
QSvgRenderer * renderer
[0]
QByteArray generateSha() const
QSSGRenderTextureFormat m_outputFormat
QSSGRhiSamplerDescription desc
QRhiRenderPassDescriptor * renderPassDescriptor
QSSGAllocateBufferFlags flags
QRhiTextureRenderTarget * renderTarget
QSSGRhiEffectTexture & operator=(const QSSGRhiEffectTexture &)=delete
static void setShaderPipeline(QSSGRhiGraphicsPipelineState &ps, const QSSGRhiShaderPipeline *pipeline)
\variable QSSGRhiGraphicsPipelineState::depthFunc
QRhiSampler::Filter magFilter