// Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "renderviewjobutils_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { using namespace Qt3DCore; /*! \internal Searches the best matching Technique from \a effect specified. */ Technique *findTechniqueForEffect(NodeManagers *manager, const TechniqueFilter *techniqueFilter, Effect *effect) { if (!effect) return nullptr; std::vector matchingTechniques; const bool hasInvalidTechniqueFilter = (techniqueFilter == nullptr || techniqueFilter->filters().isEmpty()); // Iterate through the techniques in the effect const auto techniqueIds = effect->techniques(); for (const QNodeId &techniqueId : techniqueIds) { Technique *technique = manager->techniqueManager()->lookupResource(techniqueId); // Should be valid, if not there likely a problem with node addition/destruction changes Q_ASSERT(technique); // Check if the technique is compatible with the rendering API // If no techniqueFilter is present, we return the technique as it satisfies OpenGL version if (technique->isCompatibleWithRenderer() && (hasInvalidTechniqueFilter || technique->isCompatibleWithFilters(techniqueFilter->filters()))) matchingTechniques.push_back(technique); } if (matchingTechniques.size() == 0) // We failed to find a suitable technique to use :( return nullptr; if (matchingTechniques.size() == 1) return matchingTechniques.front(); // Several compatible techniques, return technique with highest major and minor version Technique* highest = matchingTechniques.front(); GraphicsApiFilterData filter = *highest->graphicsApiFilter(); for (auto it = matchingTechniques.cbegin() + 1; it < matchingTechniques.cend(); ++it) { if (filter < *(*it)->graphicsApiFilter()) { filter = *(*it)->graphicsApiFilter(); highest = *it; } } return highest; } RenderPassList findRenderPassesForTechnique(NodeManagers *manager, const RenderPassFilter *passFilter, Technique *technique) { Q_ASSERT(manager); Q_ASSERT(technique); RenderPassList passes; const auto passIds = technique->renderPasses(); for (const QNodeId &passId : passIds) { RenderPass *renderPass = manager->renderPassManager()->lookupResource(passId); if (renderPass && renderPass->isEnabled()) { bool foundMatch = (!passFilter || passFilter->filters().size() == 0); // A pass filter is present so we need to check for matching criteria if (!foundMatch && renderPass->filterKeys().size() >= passFilter->filters().size()) { // Iterate through the filter criteria and look for render passes with criteria that satisfy them const auto filterKeyIds = passFilter->filters(); for (const QNodeId &filterKeyId : filterKeyIds) { foundMatch = false; FilterKey *filterFilterKey = manager->filterKeyManager()->lookupResource(filterKeyId); const auto passFilterKeyIds = renderPass->filterKeys(); for (const QNodeId &passFilterKeyId : passFilterKeyIds) { FilterKey *passFilterKey = manager->filterKeyManager()->lookupResource(passFilterKeyId); if ((foundMatch = (*passFilterKey == *filterFilterKey))) break; } if (!foundMatch) { // No match for criterion in any of the render pass' criteria break; } } } if (foundMatch) { // Found a renderpass that satisfies our needs. Add it in order passes << renderPass; } } } return passes; } ParameterInfoList::const_iterator findParamInfo(ParameterInfoList *params, const int nameId) { const ParameterInfoList::const_iterator end = params->cend(); ParameterInfoList::const_iterator it = std::lower_bound(params->cbegin(), end, nameId); if (it != end && it->nameId != nameId) return end; return it; } void addParametersForIds(ParameterInfoList *params, ParameterManager *manager, const Qt3DCore::QNodeIdVector ¶meterIds) { for (const QNodeId ¶mId : parameterIds) { const HParameter parameterHandle = manager->lookupHandle(paramId); const Parameter *param = manager->data(parameterHandle); ParameterInfoList::iterator it = std::lower_bound(params->begin(), params->end(), param->nameId()); if (it == params->end() || it->nameId != param->nameId()) params->insert(it, ParameterInfo(param->nameId(), parameterHandle)); } } void parametersFromMaterialEffectTechnique(ParameterInfoList *infoList, ParameterManager *manager, Material *material, Effect *effect, Technique *technique) { // The parameters are taken in the following priority order: // // 1) Material // 2) Effect // 3) Technique // // That way a user can override defaults in Effect's and Techniques on a // object manner and a Technique can override global defaults from the Effect. parametersFromParametersProvider(infoList, manager, material); parametersFromParametersProvider(infoList, manager, effect); parametersFromParametersProvider(infoList, manager, technique); } // Only add states with types we don't already have void addStatesToRenderStateSet(RenderStateSet *stateSet, const QList stateIds, RenderStateManager *manager) { for (const Qt3DCore::QNodeId &stateId : stateIds) { RenderStateNode *node = manager->lookupResource(stateId); if (node && node->isEnabled() && stateSet->canAddStateOfType(node->type())) { stateSet->addState(node->impl()); } } } ParameterInfo::ParameterInfo(const int nameId, const HParameter &handle) : nameId(nameId) , handle(handle) {} bool ParameterInfo::operator<(const ParameterInfo &other) const noexcept { return nameId < other.nameId; } bool ParameterInfo::operator<(const int otherNameId) const noexcept { return nameId < otherNameId; } int findIdealNumberOfWorkers(int elementCount, int packetSize, int maxJobCount) { if (elementCount == 0 || packetSize == 0) return 0; return std::min(std::max(elementCount / packetSize, 1), maxJobCount); } std::vector entitiesInSubset(const std::vector &entities, const std::vector &subset) { std::vector intersection; intersection.reserve(qMin(entities.size(), subset.size())); std::set_intersection(entities.begin(), entities.end(), subset.begin(), subset.end(), std::back_inserter(intersection)); return intersection; } } // namespace Render } // namespace Qt3DRender QT_END_NAMESPACE