From 58e16414e036f7cd0de6e082ef0926c8f1c574e2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 20 Nov 2020 16:01:58 +0000 Subject: [PATCH] Add a number of control functions to the Qt python interface --- docs/python_api/qrenderdoc/windows.rst | 8 + qrenderdoc/Code/Interface/QRDInterface.h | 259 +++++++++++++++- qrenderdoc/Code/QRDUtils.cpp | 5 + qrenderdoc/Code/QRDUtils.h | 1 + qrenderdoc/Windows/APIInspector.cpp | 61 ++++ qrenderdoc/Windows/APIInspector.h | 4 + qrenderdoc/Windows/BufferViewer.cpp | 12 + qrenderdoc/Windows/BufferViewer.h | 8 +- .../D3D11PipelineStateViewer.cpp | 5 + .../PipelineState/D3D11PipelineStateViewer.h | 2 + .../D3D12PipelineStateViewer.cpp | 5 + .../PipelineState/D3D12PipelineStateViewer.h | 2 + .../PipelineState/GLPipelineStateViewer.cpp | 5 + .../PipelineState/GLPipelineStateViewer.h | 2 + .../PipelineState/PipelineStateViewer.cpp | 12 + .../PipelineState/PipelineStateViewer.h | 1 + .../VulkanPipelineStateViewer.cpp | 5 + .../PipelineState/VulkanPipelineStateViewer.h | 2 + qrenderdoc/Windows/ResourceInspector.cpp | 52 ++++ qrenderdoc/Windows/ResourceInspector.h | 1 + qrenderdoc/Windows/TextureViewer.cpp | 284 +++++++++++++----- qrenderdoc/Windows/TextureViewer.h | 29 +- 22 files changed, 663 insertions(+), 102 deletions(-) diff --git a/docs/python_api/qrenderdoc/windows.rst b/docs/python_api/qrenderdoc/windows.rst index 62a55397d..cdd259602 100644 --- a/docs/python_api/qrenderdoc/windows.rst +++ b/docs/python_api/qrenderdoc/windows.rst @@ -26,12 +26,20 @@ API Inspector Pipeline State -------------- +.. autoclass:: qrenderdoc.PipelineStage + :members: + :exclude-members: enum_constants__, + .. autoclass:: qrenderdoc.PipelineStateViewer :members: Texture Viewer -------------- +.. autoclass:: qrenderdoc.FollowType + :members: + :exclude-members: enum_constants__, + .. autoclass:: qrenderdoc.TextureViewer :members: diff --git a/qrenderdoc/Code/Interface/QRDInterface.h b/qrenderdoc/Code/Interface/QRDInterface.h index 9f43ba47c..8b2016ea7 100644 --- a/qrenderdoc/Code/Interface/QRDInterface.h +++ b/qrenderdoc/Code/Interface/QRDInterface.h @@ -214,6 +214,12 @@ struct IAPIInspector DOCUMENT("Refresh the current API view - useful if callstacks are now available."); virtual void Refresh() = 0; + DOCUMENT(R"(Expand the API view to reveal a given parameter and select it. + +:param SDObject param: The parameter to reveal and select. +)"); + virtual void RevealParameter(SDObject *param) = 0; + protected: IAPIInspector() = default; ~IAPIInspector() = default; @@ -221,6 +227,94 @@ protected: DECLARE_REFLECTION_STRUCT(IAPIInspector); +DOCUMENT(R"(Specifies a pipeline stage for the :class:`PipelineStateViewer`. + +.. data:: VertexInput + + The fixed function vertex input stage. + +.. data:: VertexShader + + The vertex shader. + +.. data:: HullShader + + The vertex shader. + +.. data:: TessControlShader + + The tessellation control shader. + +.. data:: DomainShader + + The domain shader. + +.. data:: TessEvalShader + + The tessellation evaluation shader. + +.. data:: GeometryShader + + The geometry shader, including stream-out/transform feedback. + +.. data:: Rasterizer + + The fixed function rasterizer stage. + +.. data:: ViewportsScissors + + The viewports and scissors. Helper alias for :data:`Rasterizer`. + +.. data:: PixelShader + + The pixel shader. + +.. data:: FragmentShader + + The fragment shader. + +.. data:: ColorDepthOutput + + The fixed function color and depth output stage, including color blending and depth/stencil + testing state. + +.. data:: Blending + + The color blending state. Helper alias for :data:`ColorDepthOutput`. + +.. data:: DepthTest + + The depth test state. Helper alias for :data:`ColorDepthOutput`. + +.. data:: StencilTest + + The stencil test state. Helper alias for :data:`ColorDepthOutput`. + +.. data:: ComputeShader + + The compute shader. +)"); +enum class PipelineStage : int +{ + VertexInput = 0, + + VertexShader, + HullShader, + TessControlShader = HullShader, + DomainShader, + TessEvalShader = DomainShader, + GeometryShader, + Rasterizer, + ViewportsScissors = Rasterizer, + PixelShader, + FragmentShader = PixelShader, + ColorDepthOutput, + Blending = ColorDepthOutput, + DepthTest = ColorDepthOutput, + StencilTest = ColorDepthOutput, + ComputeShader, +}; + DOCUMENT("The pipeline state viewer window."); struct IPipelineStateViewer { @@ -236,6 +330,12 @@ struct IPipelineStateViewer )"); virtual bool SaveShaderFile(const ShaderReflection *shader) = 0; + DOCUMENT(R"(Select a given pipeline stage in the viewer. + +:param PipelineStage stage: The stage to select. +)"); + virtual void SelectPipelineStage(PipelineStage stage) = 0; + protected: IPipelineStateViewer() = default; ~IPipelineStateViewer() = default; @@ -243,6 +343,36 @@ protected: DECLARE_REFLECTION_STRUCT(IPipelineStateViewer); +DOCUMENT(R"(Specifies a type of followed resource for the :class:`TextureViewer`. + +.. data:: OutputColor + + The index specifies which output color target to select. Shader stage and array index are ignored. + +.. data:: OutputDepth + + The resource followed is the depth/stencil output target. All other parameters are ignored. + +.. data:: ReadWrite + + The index specifies a resource within the given shader's + :data:`read-write resources <~renderdoc.ShaderReflection.readWriteResources>`. The array element + then specifies the index within that resource's array, if applicable. + +.. data:: ReadOnly + + The index specifies a resource within the given shader's + :data:`read-only resources <~renderdoc.ShaderReflection.readOnlyResources>`. The array element + then specifies the index within that resource's array, if applicable. +)"); +enum class FollowType : int +{ + OutputColor, + OutputDepth, + ReadWrite, + ReadOnly +}; + DOCUMENT("The texture viewer window."); struct ITextureViewer { @@ -262,6 +392,38 @@ struct ITextureViewer :param bool focus: ``True`` if the :class:`TextureViewer` should be raised. )"); virtual void ViewTexture(ResourceId resourceId, CompType typeCast, bool focus) = 0; + + DOCUMENT(R"(Select the 'following' view and choose which resource slot to follow. + +:param FollowType followType: The type of followed resource. +:param ShaderStage stage: The shader stage of the shader reflection data to look up. +:param int index: The index within the given resource list (if applicable) to follow. +:param int arrayElement: The index within the given resource array (if applicable) to follow. +)"); + virtual void ViewFollowedResource(FollowType followType, ShaderStage stage, int32_t index, + int32_t arrayElement) = 0; + + DOCUMENT(R"(Return which resource is currently being displayed in the active tab. + +:return: The ID of the resource being displayed. +:rtype: ~renderdoc.ResourceId +)"); + virtual ResourceId GetCurrentResource() = 0; + + DOCUMENT(R"(Return which subresource is currently selected for viewing. + +:return: The subresource currently selected. +:rtype: ~renderdoc.Subresource +)"); + virtual Subresource GetSelectedSubresource() = 0; + + DOCUMENT(R"(Select a particular subresource within the currently selected texture. Any out of +bounds parameters will be clamped to the available subresources. + +:param Subresource sub: The subresource to select. +)"); + virtual void SetSelectedSubresource(Subresource sub) = 0; + DOCUMENT(R"(Highlights the given pixel location in the current texture. :param int x: The X co-ordinate. @@ -269,6 +431,76 @@ struct ITextureViewer )"); virtual void GotoLocation(int x, int y) = 0; + DOCUMENT(R"(Return the currently selected texture overlay. + +:return: The currently selected texture overlay. +:rtype: ~renderdoc.DebugOverlay +)"); + virtual DebugOverlay GetTextureOverlay() = 0; + + DOCUMENT(R"(Changes the currently selected overlay the given pixel location in the current texture. + +:param ~renderdoc.DebugOverlay overlay: The overlay to enable. +:param int y: The Y co-ordinate. +)"); + virtual void SetTextureOverlay(DebugOverlay overlay) = 0; + + DOCUMENT(R"(Return whether or not the texture viewer is currently auto-fitting the zoom level. + +:return: ``True`` if the zoom level is currently auto-fitting. +:rtype: ``bool`` +)"); + virtual bool IsZoomAutoFit() = 0; + + DOCUMENT(R"(Return the current zoom level, whether manually set or auto-calculated. + +:return: The current zoom level, with 100% being represented as 1.0. +:rtype: ``float`` +)"); + virtual float GetZoomLevel() = 0; + + DOCUMENT(R"(Set the zoom level for displaying textures. + +:param bool autofit: ``True`` if the zoom level should be auto-calculated continuously to + automatically fit the texture completely in view. +:param float zoom: The zoom level as a percentage, with 100% being 1.0. Ignored if :param:`autofit` + is ``True``. +)"); + virtual void SetZoomLevel(bool autofit, float zoom) = 0; + + DOCUMENT(R"(Return the current histogram blackpoint to whitepoint range. + +:return: The current histogram range. +:rtype: ``tuple`` of two ``float`` +)"); + virtual rdcpair GetHistogramRange() = 0; + + DOCUMENT(R"(Set the current histogram blackpoint to whitepoint range. + +:param float blackpoint: The value that should be mapped to black, component-wise. +:param float whitepoint: The value that should be mapped to white, component-wise. +)"); + virtual void SetHistogramRange(float blackpoint, float whitepoint) = 0; + + DOCUMENT(R"(Return which channels are currently displayed, as a bitmask. + +If red is visible ``0x1`` will be set in the returned value, if blue is visible ``0x2`` will be set, +etc. + +:return: The current bitmask showing channel visibility. +:rtype: ``int`` +)"); + virtual uint32_t GetChannelVisibilityBits() = 0; + + DOCUMENT(R"(Set the visibility of each channel. + +:param bool red: Whether the red channel should be visible. +:param bool green: Whether the green channel should be visible. +:param bool blue: Whether the blue channel should be visible. +:param bool alpha: Whether the alpha channel should be visible. +)"); + virtual void SetChannelVisibility(bool red, bool green, bool blue, bool alpha) = 0; + protected: ITextureViewer() = default; ~ITextureViewer() = default; @@ -298,22 +530,19 @@ struct IBufferViewer )"); virtual void ScrollToColumn(int column, MeshDataStage stage = MeshDataStage::VSIn) = 0; - DOCUMENT(R"(In a raw buffer viewer, load the contents from a particular buffer resource. + DOCUMENT(R"(For a mesh view, set the current instance. This is ignored when called on a raw buffer +view. -:param int byteOffset: The offset in bytes to the start of the data. -:param int byteSize: The number of bytes to read out. -:param ~renderdoc.ResourceId id: The ID of the buffer itself. -:param str format: Optionally a HLSL/GLSL style formatting string. +:param int instance: The instance to select, will be clamped to the range [0, numInstances-1] )"); - virtual void ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, - const rdcstr &format = "") = 0; - DOCUMENT(R"(In a raw buffer viewer, load the contents from a particular texture resource. + virtual void SetCurrentInstance(int instance) = 0; -:param ~renderdoc.ResourceId id: The ID of the texture itself. -:param Subresource sub: The subresource within this texture to use. -:param str format: Optionally a HLSL/GLSL style formatting string. + DOCUMENT(R"(For a mesh view, set the current multiview view. This is ignored when called on a raw +buffer view. + +:param int view: The view to select, will be clamped to the range [0, numViews-1] )"); - virtual void ViewTexture(ResourceId id, const Subresource &sub, const rdcstr &format = "") = 0; + virtual void SetCurrentView(int view) = 0; protected: IBufferViewer() = default; @@ -344,6 +573,12 @@ struct IResourceInspector )"); virtual ResourceId CurrentResource() = 0; + DOCUMENT(R"(Expand the resource initialisation chunks to reveal and select a given parameter. + +:param SDObject param: The parameter to reveal and select. +)"); + virtual void RevealParameter(SDObject *param) = 0; + protected: IResourceInspector() = default; ~IResourceInspector() = default; diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index 9ffa9a970..faecf2041 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -2746,6 +2746,11 @@ void UpdateVisibleColumns(rdcstr windowTitle, int columnCount, QHeaderView *head } } +const rdcarray &StructuredDataItemModel::objects() const +{ + return m_Objects; +} + void StructuredDataItemModel::setObjects(const rdcarray &objs) { emit beginResetModel(); diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index f54789f0d..e7850a9f8 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -593,6 +593,7 @@ public: m_ColumnValues = values; } + const rdcarray &objects() const; void setObjects(const rdcarray &objs); StructuredDataItemModel(QWidget *parent) : QAbstractItemModel(parent) {} QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; diff --git a/qrenderdoc/Windows/APIInspector.cpp b/qrenderdoc/Windows/APIInspector.cpp index 73c78e70f..bf932993c 100644 --- a/qrenderdoc/Windows/APIInspector.cpp +++ b/qrenderdoc/Windows/APIInspector.cpp @@ -56,6 +56,62 @@ APIInspector::~APIInspector() delete ui; } +void APIInspector::RevealParameter(SDObject *param) +{ + if(!param) + return; + + rdcarray hierarchy; + while(param) + { + hierarchy.push_back(param); + param = param->GetParent(); + } + + if(hierarchy.back()->type.basetype == SDBasic::Chunk) + { + SDChunk *chunk = (SDChunk *)hierarchy.back(); + hierarchy.pop_back(); + + int rootIdx = m_Chunks.indexOf(chunk); + + SDObject *current = chunk; + + if(rootIdx >= 0) + { + RDTreeWidgetItem *parent = ui->apiEvents->topLevelItem(rootIdx); + + while(parent) + { + ui->apiEvents->expandItem(parent); + + SDObject *next = hierarchy.back(); + hierarchy.pop_back(); + + RDTreeWidgetItem *item = NULL; + + for(size_t i = 0; i < current->NumChildren(); i++) + { + if(current->GetChild(i) == next) + { + current = next; + item = parent->child((int)i); + break; + } + } + + parent = item; + + if(hierarchy.empty()) + break; + } + + ui->apiEvents->setSelectedItem(parent); + ui->apiEvents->scrollToItem(parent); + } + } +} + void APIInspector::OnCaptureLoaded() { OnSelectedEventChanged(m_Ctx.CurSelectedEvent()); @@ -63,6 +119,7 @@ void APIInspector::OnCaptureLoaded() void APIInspector::OnCaptureClosed() { + m_Chunks.clear(); ui->apiEvents->clear(); ui->callstack->clear(); ui->apiEvents->clearInternalExpansions(); @@ -139,6 +196,8 @@ void APIInspector::fillAPIView() ui->apiEvents->setUpdatesEnabled(false); ui->apiEvents->clear(); + m_Chunks.clear(); + const SDFile &file = m_Ctx.GetStructuredFile(); const DrawcallDescription *draw = m_Ctx.CurSelectedDrawcall(); @@ -152,6 +211,8 @@ void APIInspector::fillAPIView() { SDChunk *chunk = file.chunks[ev.chunkIndex]; + m_Chunks.push_back(chunk); + root->setText(1, chunk->name); addStructuredChildren(root, *chunk); diff --git a/qrenderdoc/Windows/APIInspector.h b/qrenderdoc/Windows/APIInspector.h index a2f5578fa..f2a8309b7 100644 --- a/qrenderdoc/Windows/APIInspector.h +++ b/qrenderdoc/Windows/APIInspector.h @@ -45,6 +45,8 @@ public: // IAPIInspector QWidget *Widget() override { return this; } void Refresh() override { on_apiEvents_itemSelectionChanged(); } + void RevealParameter(SDObject *param) override; + // ICaptureViewer void OnCaptureLoaded() override; void OnCaptureClosed() override; @@ -59,6 +61,8 @@ private: uint32_t m_EventID = 0; + rdcarray m_Chunks; + void addCallstack(rdcarray calls); void fillAPIView(); }; diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index ed0c46d63..4fdba97ad 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -3378,6 +3378,18 @@ void BufferViewer::ScrollToColumn(RDTableView *view, int column) view->verticalScrollBar()->setValue(vs); } +void BufferViewer::SetCurrentInstance(int instance) +{ + if(ui->instance->isVisible() && ui->instance->isEnabled()) + ui->instance->setValue(instance); +} + +void BufferViewer::SetCurrentView(int view) +{ + if(ui->viewIndex->isVisible() && ui->viewIndex->isEnabled()) + ui->viewIndex->setValue(view); +} + void BufferViewer::ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, const rdcstr &format) { diff --git a/qrenderdoc/Windows/BufferViewer.h b/qrenderdoc/Windows/BufferViewer.h index e466bc433..ad289191b 100644 --- a/qrenderdoc/Windows/BufferViewer.h +++ b/qrenderdoc/Windows/BufferViewer.h @@ -79,13 +79,15 @@ public: explicit BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent = 0); ~BufferViewer(); + void ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, const rdcstr &format = ""); + void ViewTexture(ResourceId id, const Subresource &sub, const rdcstr &format = ""); + // IBufferViewer QWidget *Widget() override { return this; } void ScrollToRow(int row, MeshDataStage stage = MeshDataStage::VSIn) override; void ScrollToColumn(int column, MeshDataStage stage = MeshDataStage::VSIn) override; - void ViewBuffer(uint64_t byteOffset, uint64_t byteSize, ResourceId id, - const rdcstr &format = "") override; - void ViewTexture(ResourceId id, const Subresource &sub, const rdcstr &format = "") override; + void SetCurrentInstance(int instance) override; + void SetCurrentView(int view) override; // ICaptureViewer void OnCaptureLoaded() override; diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index 020460a90..b92848ebb 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -467,6 +467,11 @@ void D3D11PipelineStateViewer::OnEventChanged(uint32_t eventId) setState(); } +void D3D11PipelineStateViewer::SelectPipelineStage(PipelineStage stage) +{ + ui->pipeFlow->setSelectedStage((int)stage); +} + void D3D11PipelineStateViewer::on_showUnused_toggled(bool checked) { setState(); diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h index ebdbff66a..f9f9d8d0b 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.h @@ -54,6 +54,8 @@ public: void OnSelectedEventChanged(uint32_t eventId) override {} void OnEventChanged(uint32_t eventId) override; + void SelectPipelineStage(PipelineStage stage); + private slots: // automatic slots void on_showUnused_toggled(bool checked); diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp index cc55bf31d..a31cf624c 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp @@ -493,6 +493,11 @@ void D3D12PipelineStateViewer::OnEventChanged(uint32_t eventId) setState(); } +void D3D12PipelineStateViewer::SelectPipelineStage(PipelineStage stage) +{ + ui->pipeFlow->setSelectedStage((int)stage); +} + void D3D12PipelineStateViewer::on_showUnused_toggled(bool checked) { setState(); diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h index e1c143033..3afda1f5e 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.h @@ -55,6 +55,8 @@ public: void OnSelectedEventChanged(uint32_t eventId) override {} void OnEventChanged(uint32_t eventId) override; + void SelectPipelineStage(PipelineStage stage); + private slots: // automatic slots void on_showUnused_toggled(bool checked); diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp index bc718a63c..26cdc6f0a 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp @@ -450,6 +450,11 @@ void GLPipelineStateViewer::OnEventChanged(uint32_t eventId) setState(); } +void GLPipelineStateViewer::SelectPipelineStage(PipelineStage stage) +{ + ui->pipeFlow->setSelectedStage((int)stage); +} + void GLPipelineStateViewer::on_showUnused_toggled(bool checked) { setState(); diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h index f871e1680..69647ea53 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.h @@ -54,6 +54,8 @@ public: void OnSelectedEventChanged(uint32_t eventId) override {} void OnEventChanged(uint32_t eventId) override; + void SelectPipelineStage(PipelineStage stage); + private slots: // automatic slots void on_showUnused_toggled(bool checked); diff --git a/qrenderdoc/Windows/PipelineState/PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/PipelineStateViewer.cpp index 34b0195c0..132691993 100644 --- a/qrenderdoc/Windows/PipelineState/PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/PipelineStateViewer.cpp @@ -1195,3 +1195,15 @@ bool PipelineStateViewer::SaveShaderFile(const ShaderReflection *shader) return true; } + +void PipelineStateViewer::SelectPipelineStage(PipelineStage stage) +{ + if(m_D3D11) + m_D3D11->SelectPipelineStage(stage); + else if(m_D3D12) + m_D3D12->SelectPipelineStage(stage); + else if(m_GL) + m_GL->SelectPipelineStage(stage); + else if(m_Vulkan) + m_Vulkan->SelectPipelineStage(stage); +} diff --git a/qrenderdoc/Windows/PipelineState/PipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/PipelineStateViewer.h index 541300c60..7868636e6 100644 --- a/qrenderdoc/Windows/PipelineState/PipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/PipelineStateViewer.h @@ -58,6 +58,7 @@ public: // IPipelineStateViewer QWidget *Widget() override { return this; } bool SaveShaderFile(const ShaderReflection *shader) override; + void SelectPipelineStage(PipelineStage stage) override; // ICaptureViewer void OnCaptureLoaded() override; diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index f6b9fbe3b..ed277e01e 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -463,6 +463,11 @@ void VulkanPipelineStateViewer::OnEventChanged(uint32_t eventId) setState(); } +void VulkanPipelineStateViewer::SelectPipelineStage(PipelineStage stage) +{ + ui->pipeFlow->setSelectedStage((int)stage); +} + void VulkanPipelineStateViewer::on_showUnused_toggled(bool checked) { setState(); diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h index 68ffcfa76..5ecd4ce2c 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h @@ -60,6 +60,8 @@ public: void OnSelectedEventChanged(uint32_t eventId) {} void OnEventChanged(uint32_t eventId); + void SelectPipelineStage(PipelineStage stage); + private slots: // automatic slots void on_showUnused_toggled(bool checked); diff --git a/qrenderdoc/Windows/ResourceInspector.cpp b/qrenderdoc/Windows/ResourceInspector.cpp index bea1f3d93..d8e580ea9 100644 --- a/qrenderdoc/Windows/ResourceInspector.cpp +++ b/qrenderdoc/Windows/ResourceInspector.cpp @@ -336,6 +336,58 @@ void ResourceInspector::Inspect(ResourceId id) 0); } +void ResourceInspector::RevealParameter(SDObject *param) +{ + if(!param) + return; + + rdcarray hierarchy; + while(param) + { + hierarchy.push_back(param); + param = param->GetParent(); + } + + SDObject *current = hierarchy.back(); + hierarchy.pop_back(); + + int rootIdx = m_ChunksModel->objects().indexOf(current); + + if(rootIdx >= 0) + { + QModelIndex parent = m_ChunksModel->index(rootIdx, 0); + + while(parent.isValid()) + { + ui->initChunks->expand(parent); + + SDObject *next = hierarchy.back(); + hierarchy.pop_back(); + + QModelIndex item; + + for(size_t i = 0; i < current->NumChildren(); i++) + { + if(current->GetChild(i) == next) + { + current = next; + item = parent.child((int)i, 0); + break; + } + } + + parent = item; + + if(hierarchy.empty()) + break; + } + + ui->initChunks->selectionModel()->select( + parent, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + ui->initChunks->scrollTo(parent); + } +} + void ResourceInspector::OnCaptureLoaded() { ui->renameResource->setEnabled(true); diff --git a/qrenderdoc/Windows/ResourceInspector.h b/qrenderdoc/Windows/ResourceInspector.h index 753877caa..ee57438f2 100644 --- a/qrenderdoc/Windows/ResourceInspector.h +++ b/qrenderdoc/Windows/ResourceInspector.h @@ -51,6 +51,7 @@ public: QWidget *Widget() override { return this; } void Inspect(ResourceId id) override; ResourceId CurrentResource() override { return m_Resource; } + void RevealParameter(SDObject *param) override; // ICaptureViewer void OnCaptureLoaded() override; void OnCaptureClosed() override; diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 4ddb6b806..ded4a3230 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -107,7 +107,7 @@ bool Following::operator!=(const Following &o) bool Following::operator==(const Following &o) { - return Type == o.Type && Stage == o.Stage && index == o.index; + return Type == o.Type && Stage == o.Stage && index == o.index && arrayEl == o.arrayEl; } void Following::GetDrawContext(ICaptureContext &ctx, bool ©, bool &clear, bool &compute) @@ -144,7 +144,7 @@ BoundResource Following::GetBoundResource(ICaptureContext &ctx, int arrayIdx) { BoundResource ret; - if(Type == FollowType::OutputColour) + if(Type == FollowType::OutputColor) { rdcarray outputs = GetOutputTargets(ctx); @@ -446,7 +446,7 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent) : QFrame(parent), ui(new Ui::TextureViewer), m_Ctx(ctx), - m_Following(*this, FollowType::OutputColour, ShaderStage::Pixel, 0, 0) + m_Following(*this, FollowType::OutputColor, ShaderStage::Pixel, 0, 0) { ui->setupUi(this); @@ -688,6 +688,30 @@ void TextureViewer::HighlightUsage() m_Ctx.GetTimelineBar()->HighlightResourceUsage(texptr->resourceId); } +void TextureViewer::SelectPreview(ResourcePreview *prev) +{ + Following follow = prev->property("f").value(); + + for(ResourcePreview *p : ui->outputThumbs->thumbs()) + p->setSelected(false); + + for(ResourcePreview *p : ui->inputThumbs->thumbs()) + p->setSelected(false); + + m_Following = Following(follow); + prev->setSelected(true); + + UI_UpdateCachedTexture(); + + ResourceId id = m_Following.GetResourceId(m_Ctx); + + if(id != ResourceId()) + { + UI_OnTextureSelectionChanged(false); + ui->renderContainer->show(); + } +} + void TextureViewer::RT_FetchCurrentPixel(IReplayController *r, uint32_t x, uint32_t y, PixelValue &pickValue, PixelValue &realValue) { @@ -1126,7 +1150,7 @@ void TextureViewer::UI_UpdateTextureDetails() switch(m_Following.Type) { - case FollowType::OutputColour: + case FollowType::OutputColor: title = QString(tr("Cur Output %1 - %2")).arg(m_Following.index).arg(name); break; case FollowType::OutputDepth: title = QString(tr("Cur Depth Output - %1")).arg(name); break; @@ -1142,7 +1166,7 @@ void TextureViewer::UI_UpdateTextureDetails() { switch(m_Following.Type) { - case FollowType::OutputColour: + case FollowType::OutputColor: title = QString(tr("Cur Output %1")).arg(m_Following.index); break; case FollowType::OutputDepth: title = QString(tr("Cur Depth Output")); break; @@ -1967,40 +1991,6 @@ void TextureViewer::UI_CreateThumbnails() UI_CreateThumbnail(ui->inputThumbs); } -void TextureViewer::GotoLocation(int x, int y) -{ - if(!m_Ctx.IsCaptureLoaded()) - return; - - TextureDescription *tex = GetCurrentTexture(); - - if(tex == NULL) - return; - - x = qMin(x << m_TexDisplay.subresource.mip, int(tex->width - 1)); - y = qMin(y << m_TexDisplay.subresource.mip, int(tex->height - 1)); - - m_PickedPoint = QPoint(x, y); - - if(m_Ctx.APIProps().pipelineType == GraphicsAPI::OpenGL) - m_PickedPoint.setY((int)(tex->height - 1) - m_PickedPoint.y()); - if(m_TexDisplay.flipY) - m_PickedPoint.setY((int)(tex->height - 1) - m_PickedPoint.x()); - - // centre the picked point. - QPoint scrollPos; - scrollPos.setX(-m_PickedPoint.x() * m_TexDisplay.scale + realRenderWidth() / 2); - scrollPos.setY(-m_PickedPoint.y() * m_TexDisplay.scale + realRenderHeight() / 2); - - setScrollPosition(scrollPos); - - if(m_Output != NULL) - INVOKE_MEMFN(RT_PickPixelsAndUpdate); - INVOKE_MEMFN(RT_UpdateAndDisplay); - - UI_UpdateStatusText(); -} - void TextureViewer::ViewTexture(ResourceId ID, CompType typeCast, bool focus) { if(QThread::currentThread() != QCoreApplication::instance()->thread()) @@ -2074,6 +2064,179 @@ void TextureViewer::ViewTexture(ResourceId ID, CompType typeCast, bool focus) } } +void TextureViewer::ViewFollowedResource(FollowType followType, ShaderStage stage, int32_t index, + int32_t arrayElement) +{ + Following f; + f.Type = followType; + f.Stage = stage; + f.index = index; + f.arrayEl = arrayElement; + + if(f.Type == FollowType::OutputColor || f.Type == FollowType::OutputDepth) + { + f.Stage = ShaderStage::Pixel; + f.arrayEl = 0; + } + + if(f.Type == FollowType::OutputDepth) + f.index = 0; + + for(ResourcePreview *p : + (f.Type == FollowType::ReadOnly ? ui->inputThumbs->thumbs() : ui->outputThumbs->thumbs())) + { + Following follow = p->property("f").value(); + + if(follow == f) + { + SelectPreview(p); + + ToolWindowManagerArea *textureTabs = ui->dockarea->areaOf(ui->renderContainer); + + // following tab is always tab 0. + textureTabs->setCurrentIndex(0); + + return; + } + } + + qWarning() << "Couldn't find matching bound resource"; +} + +ResourceId TextureViewer::GetCurrentResource() +{ + TextureDescription *tex = GetCurrentTexture(); + if(tex) + return tex->resourceId; + return ResourceId(); +} + +Subresource TextureViewer::GetSelectedSubresource() +{ + return m_TexDisplay.subresource; +} + +void TextureViewer::SetSelectedSubresource(Subresource sub) +{ + TextureDescription *tex = GetCurrentTexture(); + if(!tex) + return; + + if(tex->mips > 1) + ui->mipLevel->setCurrentIndex(qMin(sub.mip, tex->mips - 1)); + else if(tex->msSamp > 1) + ui->mipLevel->setCurrentIndex(qMin(sub.sample, tex->msSamp - 1)); + + if(tex->depth > 1) + ui->sliceFace->setCurrentIndex(qMin(sub.slice, tex->depth - 1)); + else + ui->sliceFace->setCurrentIndex(qMin(sub.slice, tex->arraysize - 1)); +} + +void TextureViewer::GotoLocation(int x, int y) +{ + if(!m_Ctx.IsCaptureLoaded()) + return; + + TextureDescription *tex = GetCurrentTexture(); + + if(tex == NULL) + return; + + x = qMin(x << m_TexDisplay.subresource.mip, int(tex->width - 1)); + y = qMin(y << m_TexDisplay.subresource.mip, int(tex->height - 1)); + + m_PickedPoint = QPoint(x, y); + + if(m_Ctx.APIProps().pipelineType == GraphicsAPI::OpenGL) + m_PickedPoint.setY((int)(tex->height - 1) - m_PickedPoint.y()); + if(m_TexDisplay.flipY) + m_PickedPoint.setY((int)(tex->height - 1) - m_PickedPoint.x()); + + // centre the picked point. + QPoint scrollPos; + scrollPos.setX(-m_PickedPoint.x() * m_TexDisplay.scale + realRenderWidth() / 2); + scrollPos.setY(-m_PickedPoint.y() * m_TexDisplay.scale + realRenderHeight() / 2); + + setScrollPosition(scrollPos); + + if(m_Output != NULL) + INVOKE_MEMFN(RT_PickPixelsAndUpdate); + INVOKE_MEMFN(RT_UpdateAndDisplay); + + UI_UpdateStatusText(); +} + +DebugOverlay TextureViewer::GetTextureOverlay() +{ + return m_TexDisplay.overlay; +} + +void TextureViewer::SetTextureOverlay(DebugOverlay overlay) +{ + ui->overlay->setCurrentIndex((int)overlay); +} + +bool TextureViewer::IsZoomAutoFit() +{ + return ui->fitToWindow->isChecked(); +} + +float TextureViewer::GetZoomLevel() +{ + if(ui->fitToWindow->isChecked()) + return m_TexDisplay.scale; + + QString zoomText = ui->zoomOption->currentText().replace(QLatin1Char('%'), QLatin1Char(' ')); + + bool ok = false; + int zoom = zoomText.toInt(&ok); + + if(!ok) + zoom = 100; + + return (float)(zoom) / 100.0f; +} + +void TextureViewer::SetZoomLevel(bool autofit, float zoom) +{ + ui->fitToWindow->setChecked(autofit); + if(!autofit) + UI_SetScale(zoom); +} + +rdcpair TextureViewer::GetHistogramRange() +{ + return {m_TexDisplay.rangeMin, m_TexDisplay.rangeMax}; +} + +void TextureViewer::SetHistogramRange(float blackpoint, float whitepoint) +{ + ui->rangeHistogram->setRange(blackpoint, whitepoint); +} + +uint32_t TextureViewer::GetChannelVisibilityBits() +{ + uint32_t ret = 0; + if(m_TexDisplay.red) + ret |= 0x1; + if(m_TexDisplay.green) + ret |= 0x2; + if(m_TexDisplay.blue) + ret |= 0x4; + if(m_TexDisplay.alpha) + ret |= 0x8; + return ret; +} + +void TextureViewer::SetChannelVisibility(bool red, bool green, bool blue, bool alpha) +{ + ui->channelRed->setChecked(red); + ui->channelGreen->setChecked(green); + ui->channelBlue->setChecked(blue); + ui->channelAlpha->setChecked(alpha); +} + void TextureViewer::texContextItem_triggered() { QAction *act = qobject_cast(QObject::sender()); @@ -2401,26 +2564,7 @@ void TextureViewer::thumb_clicked(QMouseEvent *e) { ResourcePreview *prev = qobject_cast(QObject::sender()); - Following follow = prev->property("f").value(); - - for(ResourcePreview *p : ui->outputThumbs->thumbs()) - p->setSelected(false); - - for(ResourcePreview *p : ui->inputThumbs->thumbs()) - p->setSelected(false); - - m_Following = Following(follow); - prev->setSelected(true); - - UI_UpdateCachedTexture(); - - ResourceId id = m_Following.GetResourceId(m_Ctx); - - if(id != ResourceId()) - { - UI_OnTextureSelectionChanged(false); - ui->renderContainer->show(); - } + SelectPreview(prev); } if(e->buttons() & Qt::RightButton) @@ -3001,7 +3145,7 @@ void TextureViewer::OnEventChanged(uint32_t eventId) outIndex++; - Following follow(*this, FollowType::OutputColour, ShaderStage::Pixel, rt, 0); + Following follow(*this, FollowType::OutputColor, ShaderStage::Pixel, rt, 0); QString bindName = (copy || clear) ? tr("Destination") : QString(); QString slotName = (copy || clear) ? tr("DST") @@ -3219,22 +3363,6 @@ void TextureViewer::setCurrentZoomValue(float zoom) ui->zoomOption->setCurrentText(QString::number(ceil(zoom * 100)) + lit("%")); } -float TextureViewer::getCurrentZoomValue() -{ - if(ui->fitToWindow->isChecked()) - return m_TexDisplay.scale; - - QString zoomText = ui->zoomOption->currentText().replace(QLatin1Char('%'), QLatin1Char(' ')); - - bool ok = false; - int zoom = zoomText.toInt(&ok); - - if(!ok) - zoom = 100; - - return (float)(zoom) / 100.0f; -} - void TextureViewer::setFitToWindow(bool checked) { if(checked) @@ -3268,13 +3396,13 @@ void TextureViewer::on_zoomOption_currentIndexChanged(int index) { setFitToWindow(false); ui->zoomOption->setCurrentText(ui->zoomOption->itemText(index)); - UI_SetScale(getCurrentZoomValue()); + UI_SetScale(GetZoomLevel()); } } void TextureViewer::zoomOption_returnPressed() { - UI_SetScale(getCurrentZoomValue()); + UI_SetScale(GetZoomLevel()); } void TextureViewer::on_overlay_currentIndexChanged(int index) diff --git a/qrenderdoc/Windows/TextureViewer.h b/qrenderdoc/Windows/TextureViewer.h index 41c7637bb..4f6f3e2f7 100644 --- a/qrenderdoc/Windows/TextureViewer.h +++ b/qrenderdoc/Windows/TextureViewer.h @@ -43,14 +43,6 @@ class TextureGoto; class QFileSystemWatcher; class TextureViewer; -enum struct FollowType -{ - OutputColour, - OutputDepth, - ReadWrite, - ReadOnly -}; - struct Following { FollowType Type; @@ -145,7 +137,25 @@ public: // ITextureViewer QWidget *Widget() override { return this; } void ViewTexture(ResourceId ID, CompType typeCast, bool focus) override; + void ViewFollowedResource(FollowType followType, ShaderStage stage, int32_t index, + int32_t arrayElement) override; + ResourceId GetCurrentResource() override; + + Subresource GetSelectedSubresource() override; + void SetSelectedSubresource(Subresource sub) override; void GotoLocation(int x, int y) override; + DebugOverlay GetTextureOverlay() override; + void SetTextureOverlay(DebugOverlay overlay) override; + + bool IsZoomAutoFit() override; + float GetZoomLevel() override; + void SetZoomLevel(bool autofit, float zoom) override; + + rdcpair GetHistogramRange() override; + void SetHistogramRange(float blackpoint, float whitepoint) override; + + uint32_t GetChannelVisibilityBits() override; + void SetChannelVisibility(bool red, bool green, bool blue, bool alpha) override; // ICaptureViewer void OnCaptureLoaded() override; @@ -248,6 +258,8 @@ private: void HighlightUsage(); + void SelectPreview(ResourcePreview *prev); + void SetupTextureTabs(); void RemoveTextureTabs(int firstIndex); @@ -278,7 +290,6 @@ private: void setFitToWindow(bool checked); void setCurrentZoomValue(float zoom); - float getCurrentZoomValue(); bool ScrollUpdateScrollbars = true;