7#include <QtQuick3DRuntimeRender/private/qssgrenderloadedtexture_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgruntimerenderlogging_p.h>
10#include <QtQuick3DUtils/private/qssgmeshbvhbuilder_p.h>
11#include <QtQuick3DUtils/private/qssgbounds3_p.h>
13#include <QtQuick/QSGTexture>
16#include <QtGui/private/qimage_p.h>
17#include <QtQuick/private/qsgtexture_p.h>
18#include <QtQuick/private/qsgcompressedtexture_p.h>
20#include <QtQuick3DUtils/private/qssgrenderbasetypes_p.h>
21#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
22#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
23#include <QtQuick3DRuntimeRender/private/qssgrenderimage_p.h>
24#include <QtQuick3DRuntimeRender/private/qssgrendertexturedata_p.h>
25#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
26#include <QtQuick3DRuntimeRender/private/qssglightmapper_p.h>
27#include <QtQuick3DRuntimeRender/private/qssgrenderresourceloader_p.h>
28#include <qtquick3d_tracepoints_p.h>
86 const char *primitive;
94 {
"#Rectangle",
"/Rectangle.mesh"},
95 {
"#Sphere",
"/Sphere.mesh"},
96 {
"#Cube",
"/Cube.mesh"},
97 {
"#Cone",
"/Cone.mesh"},
98 {
"#Cylinder",
"/Cylinder.mesh"},
115 m_contextInterface =
nullptr;
120 m_contextInterface =
ctx;
130 LoadRenderImageFlags
flags)
137 if (
image->m_qsgTexture) {
141 if (!rhiTex || rhiTex->
rhi() == rhi) {
156 context->commandBuffer()->resourceUpdate(rub);
157 auto theImage = qsgImageMap.find(qsgTexture);
158 if (theImage == qsgImageMap.end())
159 theImage = qsgImageMap.insert(qsgTexture,
ImageData());
160 theImage.value().renderImageTexture.m_texture = qsgTexture->
rhiTexture();
162 theImage.value().usageCounts[currentLayer]++;
163 result = theImage.value().renderImageTexture;
170 qWarning(
"Cannot use QSGTexture from Texture.sourceItem as light probe.");
172 qWarning(
"Cannot use QSGTexture (presumably from Texture.sourceItem) created in another "
173 "window that was using a different graphics device/context. "
174 "Avoid using View3D.importScene between multiple windows.");
177 }
else if (
image->m_rawTextureData) {
180 result = loadTextureData(
image->m_rawTextureData, inMipMode);
182 }
else if (!
image->m_imagePath.isEmpty()) {
185 auto foundIt = imageMap.find(imageKey);
186 if (foundIt != imageMap.cend()) {
187 result = foundIt.value().renderImageTexture;
191 const auto &
path =
image->m_imagePath.path();
195 if (theLoadedTexture) {
196 foundIt = imageMap.insert(imageKey,
ImageData());
197 CreateRhiTextureFlags rhiTexFlags = ScanForTransparency;
198 if (
image->type == QSSGRenderGraphObject::Type::ImageCube)
199 rhiTexFlags |= CubeMap;
200 if (!createRhiTexture(foundIt.value().renderImageTexture, theLoadedTexture.
data(), inMipMode, rhiTexFlags,
QFileInfo(
path).
fileName())) {
203#ifdef QSSG_RENDERBUFFER_DEBUGGING
204 qDebug() <<
"+ uploadTexture: " <<
image->m_imagePath.path() << currentLayer;
207 result = foundIt.value().renderImageTexture;
213 foundIt = imageMap.insert(imageKey,
ImageData());
218 foundIt.value().usageCounts[currentLayer]++;
225 const CustomImageCacheKey imageKey = {
data, inMipMode };
226 auto theImageData = customTextureMap.find(imageKey);
227 if (theImageData == customTextureMap.end()) {
228 theImageData = customTextureMap.insert(imageKey, ImageData());
229 }
else if (
data->generationId() != theImageData->generationId) {
233 theImageData = customTextureMap.insert(imageKey, ImageData());
236 theImageData.value().usageCounts[currentLayer]++;
237 return theImageData.value().renderImageTexture;
242 if (!
data->textureData().isNull()) {
244 theLoadedTexture->ownsData =
false;
245 CreateRhiTextureFlags rhiTexFlags = {};
246 if (theLoadedTexture->depth > 0)
247 rhiTexFlags |= Texture3D;
248 if (createRhiTexture(theImageData.value().renderImageTexture, theLoadedTexture.
data(), inMipMode, rhiTexFlags,
data->debugObjectName)) {
249#ifdef QSSG_RENDERBUFFER_DEBUGGING
250 qDebug() <<
"+ uploadTexture: " <<
data << currentLayer;
252 theImageData.value().generationId =
data->generationId();
255 theImageData.value() = ImageData();
259 theImageData.value().usageCounts[currentLayer]++;
260 return theImageData.value().renderImageTexture;
270 auto foundIt = imageMap.find(imageKey);
271 if (foundIt != imageMap.end()) {
272 result = foundIt.value().renderImageTexture;
278 if (!theLoadedTexture)
280 foundIt = imageMap.insert(imageKey,
ImageData());
281 if (theLoadedTexture) {
282 if (!createRhiTexture(foundIt.value().renderImageTexture, theLoadedTexture.
data(),
MipModeDisable, {}, imagePath))
284 result = foundIt.value().renderImageTexture;
289 foundIt.value().usageCounts[currentLayer]++;
300 if (!
model.meshPath.isNull()) {
301 const auto foundIt = meshMap.constFind(
model.meshPath);
302 if (foundIt != meshMap.constEnd())
303 return foundIt->mesh;
306 if (
model.geometry) {
307 const auto foundIt = customMeshMap.constFind(
model.geometry);
308 if (foundIt != customMeshMap.constEnd())
309 return foundIt->mesh;
504 int suggestedSize = inImage->
height * 0.5f;
505 suggestedSize =
qMax(512, suggestedSize);
506 const QSize environmentMapSize(suggestedSize, suggestedSize);
510 if (!rhi->isTextureFormatSupported(sourceTextureFormat))
515 : sourceTextureFormat;
522 const int colorSpace = inImage->
isSRGB ? 1 : 0;
525 QRhiTexture *envCubeMap = rhi->newTexture(cubeTextureFormat, environmentMapSize, 1,
527 if (!envCubeMap->
create()) {
528 qWarning(
"Failed to create Environment Cube Map");
535 if (!envMapRenderBuffer->
create()) {
536 qWarning(
"Failed to create Environment Map Render Buffer");
551 auto renderTarget = rhi->newTextureRenderTarget(rtDesc);
553 renderTarget->setDescription(rtDesc);
556 renderTarget->setRenderPassDescriptor(renderPassDesc);
557 if (!renderTarget->create()) {
558 qWarning(
"Failed to build env map render target");
561 renderTarget->deleteLater();
562 renderTargets << renderTarget;
570 qWarning(
"failed to create source env map texture");
581 auto *rub = rhi->nextResourceUpdateBatch();
595 const auto &shaderCache = m_contextInterface->
shaderCache();
596 const auto &envMapShaderStages = shaderCache->loadBuiltinForRhi(
"environmentmap");
602 rub->uploadStaticBuffer(vertexBuffer,
cube);
605 int ubufElementSize = rhi->ubufAligned(128);
610 int ubufEnvMapElementSize = rhi->ubufAligned(4);
630 *envMapShaderStages->vertexStage(),
631 *envMapShaderStages->fragmentStage()
636 { 3 *
sizeof(float) }
645 if (!envMapPipeline->
create()) {
646 qWarning(
"failed to create source env map pipeline state");
653 cb->debugMarkBegin(
"Environment Cubemap Generation");
664 viewMatrix.
lookAt(eye, center, up);
670 if (rhi->isYUpInFramebuffer()) {
681 rub->updateDynamicBuffer(uBuf,
quint8(
face) * ubufElementSize + 64, 64, views[
quint8(
face)].constData());
682 rub->updateDynamicBuffer(uBufEnvMap,
quint8(
face) * ubufEnvMapElementSize, 4, &colorSpace);
684 cb->resourceUpdate(rub);
692 cb->setGraphicsPipeline(envMapPipeline);
693 cb->setVertexInput(0, 1, &vbufBinding);
694 cb->setViewport(
QRhiViewport(0, 0, environmentMapSize.width(), environmentMapSize.height()));
699 cb->setShaderResources(envMapSrb, 2, dynamicOffset.
constData());
715 rub = rhi->nextResourceUpdateBatch();
716 rub->generateMips(envCubeMap);
717 cb->resourceUpdate(rub);
721 cb->debugMarkBegin(
"Pre-filtered Environment Cubemap Generation");
725 if (!preFilteredEnvCubeMap->
create())
726 qWarning(
"Failed to create Pre-filtered Environment Cube Map");
727 preFilteredEnvCubeMap->
setName(rtName);
728 int mipmapCount = rhi->mipLevelsForSize(environmentMapSize);
729 mipmapCount =
qMin(mipmapCount, 6);
735 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
736 const QSize levelSize =
QSize(environmentMapSize.width() * std::pow(0.5, mipLevel),
737 environmentMapSize.height() * std::pow(0.5, mipLevel));
738 mipLevelSizes.
insert(mipLevel, levelSize);
744 att.setLevel(mipLevel);
747 auto renderTarget = rhi->newTextureRenderTarget(rtDesc);
750 renderTarget->setDescription(rtDesc);
751 if (!renderPassDescriptorPhase2)
753 renderTarget->setRenderPassDescriptor(renderPassDescriptorPhase2);
754 if (!renderTarget->create())
755 qWarning(
"Failed to build prefilter env map render target");
756 renderTarget->deleteLater();
757 renderTargets << renderTarget;
759 renderTargetsMap.
insert(mipLevel, renderTargets);
766 prefilterShaderStages = shaderCache->loadBuiltinForRhi(
"environmentmapprefilter_rgbe");
768 prefilterShaderStages = shaderCache->loadBuiltinForRhi(
"environmentmapprefilter");
783 envMapCubeSampler =
context->sampler(samplerMipMapDesc);
797 int ubufPrefilterElementSize = rhi->ubufAligned(20);
818 *prefilterShaderStages->vertexStage(),
819 *prefilterShaderStages->fragmentStage()
825 if (!prefilterPipeline->
create()) {
826 qWarning(
"failed to create pre-filter env map pipeline state");
833 rub = rhi->nextResourceUpdateBatch();
834 const float resolution = environmentMapSize.width();
835 const float lodBias = 0.0f;
836 const int sampleCount = 1024;
837 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
839 const float roughness = float(mipLevel) / float(mipmapCount - 2);
840 const int distribution = mipLevel == (mipmapCount - 1) ? 0 : 1;
841 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize, 4, &roughness);
842 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4, 4, &resolution);
843 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4 + 4, 4, &lodBias);
844 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4 + 4 + 4, 4, &sampleCount);
845 rub->updateDynamicBuffer(uBufPrefilter, mipLevel * ubufPrefilterElementSize + 4 + 4 + 4 + 4, 4, &distribution);
848 cb->resourceUpdate(rub);
851 for (
int mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) {
856 cb->setGraphicsPipeline(prefilterPipeline);
857 cb->setVertexInput(0, 1, &vbufBinding);
861 { 2,
quint32(ubufPrefilterElementSize * mipLevel) }
865 cb->setShaderResources(preFilterSrb, 2, dynamicOffsets.
constData());
878 outTexture->
m_texture = preFilteredEnvCubeMap;
886 CreateRhiTextureFlags inFlags,
887 const QString &debugObjectName)
891 int textureSampleCount = 1;
892 QRhiTexture::Flags textureFlags;
894 const bool checkTransp = inFlags.testFlag(ScanForTransparency);
895 bool hasTransp =
false;
903 texture.m_flags.setRgbe8(
true);
915 const int faceCount = tex.
numFaces();
918 environmentCubeMap->
create();
927 texture.m_texture = environmentCubeMap;
931 auto *rub = rhi->nextResourceUpdateBatch();
932 rub->uploadTexture(environmentCubeMap, uploadDescription);
933 context->commandBuffer()->resourceUpdate(rub);
934 texture.m_mipmapCount = mipmapCount;
940 if (createEnvironmentMap(inTexture, &
texture, debugObjectName)) {
944 qWarning() <<
"Failed to create environment map";
956 if (tex.
numFaces() == 6 && inFlags.testFlag(CubeMap))
973 }
else if (inFlags.testFlag(Texture3D)) {
981 for (
int slice = 0; slice < inTexture->
depth; ++slice) {
986 qWarning() <<
"Texture size set larger than the data";
996 }
else if (inTexture->
data) {
1010 bool generateMipmaps =
false;
1013 generateMipmaps =
true;
1014 mipmapCount = rhi->mipLevelsForSize(
size);
1017 if (mipmapCount > 1)
1020 if (inFlags.testFlag(CubeMap))
1024 qWarning() <<
"Could not load texture";
1026 }
else if (!rhi->isTextureFormatSupported(rhiFormat)) {
1027 qWarning() <<
"Unsupported texture format";
1032 if (inFlags.testFlag(Texture3D) &&
depth > 0)
1033 tex = rhi->newTexture(rhiFormat,
size.width(),
size.height(),
depth, textureSampleCount, textureFlags);
1035 tex = rhi->newTexture(rhiFormat,
size, textureSampleCount, textureFlags);
1040 texture.m_flags.setHasTransparency(hasTransp);
1045 auto *rub = rhi->nextResourceUpdateBatch();
1046 rub->uploadTexture(tex, uploadDescription);
1047 if (generateMipmaps)
1048 rub->generateMips(tex);
1049 context->commandBuffer()->resourceUpdate(rub);
1051 texture.m_mipmapCount = mipmapCount;
1072 return &meshBufferMutex;
1093 if (
model->hasLightmap()) {
1099 if (
model->meshPath.isNull() &&
model->geometry) {
1100 theMesh = loadRenderMesh(
model->geometry, options);
1102 if (
model->hasLightmap()) {
1106 theMesh = loadRenderMesh(
model->meshPath, options);
1116 if (
model->geometry) {
1118 }
else if (!
model->meshPath.isNull()){
1121 auto meshItr = meshMap.constFind(
model->meshPath);
1122 if (meshItr != meshMap.cend())
1123 theMesh = meshItr.value().mesh;
1127 const auto &subSets = theMesh->
subsets;
1128 for (
const auto &subSet : subSets)
1129 retval.
include(subSet.bounds);
1135 auto const &subsets = mesh.
subsets();
1136 for (
const auto &subset : subsets)
1157 if (sizeofType == 2 || sizeofType == 4) {
1179 rhi.vertexBuffer = std::make_shared<QSSGRhiBuffer>(*
context.get(),
1184 rhi.vertexBuffer->buffer()->setName(debugObjectName.
toLatin1());
1188 rhi.indexBuffer = std::make_shared<QSSGRhiBuffer>(*
context.get(),
1199 const int numTexels = (targetBuffer.
data.
size() / arraySize) >> 4;
1200 const int texWidth =
qCeil(
qSqrt(numTexels));
1201 const QSize texSize(texWidth, texWidth);
1202 if (!rhi.targetsTexture) {
1204 rhi.targetsTexture->create();
1205 context->registerTexture(rhi.targetsTexture);
1206 }
else if (rhi.targetsTexture->pixelSize() != texSize
1207 || rhi.targetsTexture->arraySize() != arraySize) {
1208 rhi.targetsTexture->setPixelSize(texSize);
1209 rhi.targetsTexture->setArraySize(arraySize);
1210 rhi.targetsTexture->create();
1213 const quint32 layerSize = texWidth * texWidth * 4 * 4;
1214 for (
int arrayId = 0; arrayId < arraySize; ++arrayId) {
1220 for (
quint32 entryIdx = 0, entryEnd = targetBuffer.
entries.size(); entryIdx < entryEnd; ++entryIdx) {
1221 const char *nameStr = targetBuffer.
entries[entryIdx].name.constData();
1238 rhi.ia.targetCount = targetBuffer.
numTargets;
1239 }
else if (rhi.targetsTexture) {
1240 context->releaseTexture(rhi.targetsTexture);
1241 rhi.targetsTexture =
nullptr;
1242 rhi.ia.targetOffsets = { UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX,
1243 UINT8_MAX, UINT8_MAX, UINT8_MAX };
1244 rhi.ia.targetCount = 0;
1249 for (
quint32 entryIdx = 0, entryEnd = vertexBuffer.
entries.size(); entryIdx < entryEnd; ++entryIdx)
1250 entryBuffer[entryIdx] = vertexBuffer.
entries[entryIdx].toRenderVertexBufferEntry();
1253 for (
quint32 entryIdx = 0, entryEnd = entryBuffer.
size(); entryIdx < entryEnd; ++entryIdx) {
1255 const int binding = 0;
1258 vbe.m_componentType, vbe.m_numComponents);
1259 const int offset = int(vbe.m_firstItemOffset);
1262 const char *nameStr = vbe.m_name.constData();
1284 qWarning(
"Unknown vertex input %s in mesh", nameStr);
1289 inputAttrs.
append(inputAttr);
1292 rhi.ia.inputLayout.setAttributes(inputAttrs.
cbegin(), inputAttrs.
cend());
1293 rhi.ia.inputLayout.setBindings({ vertexBuffer.
stride });
1297 qWarning(
"Mesh topology is TriangleFan but this is not supported with the active graphics API. Rendering will be incorrect.");
1300 for (
quint32 subsetIdx = 0, subsetEnd = meshSubsets.
size(); subsetIdx < subsetEnd; ++subsetIdx) {
1311 if (rhi.vertexBuffer) {
1313 subset.
rhi.
ia = rhi.ia;
1315 if (rhi.indexBuffer)
1317 if (rhi.targetsTexture)
1320 newMesh->
subsets.push_back(subset);
1332 const auto meshItr = customMeshMap.constFind(geometry);
1333 if (meshItr != customMeshMap.cend()) {
1334#ifdef QSSG_RENDERBUFFER_DEBUGGING
1335 qDebug() <<
"- releaseGeometry: " << geometry << currentLayer;
1340 m_contextInterface->
rhiContext()->releaseMesh(meshItr.value().mesh);
1341 customMeshMap.erase(meshItr);
1350 for (
auto it = customTextureMap.cbegin(),
end = customTextureMap.cend();
it !=
end; ++
it) {
1351 if (
it.key().data ==
data)
1360 const auto textureDataItr = customTextureMap.constFind(
key);
1361 if (textureDataItr != customTextureMap.cend()) {
1362 auto rhiTexture = textureDataItr.value().renderImageTexture.m_texture;
1364#ifdef QSSG_RENDERBUFFER_DEBUGGING
1365 qDebug() <<
"- releaseTextureData: " << textureData << currentLayer;
1370 m_contextInterface->
rhiContext()->releaseTexture(rhiTexture);
1375 customTextureMap.erase(textureDataItr);
1379void QSSGBufferManager::releaseMesh(
const QSSGRenderPath &inSourcePath)
1382 const auto meshItr = meshMap.constFind(inSourcePath);
1383 if (meshItr != meshMap.cend()) {
1384#ifdef QSSG_RENDERBUFFER_DEBUGGING
1385 qDebug() <<
"- releaseMesh: " << inSourcePath.
path() << currentLayer;
1390 m_contextInterface->
rhiContext()->releaseMesh(meshItr.value().mesh);
1391 meshMap.erase(meshItr);
1397void QSSGBufferManager::releaseImage(
const ImageCacheKey &
key)
1399 const auto imageItr = imageMap.constFind(
key);
1400 if (imageItr != imageMap.cend()) {
1401 auto rhiTexture = imageItr.value().renderImageTexture.m_texture;
1403#ifdef QSSG_RENDERBUFFER_DEBUGGING
1404 qDebug() <<
"- releaseTexture: " <<
key.path.path() << currentLayer;
1409 m_contextInterface->
rhiContext()->releaseTexture(rhiTexture);
1413 imageMap.erase(imageItr);
1419#if !defined(QSSG_RENDERBUFFER_DEBUGGING) && !defined(QSSG_RENDERBUFFER_DEBUGGING_USAGES)
1424 if (frameId == frameCleanupIndex)
1428 for (
const auto &
value : std::as_const(usages))
1437 auto meshIterator = meshMap.cbegin();
1438 while (meshIterator != meshMap.cend()) {
1439 if (isUnused(meshIterator.value().usageCounts)) {
1440#ifdef QSSG_RENDERBUFFER_DEBUGGING
1441 qDebug() <<
"- releaseGeometry: " << meshIterator.key().path() << currentLayer;
1444 m_contextInterface->
rhiContext()->releaseMesh(meshIterator.value().mesh);
1445 meshIterator = meshMap.erase(meshIterator);
1452 auto customMeshIterator = customMeshMap.cbegin();
1453 while (customMeshIterator != customMeshMap.cend()) {
1454 if (isUnused(customMeshIterator.value().usageCounts)) {
1455#ifdef QSSG_RENDERBUFFER_DEBUGGING
1456 qDebug() <<
"- releaseGeometry: " << customMeshIterator.key() << currentLayer;
1459 m_contextInterface->
rhiContext()->releaseMesh(customMeshIterator.value().mesh);
1460 customMeshIterator = customMeshMap.erase(customMeshIterator);
1462 ++customMeshIterator;
1468 auto sgIterator = qsgImageMap.cbegin();
1469 while (sgIterator != qsgImageMap.cend()) {
1470 if (isUnused(sgIterator.value().usageCounts)) {
1474 sgIterator = qsgImageMap.erase(sgIterator);
1481 auto imageKeyIterator = imageMap.cbegin();
1482 while (imageKeyIterator != imageMap.cend()) {
1483 if (isUnused(imageKeyIterator.value().usageCounts)) {
1484 auto rhiTexture = imageKeyIterator.value().renderImageTexture.m_texture;
1486#ifdef QSSG_RENDERBUFFER_DEBUGGING
1487 qDebug() <<
"- releaseTexture: " << imageKeyIterator.key().path.path() << currentLayer;
1490 m_contextInterface->
rhiContext()->releaseTexture(rhiTexture);
1492 imageKeyIterator = imageMap.erase(imageKeyIterator);
1499 auto textureDataIterator = customTextureMap.cbegin();
1500 while (textureDataIterator != customTextureMap.cend()) {
1501 if (isUnused(textureDataIterator.value().usageCounts)) {
1502 auto rhiTexture = textureDataIterator.value().renderImageTexture.m_texture;
1504#ifdef QSSG_RENDERBUFFER_DEBUGGING
1505 qDebug() <<
"- releaseTextureData: " << textureDataIterator.key() << currentLayer;
1508 m_contextInterface->
rhiContext()->releaseTexture(rhiTexture);
1510 textureDataIterator = customTextureMap.erase(textureDataIterator);
1512 ++textureDataIterator;
1517 frameCleanupIndex = frameId;
1518#ifdef QSSG_RENDERBUFFER_DEBUGGING_USAGES
1519 qDebug() <<
"QSSGBufferManager::cleanupUnreferencedBuffers()" <<
this <<
"frame:" << frameCleanupIndex << currentLayer;
1520 qDebug() <<
"Textures(by path): " << imageMap.count();
1521 qDebug() <<
"Textures(custom): " << customTextureMap.count();
1522 qDebug() <<
"Textures(qsg): " << qsgImageMap.count();
1523 qDebug() <<
"Geometry(by path): " << meshMap.count();
1524 qDebug() <<
"Geometry(custom): " << customMeshMap.count();
1530 if (frameResetIndex == frameId)
1542 for (
auto &
imageData : customTextureMap)
1545 for (
auto &meshData : meshMap)
1546 meshData.usageCounts[
layer] = 0;
1549 for (
auto &meshData : customMeshMap)
1550 meshData.usageCounts[
layer] = 0;
1552 frameResetIndex = frameId;
1553 currentLayer =
layer;
1558 auto it = g_assetMeshMap->
find(assetId);
1559 if (
it != g_assetMeshMap->
end())
1562 g_assetMeshMap->
insert(assetId, { meshData, 1 });
1567 auto it = g_assetMeshMap->
find(assetId);
1568 if (
it != g_assetMeshMap->
end() && (--
it->ref == 0))
1578 auto meshItr = meshMap.find(inMeshPath);
1579 if (meshItr != meshMap.cend()) {
1581 meshItr.value().usageCounts[currentLayer]++;
1582 return meshItr.value().mesh;
1584 releaseMesh(inMeshPath);
1605 resultSourcePath = inMeshPath.
path();
1615#ifdef QSSG_RENDERBUFFER_DEBUGGING
1616 qDebug() <<
"+ uploadGeometry: " << inMeshPath.
path() << currentLayer;
1627 meshMap.insert(inMeshPath, {
ret, {{currentLayer, 1}}, 0, options });
1637 auto meshIterator = customMeshMap.find(geometry);
1638 if (meshIterator == customMeshMap.end()) {
1639 meshIterator = customMeshMap.insert(geometry, MeshData());
1640 }
else if (geometry->
generationId() != meshIterator->generationId || !options.
isCompatible(meshIterator->options)) {
1643 meshIterator = customMeshMap.insert(geometry, MeshData());
1646 meshIterator.value().usageCounts[currentLayer]++;
1647 return meshIterator.value().mesh;
1658 #ifdef QSSG_RENDERBUFFER_DEBUGGING
1659 qDebug() <<
"+ uploadGeometry: " << geometry << currentLayer;
1667 meshIterator->mesh = createRenderMesh(mesh, geometry->
debugObjectName);
1668 meshIterator->usageCounts[currentLayer] = 1;
1670 meshIterator->options = options;
1671 m_contextInterface->
rhiContext()->registerMesh(meshIterator->mesh);
1681 return meshIterator->mesh;
1701 if (geometry->
primitiveType() != QSSGMesh::Mesh::DrawMode::Triangles)
1705 bool hasIndexBuffer =
false;
1722 hasIndexBuffer =
true;
1723 if (
attribute.componentType == QSSGMesh::Mesh::ComponentType::Int16)
1725 else if (
attribute.componentType == QSSGMesh::Mesh::ComponentType::Int32)
1753 const auto ait = g_assetMeshMap->constFind(assetId);
1754 if (ait != g_assetMeshMap->constEnd()) {
1755 const auto &meshes = ait->meshes;
1756 if (idx < meshes.size())
1757 result = ait->meshes.at(idx);
1769 if (poundIndex != -1) {
1771 pathBuilder = pathBuilder.
left(poundIndex);
1796void QSSGBufferManager::clear()
1798 if (meshBufferUpdates) {
1800 meshBufferUpdates =
nullptr;
1806 auto meshMapCopy = meshMap;
1807 meshMapCopy.detach();
1808 for (
auto iter = meshMapCopy.begin(),
end = meshMapCopy.end();
iter !=
end; ++
iter) {
1811#ifdef QSSG_RENDERBUFFER_DEBUGGING
1812 qDebug() <<
"- releaseGeometry: " <<
iter.key().path() << currentLayer;
1815 m_contextInterface->
rhiContext()->releaseMesh(theMesh);
1821 auto customMeshMapCopy = customMeshMap;
1822 customMeshMapCopy.detach();
1823 for (
auto iter = customMeshMapCopy.begin(),
end = customMeshMapCopy.end();
iter !=
end; ++
iter) {
1826#ifdef QSSG_RENDERBUFFER_DEBUGGING
1827 qDebug() <<
"- releaseGeometry: " <<
iter.key() << currentLayer;
1830 m_contextInterface->
rhiContext()->releaseMesh(theMesh);
1833 customMeshMap.clear();
1837 for (
const auto &k : imageMap.
keys())
1843 for (
const auto &k : customTextureMap.
keys())
1846 customTextureMap.clear();
1850 qsgImageMap.clear();
1855 if (!meshBufferUpdates)
1856 meshBufferUpdates = m_contextInterface->
rhiContext()->rhi()->nextResourceUpdateBatch();
1857 return meshBufferUpdates;
1862 if (meshBufferUpdates) {
1863 m_contextInterface->
rhiContext()->commandBuffer()->resourceUpdate(meshBufferUpdates);
1864 meshBufferUpdates =
nullptr;
1870 for (
auto &mesh : std::as_const(
loader->meshes))
1871 loadRenderMesh(mesh, {});
1873 for (
auto customMesh : std::as_const(
loader->geometries))
1914 static const quint64 pixelSizes[] = {0, 4, 4, 1, 2, 2, 4, 1, 2, 4, 2, 4, 4, 2, 4, 4, 4};
1926 static const quint64 blockSizes[] = {8, 16, 16, 8, 16, 16, 16, 8, 8, 16};
1928 "QRhiTexture format constant value missmatch.");
IOBluetoothDevice * device
QByteArray toByteArray() const
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
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.
static constexpr QChar fromLatin1(char c) noexcept
Converts the Latin-1 character c to its equivalent QChar.
The QColor class provides colors based on RGB, HSV or CMYK values.
\inmodule QtCore \reentrant
bool exists() const
Returns true if the file exists; otherwise returns false.
QSize size() const
Returns the size of the image, i.e.
bool isNull() const
Returns true if it is a null image, otherwise returns false.
qsizetype size() const noexcept
const_pointer constData() const noexcept
bool isEmpty() const noexcept
void resize(qsizetype size)
iterator insert(const Key &key, const T &value)
bool contains(const Key &key) const
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
void lookAt(const QVector3D &eye, const QVector3D ¢er, const QVector3D &up)
Multiplies this matrix by a viewing matrix derived from an eye point.
void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane)
Multiplies this matrix by another that applies a perspective projection.
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
virtual bool create()=0
Creates the corresponding native graphics resources.
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
IndexFormat
Specifies the index data type.
void setCullMode(CullMode mode)
Sets the specified face culling mode.
void setFrontFace(FrontFace f)
Sets the front face mode f.
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
void setDepthOp(CompareOp op)
Sets the depth comparison function op.
void setVertexInputLayout(const QRhiVertexInputLayout &layout)
Specifies the vertex input layout.
void setShaderStages(std::initializer_list< QRhiShaderStage > list)
Sets the list of shader stages.
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Associates with the specified QRhiRenderPassDescriptor desc.
virtual bool create()=0
Creates the corresponding native graphics resources.
virtual bool create()=0
Creates the corresponding native graphics resources.
virtual QRhiRenderPassDescriptor * newCompatibleRenderPassDescriptor() const =0
void uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Enqueues updating a region of a QRhiBuffer buf created with the type QRhiBuffer::Immutable or QRhiBuf...
void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
Enqueues uploading the image data for one or more mip levels in one or more layers of the texture tex...
void setName(const QByteArray &name)
Sets a name for the object.
void deleteLater()
When called without a frame being recorded, this function is equivalent to deleting the object.
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
void setBindings(std::initializer_list< QRhiShaderResourceBinding > list)
Sets the list of bindings.
void setColorAttachments(std::initializer_list< QRhiColorAttachment > list)
Sets the list of color attachments.
void setData(const QByteArray &data)
Sets data.
void setSourceSize(const QSize &size)
Sets the source size in pixels.
void setImage(const QImage &image)
Sets image.
void setEntries(std::initializer_list< QRhiTextureUploadEntry > list)
Sets the list of entries.
virtual bool create()=0
Creates the corresponding native graphics resources.
Format
Specifies the texture format.
QRhiResourceUpdateBatch * nextResourceUpdateBatch()
static bool formatIsOpaque(quint32 glTextureFormat)
virtual void commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
Call this function to enqueue image upload operations to resourceUpdates, in case there are any pendi...
virtual QSGTexture * removedFromAtlas(QRhiResourceUpdateBatch *resourceUpdates=nullptr) const
This function returns a copy of the current texture which is removed from its atlas.
virtual bool hasAlphaChannel() const =0
Returns true if the texture data contains an alpha channel.
virtual bool isAtlasTexture() const
Returns whether this texture is part of an atlas or not.
virtual QRhiTexture * rhiTexture() const
static const char * displayName(QSSGRenderTextureCubeFace face)
static size_t getSizeOfType(QSSGRenderComponentType type)
Class representing 3D range or axis aligned bounding box.
void include(const QVector3D &v)
expands the volume to include v
void releaseCachedResources()
void setRenderContextInterface(QSSGRenderContextInterface *ctx)
QSSGRenderImageTexture loadSkinmap(QSSGRenderTextureData *skin)
void releaseGeometry(QSSGRenderGeometry *geometry)
QSSGBounds3 getModelBounds(const QSSGRenderModel *model) const
static QRhiTexture::Format toRhiFormat(const QSSGRenderTextureFormat format)
void increaseMemoryStat(QRhiTexture *texture)
void cleanupUnreferencedBuffers(quint32 frameId, QSSGRenderLayer *layer)
QSSGRenderMesh * getMeshForPicking(const QSSGRenderModel &model) const
static QSSGMesh::Mesh loadMeshData(const QSSGRenderPath &inSourcePath)
QSSGRenderImageTexture loadRenderImage(const QSSGRenderImage *image, MipMode inMipMode=MipModeFollowRenderImage, LoadRenderImageFlags flags=LoadWithFlippedY)
void commitBufferResourceUpdates()
@ MipModeFollowRenderImage
static void unregisterMeshData(const QString &assetId)
static QString primitivePath(const QString &primitive)
void releaseTextureData(const QSSGRenderTextureData *data)
QSSGRenderMesh * loadMesh(const QSSGRenderModel *model)
QSSGRenderImageTexture loadLightmap(const QSSGRenderModel &model)
QMutex * meshUpdateMutex()
static void registerMeshData(const QString &assetId, const QVector< QSSGMesh::Mesh > &meshData)
void decreaseMemoryStat(QRhiTexture *texture)
void resetUsageCounters(quint32 frameId, QSSGRenderLayer *layer)
static QSSGMeshBVH * loadMeshBVH(const QSSGRenderPath &inSourcePath)
void processResourceLoader(const QSSGRenderResourceLoader *loader)
static QString lightmapAssetPathForLoad(const QSSGRenderModel &model, LightmapAsset asset)
QSSGMeshBVH * buildTree()
bool createLightmapUVChannel(uint lightmapBaseResolution)
static Mesh fromRuntimeData(const RuntimeMeshData &data, QString *error)
static Mesh loadMesh(QIODevice *device, quint32 id=0)
VertexBuffer vertexBuffer() const
IndexBuffer indexBuffer() const
QVector< Subset > subsets() const
TargetBuffer targetBuffer() const
DrawMode drawMode() const
const std::unique_ptr< QSSGRhiContext > & rhiContext() const
const std::unique_ptr< QSSGShaderCache > & shaderCache() const
Attribute attribute(int idx) const
const QSSGMesh::RuntimeMeshData & meshData() const
uint32_t generationId() const
int attributeCount() const
const QByteArray & indexBuffer() const
const QByteArray & vertexBuffer() const
QSSGMesh::Mesh::DrawMode primitiveType() const
static QRhiCommandBuffer::BeginPassFlags commonPassFlags()
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
iterator find(const T &value)
iterator insert(const T &value)
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
uint toUInt(bool *ok=nullptr, int base=10) const
Returns the string view converted to an {unsigned int} using base base, which is 10 by default and mu...
\macro QT_RESTRICTED_CAST_FROM_ASCII
QByteArray toLatin1() const &
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf16(const char16_t *, qsizetype size=-1)
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
QByteArray toUtf8() const &
quint32 glInternalFormat() const
QMap< QByteArray, QByteArray > keyValueMetadata() const
QByteArrayView getDataView(int level=0, int face=0) const
const_iterator cbegin() const noexcept
const_iterator cend() const noexcept
The QVector3D class represents a vector or vertex in 3D space.
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QTextStream & center(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter) on stream and returns stream.
#define Q_STATIC_ASSERT_X(Condition, Message)
#define QByteArrayLiteral(str)
std::pair< T1, T2 > QPair
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputLayerEXT EGLint attribute
qfloat16 qSqrt(qfloat16 f)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCCritical(category,...)
#define qCWarning(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLint level
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei const GLchar ** strings
[1]
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
#define Q_QUICK3D_PROFILE_END_WITH_PAYLOAD(Type, Payload)
#define Q_QUICK3D_PROFILE_START(Type)
#define Q_QUICK3D_PROFILE_END_WITH_ID(Type, Payload, POID)
#define QSSG_RENDERPASS_NAME(passName, level, face)
#define Q_QUICK3D_PROFILE_END_WITH_STRING(Type, Payload, Str)
static constexpr QSSGRenderTextureCubeFace QSSGRenderTextureCubeFaces[]
static constexpr QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
static quint64 textureMemorySize(QRhiTexture *texture)
static MeshIdxNamePair splitRuntimeMeshPath(const QSSGRenderPath &rpath)
static const float cube[]
static const PrimitiveEntry primitives[nPrimitives]
static quint64 bufferMemorySize(const QSSGRhiBufferPtr &buffer)
static const int nPrimitives
static const char * primitivesDirectory
QPair< qsizetype, QString > MeshIdxNamePair
#define QSSGRHICTX_STAT(ctx, f)
std::shared_ptr< QSSGRhiBuffer > QSSGRhiBufferPtr
std::shared_ptr< QSSGRhiShaderPipeline > QSSGRhiShaderPipelinePtr
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
#define Q_TRACE_SCOPE(x,...)
#define Q_TRACE_POINT(provider, tracepoint,...)
unsigned long long quint64
QSqlQueryModel * model
[16]
myFilter draw(painter, QPoint(0, 0), originalPixmap)
QVector< QSSGMesh::Mesh > meshes
bool checkForAlphaPixels() const
static QImageData * get(QImage &img) noexcept
QTextureFileData textureFileData
QSSGRenderTextureFormat format
static QSSGLoadedTexture * load(const QString &inPath, const QSSGRenderTextureFormat &inFormat, bool inFlipY=true)
static QSSGLoadedTexture * loadTextureData(QSSGRenderTextureData *textureData)
bool scanForTransparency() const
bool isCompatible(const QSSGMeshProcessingOptions &other) const
uint lightmapBaseResolution
static const char * getLightmapUVAttrName()
static const char * getNormalAttrName()
static const char * getUV1AttrName()
static const char * getTexBinormalAttrName()
static const char * getPositionAttrName()
static const char * getTexTanAttrName()
static const char * getColorAttrName()
static const char * getJointAttrName()
static const char * getUV0AttrName()
static const char * getWeightAttrName()
ComponentType componentType
QVector< VertexBufferEntry > entries
QVector< VertexBufferEntry > entries
QByteArray m_vertexBuffer
QVector< QSSGRenderSubset > subsets
QSSGRhiBufferPtr indexBuffer
QSSGRhiInputAssemblerState ia
QRhiTexture * targetsTexture
QSSGRhiBufferPtr vertexBuffer
QSSGMeshBVHNode * bvhRoot
struct QSSGRenderSubset::@751 rhi
constexpr bool isCompressedTextureFormat() const noexcept
qint32 getSizeofFormat() const