/****************************************************************************
**
** Copyright (C) 2008-2012 NVIDIA Corporation.
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendererimpl_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderimage_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderresourcemanager_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercustommaterialsystem_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendershadercodegeneratorv2_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h>
#include <QtQuick3DRuntimeRender/private/qssgperframeallocator_p.h>

#include <QtQuick3DRender/private/qssgrenderframebuffer_p.h>
#include <QtQuick3DUtils/private/qssgdataref_p.h>
#include <QtQuick3DUtils/private/qssgutils_p.h>

#include <cstdlib>
#include <algorithm>

#ifdef Q_CC_MSVC
#pragma warning(disable : 4355)
#endif

// Quick tests you can run to find performance problems

//#define QSSG_RENDER_DISABLE_HARDWARE_BLENDING 1
//#define QSSG_RENDER_DISABLE_LIGHTING 1
//#define QSSG_RENDER_DISABLE_TEXTURING 1
//#define QSSG_RENDER_DISABLE_TRANSPARENCY 1
//#define QSSG_RENDER_DISABLE_FRUSTUM_CULLING 1

// If you are fillrate bound then sorting opaque objects can help in some circumstances
//#define QSSG_RENDER_DISABLE_OPAQUE_SORT 1

QT_BEGIN_NAMESPACE

struct QSSGRenderableImage;
struct QSSGShaderGeneratorGeneratedShader;
struct QSSGSubsetRenderable;

QSSGRendererImpl::QSSGRendererImpl(const QSSGRef<QSSGRenderContextInterface> &ctx)
    : m_contextInterface(ctx)
    , m_context(ctx->renderContext())
    , m_bufferManager(ctx->bufferManager())
    , m_currentLayer(nullptr)
    , m_pickRenderPlugins(true)
    , m_layerCachingEnabled(true)
    , m_layerGPuProfilingEnabled(false)
    , m_progressiveAARenderRequest(false)
{
}

QSSGRendererImpl::~QSSGRendererImpl()
{
    m_shaders.clear();
    m_instanceRenderMap.clear();
    m_constantBuffers.clear();
}

void QSSGRendererImpl::childrenUpdated(QSSGRenderNode &inParent)
{   
    if (inParent.type == QSSGRenderGraphObject::Type::Layer) {
        const QSSGRenderLayer *theLayer = layerForNode(inParent);
        auto theIter = m_instanceRenderMap.find(theLayer);
        if (theIter != m_instanceRenderMap.end()) {
            theIter.value()->cameras.clear();
            theIter.value()->lights.clear();
            theIter.value()->renderableNodes.clear();
        }
    } else if (inParent.parent) {
        childrenUpdated(*inParent.parent);
    }
}

static inline QSSGRenderLayer *getNextLayer(QSSGRenderLayer &inLayer)
{
    if (inLayer.nextSibling && inLayer.nextSibling->type == QSSGRenderGraphObject::Type::Layer)
        return static_cast<QSSGRenderLayer *>(inLayer.nextSibling);
    return nullptr;
}

// Found by fair roll of the dice (in practice we'll never have more then 1 layer!).
using QSSGRenderLayerList = QVarLengthArray<QSSGRenderLayer *, 4>;

static inline void maybePushLayer(QSSGRenderLayer &inLayer, QSSGRenderLayerList &outLayerList)
{
    inLayer.calculateGlobalVariables();
    if (inLayer.flags.testFlag(QSSGRenderLayer::Flag::GloballyActive) && inLayer.flags.testFlag(QSSGRenderLayer::Flag::LayerRenderToTarget))
        outLayerList.push_back(&inLayer);
}

bool QSSGRendererImpl::prepareLayerForRender(QSSGRenderLayer &inLayer,
                                               const QSize &surfaceSize)
{

    QSSGRenderLayerList renderableLayers;
    maybePushLayer(inLayer, renderableLayers);

    bool retval = false;

    auto iter = renderableLayers.crbegin();
    const auto end = renderableLayers.crend();
    for (; iter != end; ++iter) {
        // Store the previous state of if we were rendering a layer.
        QSSGRenderLayer *theLayer = *iter;
        QSSGRef<QSSGLayerRenderData> theRenderData = getOrCreateLayerRenderDataForNode(*theLayer);

        if (Q_LIKELY(theRenderData)) {
            theRenderData->prepareForRender(surfaceSize);
            retval = retval || theRenderData->layerPrepResult->flags.wasDirty();
        } else {
            Q_ASSERT(false);
        }
    }

    return retval;
}

void QSSGRendererImpl::renderLayer(QSSGRenderLayer &inLayer,
                                     const QSize &surfaceSize,
                                     bool clear,
                                     const QColor &clearColor)
{
    Q_UNUSED(surfaceSize)
    Q_UNUSED(clearColor)
    QSSGRenderLayerList renderableLayers;
    maybePushLayer(inLayer, renderableLayers);

    const QSSGRef<QSSGRenderContext> &theRenderContext(m_contextInterface->renderContext());
    // Do not use reference since it will just shadow the hardware context variable in the
    // render context breaking the caching.
    const QSSGRef<QSSGRenderFrameBuffer> theFB = theRenderContext->renderTarget();
    auto iter = renderableLayers.crbegin();
    const auto end = renderableLayers.crend();
    m_progressiveAARenderRequest = false;

    for (iter = renderableLayers.crbegin(); iter != end; ++iter) {
        // Store the previous state of if we were rendering a layer.
        QSSGRenderLayer *theLayer = *iter;
        const QSSGRef<QSSGLayerRenderData> &theRenderData = getOrCreateLayerRenderDataForNode(*theLayer);

        if (Q_LIKELY(theRenderData)) {
            // Make sure that we don't clear the window, when requested not to.
            theRenderData->layerPrepResult->flags.setRequiresTransparentClear(clear);
            if (theRenderData->layerPrepResult->isLayerVisible()) {
                theRenderData->runnableRenderToViewport(theFB);
                m_progressiveAARenderRequest |= theRenderData->progressiveAARenderRequest();
            }
        } else {
            Q_ASSERT(false);
        }
    }
}

QSSGRenderLayer *QSSGRendererImpl::layerForNode(const QSSGRenderNode &inNode) const
{
    if (inNode.type == QSSGRenderGraphObject::Type::Layer)
        return &const_cast<QSSGRenderLayer &>(static_cast<const QSSGRenderLayer &>(inNode));

    if (inNode.parent)
        return layerForNode(*inNode.parent);

    return nullptr;
}

QSSGRef<QSSGLayerRenderData> QSSGRendererImpl::getOrCreateLayerRenderDataForNode(const QSSGRenderNode &inNode)
{
    const QSSGRenderLayer *theLayer = layerForNode(inNode);
    if (theLayer) {
        auto it = m_instanceRenderMap.constFind(theLayer);
        if (it != m_instanceRenderMap.cend())
            return it.value();

        it = m_instanceRenderMap.insert(theLayer, new QSSGLayerRenderData(const_cast<QSSGRenderLayer &>(*theLayer), this));

        // create a profiler if enabled
        if (isLayerGpuProfilingEnabled() && it.value())
            it.value()->createGpuProfiler();

        return *it;
    }
    return nullptr;
}

QSSGRenderCamera *QSSGRendererImpl::cameraForNode(const QSSGRenderNode &inNode) const
{
    const QSSGRef<QSSGLayerRenderData> &theLayer = const_cast<QSSGRendererImpl &>(*this).getOrCreateLayerRenderDataForNode(inNode);
    if (theLayer)
        return theLayer->camera;
    return nullptr;
}

QSSGOption<QSSGCuboidRect> QSSGRendererImpl::cameraBounds(const QSSGRenderGraphObject &inObject)
{
    if (inObject.isNodeType()) {
        const QSSGRenderNode &theNode = static_cast<const QSSGRenderNode &>(inObject);
        const QSSGRef<QSSGLayerRenderData> &theLayer = getOrCreateLayerRenderDataForNode(theNode);

        QSSGRenderCamera *theCamera = theLayer->camera;
        if (theCamera)
            return theCamera->getCameraBounds(theLayer->layerPrepResult->viewport());

    }
    return QSSGOption<QSSGCuboidRect>();
}

void QSSGRendererImpl::drawScreenRect(QRectF inRect, const QVector3D &inColor)
{
    QSSGRenderCamera theScreenCamera;
    theScreenCamera.markDirty(QSSGRenderCamera::TransformDirtyFlag::TransformIsDirty);
    QRectF theViewport(m_context->viewport());
    theScreenCamera.flags.setFlag(QSSGRenderCamera::Flag::Orthographic);
    theScreenCamera.calculateGlobalVariables(theViewport);
    generateXYQuad();
    if (!m_screenRectShader) {
        QSSGRef<QSSGShaderProgramGeneratorInterface> theGenerator(getProgramGenerator());
        theGenerator->beginProgram();
        QSSGShaderStageGeneratorInterface &vertexGenerator(*theGenerator->getStage(QSSGShaderGeneratorStage::Vertex));
        QSSGShaderStageGeneratorInterface &fragmentGenerator(*theGenerator->getStage(QSSGShaderGeneratorStage::Fragment));
        // TODO: Move out and change type!
        vertexGenerator.addIncoming("attr_pos", "vec3");
        vertexGenerator.addUniform("modelViewProjection", "mat4");
        vertexGenerator.addUniform("rectangle_dims", "vec3");
        vertexGenerator.append("void main() {");
        vertexGenerator.append("\tgl_Position = modelViewProjection * vec4(attr_pos * rectangle_dims, 1.0);");
        vertexGenerator.append("}");
        fragmentGenerator.addUniform("output_color", "vec3");
        fragmentGenerator.append("void main() {");
        fragmentGenerator.append("\tgl_FragColor.rgb = output_color;");
        fragmentGenerator.append("\tgl_FragColor.a = 1.0;");
        fragmentGenerator.append("}");
        // No flags enabled
        m_screenRectShader = theGenerator->compileGeneratedShader("DrawScreenRect", QSSGShaderCacheProgramFlags(), ShaderFeatureSetList());
    }
    if (m_screenRectShader) {
        // Fudge the rect by one pixel to ensure we see all the corners.
        if (inRect.width() > 1)
            inRect.setWidth(inRect.width() - 1);
        if (inRect.height() > 1)
            inRect.setHeight(inRect.height() - 1);
        inRect.setX(inRect.x() + 1);
        inRect.setY(inRect.y() + 1);
        // Figure out the rect center.
        QSSGRenderNode theNode;

        const QPointF &center = inRect.center();
        QVector2D rectGlobalCenter = { float(center.x()), float(center.y()) };
        QVector2D rectCenter(toNormalizedRectRelative(theViewport, rectGlobalCenter));
        theNode.position.setX(rectCenter.x());
        theNode.position.setY(rectCenter.y());
        theNode.markDirty(QSSGRenderNode::TransformDirtyFlag::TransformIsDirty);
        theNode.calculateGlobalVariables();
        QMatrix4x4 theViewProjection;
        theScreenCamera.calculateViewProjectionMatrix(theViewProjection);
        QMatrix4x4 theMVP;
        QMatrix3x3 theNormal;
        theNode.calculateMVPAndNormalMatrix(theViewProjection, theMVP, theNormal);
        m_context->setBlendingEnabled(false);
        m_context->setDepthWriteEnabled(false);
        m_context->setDepthTestEnabled(false);
        m_context->setCullingEnabled(false);
        m_context->setActiveShader(m_screenRectShader);
        m_screenRectShader->setPropertyValue("modelViewProjection", theMVP);
        m_screenRectShader->setPropertyValue("output_color", inColor);
        m_screenRectShader->setPropertyValue("rectangle_dims", QVector3D(float(inRect.width()) / 2.0f, float(inRect.height()) / 2.0f, 0.0f));
    }
    if (!m_rectInputAssembler) {
        Q_ASSERT(m_quadVertexBuffer);
        const quint8 indexData[] = { 0, 1, 1, 2, 2, 3, 3, 0 };

        m_rectIndexBuffer = new QSSGRenderIndexBuffer(m_context, QSSGRenderBufferUsageType::Static,
                                                        QSSGRenderComponentType::UnsignedInteger8,
                                                        toDataView(indexData, sizeof(indexData)));

        QSSGRenderVertexBufferEntry theEntries[] = {
            QSSGRenderVertexBufferEntry("attr_pos", QSSGRenderComponentType::Float32, 3),
        };

        // create our attribute layout
        m_rectAttribLayout = m_context->createAttributeLayout(toDataView(theEntries, 1));

        quint32 strides = m_quadVertexBuffer->stride();
        quint32 offsets = 0;
        m_rectInputAssembler = m_context->createInputAssembler(m_rectAttribLayout,
                                                               toDataView(&m_quadVertexBuffer, 1),
                                                               m_rectIndexBuffer,
                                                               toDataView(&strides, 1),
                                                               toDataView(&offsets, 1));
    }

    m_context->setInputAssembler(m_rectInputAssembler);
    m_context->draw(QSSGRenderDrawMode::Lines, m_rectIndexBuffer->numIndices(), 0);
}

void QSSGRendererImpl::setupWidgetLayer()
{
    const QSSGRef<QSSGRenderContext> &theContext = m_contextInterface->renderContext();

    if (!m_widgetTexture) {
        const QSSGRef<QSSGResourceManager> &theManager = m_contextInterface->resourceManager();
        m_widgetTexture = theManager->allocateTexture2D(m_beginFrameViewport.width(),
                                                        m_beginFrameViewport.height(),
                                                        QSSGRenderTextureFormat::RGBA8);
        m_widgetFbo = theManager->allocateFrameBuffer();
        m_widgetFbo->attach(QSSGRenderFrameBufferAttachment::Color0, QSSGRenderTextureOrRenderBuffer(m_widgetTexture));
        theContext->setRenderTarget(m_widgetFbo);

        // QSSGRenderRect theScissorRect( 0, 0, m_BeginFrameViewport.m_Width,
        // m_BeginFrameViewport.m_Height );
        // QSSGRenderContextScopedProperty<QSSGRenderRect> __scissorRect( theContext,
        // &QSSGRenderContext::GetScissorRect, &QSSGRenderContext::SetScissorRect, theScissorRect );
        QSSGRenderContextScopedProperty<bool> __scissorEnabled(*theContext,
                                                                 &QSSGRenderContext::isScissorTestEnabled,
                                                                 &QSSGRenderContext::setScissorTestEnabled,
                                                                 false);
        m_context->setClearColor(QVector4D(0, 0, 0, 0));
        m_context->clear(QSSGRenderClearValues::Color);

    } else {
        theContext->setRenderTarget(m_widgetFbo);
    }
}

void QSSGRendererImpl::addMaterialDirtyClear(QSSGRenderGraphObject *material)
{
    m_materialClearDirty.insert(material);
}

void QSSGRendererImpl::beginFrame()
{
    for (int idx = 0, end = m_lastFrameLayers.size(); idx < end; ++idx)
        m_lastFrameLayers[idx]->resetForFrame();
    m_lastFrameLayers.clear();
    m_beginFrameViewport = m_contextInterface->viewport();
    for (auto *matObj : qAsConst(m_materialClearDirty)) {
        if (matObj->type == QSSGRenderGraphObject::Type::CustomMaterial)
            static_cast<QSSGRenderCustomMaterial *>(matObj)->updateDirtyForFrame();
        else if (matObj->type == QSSGRenderGraphObject::Type::DefaultMaterial)
            static_cast<QSSGRenderDefaultMaterial *>(matObj)->dirty.updateDirtyForFrame();
    }
    m_materialClearDirty.clear();
}
void QSSGRendererImpl::endFrame()
{
    if (m_widgetTexture) {
        // Releasing the widget FBO can set it as the active frame buffer.
        QSSGRenderContextScopedProperty<const QSSGRef<QSSGRenderFrameBuffer> &> __fbo(*m_context,
                                                                                    &QSSGRenderContext::renderTarget,
                                                                                    &QSSGRenderContext::setRenderTarget);
        QSSGTextureDetails theDetails = m_widgetTexture->textureDetails();
        m_context->setBlendingEnabled(true);
        // Colors are expected to be non-premultiplied, so we premultiply alpha into them at
        // this point.
        m_context->setBlendFunction(QSSGRenderBlendFunctionArgument(QSSGRenderSrcBlendFunc::One,
                                                                      QSSGRenderDstBlendFunc::OneMinusSrcAlpha,
                                                                      QSSGRenderSrcBlendFunc::One,
                                                                      QSSGRenderDstBlendFunc::OneMinusSrcAlpha));
        m_context->setBlendEquation(QSSGRenderBlendEquationArgument(QSSGRenderBlendEquation::Add, QSSGRenderBlendEquation::Add));

        m_context->setDepthTestEnabled(false);
        m_context->setScissorTestEnabled(false);
        m_context->setViewport(m_beginFrameViewport);
        QSSGRenderCamera theCamera;
        theCamera.markDirty(QSSGRenderCamera::TransformDirtyFlag::TransformIsDirty);
        theCamera.flags.setFlag(QSSGRenderCamera::Flag::Orthographic);
        QVector2D theTextureDims(float(theDetails.width), float(theDetails.height));
        theCamera.calculateGlobalVariables(QRectF(0, 0, theDetails.width, theDetails.height));
        QMatrix4x4 theViewProj;
        theCamera.calculateViewProjectionMatrix(theViewProj);
        renderQuad(theTextureDims, theViewProj, *m_widgetTexture);

        const QSSGRef<QSSGResourceManager> &theManager(m_contextInterface->resourceManager());
        theManager->release(m_widgetFbo);
        theManager->release(m_widgetTexture);
        m_widgetTexture = nullptr;
        m_widgetFbo = nullptr;
    }
}

inline bool pickResultLessThan(const QSSGRenderPickResult &lhs, const QSSGRenderPickResult &rhs)
{
    return lhs.m_cameraDistanceSq < rhs.m_cameraDistanceSq;
}

inline float clampUVCoord(float inUVCoord, QSSGRenderTextureCoordOp inCoordOp)
{
    if (inUVCoord > 1.0f || inUVCoord < 0.0f) {
        switch (inCoordOp) {
        default:
            Q_ASSERT(false);
            break;
        case QSSGRenderTextureCoordOp::ClampToEdge:
            inUVCoord = qMin(inUVCoord, 1.0f);
            inUVCoord = qMax(inUVCoord, 0.0f);
            break;
        case QSSGRenderTextureCoordOp::Repeat: {
            float multiplier = inUVCoord > 0.0f ? 1.0f : -1.0f;
            float clamp = std::fabs(inUVCoord);
            clamp = clamp - std::floor(clamp);
            if (multiplier < 0)
                inUVCoord = 1.0f - clamp;
            else
                inUVCoord = clamp;
        } break;
        case QSSGRenderTextureCoordOp::MirroredRepeat: {
            float multiplier = inUVCoord > 0.0f ? 1.0f : -1.0f;
            float clamp = std::fabs(inUVCoord);
            if (multiplier > 0.0f)
                clamp -= 1.0f;
            quint32 isMirrored = (quint32(clamp)) % 2 == 0;
            float remainder = clamp - std::floor(clamp);
            inUVCoord = remainder;
            if (isMirrored) {
                if (multiplier > 0.0f)
                    inUVCoord = 1.0f - inUVCoord;
            } else {
                if (multiplier < 0.0f)
                    inUVCoord = 1.0f - remainder;
            }
        } break;
        }
    }
    return inUVCoord;
}

QSSGPickResultProcessResult QSSGRendererImpl::processPickResultList(bool inPickEverything)
{
    Q_UNUSED(inPickEverything)
    if (m_lastPickResults.empty())
        return QSSGPickResultProcessResult();
    // Things are rendered in a particular order and we need to respect that ordering.
    std::stable_sort(m_lastPickResults.begin(), m_lastPickResults.end(), pickResultLessThan);

    // We need to pick against sub objects basically somewhat recursively
    // but if we don't hit any sub objects and the parent isn't pickable then
    // we need to move onto the next item in the list.
    // We need to keep in mind that theQuery->Pick will enter this method in a later
    // stack frame so *if* we get to sub objects we need to pick against them but if the pick
    // completely misses *and* the parent object locally pickable is false then we need to move
    // onto the next object.

    const int numToCopy = m_lastPickResults.size();
    Q_ASSERT(numToCopy >= 0);
    size_t numCopyBytes = size_t(numToCopy) * sizeof(QSSGRenderPickResult);
    QSSGRenderPickResult *thePickResults = reinterpret_cast<QSSGRenderPickResult *>(
            m_contextInterface->perFrameAllocator().allocate(numCopyBytes));
    ::memcpy(thePickResults, m_lastPickResults.data(), numCopyBytes);
    m_lastPickResults.clear();
    QSSGPickResultProcessResult thePickResult(thePickResults[0]);
    return thePickResult;
}

QSSGRenderPickResult QSSGRendererImpl::pick(QSSGRenderLayer &inLayer,
                                                const QVector2D &inViewportDimensions,
                                                const QVector2D &inMouseCoords,
                                                bool inPickSiblings,
                                                bool inPickEverything)
{
    m_lastPickResults.clear();

    QSSGRenderLayer *theLayer = &inLayer;
    // Stepping through how the original runtime did picking it picked layers in order
    // stopping at the first hit.  So objects on the top layer had first crack at the pick
    // vector itself.
    do {
        if (theLayer->flags.testFlag(QSSGRenderLayer::Flag::Active)) {
            const auto theIter = m_instanceRenderMap.constFind(theLayer);
            if (theIter != m_instanceRenderMap.cend()) {
                m_lastPickResults.clear();
                getLayerHitObjectList(*theIter.value(), inViewportDimensions, inMouseCoords, inPickEverything, m_lastPickResults);
                QSSGPickResultProcessResult retval(processPickResultList(inPickEverything));
                if (retval.m_wasPickConsumed)
                    return retval;
            } else {
                // Q_ASSERT( false );
            }
        }

        if (inPickSiblings)
            theLayer = getNextLayer(*theLayer);
        else
            theLayer = nullptr;
    } while (theLayer != nullptr);

    return QSSGRenderPickResult();
}

QSSGRenderPickResult QSSGRendererImpl::syncPick(QSSGRenderLayer &inLayer, const QVector2D &inViewportDimensions, const QVector2D &inMouseCoords, bool inPickSiblings, bool inPickEverything)
{
    using PickResultList = QVarLengthArray<QSSGRenderPickResult, 20>; // Lets assume most items are filtered out already
    static const auto processResults = [](PickResultList &pickResults) {
        if (pickResults.empty())
            return QSSGPickResultProcessResult();
        // Things are rendered in a particular order and we need to respect that ordering.
        std::stable_sort(pickResults.begin(), pickResults.end(), [](const QSSGRenderPickResult &lhs, const QSSGRenderPickResult &rhs) {
            return lhs.m_cameraDistanceSq < rhs.m_cameraDistanceSq;
        });
        return QSSGPickResultProcessResult{ pickResults.at(0), true };
    };

    PickResultList pickResults;
    QSSGRenderLayer *layer = &inLayer;
    while (layer != nullptr) {
        if (layer->flags.testFlag(QSSGRenderLayer::Flag::Active)) {
            pickResults.clear();
            getLayerHitObjectList(*layer, inViewportDimensions, inMouseCoords, inPickEverything, pickResults);
            QSSGPickResultProcessResult retval = processResults(pickResults);
            if (retval.m_wasPickConsumed)
                return retval;
        }

        layer = inPickSiblings ? getNextLayer(*layer) : nullptr;
    }

    return QSSGPickResultProcessResult();
}

QSSGOption<QVector2D> QSSGRendererImpl::facePosition(QSSGRenderNode &inNode,
                                                         QSSGBounds3 inBounds,
                                                         const QMatrix4x4 &inGlobalTransform,
                                                         const QVector2D &inViewportDimensions,
                                                         const QVector2D &inMouseCoords,
                                                         QSSGDataView<QSSGRenderGraphObject *> inMapperObjects,
                                                         QSSGRenderBasisPlanes inPlane)
{
    Q_UNUSED(inMapperObjects)
    const QSSGRef<QSSGLayerRenderData> &theLayerData = getOrCreateLayerRenderDataForNode(inNode);
    if (theLayerData == nullptr)
        return QSSGEmpty();
    // This function assumes the layer was rendered to the scene itself.  There is another
    // function
    // for completely offscreen layers that don't get rendered to the scene.
    bool wasRenderToTarget(theLayerData->layer.flags.testFlag(QSSGRenderLayer::Flag::LayerRenderToTarget));
    if (!wasRenderToTarget || theLayerData->camera == nullptr || theLayerData->layerPrepResult.hasValue() == false)
        return QSSGEmpty();

    QVector2D theMouseCoords(inMouseCoords);
    QVector2D theViewportDimensions(inViewportDimensions);

    const auto camera = theLayerData->layerPrepResult->camera();
    const auto viewport = theLayerData->layerPrepResult->viewport();
    QSSGOption<QSSGRenderRay> theHitRay = QSSGLayerRenderHelper::pickRay(*camera, viewport, theMouseCoords, theViewportDimensions, false);
    if (!theHitRay.hasValue())
        return QSSGEmpty();

    // Scale the mouse coords to change them into the camera's numerical space.
    QSSGRenderRay thePickRay = *theHitRay;
    QSSGOption<QVector2D> newValue = thePickRay.relative(inGlobalTransform, inBounds, inPlane);
    return newValue;
}

QVector3D QSSGRendererImpl::unprojectToPosition(QSSGRenderNode &inNode, QVector3D &inPosition, const QVector2D &inMouseVec) const
{
    // Translate mouse into layer's coordinates
    const QSSGRef<QSSGLayerRenderData> &theData = const_cast<QSSGRendererImpl &>(*this).getOrCreateLayerRenderDataForNode(inNode);
    if (theData == nullptr || theData->camera == nullptr) {
        return QVector3D(0, 0, 0);
    } // Q_ASSERT( false ); return QVector3D(0,0,0); }

    QSize theWindow = m_contextInterface->windowDimensions();
    QVector2D theDims(float(theWindow.width()), float(theWindow.height()));

    QSSGLayerRenderPreparationResult &thePrepResult(*theData->layerPrepResult);
    const auto camera = thePrepResult.camera();
    const auto viewport = thePrepResult.viewport();
    QSSGRenderRay theRay = QSSGLayerRenderHelper::pickRay(*camera, viewport, inMouseVec, theDims, true);

    return theData->camera->unprojectToPosition(inPosition, theRay);
}

QVector3D QSSGRendererImpl::unprojectWithDepth(QSSGRenderNode &inNode, QVector3D &, const QVector3D &inMouseVec) const
{
    // Translate mouse into layer's coordinates
    const QSSGRef<QSSGLayerRenderData> &theData = const_cast<QSSGRendererImpl &>(*this).getOrCreateLayerRenderDataForNode(inNode);
    if (theData == nullptr || theData->camera == nullptr) {
        return QVector3D(0, 0, 0);
    } // Q_ASSERT( false ); return QVector3D(0,0,0); }

    // Flip the y into gl coordinates from window coordinates.
    QVector2D theMouse(inMouseVec.x(), inMouseVec.y());
    float theDepth = inMouseVec.z();

    QSSGLayerRenderPreparationResult &thePrepResult(*theData->layerPrepResult);
    QSize theWindow = m_contextInterface->windowDimensions();
    const auto camera = thePrepResult.camera();
    const auto viewport = thePrepResult.viewport();
    QSSGRenderRay theRay = QSSGLayerRenderHelper::pickRay(*camera, viewport, theMouse, QVector2D(float(theWindow.width()), float(theWindow.height())), true);
    QVector3D theTargetPosition = theRay.origin + theRay.direction * theDepth;
    if (inNode.parent != nullptr && inNode.parent->type != QSSGRenderGraphObject::Type::Layer)
        theTargetPosition = mat44::transform(inNode.parent->globalTransform.inverted(), theTargetPosition);
    // Our default global space is right handed, so if you are left handed z means something
    // opposite.
    if (inNode.flags.testFlag(QSSGRenderNode::Flag::LeftHanded))
        theTargetPosition.setZ(theTargetPosition.z() * -1);
    return theTargetPosition;
}

QVector3D QSSGRendererImpl::projectPosition(QSSGRenderNode &inNode, const QVector3D &inPosition) const
{
    // Translate mouse into layer's coordinates
    const QSSGRef<QSSGLayerRenderData> &theData = const_cast<QSSGRendererImpl &>(*this).getOrCreateLayerRenderDataForNode(inNode);
    if (theData == nullptr || theData->camera == nullptr) {
        return QVector3D(0, 0, 0);
    }

    QMatrix4x4 viewProj;
    theData->camera->calculateViewProjectionMatrix(viewProj);
    QVector4D projPos = mat44::transform(viewProj, QVector4D(inPosition, 1.0f));
    projPos.setX(projPos.x() / projPos.w());
    projPos.setY(projPos.y() / projPos.w());

    QRectF theViewport = theData->layerPrepResult->viewport();
    QVector2D theDims(float(theViewport.width()), float(theViewport.height()));
    projPos.setX(projPos.x() + 1.0f);
    projPos.setY(projPos.y() + 1.0f);
    projPos.setX(projPos.x() * 0.5f);
    projPos.setY(projPos.y() * 0.5f);
    QVector3D cameraToObject = theData->camera->getGlobalPos() - inPosition;
    projPos.setZ(sqrtf(QVector3D::dotProduct(cameraToObject, cameraToObject)));
    QVector3D mouseVec = QVector3D(projPos.x(), projPos.y(), projPos.z());
    mouseVec.setX(mouseVec.x() * theDims.x());
    mouseVec.setY(mouseVec.y() * theDims.y());

    mouseVec.setX(mouseVec.x() + float(theViewport.x()));
    mouseVec.setY(mouseVec.y() + float(theViewport.y()));

    // Flip the y into window coordinates so it matches the mouse.
    QSize theWindow = m_contextInterface->windowDimensions();
    mouseVec.setY(theWindow.height() - mouseVec.y());

    return mouseVec;
}

QSSGOption<QSSGLayerPickSetup> QSSGRendererImpl::getLayerPickSetup(QSSGRenderLayer &inLayer,
                                                                         const QVector2D &inMouseCoords,
                                                                         const QSize &inPickDims)
{
    const QSSGRef<QSSGLayerRenderData> &theData = getOrCreateLayerRenderDataForNode(inLayer);
    if (Q_UNLIKELY(theData == nullptr || theData->camera == nullptr)) {
        Q_ASSERT(false);
        return QSSGEmpty();
    }
    QSize theWindow = m_contextInterface->windowDimensions();
    QVector2D theDims(float(theWindow.width()), float(theWindow.height()));
    // The mouse is relative to the layer
    QSSGOption<QVector2D> theLocalMouse = getLayerMouseCoords(*theData, inMouseCoords, theDims, false);
    if (!theLocalMouse.hasValue())
        return QSSGEmpty();

    QSSGLayerRenderPreparationResult &thePrepResult(*theData->layerPrepResult);
    if (thePrepResult.camera() == nullptr) {
        return QSSGEmpty();
    }
    // Perform gluPickMatrix and pre-multiply it into the view projection
    QSSGRenderCamera &theCamera(*thePrepResult.camera());

    QRectF layerToPresentation = thePrepResult.viewport();
    // Offsetting is already taken care of in the camera's projection.
    // All we need to do is to scale and translate the image.
    layerToPresentation.setX(0);
    layerToPresentation.setY(0);
    QVector2D theMouse(*theLocalMouse);
    // The viewport will need to center at this location
    QVector2D viewportDims(float(inPickDims.width()), float(inPickDims.height()));
    QVector2D bottomLeft = QVector2D(theMouse.x() - viewportDims.x() / 2.0f, theMouse.y() - viewportDims.y() / 2.0f);
    // For some reason, and I haven't figured out why yet, the offsets need to be backwards for
    // this to work.
    // bottomLeft.x = layerToPresentation.m_Width - bottomLeft.x;
    // bottomLeft.y = layerToPresentation.m_Height - bottomLeft.y;
    // Virtual rect is relative to the layer.
    QRectF thePickRect(qreal(bottomLeft.x()), qreal(bottomLeft.y()), qreal(viewportDims.x()), qreal(viewportDims.y()));
    QMatrix4x4 projectionPremult;
    projectionPremult = QSSGRenderContext::applyVirtualViewportToProjectionMatrix(projectionPremult, layerToPresentation, thePickRect);
    projectionPremult = projectionPremult.inverted();

    QMatrix4x4 globalInverse = theCamera.globalTransform.inverted();
    QMatrix4x4 theVP = theCamera.projection * globalInverse;
    // For now we won't setup the scissor, so we may be off by inPickDims at most because
    // GetLayerMouseCoords will return
    // false if the mouse is too far off the layer.
    return QSSGLayerPickSetup(projectionPremult,
                                theVP,
                                QRect(0, 0, int(layerToPresentation.width()), int(layerToPresentation.height())));
}

QSSGOption<QRectF> QSSGRendererImpl::layerRect(QSSGRenderLayer &inLayer)
{
    QSSGRef<QSSGLayerRenderData> theData = getOrCreateLayerRenderDataForNode(inLayer);
    if (Q_UNLIKELY(theData == nullptr || theData->camera == nullptr)) {
        Q_ASSERT(false);
        return QSSGEmpty();
    }
    QSSGLayerRenderPreparationResult &thePrepResult(*theData->layerPrepResult);
    return thePrepResult.viewport();
}

// This doesn't have to be cheap.
void QSSGRendererImpl::runLayerRender(QSSGRenderLayer &inLayer, const QMatrix4x4 &inViewProjection)
{
    QSSGRef<QSSGLayerRenderData> theData = getOrCreateLayerRenderDataForNode(inLayer);
    if (Q_UNLIKELY(theData == nullptr || theData->camera == nullptr)) {
        Q_ASSERT(false);
        return;
    }
    theData->prepareAndRender(inViewProjection);
}

void QSSGRendererImpl::renderLayerRect(QSSGRenderLayer &inLayer, const QVector3D &inColor)
{
    QSSGRef<QSSGLayerRenderData> theData = getOrCreateLayerRenderDataForNode(inLayer);
    if (theData)
        theData->m_boundingRectColor = inColor;
}

void QSSGRendererImpl::releaseLayerRenderResources(QSSGRenderLayer &inLayer)
{
    auto theIter = m_instanceRenderMap.find(&inLayer);
    if (theIter != m_instanceRenderMap.end()) {
        auto theLastFrm = std::find(m_lastFrameLayers.begin(), m_lastFrameLayers.end(), theIter.value());
        if (theLastFrm != m_lastFrameLayers.end()) {
            theIter.value()->resetForFrame();
            m_lastFrameLayers.erase(theLastFrm);
        }
        m_instanceRenderMap.erase(theIter);
    }
}

void QSSGRendererImpl::renderQuad(const QVector2D inDimensions, const QMatrix4x4 &inMVP, QSSGRenderTexture2D &inQuadTexture)
{
    m_context->setCullingEnabled(false);
    QSSGRef<QSSGLayerSceneShader> theShader = getSceneLayerShader();
    m_context->setActiveShader(theShader->shader);
    theShader->mvp.set(inMVP);
    theShader->dimensions.set(inDimensions);
    theShader->sampler.set(&inQuadTexture);

    generateXYQuad();
    m_context->setInputAssembler(m_quadInputAssembler);
    m_context->draw(QSSGRenderDrawMode::Triangles, m_quadIndexBuffer->numIndices(), 0);
}

void QSSGRendererImpl::renderQuad()
{
    m_context->setCullingEnabled(false);
    generateXYQuad();
    m_context->setInputAssembler(m_quadInputAssembler);
    m_context->draw(QSSGRenderDrawMode::Triangles, m_quadIndexBuffer->numIndices(), 0);
}

void QSSGRendererImpl::layerNeedsFrameClear(QSSGLayerRenderData &inLayer)
{
    m_lastFrameLayers.push_back(&inLayer);
}

void QSSGRendererImpl::beginLayerDepthPassRender(QSSGLayerRenderData &inLayer)
{
    m_currentLayer = &inLayer;
}

void QSSGRendererImpl::endLayerDepthPassRender()
{
    m_currentLayer = nullptr;
}

void QSSGRendererImpl::beginLayerRender(QSSGLayerRenderData &inLayer)
{
    m_currentLayer = &inLayer;
}
void QSSGRendererImpl::endLayerRender()
{
    m_currentLayer = nullptr;
}

void QSSGRendererImpl::prepareImageForIbl(QSSGRenderImage &inImage)
{
    if (inImage.m_textureData.m_texture && inImage.m_textureData.m_texture->numMipmaps() < 1)
        inImage.m_textureData.m_texture->generateMipmaps();
}

bool nodeContainsBoneRoot(QSSGRenderNode &childNode, qint32 rootID)
{
    for (QSSGRenderNode *childChild = childNode.firstChild; childChild != nullptr; childChild = childChild->nextSibling) {
        if (childChild->skeletonId == rootID)
            return true;
    }

    return false;
}

void fillBoneIdNodeMap(QSSGRenderNode &childNode, QHash<long, QSSGRenderNode *> &ioMap)
{
    if (childNode.skeletonId >= 0)
        ioMap[childNode.skeletonId] = &childNode;
    for (QSSGRenderNode *childChild = childNode.firstChild; childChild != nullptr; childChild = childChild->nextSibling)
        fillBoneIdNodeMap(*childChild, ioMap);
}

QSSGOption<QVector2D> QSSGRendererImpl::getLayerMouseCoords(QSSGLayerRenderData &inLayerRenderData,
                                                                const QVector2D &inMouseCoords,
                                                                const QVector2D &inViewportDimensions,
                                                                bool forceImageIntersect) const
{
    if (inLayerRenderData.layerPrepResult.hasValue()) {
        const auto viewport = inLayerRenderData.layerPrepResult->viewport();
        return QSSGLayerRenderHelper::layerMouseCoords(viewport, inMouseCoords, inViewportDimensions, forceImageIntersect);
    }
    return QSSGEmpty();
}

bool QSSGRendererImpl::rendererRequestsFrames() const
{
    return m_progressiveAARenderRequest;
}

void QSSGRendererImpl::getLayerHitObjectList(QSSGLayerRenderData &inLayerRenderData,
                                               const QVector2D &inViewportDimensions,
                                               const QVector2D &inPresCoords,
                                               bool inPickEverything,
                                               TPickResultArray &outIntersectionResult)
{
    // This function assumes the layer was rendered to the scene itself. There is another
    // function for completely offscreen layers that don't get rendered to the scene.
    bool wasRenderToTarget(inLayerRenderData.layer.flags.testFlag(QSSGRenderLayer::Flag::LayerRenderToTarget));
    if (wasRenderToTarget && inLayerRenderData.camera != nullptr) {
        QSSGOption<QSSGRenderRay> theHitRay;
        if (inLayerRenderData.layerPrepResult.hasValue()) {
            const auto camera = inLayerRenderData.layerPrepResult->camera();
            const auto viewport = inLayerRenderData.layerPrepResult->viewport();
            theHitRay = QSSGLayerRenderHelper::pickRay(*camera, viewport, inPresCoords, inViewportDimensions, false);
        }

        if (theHitRay.hasValue()) {
            // Scale the mouse coords to change them into the camera's numerical space.
            QSSGRenderRay thePickRay = *theHitRay;
            for (int idx = inLayerRenderData.opaqueObjects.size(), end = 0; idx > end; --idx) {
                QSSGRenderableObject *theRenderableObject = inLayerRenderData.opaqueObjects.at(idx - 1).obj;
                if (inPickEverything || theRenderableObject->renderableFlags.isPickable())
                    intersectRayWithSubsetRenderable(thePickRay, *theRenderableObject, outIntersectionResult);
            }
            for (int idx = inLayerRenderData.transparentObjects.size(), end = 0; idx > end; --idx) {
                QSSGRenderableObject *theRenderableObject = inLayerRenderData.transparentObjects.at(idx - 1).obj;
                if (inPickEverything || theRenderableObject->renderableFlags.isPickable())
                    intersectRayWithSubsetRenderable(thePickRay, *theRenderableObject, outIntersectionResult);
            }
        }
    }
}

using RenderableList = QVarLengthArray<const QSSGRenderNode *>;
static void dfs(const QSSGRenderNode &node, RenderableList &renderables)
{
    if (node.isRenderableType())
        renderables.push_back(&node);

    for (QSSGRenderNode *child = node.firstChild; child != nullptr; child = child->nextSibling)
        dfs(*child, renderables);
}

void QSSGRendererImpl::getLayerHitObjectList(QSSGRenderLayer &layer,
                                             const QVector2D &inViewportDimensions,
                                             const QVector2D &inPresCoords,
                                             bool inPickEverything,
                                             PickResultList &outIntersectionResult)
{

    // This function assumes the layer was rendered to the scene itself. There is another
    // function for completely offscreen layers that don't get rendered to the scene.
    const bool wasRenderToTarget(layer.flags.testFlag(QSSGRenderLayer::Flag::LayerRenderToTarget));
    if (wasRenderToTarget && layer.renderedCamera != nullptr) {
        const auto camera = layer.renderedCamera;
        // TODO: Need to make sure we get the right Viewport rect here.
        const auto viewport = QRectF(QPointF(), QSizeF(qreal(inViewportDimensions.x()), qreal(inViewportDimensions.y())));
        const QSSGOption<QSSGRenderRay> hitRay = QSSGLayerRenderHelper::pickRay(*camera, viewport, inPresCoords, inViewportDimensions, false);
        if (hitRay.hasValue()) {
            // Scale the mouse coords to change them into the camera's numerical space.
            RenderableList renderables;
            for (QSSGRenderNode *childNode = layer.firstChild; childNode; childNode = childNode->nextSibling)
                dfs(*childNode, renderables);

            const auto &bufferManager = contextInterface()->bufferManager();
            for (int idx = renderables.size(), end = 0; idx > end; --idx) {
                const auto &pickableObject = renderables.at(idx - 1);
                if (inPickEverything || pickableObject->flags.testFlag(QSSGRenderNode::Flag::LocallyPickable))
                    intersectRayWithSubsetRenderable(bufferManager, *hitRay, *pickableObject, outIntersectionResult);
            }
        }
    }
}

void QSSGRendererImpl::intersectRayWithSubsetRenderable(const QSSGRef<QSSGBufferManager> &bufferManager,
                                                        const QSSGRenderRay &inRay,
                                                        const QSSGRenderNode &node,
                                                        QSSGRendererImpl::PickResultList &outIntersectionResultList)
{
    if (node.type != QSSGRenderGraphObject::Type::Model)
        return;

    const QSSGRenderModel *model = static_cast<const QSSGRenderModel *>(&node);

    // TODO: Technically we should have some guard here, as the meshes are usually loaded on a different thread,
    // so this isn't really nice (assumes all meshes are loaded before picking and none are removed, which currently should be the case).
    auto mesh = bufferManager->getMesh(model->meshPath);
    if (!mesh)
        return;

    const auto &globalTransform = model->globalTransform;
    const auto &subMeshes = mesh->subsets;
    QSSGBounds3 modelBounds = QSSGBounds3::empty();
    for (const auto &subMesh : subMeshes)
        modelBounds.include(subMesh.bounds);

    if (modelBounds.isEmpty())
        return;

    QSSGRenderRay::IntersectionResult intersectionResult = inRay.intersectWithAABB(globalTransform, modelBounds);

    // If we don't intersect with the model at all, then there's no need to go furher down!
    if (!intersectionResult.intersects)
        return;

    for (const auto &subMesh : subMeshes) {
        intersectionResult = inRay.intersectWithAABB(globalTransform, subMesh.bounds);
        if (intersectionResult.intersects)
            break;
    }

    if (!intersectionResult.intersects)
        return;

    outIntersectionResultList.push_back(
                                QSSGRenderPickResult(*model,
                                                     intersectionResult.rayLengthSquared,
                                                     intersectionResult.relXY,
                                                     intersectionResult.scenePosition));
}

void QSSGRendererImpl::intersectRayWithSubsetRenderable(const QSSGRenderRay &inRay,
                                                        QSSGRenderableObject &inRenderableObject,
                                                        TPickResultArray &outIntersectionResultList)
{
    QSSGRenderRay::IntersectionResult intersectionResult = inRay.intersectWithAABB(inRenderableObject.globalTransform, inRenderableObject.bounds);
    if (!intersectionResult.intersects)
        return;

    // Leave the coordinates relative for right now.
    const QSSGRenderGraphObject *thePickObject = nullptr;
    if (inRenderableObject.renderableFlags.isDefaultMaterialMeshSubset())
        thePickObject = &static_cast<QSSGSubsetRenderable *>(&inRenderableObject)->modelContext.model;
    else if (inRenderableObject.renderableFlags.isCustomMaterialMeshSubset())
        thePickObject = &static_cast<QSSGCustomMaterialRenderable *>(&inRenderableObject)->modelContext.model;

    if (thePickObject != nullptr) {
        outIntersectionResultList.push_back(
                                    QSSGRenderPickResult(*thePickObject,
                                                         intersectionResult.rayLengthSquared,
                                                         intersectionResult.relXY,
                                                         intersectionResult.scenePosition));
    }
}

QSSGRef<QSSGRenderShaderProgram> QSSGRendererImpl::compileShader(const QByteArray &inName, const char *inVert, const char *inFrag)
{
    getProgramGenerator()->beginProgram();
    getProgramGenerator()->getStage(QSSGShaderGeneratorStage::Vertex)->append(inVert);
    getProgramGenerator()->getStage(QSSGShaderGeneratorStage::Fragment)->append(inFrag);
    return getProgramGenerator()->compileGeneratedShader(inName);
}

QSSGRef<QSSGShaderGeneratorGeneratedShader> QSSGRendererImpl::getShader(QSSGSubsetRenderable &inRenderable,
                                                                              const ShaderFeatureSetList &inFeatureSet)
{
    if (Q_UNLIKELY(m_currentLayer == nullptr)) {
        Q_ASSERT(false);
        return nullptr;
    }
    auto shaderIt = m_shaders.constFind(inRenderable.shaderDescription);
    if (shaderIt == m_shaders.cend()) {
        // Generate the shader.
        const QSSGRef<QSSGRenderShaderProgram> &theShader(generateShader(inRenderable, inFeatureSet));
        if (theShader) {
            QSSGRef<QSSGShaderGeneratorGeneratedShader> theGeneratedShader = QSSGRef<QSSGShaderGeneratorGeneratedShader>(
                    new QSSGShaderGeneratorGeneratedShader(m_generatedShaderString, theShader));
            shaderIt = m_shaders.insert(inRenderable.shaderDescription, theGeneratedShader);
        } else {
            // We still insert something because we don't to attempt to generate the same bad shader
            // twice.
            shaderIt = m_shaders.insert(inRenderable.shaderDescription, nullptr);
        }
    }

    if (!shaderIt->isNull()) {
        if (m_currentLayer && m_currentLayer->camera) {
            QSSGRenderCamera &theCamera(*m_currentLayer->camera);
            if (!m_currentLayer->cameraDirection.hasValue())
                m_currentLayer->cameraDirection = theCamera.getScalingCorrectDirection();
        }
    }
    return *shaderIt;
}
static QVector3D g_fullScreenRectFace[] = {
    QVector3D(-1, -1, 0),
    QVector3D(-1, 1, 0),
    QVector3D(1, 1, 0),
    QVector3D(1, -1, 0),
};

static QVector2D g_fullScreenRectUVs[] = { QVector2D(0, 0), QVector2D(0, 1), QVector2D(1, 1), QVector2D(1, 0) };

void QSSGRendererImpl::generateXYQuad()
{
    if (m_quadInputAssembler)
        return;

    QSSGRenderVertexBufferEntry theEntries[] = {
        QSSGRenderVertexBufferEntry("attr_pos", QSSGRenderComponentType::Float32, 3),
        QSSGRenderVertexBufferEntry("attr_uv", QSSGRenderComponentType::Float32, 2, 12),
    };

    float tempBuf[20];
    float *bufPtr = tempBuf;
    QVector3D *facePtr(g_fullScreenRectFace);
    QVector2D *uvPtr(g_fullScreenRectUVs);
    for (int j = 0; j < 4; j++, ++facePtr, ++uvPtr, bufPtr += 5) {
        bufPtr[0] = facePtr->x();
        bufPtr[1] = facePtr->y();
        bufPtr[2] = facePtr->z();
        bufPtr[3] = uvPtr->x();
        bufPtr[4] = uvPtr->y();
    }
    m_quadVertexBuffer = new QSSGRenderVertexBuffer(m_context, QSSGRenderBufferUsageType::Static,
                                                       3 * sizeof(float) + 2 * sizeof(float),
                                                       toByteView(tempBuf, 20));

    quint8 indexData[] = {
        0, 1, 2, 0, 2, 3,
    };
    m_quadIndexBuffer = new QSSGRenderIndexBuffer(m_context, QSSGRenderBufferUsageType::Static,
                                                     QSSGRenderComponentType::UnsignedInteger8,
                                                     toByteView(indexData, sizeof(indexData)));

    // create our attribute layout
    m_quadAttribLayout = m_context->createAttributeLayout(toDataView(theEntries, 2));

    // create input assembler object
    quint32 strides = m_quadVertexBuffer->stride();
    quint32 offsets = 0;
    m_quadInputAssembler = m_context->createInputAssembler(m_quadAttribLayout,
                                                           toDataView(&m_quadVertexBuffer, 1),
                                                           m_quadIndexBuffer,
                                                           toDataView(&strides, 1),
                                                           toDataView(&offsets, 1));
}

void QSSGRendererImpl::generateXYZPoint()
{
    if (m_pointInputAssembler)
        return;

    QSSGRenderVertexBufferEntry theEntries[] = {
        QSSGRenderVertexBufferEntry("attr_pos", QSSGRenderComponentType::Float32, 3),
        QSSGRenderVertexBufferEntry("attr_uv", QSSGRenderComponentType::Float32, 2, 12),
    };

    float tempBuf[5] { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
    m_pointVertexBuffer = new QSSGRenderVertexBuffer(m_context, QSSGRenderBufferUsageType::Static,
                                                        3 * sizeof(float) + 2 * sizeof(float),
                                                        toByteView(tempBuf, 5));

    // create our attribute layout
    m_pointAttribLayout = m_context->createAttributeLayout(toDataView(theEntries, 2));

    // create input assembler object
    quint32 strides = m_pointVertexBuffer->stride();
    quint32 offsets = 0;
    m_pointInputAssembler = m_context->createInputAssembler(m_pointAttribLayout,
                                                            toDataView(&m_pointVertexBuffer, 1),
                                                            nullptr,
                                                            toDataView(&strides, 1),
                                                            toDataView(&offsets, 1));
}

QPair<QSSGRef<QSSGRenderVertexBuffer>, QSSGRef<QSSGRenderIndexBuffer>> QSSGRendererImpl::getXYQuad()
{
    if (!m_quadInputAssembler)
        generateXYQuad();

    return QPair<QSSGRef<QSSGRenderVertexBuffer>, QSSGRef<QSSGRenderIndexBuffer>>(m_quadVertexBuffer, m_quadIndexBuffer);
}

QSSGLayerGlobalRenderProperties QSSGRendererImpl::getLayerGlobalRenderProperties()
{
    QSSGLayerRenderData &theData = *m_currentLayer;
    const QSSGRenderLayer &theLayer = theData.layer;
    if (!theData.cameraDirection.hasValue())
        theData.cameraDirection = theData.camera->getScalingCorrectDirection();

    return QSSGLayerGlobalRenderProperties{ theLayer,
                                              *theData.camera,
                                              *theData.cameraDirection,
                                              theData.globalLights,
                                              theData.lightDirections,
                                              theData.shadowMapManager,
                                              theData.m_layerDepthTexture,
                                              theData.m_layerSsaoTexture,
                                              theLayer.lightProbe,
                                              theLayer.lightProbe2,
                                              theLayer.probeHorizon,
                                              theLayer.probeBright,
                                              theLayer.probe2Window,
                                              theLayer.probe2Pos,
                                              theLayer.probe2Fade,
                                              theLayer.probeFov };
}

void QSSGRendererImpl::generateXYQuadStrip()
{
    if (m_quadStripInputAssembler)
        return;

    QSSGRenderVertexBufferEntry theEntries[] = {
        QSSGRenderVertexBufferEntry("attr_pos", QSSGRenderComponentType::Float32, 3),
        QSSGRenderVertexBufferEntry("attr_uv", QSSGRenderComponentType::Float32, 2, 12),
    };

    // this buffer is filled dynmically
    m_quadStripVertexBuffer = new QSSGRenderVertexBuffer(m_context, QSSGRenderBufferUsageType::Dynamic,
                                                            3 * sizeof(float) + 2 * sizeof(float), // stride
                                                            QSSGByteView());

    // create our attribute layout
    m_quadStripAttribLayout = m_context->createAttributeLayout(toDataView(theEntries, 2));

    // create input assembler object
    quint32 strides = m_quadStripVertexBuffer->stride();
    quint32 offsets = 0;
    m_quadStripInputAssembler = m_context->createInputAssembler(m_quadStripAttribLayout,
                                                                toDataView(&m_quadStripVertexBuffer, 1),
                                                                nullptr,
                                                                toDataView(&strides, 1),
                                                                toDataView(&offsets, 1));
}

void QSSGRendererImpl::updateCbAoShadow(const QSSGRenderLayer *pLayer, const QSSGRenderCamera *pCamera, QSSGResourceTexture2D &inDepthTexture)
{
    if (m_context->supportsConstantBuffer()) {
        const char *theName = "aoShadow";
        QSSGRef<QSSGRenderConstantBuffer> pCB = m_context->getConstantBuffer(theName);

        if (!pCB) {
            // the  size is determined automatically later on
            pCB = new QSSGRenderConstantBuffer(m_context, theName,
                                                  QSSGRenderBufferUsageType::Static,
                                                  QSSGByteView());
            if (!pCB) {
                Q_ASSERT(false);
                return;
            }
            m_constantBuffers.insert(theName, pCB);

            // Add paramters. Note should match the appearance in the shader program
            pCB->addParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::AoProperties>::handle(), QSSGRenderShaderDataType::Vec4, 1);
            pCB->addParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::AoProperties2>::handle(), QSSGRenderShaderDataType::Vec4, 1);
            pCB->addParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::ShadowProperties>::handle(), QSSGRenderShaderDataType::Vec4, 1);
            pCB->addParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::AoScreenConst>::handle(), QSSGRenderShaderDataType::Vec4, 1);
            pCB->addParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::UvToEyeConst>::handle(), QSSGRenderShaderDataType::Vec4, 1);
        }

        // update values
        QVector4D aoProps(pLayer->aoStrength * 0.01f, pLayer->aoDistance * 0.4f, pLayer->aoSoftness * 0.02f, pLayer->aoBias);
        pCB->updateParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::AoProperties>::handle(), toByteView(aoProps));
        QVector4D aoProps2(float(pLayer->aoSamplerate), (pLayer->aoDither) ? 1.0f : 0.0f, 0.0f, 0.0f);
        pCB->updateParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::AoProperties2>::handle(), toByteView(aoProps2));
        QVector4D shadowProps(pLayer->shadowStrength * 0.01f, pLayer->shadowDist, pLayer->shadowSoftness * 0.01f, pLayer->shadowBias);
        pCB->updateParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::ShadowProperties>::handle(), toByteView(shadowProps));

        float R2 = pLayer->aoDistance * pLayer->aoDistance * 0.16f;
        float rw = 100, rh = 100;

        if (inDepthTexture.getTexture()) {
            rw = float(inDepthTexture.getTexture()->textureDetails().width);
            rh = float(inDepthTexture.getTexture()->textureDetails().height);
        }
        float fov = (pCamera) ? pCamera->verticalFov(rw / rh) : 1.0f;
        float tanHalfFovY = tanf(0.5f * fov * (rh / rw));
        float invFocalLenX = tanHalfFovY * (rw / rh);

        QVector4D aoScreenConst(1.0f / R2, rh / (2.0f * tanHalfFovY), 1.0f / rw, 1.0f / rh);
        pCB->updateParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::AoScreenConst>::handle(), toByteView(aoScreenConst));
        QVector4D uvToEyeConst(2.0f * invFocalLenX, -2.0f * tanHalfFovY, -invFocalLenX, tanHalfFovY);
        pCB->updateParam(QSSGRenderConstantBuffer::ParamData<QSSGRenderConstantBuffer::Param::UvToEyeConst>::handle(), toByteView(uvToEyeConst));

        // update buffer to hardware
        pCB->update();
    }
}

// widget context implementation

QSSGRef<QSSGRenderVertexBuffer> QSSGRendererImpl::getOrCreateVertexBuffer(const QByteArray &inStr,
                                                                                quint32 stride,
                                                                                QSSGByteView bufferData)
{
    const QSSGRef<QSSGRenderVertexBuffer> &retval = getVertexBuffer(inStr);
    if (retval) {
        // we update the buffer
        retval->updateBuffer(bufferData);
        return retval;
    }

    return *m_widgetVertexBuffers.insert(inStr, new QSSGRenderVertexBuffer(m_context, QSSGRenderBufferUsageType::Dynamic, stride, bufferData));
}
QSSGRef<QSSGRenderIndexBuffer> QSSGRendererImpl::getOrCreateIndexBuffer(const QByteArray &inStr,
                                                                              QSSGRenderComponentType componentType,
                                                                              QSSGByteView bufferData)
{
    const QSSGRef<QSSGRenderIndexBuffer> &retval = getIndexBuffer(inStr);
    if (retval) {
        // we update the buffer
        retval->updateBuffer(bufferData);
        return retval;
    }

    return *m_widgetIndexBuffers.insert(inStr, new QSSGRenderIndexBuffer(m_context, QSSGRenderBufferUsageType::Dynamic, componentType, bufferData));
}

QSSGRef<QSSGRenderAttribLayout> QSSGRendererImpl::createAttributeLayout(QSSGDataView<QSSGRenderVertexBufferEntry> attribs)
{
    // create our attribute layout
    return m_context->createAttributeLayout(attribs);
}

QSSGRef<QSSGRenderInputAssembler> QSSGRendererImpl::getOrCreateInputAssembler(const QByteArray &inStr,
                                                                                    const QSSGRef<QSSGRenderAttribLayout> &attribLayout,
                                                                                    QSSGDataView<QSSGRef<QSSGRenderVertexBuffer>> buffers,
                                                                                    const QSSGRef<QSSGRenderIndexBuffer> indexBuffer,
                                                                                    QSSGDataView<quint32> strides,
                                                                                    QSSGDataView<quint32> offsets)
{
    const QSSGRef<QSSGRenderInputAssembler> &retval = getInputAssembler(inStr);
    if (retval)
        return retval;

    return *m_widgetInputAssembler.insert(inStr, m_context->createInputAssembler(attribLayout, buffers, indexBuffer, strides, offsets));
}

QSSGRef<QSSGRenderVertexBuffer> QSSGRendererImpl::getVertexBuffer(const QByteArray &inStr) const
{
    const auto theIter = m_widgetVertexBuffers.constFind(inStr);
    if (theIter != m_widgetVertexBuffers.cend())
        return theIter.value();
    return nullptr;
}

QSSGRef<QSSGRenderIndexBuffer> QSSGRendererImpl::getIndexBuffer(const QByteArray &inStr) const
{
    const auto theIter = m_widgetIndexBuffers.constFind(inStr);
    if (theIter != m_widgetIndexBuffers.cend())
        return theIter.value();
    return nullptr;
}

QSSGRef<QSSGRenderInputAssembler> QSSGRendererImpl::getInputAssembler(const QByteArray &inStr) const
{
    const auto theIter = m_widgetInputAssembler.constFind(inStr);
    if (theIter != m_widgetInputAssembler.cend())
        return theIter.value();
    return nullptr;
}

QSSGRef<QSSGRenderShaderProgram> QSSGRendererImpl::getShader(const QByteArray &inStr) const
{
    const auto theIter = m_widgetShaders.constFind(inStr);
    if (theIter != m_widgetShaders.cend())
        return theIter.value();
    return nullptr;
}

QSSGRef<QSSGRenderShaderProgram> QSSGRendererImpl::compileAndStoreShader(const QByteArray &inStr)
{
    const QSSGRef<QSSGRenderShaderProgram> &newProgram = getProgramGenerator()->compileGeneratedShader(inStr);
    if (newProgram)
        m_widgetShaders.insert(inStr, newProgram);
    return newProgram;
}

const QSSGRef<QSSGShaderProgramGeneratorInterface> &QSSGRendererImpl::getProgramGenerator()
{
    return m_contextInterface->shaderProgramGenerator();
}

void QSSGRendererImpl::dumpGpuProfilerStats()
{
    if (!isLayerGpuProfilingEnabled())
        return;

    auto it = m_instanceRenderMap.cbegin();
    const auto end = m_instanceRenderMap.cend();
    for (; it != end; it++) {
        const QSSGRef<QSSGLayerRenderData> &theLayerRenderData = it.value();
        const QSSGRenderLayer *theLayer = &theLayerRenderData->layer;

        if (theLayer->flags.testFlag(QSSGRenderLayer::Flag::Active) && theLayerRenderData->m_layerProfilerGpu) {
            const QVector<QString> &idList = theLayerRenderData->m_layerProfilerGpu->timerIDs();
            if (!idList.empty()) {
#if QSSG_DEBUG_ID
                qDebug() << theLayer->id;
#endif
                auto theIdIter = idList.begin();
                for (; theIdIter != idList.end(); theIdIter++) {
                    char messageLine[1024];
                    sprintf(messageLine,
                            "%s: %.3f ms",
                            theIdIter->toLatin1().constData(),
                            theLayerRenderData->m_layerProfilerGpu->elapsed(*theIdIter));
                    qDebug() << "    " << messageLine;
                }
            }
        }
    }
}

QSSGOption<QVector2D> QSSGRendererImpl::getLayerMouseCoords(QSSGRenderLayer &inLayer,
                                                                const QVector2D &inMouseCoords,
                                                                const QVector2D &inViewportDimensions,
                                                                bool forceImageIntersect) const
{
    QSSGRef<QSSGLayerRenderData> theData = const_cast<QSSGRendererImpl &>(*this).getOrCreateLayerRenderDataForNode(inLayer);
    return getLayerMouseCoords(*theData, inMouseCoords, inViewportDimensions, forceImageIntersect);
}

bool QSSGRendererInterface::isGlEsContext(const QSSGRenderContextType &inContextType)
{
    QSSGRenderContextTypes esContextTypes(QSSGRenderContextType::GLES2 | QSSGRenderContextType::GLES3
                                           | QSSGRenderContextType::GLES3PLUS);

    return (esContextTypes & inContextType);
}

bool QSSGRendererInterface::isGlEs3Context(const QSSGRenderContextType &inContextType)
{
    return (inContextType == QSSGRenderContextType::GLES3 || inContextType == QSSGRenderContextType::GLES3PLUS);
}

bool QSSGRendererInterface::isGl2Context(const QSSGRenderContextType &inContextType)
{
    return (inContextType == QSSGRenderContextType::GL2);
}

QSSGRef<QSSGRendererInterface> QSSGRendererInterface::createRenderer(QSSGRenderContextInterface *inContext)
{
    return QSSGRef<QSSGRendererImpl>(new QSSGRendererImpl(inContext));
}

QSSGRenderPickResult::QSSGRenderPickResult(const QSSGRenderGraphObject &inHitObject,
                                           float inCameraDistance,
                                           const QVector2D &inLocalUVCoords,
                                           const QVector3D &scenePosition)
    : m_hitObject(&inHitObject)
    , m_cameraDistanceSq(inCameraDistance)
    , m_localUVCoords(inLocalUVCoords)
    , m_scenePosition(scenePosition)
{
}

QT_END_NAMESPACE
