| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- // Copyright (C) 2023 The Qt Company Ltd.
- // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
- import QtQuick
- import QtQuick.Controls
- import QtQuick.Layouts
- import QtQuick3D
- import QtQuick3D.Helpers.impl
- Pane {
- id: root
- property var source: null
- property bool resourceDetailsVisible: false
- opacity: 0.9
- ColumnLayout {
- id: layout
- RowLayout {
- Label {
- Layout.fillWidth: true
- text: root.source.renderStats.fps + " FPS"
- font.pointSize: 14
- }
- Label {
- text: "Details"
- }
- CheckBox {
- checked: root.resourceDetailsVisible
- onCheckedChanged: {
- resourceDetailsVisible = checked;
- }
- }
- }
- component TimeLabel : RowLayout {
- id: timeLabel
- property alias text: label.text
- property real value: 0.0
- Label {
- id: label
- Layout.fillWidth: true
- text: "Frame: "
- }
- Label {
- text: timeLabel.value.toFixed(3) + "ms"
- }
- }
- TimeLabel {
- text: "Frame: "
- value: root.source.renderStats.frameTime
- }
- TimeLabel {
- text: " Sync: "
- value: root.source.renderStats.syncTime
- }
- TimeLabel {
- text: " Prep: "
- value: root.source.renderStats.renderPrepareTime
- }
- TimeLabel {
- text: " Render: "
- value: root.source.renderStats.renderTime
- }
- TimeLabel {
- text: "Max: "
- value: root.source.renderStats.maxFrameTime
- }
- TimeLabel {
- text: "GPU: "
- value: root.source.renderStats.lastCompletedGpuTime
- visible: root.source.renderStats.lastCompletedGpuTime > 0
- }
- Page {
- Layout.fillWidth: true
- Layout.minimumWidth: 530
- visible: root.resourceDetailsVisible
- header: TabBar {
- id: tabBar
- TabButton {
- text: "Summary"
- }
- TabButton {
- text: "Passes"
- }
- TabButton {
- text: "Textures"
- }
- TabButton {
- text: "Meshes"
- }
- TabButton {
- text: "Tools"
- }
- TabButton {
- text: "Shadows"
- }
- }
- StackLayout {
- anchors.fill: parent
- anchors.margins: 10
- currentIndex: tabBar.currentIndex
- Pane {
- id: summaryPane
- ColumnLayout {
- Label {
- text: "Graphics API: " + root.source.renderStats.graphicsApiName
- visible: root.resourceDetailsVisible
- }
- Label {
- text: root.source.renderStats.renderPassCount + " render passes"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: root.source.renderStats.drawCallCount + " draw calls"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: root.source.renderStats.drawVertexCount + " vertices"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: "Image assets: " + (root.source.renderStats.imageDataSize / 1024).toFixed(2) + " KB"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: "Mesh assets: " + (root.source.renderStats.meshDataSize / 1024).toFixed(2) + " KB"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: "Pipelines: " + root.source.renderStats.pipelineCount
- visible: root.resourceDetailsVisible
- }
- Label {
- text: "Material build time: " + root.source.renderStats.materialGenerationTime + " ms"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: "Effect build time: " + root.source.renderStats.effectGenerationTime + " ms"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: "Pipeline build time: " + root.source.renderStats.pipelineCreationTime + " ms"
- visible: root.resourceDetailsVisible
- }
- Label {
- text: root.source.renderStats.vmemAllocCount + " vmem allocs with " + root.source.renderStats.vmemUsedBytes + " bytes"
- visible: root.resourceDetailsVisible && root.source.renderStats.vmemAllocCount > 0
- }
- }
- }
- Pane {
- id: passesPane
- RenderStatsPassesModel {
- id: passesModel
- passData: root.source.renderStats.renderPassDetails
- }
- ColumnLayout {
- anchors.fill: parent
- spacing: 0
- HorizontalHeaderView {
- syncView: passesTableView
- resizableColumns: false // otherwise QTBUG-111013 happens
- boundsBehavior: Flickable.StopAtBounds
- flickableDirection: Flickable.VerticalFlick
- }
- ListModel {
- id: passesHeaderModel
- ListElement {
- columnWidth: 300 // name
- }
- ListElement {
- columnWidth: 80 // size
- }
- ListElement {
- columnWidth: 60 // vertices
- }
- ListElement {
- columnWidth: 60 // draw calls
- }
- }
- Item {
- Layout.fillHeight: true
- Layout.fillWidth: true
- TableView {
- id: passesTableView
- anchors.fill: parent
- // name, size, vertices, draw calls
- property var columnFactors: [58, 14, 12, 12]; // == 96, leave space for the scrollbar
- columnWidthProvider: function (column) {
- return passesPane.width * (columnFactors[column] / 100.0);
- }
- boundsBehavior: Flickable.StopAtBounds
- flickableDirection: Flickable.VerticalFlick
- ScrollBar.vertical: ScrollBar {
- parent: passesTableView.parent
- anchors.top: passesTableView.top
- anchors.bottom: passesTableView.bottom
- anchors.left: passesTableView.right
- }
- clip: true
- model: passesModel
- columnSpacing: 1
- rowSpacing: 1
- implicitWidth: parent.width + columnSpacing
- implicitHeight: parent.height + rowSpacing
- delegate: CustomTableItemDelegate {
- required property string display
- text: display
- color: TableView.view.palette.base
- textColor: TableView.view.palette.text
- }
- }
- }
- }
- }
- Pane {
- id: texturesPane
- RenderStatsTexturesModel {
- id: texturesModel
- textureData: root.source.renderStats.textureDetails
- }
- ColumnLayout {
- anchors.fill: parent
- spacing: 0
- HorizontalHeaderView {
- syncView: texturesTableView
- resizableColumns: false // otherwise QTBUG-111013 happens
- boundsBehavior: Flickable.StopAtBounds
- flickableDirection: Flickable.VerticalFlick
- }
- Item {
- Layout.fillHeight: true
- Layout.fillWidth: true
- TableView {
- id: texturesTableView
- anchors.fill: parent
- // name, size, format, miplevels, flags
- property var columnFactors: [48, 12, 12, 12, 12]; // == 96, leave space for the scrollbar
- columnWidthProvider: function (column) {
- return texturesPane.width * (columnFactors[column] / 100.0);
- }
- boundsBehavior: Flickable.StopAtBounds
- flickableDirection: Flickable.VerticalFlick
- ScrollBar.vertical: ScrollBar {
- parent: texturesTableView.parent
- anchors.top: texturesTableView.top
- anchors.bottom: texturesTableView.bottom
- anchors.left: texturesTableView.right
- }
- ScrollBar.horizontal: ScrollBar { }
- clip: true
- model: texturesModel
- columnSpacing: 1
- rowSpacing: 1
- implicitWidth: parent.width + columnSpacing
- implicitHeight: parent.height + rowSpacing
- delegate: CustomTableItemDelegate {
- required property string display
- text: display
- color: TableView.view.palette.base
- textColor: TableView.view.palette.text
- }
- }
- }
- }
- }
- Pane {
- id: meshesPane
- RenderStatsMeshesModel {
- id: meshesModel
- meshData: root.source.renderStats.meshDetails
- }
- ColumnLayout {
- anchors.fill: parent
- spacing: 0
- HorizontalHeaderView {
- syncView: meshesTableView
- resizableColumns: false // otherwise QTBUG-111013 happens
- boundsBehavior: Flickable.StopAtBounds
- flickableDirection: Flickable.VerticalFlick
- }
- Item {
- Layout.fillHeight: true
- Layout.fillWidth: true
- TableView {
- id: meshesTableView
- anchors.fill: parent
- // name, submeshes, vertices, vbufsize, ibufsize
- property var columnFactors: [48, 12, 12, 12, 12]; // == 96, leave space for the scrollbar
- columnWidthProvider: function (column) {
- return meshesPane.width * (columnFactors[column] / 100.0);
- }
- boundsBehavior: Flickable.StopAtBounds
- flickableDirection: Flickable.VerticalFlick
- ScrollBar.vertical: ScrollBar {
- parent: meshesTableView.parent
- anchors.top: meshesTableView.top
- anchors.bottom: meshesTableView.bottom
- anchors.left: meshesTableView.right
- }
- clip: true
- model: meshesModel
- columnSpacing: 1
- rowSpacing: 1
- implicitWidth: parent.width + columnSpacing
- implicitHeight: parent.height + rowSpacing
- delegate: CustomTableItemDelegate {
- required property string display
- text: display
- color: TableView.view.palette.base
- textColor: TableView.view.palette.text
- }
- }
- }
- }
- }
- Pane {
- id: visualizePane
- ColumnLayout {
- id: visCtrCol
- width: parent.width
- CheckBox {
- text: "Wireframe mode"
- onCheckedChanged: root.source.environment.debugSettings.wireframeEnabled = checked
- }
- RowLayout {
- Label {
- text: "Material override"
- }
- ComboBox {
- id: materialOverrideComboBox
- textRole: "text"
- valueRole: "value"
- implicitContentWidthPolicy: ComboBox.WidestText
- onActivated: root.source.environment.debugSettings.materialOverride = currentValue
- Component.onCompleted: materialOverrideComboBox.currentIndex = materialOverrideComboBox.indexOfValue(root.source.environment.debugSettings.materialOverride)
- model: [
- { value: DebugSettings.None, text: "None"},
- { value: DebugSettings.BaseColor, text: "Base Color"},
- { value: DebugSettings.Roughness, text: "Roughness"},
- { value: DebugSettings.Metalness, text: "Metalness"},
- { value: DebugSettings.Diffuse, text: "Diffuse"},
- { value: DebugSettings.Specular, text: "Specular"},
- { value: DebugSettings.ShadowOcclusion, text: "Shadow Occlusion"},
- { value: DebugSettings.Emission, text: "Emission"},
- { value: DebugSettings.AmbientOcclusion, text: "Ambient Occlusion"},
- { value: DebugSettings.Normals, text: "Normals"},
- { value: DebugSettings.Tangents, text: "Tangents"},
- { value: DebugSettings.Binormals, text: "Binormals"},
- { value: DebugSettings.F0, text: "F0"}
- ]
- }
- }
- RowLayout {
- spacing: 20
- Button {
- text: "Release cached resources"
- onClicked: root.source.renderStats.releaseCachedResources()
- }
- Button {
- text: "Bake lightmap"
- onClicked: root.source.bakeLightmap()
- }
- Button {
- text: "Denoise lightmap"
- onClicked: root.source.denoiseLightmap()
- }
- }
- RowLayout {
- Label {
- text: "Render mode override"
- }
- ComboBox {
- id: renderModeOverrideComboBox
- textRole: "text"
- valueRole: "value"
- implicitContentWidthPolicy: ComboBox.WidestText
- onActivated: root.source.renderMode = currentValue
- Component.onCompleted: renderModeOverrideComboBox.currentIndex = renderModeOverrideComboBox.indexOfValue(root.source.renderMode)
- model: [
- { value: View3D.Offscreen, text: "Offscreen" },
- { value: View3D.Underlay, text: "Underlay" },
- { value: View3D.Overlay, text: "Overlay" },
- { value: View3D.Inline, text: "Inline" }
- ]
- }
- }
- Label {
- text: "View3D logical size is " + root.source.width + "x" + root.source.height
- }
- Label {
- text: "Backing texture pixel size is " + root.source.effectiveTextureSize.width + "x" + root.source.effectiveTextureSize.height
- visible: root.source.renderMode === View3D.Offscreen
- }
- RowLayout {
- CheckBox {
- id: explicitTextureSizeCheckBox
- visible: root.source.renderMode === View3D.Offscreen
- text: "Explicit backing texture size"
- property real aspectRatio: root.source.width / root.source.height
- onCheckedChanged: updateSize()
- function updateSize() {
- if (!explicitTextureSizeCheckBox.checked) {
- root.source.explicitTextureWidth = 0;
- root.source.explicitTextureHeight = 0;
- return;
- }
- var newWidth = explicitWidthSlider.value;
- var newHeight = explicitHeightSlider.value;
- if (keepAspectRatioCheckBox.checked) {
- var aspectRatio = explicitTextureSizeCheckBox.aspectRatio;
- if (newHeight * aspectRatio <= newWidth)
- newWidth = newHeight * aspectRatio;
- else
- newHeight = newWidth * (1.0 / aspectRatio);
- }
- root.source.explicitTextureWidth = newWidth;
- root.source.explicitTextureHeight = newHeight;
- }
- Connections {
- target: root.source
- function onWidthChanged() { explicitTextureSizeCheckBox.updateSize() }
- function onHeightChanged() { explicitTextureSizeCheckBox.updateSize() }
- }
- }
- CheckBox {
- id: keepAspectRatioCheckBox
- visible: root.source.renderMode === View3D.Offscreen && explicitTextureSizeCheckBox.checked
- text: "Keep aspect ratio (" + explicitTextureSizeCheckBox.aspectRatio.toFixed(2) + ")"
- checked: false
- onCheckedChanged: explicitTextureSizeCheckBox.updateSize()
- }
- }
- RowLayout {
- visible: root.source.renderMode === View3D.Offscreen && explicitTextureSizeCheckBox.checked
- Label {
- text: "Width: " + explicitWidthSlider.value.toFixed(0) + " px"
- }
- Slider {
- id: explicitWidthSlider
- from: 16
- to: 4096
- value: 1280
- onValueChanged: explicitTextureSizeCheckBox.updateSize()
- Layout.maximumWidth: 120
- }
- Label {
- text: "Height: " + explicitHeightSlider.value.toFixed(0) + " px"
- }
- Slider {
- id: explicitHeightSlider
- from: 16
- to: 4096
- value: 720
- onValueChanged: explicitTextureSizeCheckBox.updateSize()
- Layout.maximumWidth: 120
- }
- }
- }
- }
- Pane {
- id: shadowsPane
- ColumnLayout {
- width: parent.width
- CheckBox {
- text: "Draw directional light shadow bounding boxes"
- checked: root.source.environment.debugSettings.drawDirectionalLightShadowBoxes
- onCheckedChanged: root.source.environment.debugSettings.drawDirectionalLightShadowBoxes = checked
- }
- CheckBox {
- text: "Draw point light shadow bounding boxes"
- checked: root.source.environment.debugSettings.drawPointLightShadowBoxes
- onCheckedChanged: root.source.environment.debugSettings.drawPointLightShadowBoxes = checked
- }
- CheckBox {
- text: "Draw shadow casting bounding box"
- checked: root.source.environment.debugSettings.drawShadowCastingBounds
- onCheckedChanged: root.source.environment.debugSettings.drawShadowCastingBounds = checked
- }
- CheckBox {
- text: "Draw shadow receiving bounding box"
- checked: root.source.environment.debugSettings.drawShadowReceivingBounds
- onCheckedChanged: root.source.environment.debugSettings.drawShadowReceivingBounds = checked
- }
- CheckBox {
- text: "Draw cascades"
- checked: root.source.environment.debugSettings.drawCascades
- onCheckedChanged: root.source.environment.debugSettings.drawCascades = checked
- }
- CheckBox {
- text: "Draw scene cascade intersection"
- checked: root.source.environment.debugSettings.drawSceneCascadeIntersection
- onCheckedChanged: root.source.environment.debugSettings.drawSceneCascadeIntersection = checked
- }
- CheckBox {
- text: "Disable Shadow Camera Update"
- checked: root.source.environment.debugSettings.disableShadowCameraUpdate
- onCheckedChanged: root.source.environment.debugSettings.disableShadowCameraUpdate = checked
- }
- }
- }
- }
- }
- }
- component CustomTableItemDelegate : Rectangle {
- property alias text: textLabel.text
- property alias textColor: textLabel.color
- implicitWidth: 100
- implicitHeight: textLabel.implicitHeight + 4
- color: palette.base
- Label {
- id: textLabel
- anchors.centerIn: parent
- color: palette.text
- }
- }
- function syncVisible() {
- if (source) {
- source.renderStats.extendedDataCollectionEnabled = visible && resourceDetailsVisible;
- if (source.renderStats.extendedDataCollectionEnabled)
- source.update();
- }
- }
- Component.onCompleted: syncVisible()
- onSourceChanged: syncVisible()
- onVisibleChanged: syncVisible()
- onResourceDetailsVisibleChanged: syncVisible()
- }
|