mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-28 17:36:36 +00:00
Optimise tree widget clearing and child adding by batching updates
* This takes a nice chunk of time off the pipeline state view in particular when changing between events.
This commit is contained in:
@@ -339,13 +339,13 @@ void RDTreeWidgetItem::addChild(RDTreeWidgetItem *item)
|
||||
item->m_data->resize(qMax(item->m_data->count(), colCount));
|
||||
|
||||
if(m_widget)
|
||||
m_widget->m_model->beginAddChild(this);
|
||||
m_widget->beginAddChild(this);
|
||||
|
||||
// add to our list of children
|
||||
m_children.push_back(item);
|
||||
|
||||
if(m_widget)
|
||||
m_widget->m_model->endAddChild(this);
|
||||
m_widget->endAddChild(this);
|
||||
}
|
||||
|
||||
void RDTreeWidgetItem::setWidget(RDTreeWidget *widget)
|
||||
@@ -367,13 +367,13 @@ void RDTreeWidgetItem::dataChanged(int role)
|
||||
|
||||
RDTreeWidgetItem *RDTreeWidgetItem::takeChild(int index)
|
||||
{
|
||||
if(m_widget)
|
||||
if(m_widget && !m_widget->m_clearing)
|
||||
m_widget->m_model->beginRemoveChildren(this, index, index);
|
||||
|
||||
m_children[index]->m_parent = NULL;
|
||||
RDTreeWidgetItem *ret = m_children.takeAt(index);
|
||||
|
||||
if(m_widget)
|
||||
if(m_widget && !m_widget->m_clearing)
|
||||
m_widget->m_model->endRemoveChildren();
|
||||
|
||||
return ret;
|
||||
@@ -398,7 +398,7 @@ void RDTreeWidgetItem::clear()
|
||||
if(!childCount())
|
||||
return;
|
||||
|
||||
if(m_widget)
|
||||
if(m_widget && !m_widget->m_clearing)
|
||||
m_widget->m_model->beginRemoveChildren(this, 0, childCount() - 1);
|
||||
|
||||
while(childCount() > 0)
|
||||
@@ -408,7 +408,7 @@ void RDTreeWidgetItem::clear()
|
||||
delete child;
|
||||
}
|
||||
|
||||
if(m_widget)
|
||||
if(m_widget && !m_widget->m_clearing)
|
||||
m_widget->m_model->endRemoveChildren();
|
||||
}
|
||||
|
||||
@@ -448,7 +448,10 @@ void RDTreeWidget::beginUpdate()
|
||||
|
||||
m_queuedItem = NULL;
|
||||
m_lowestIndex = m_highestIndex = qMakePair<int, int>(-1, -1);
|
||||
m_queuedChildren = false;
|
||||
m_queuedRoles = 0;
|
||||
|
||||
setUpdatesEnabled(false);
|
||||
}
|
||||
|
||||
void RDTreeWidget::endUpdate()
|
||||
@@ -471,9 +474,19 @@ void RDTreeWidget::endUpdate()
|
||||
if(m_queuedRoles & (1ULL << r))
|
||||
roles.push_back(r);
|
||||
}
|
||||
m_model->itemsChanged(m_queuedItem, m_lowestIndex, m_highestIndex, roles);
|
||||
|
||||
if(m_queuedChildren)
|
||||
{
|
||||
m_model->beginAddChild(m_queuedItem);
|
||||
m_model->endAddChild(m_queuedItem);
|
||||
}
|
||||
|
||||
if(!roles.isEmpty())
|
||||
m_model->itemsChanged(m_queuedItem, m_lowestIndex, m_highestIndex, roles);
|
||||
}
|
||||
}
|
||||
|
||||
setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void RDTreeWidget::setColumns(const QStringList &columns)
|
||||
@@ -558,7 +571,11 @@ void RDTreeWidget::scrollToItem(RDTreeWidgetItem *node)
|
||||
|
||||
void RDTreeWidget::clear()
|
||||
{
|
||||
m_clearing = true;
|
||||
m_root->clear();
|
||||
m_clearing = false;
|
||||
|
||||
m_model->refresh();
|
||||
}
|
||||
|
||||
void RDTreeWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
@@ -821,3 +838,44 @@ void RDTreeWidget::itemDataChanged(RDTreeWidgetItem *item, int role)
|
||||
m_model->itemChanged(item, {role});
|
||||
}
|
||||
}
|
||||
|
||||
void RDTreeWidget::beginAddChild(RDTreeWidgetItem *item)
|
||||
{
|
||||
if(m_queueUpdates)
|
||||
{
|
||||
m_queuedChildren = true;
|
||||
|
||||
if(m_lowestIndex.first == -1)
|
||||
{
|
||||
m_queuedItem = item;
|
||||
// make an update of row 0. This will be a bit pessimistic if there are later data changes
|
||||
// in a later row, but we're generally only changing data *or* adding children, not both, and
|
||||
// in either case this is primarily about batching updates not providing a minimal update set
|
||||
m_lowestIndex = qMakePair<int, int>(0, 0);
|
||||
m_highestIndex = qMakePair<int, int>(0, m_headers.count() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_queuedItem == item)
|
||||
{
|
||||
// there's already an update. don't need to expand it, the m_queuedChildren is enough
|
||||
}
|
||||
else
|
||||
{
|
||||
// can't batch updates across multiple parents, so we just fallback to full model refresh
|
||||
m_queuedItem = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->beginAddChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
void RDTreeWidget::endAddChild(RDTreeWidgetItem *item)
|
||||
{
|
||||
// work is all done in beginAddChild
|
||||
if(!m_queueUpdates)
|
||||
m_model->endAddChild(item);
|
||||
}
|
||||
|
||||
@@ -223,6 +223,8 @@ private:
|
||||
|
||||
void setModel(QAbstractItemModel *model) override {}
|
||||
void itemDataChanged(RDTreeWidgetItem *item, int role);
|
||||
void beginAddChild(RDTreeWidgetItem *item);
|
||||
void endAddChild(RDTreeWidgetItem *item);
|
||||
|
||||
friend class RDTreeWidgetModel;
|
||||
friend class RDTreeWidgetItem;
|
||||
@@ -232,6 +234,8 @@ private:
|
||||
|
||||
RDTreeWidgetModel *m_model;
|
||||
|
||||
bool m_clearing = false;
|
||||
|
||||
QStringList m_headers;
|
||||
|
||||
bool m_queueUpdates = false;
|
||||
@@ -239,7 +243,8 @@ private:
|
||||
RDTreeWidgetItem *m_queuedItem;
|
||||
QPair<int, int> m_lowestIndex;
|
||||
QPair<int, int> m_highestIndex;
|
||||
uint64_t m_queuedRoles;
|
||||
uint64_t m_queuedRoles = 0;
|
||||
bool m_queuedChildren = false;
|
||||
|
||||
bool m_instantTooltips = false;
|
||||
bool m_customCopyPaste = false;
|
||||
|
||||
@@ -295,7 +295,7 @@ bool ConstantBufferPreviewer::updateVariables(RDTreeWidgetItem *root,
|
||||
|
||||
void ConstantBufferPreviewer::setVariables(const rdctype::array<ShaderVariable> &vars)
|
||||
{
|
||||
ui->variables->setUpdatesEnabled(false);
|
||||
ui->variables->beginUpdate();
|
||||
|
||||
// try to update the variables in-place by only changing their values, if the set of variables
|
||||
// matches *exactly* to what we had before.
|
||||
@@ -308,7 +308,7 @@ void ConstantBufferPreviewer::setVariables(const rdctype::array<ShaderVariable>
|
||||
|
||||
if(updated)
|
||||
{
|
||||
ui->variables->setUpdatesEnabled(true);
|
||||
ui->variables->endUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ void ConstantBufferPreviewer::setVariables(const rdctype::array<ShaderVariable>
|
||||
ui->saveCSV->setEnabled(true);
|
||||
}
|
||||
|
||||
ui->variables->setUpdatesEnabled(true);
|
||||
ui->variables->endUpdate();
|
||||
}
|
||||
|
||||
void ConstantBufferPreviewer::updateLabels()
|
||||
|
||||
@@ -861,7 +861,7 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
int vs = 0;
|
||||
|
||||
vs = resources->verticalScrollBar()->value();
|
||||
resources->setUpdatesEnabled(false);
|
||||
resources->beginUpdate();
|
||||
resources->clear();
|
||||
for(int i = 0; i < stage.SRVs.count; i++)
|
||||
{
|
||||
@@ -882,11 +882,11 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
addResourceRow(D3D11ViewTag(D3D11ViewTag::SRV, i, stage.SRVs[i]), shaderInput, resources);
|
||||
}
|
||||
resources->clearSelection();
|
||||
resources->setUpdatesEnabled(true);
|
||||
resources->endUpdate();
|
||||
resources->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = samplers->verticalScrollBar()->value();
|
||||
samplers->setUpdatesEnabled(false);
|
||||
samplers->beginUpdate();
|
||||
samplers->clear();
|
||||
for(int i = 0; i < stage.Samplers.count; i++)
|
||||
{
|
||||
@@ -984,11 +984,11 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
}
|
||||
|
||||
samplers->clearSelection();
|
||||
samplers->setUpdatesEnabled(true);
|
||||
samplers->endUpdate();
|
||||
samplers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = cbuffers->verticalScrollBar()->value();
|
||||
cbuffers->setUpdatesEnabled(false);
|
||||
cbuffers->beginUpdate();
|
||||
cbuffers->clear();
|
||||
for(int i = 0; i < stage.ConstantBuffers.count; i++)
|
||||
{
|
||||
@@ -1068,11 +1068,11 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
}
|
||||
}
|
||||
cbuffers->clearSelection();
|
||||
cbuffers->setUpdatesEnabled(true);
|
||||
cbuffers->endUpdate();
|
||||
cbuffers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = classes->verticalScrollBar()->value();
|
||||
classes->setUpdatesEnabled(false);
|
||||
classes->beginUpdate();
|
||||
classes->clear();
|
||||
for(int i = 0; i < stage.ClassInstances.count; i++)
|
||||
{
|
||||
@@ -1084,7 +1084,7 @@ void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, QL
|
||||
classes->addTopLevelItem(new RDTreeWidgetItem({i, interfaceName, stage.ClassInstances[i]}));
|
||||
}
|
||||
classes->clearSelection();
|
||||
classes->setUpdatesEnabled(true);
|
||||
classes->endUpdate();
|
||||
classes->verticalScrollBar()->setValue(vs);
|
||||
|
||||
classes->parentWidget()->setVisible(!stage.ClassInstances.empty());
|
||||
@@ -1208,7 +1208,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
uint32_t layoutOffs[128] = {};
|
||||
|
||||
vs = ui->iaLayouts->verticalScrollBar()->value();
|
||||
ui->iaLayouts->setUpdatesEnabled(false);
|
||||
ui->iaLayouts->beginUpdate();
|
||||
ui->iaLayouts->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1262,7 +1262,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->iaLayouts->clearSelection();
|
||||
ui->iaLayouts->setUpdatesEnabled(true);
|
||||
ui->iaLayouts->endUpdate();
|
||||
ui->iaLayouts->verticalScrollBar()->setValue(vs);
|
||||
|
||||
Topology topo = draw ? draw->topology : Topology::Unknown;
|
||||
@@ -1282,7 +1282,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
bool ibufferUsed = draw && (draw->flags & DrawFlags::UseIBuffer);
|
||||
|
||||
vs = ui->iaBuffers->verticalScrollBar()->value();
|
||||
ui->iaBuffers->setUpdatesEnabled(false);
|
||||
ui->iaBuffers->beginUpdate();
|
||||
ui->iaBuffers->clear();
|
||||
|
||||
if(state.m_IA.ibuffer.Buffer != ResourceId())
|
||||
@@ -1387,7 +1387,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->iaBuffers->clearSelection();
|
||||
ui->iaBuffers->setUpdatesEnabled(true);
|
||||
ui->iaBuffers->endUpdate();
|
||||
ui->iaBuffers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
setShaderState(state.m_VS, ui->vsShader, ui->vsResources, ui->vsSamplers, ui->vsCBuffers,
|
||||
@@ -1404,7 +1404,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
ui->csClasses);
|
||||
|
||||
vs = ui->csUAVs->verticalScrollBar()->value();
|
||||
ui->csUAVs->setUpdatesEnabled(false);
|
||||
ui->csUAVs->beginUpdate();
|
||||
ui->csUAVs->clear();
|
||||
for(int i = 0; i < state.m_CS.UAVs.count; i++)
|
||||
{
|
||||
@@ -1425,12 +1425,12 @@ void D3D11PipelineStateViewer::setState()
|
||||
addResourceRow(D3D11ViewTag(D3D11ViewTag::UAV, i, state.m_CS.UAVs[i]), shaderInput, ui->csUAVs);
|
||||
}
|
||||
ui->csUAVs->clearSelection();
|
||||
ui->csUAVs->setUpdatesEnabled(true);
|
||||
ui->csUAVs->endUpdate();
|
||||
ui->csUAVs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
bool streamoutSet = false;
|
||||
vs = ui->gsStreamOut->verticalScrollBar()->value();
|
||||
ui->gsStreamOut->setUpdatesEnabled(false);
|
||||
ui->gsStreamOut->beginUpdate();
|
||||
ui->gsStreamOut->clear();
|
||||
for(int i = 0; i < state.m_SO.Outputs.count; i++)
|
||||
{
|
||||
@@ -1473,7 +1473,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
ui->gsStreamOut->verticalScrollBar()->setValue(vs);
|
||||
ui->gsStreamOut->clearSelection();
|
||||
ui->gsStreamOut->setUpdatesEnabled(true);
|
||||
ui->gsStreamOut->endUpdate();
|
||||
|
||||
ui->gsStreamOut->setVisible(streamoutSet);
|
||||
ui->soGroup->setVisible(streamoutSet);
|
||||
@@ -1482,7 +1482,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
// Rasterizer
|
||||
|
||||
vs = ui->viewports->verticalScrollBar()->value();
|
||||
ui->viewports->setUpdatesEnabled(false);
|
||||
ui->viewports->beginUpdate();
|
||||
ui->viewports->clear();
|
||||
for(int i = 0; i < state.m_RS.Viewports.count; i++)
|
||||
{
|
||||
@@ -1504,10 +1504,10 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
ui->viewports->verticalScrollBar()->setValue(vs);
|
||||
ui->viewports->clearSelection();
|
||||
ui->viewports->setUpdatesEnabled(true);
|
||||
ui->viewports->endUpdate();
|
||||
|
||||
vs = ui->scissors->verticalScrollBar()->value();
|
||||
ui->scissors->setUpdatesEnabled(false);
|
||||
ui->scissors->beginUpdate();
|
||||
ui->scissors->clear();
|
||||
for(int i = 0; i < state.m_RS.Scissors.count; i++)
|
||||
{
|
||||
@@ -1529,7 +1529,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
ui->scissors->clearSelection();
|
||||
ui->scissors->verticalScrollBar()->setValue(vs);
|
||||
ui->scissors->setUpdatesEnabled(true);
|
||||
ui->scissors->endUpdate();
|
||||
|
||||
ui->fillMode->setText(ToQStr(state.m_RS.m_State.fillMode));
|
||||
ui->cullMode->setText(ToQStr(state.m_RS.m_State.cullMode));
|
||||
@@ -1552,7 +1552,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
bool targets[32] = {};
|
||||
|
||||
vs = ui->targetOutputs->verticalScrollBar()->value();
|
||||
ui->targetOutputs->setUpdatesEnabled(false);
|
||||
ui->targetOutputs->beginUpdate();
|
||||
ui->targetOutputs->clear();
|
||||
{
|
||||
for(int i = 0; i < state.m_OM.RenderTargets.count; i++)
|
||||
@@ -1597,11 +1597,11 @@ void D3D11PipelineStateViewer::setState()
|
||||
ui->targetOutputs);
|
||||
}
|
||||
ui->targetOutputs->clearSelection();
|
||||
ui->targetOutputs->setUpdatesEnabled(true);
|
||||
ui->targetOutputs->endUpdate();
|
||||
ui->targetOutputs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ui->blends->verticalScrollBar()->value();
|
||||
ui->blends->setUpdatesEnabled(false);
|
||||
ui->blends->beginUpdate();
|
||||
ui->blends->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1645,7 +1645,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->blends->clearSelection();
|
||||
ui->blends->setUpdatesEnabled(true);
|
||||
ui->blends->endUpdate();
|
||||
ui->blends->verticalScrollBar()->setValue(vs);
|
||||
|
||||
ui->alphaToCoverage->setPixmap(state.m_OM.m_BlendState.AlphaToCoverage ? tick : cross);
|
||||
@@ -1667,7 +1667,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
ui->stencilWriteMask->setText(Formatter::Format(state.m_OM.m_State.StencilWriteMask, true));
|
||||
ui->stencilRef->setText(Formatter::Format(state.m_OM.m_State.StencilRef, true));
|
||||
|
||||
ui->stencils->setUpdatesEnabled(false);
|
||||
ui->stencils->beginUpdate();
|
||||
ui->stencils->clear();
|
||||
ui->stencils->addTopLevelItem(
|
||||
new RDTreeWidgetItem({tr("Front"), ToQStr(state.m_OM.m_State.m_FrontFace.Func),
|
||||
@@ -1679,7 +1679,7 @@ void D3D11PipelineStateViewer::setState()
|
||||
ToQStr(state.m_OM.m_State.m_BackFace.FailOp), ToQStr(state.m_OM.m_State.m_BackFace.DepthFailOp),
|
||||
ToQStr(state.m_OM.m_State.m_BackFace.PassOp)}));
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->setUpdatesEnabled(true);
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// set up thread debugging inputs
|
||||
if(state.m_CS.ShaderDetails && draw && (draw->flags & DrawFlags::Dispatch))
|
||||
|
||||
@@ -932,7 +932,7 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
int vs = 0;
|
||||
|
||||
vs = resources->verticalScrollBar()->value();
|
||||
resources->setUpdatesEnabled(false);
|
||||
resources->beginUpdate();
|
||||
resources->clear();
|
||||
for(int space = 0; space < stage.Spaces.count; space++)
|
||||
{
|
||||
@@ -943,11 +943,11 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
}
|
||||
}
|
||||
resources->clearSelection();
|
||||
resources->setUpdatesEnabled(true);
|
||||
resources->endUpdate();
|
||||
resources->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = uavs->verticalScrollBar()->value();
|
||||
uavs->setUpdatesEnabled(false);
|
||||
uavs->beginUpdate();
|
||||
uavs->clear();
|
||||
for(int space = 0; space < stage.Spaces.count; space++)
|
||||
{
|
||||
@@ -958,11 +958,11 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
}
|
||||
}
|
||||
uavs->clearSelection();
|
||||
uavs->setUpdatesEnabled(true);
|
||||
uavs->endUpdate();
|
||||
uavs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = samplers->verticalScrollBar()->value();
|
||||
samplers->setUpdatesEnabled(false);
|
||||
samplers->beginUpdate();
|
||||
samplers->clear();
|
||||
for(int space = 0; space < stage.Spaces.count; space++)
|
||||
{
|
||||
@@ -1079,11 +1079,11 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
}
|
||||
}
|
||||
samplers->clearSelection();
|
||||
samplers->setUpdatesEnabled(true);
|
||||
samplers->endUpdate();
|
||||
samplers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = cbuffers->verticalScrollBar()->value();
|
||||
cbuffers->setUpdatesEnabled(false);
|
||||
cbuffers->beginUpdate();
|
||||
cbuffers->clear();
|
||||
for(int space = 0; space < stage.Spaces.count; space++)
|
||||
{
|
||||
@@ -1193,7 +1193,7 @@ void D3D12PipelineStateViewer::setShaderState(const D3D12Pipe::Shader &stage, QL
|
||||
}
|
||||
}
|
||||
cbuffers->clearSelection();
|
||||
cbuffers->setUpdatesEnabled(true);
|
||||
cbuffers->endUpdate();
|
||||
cbuffers->verticalScrollBar()->setValue(vs);
|
||||
}
|
||||
|
||||
@@ -1220,7 +1220,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
uint32_t layoutOffs[128] = {};
|
||||
|
||||
vs = ui->iaLayouts->verticalScrollBar()->value();
|
||||
ui->iaLayouts->setUpdatesEnabled(false);
|
||||
ui->iaLayouts->beginUpdate();
|
||||
ui->iaLayouts->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1274,7 +1274,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->iaLayouts->clearSelection();
|
||||
ui->iaLayouts->setUpdatesEnabled(true);
|
||||
ui->iaLayouts->endUpdate();
|
||||
ui->iaLayouts->verticalScrollBar()->setValue(vs);
|
||||
|
||||
Topology topo = draw ? draw->topology : Topology::Unknown;
|
||||
@@ -1294,7 +1294,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
bool ibufferUsed = draw && (draw->flags & DrawFlags::UseIBuffer);
|
||||
|
||||
vs = ui->iaBuffers->verticalScrollBar()->value();
|
||||
ui->iaBuffers->setUpdatesEnabled(false);
|
||||
ui->iaBuffers->beginUpdate();
|
||||
ui->iaBuffers->clear();
|
||||
|
||||
if(state.m_IA.ibuffer.Buffer != ResourceId())
|
||||
@@ -1399,7 +1399,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->iaBuffers->clearSelection();
|
||||
ui->iaBuffers->setUpdatesEnabled(true);
|
||||
ui->iaBuffers->endUpdate();
|
||||
ui->iaBuffers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
setShaderState(state.m_VS, ui->vsShader, ui->vsResources, ui->vsSamplers, ui->vsCBuffers,
|
||||
@@ -1417,7 +1417,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
|
||||
bool streamoutSet = false;
|
||||
vs = ui->gsStreamOut->verticalScrollBar()->value();
|
||||
ui->gsStreamOut->setUpdatesEnabled(false);
|
||||
ui->gsStreamOut->beginUpdate();
|
||||
ui->gsStreamOut->clear();
|
||||
for(int i = 0; i < state.m_SO.Outputs.count; i++)
|
||||
{
|
||||
@@ -1461,7 +1461,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
ui->gsStreamOut->verticalScrollBar()->setValue(vs);
|
||||
ui->gsStreamOut->clearSelection();
|
||||
ui->gsStreamOut->setUpdatesEnabled(true);
|
||||
ui->gsStreamOut->endUpdate();
|
||||
|
||||
ui->gsStreamOut->setVisible(streamoutSet);
|
||||
ui->soGroup->setVisible(streamoutSet);
|
||||
@@ -1470,7 +1470,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
// Rasterizer
|
||||
|
||||
vs = ui->viewports->verticalScrollBar()->value();
|
||||
ui->viewports->setUpdatesEnabled(false);
|
||||
ui->viewports->beginUpdate();
|
||||
ui->viewports->clear();
|
||||
for(int i = 0; i < state.m_RS.Viewports.count; i++)
|
||||
{
|
||||
@@ -1486,10 +1486,10 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
ui->viewports->verticalScrollBar()->setValue(vs);
|
||||
ui->viewports->clearSelection();
|
||||
ui->viewports->setUpdatesEnabled(true);
|
||||
ui->viewports->endUpdate();
|
||||
|
||||
vs = ui->scissors->verticalScrollBar()->value();
|
||||
ui->scissors->setUpdatesEnabled(false);
|
||||
ui->scissors->beginUpdate();
|
||||
ui->scissors->clear();
|
||||
for(int i = 0; i < state.m_RS.Scissors.count; i++)
|
||||
{
|
||||
@@ -1505,7 +1505,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
ui->scissors->clearSelection();
|
||||
ui->scissors->verticalScrollBar()->setValue(vs);
|
||||
ui->scissors->setUpdatesEnabled(true);
|
||||
ui->scissors->endUpdate();
|
||||
|
||||
ui->fillMode->setText(ToQStr(state.m_RS.m_State.fillMode));
|
||||
ui->cullMode->setText(ToQStr(state.m_RS.m_State.cullMode));
|
||||
@@ -1527,7 +1527,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
bool targets[32] = {};
|
||||
|
||||
vs = ui->targetOutputs->verticalScrollBar()->value();
|
||||
ui->targetOutputs->setUpdatesEnabled(false);
|
||||
ui->targetOutputs->beginUpdate();
|
||||
ui->targetOutputs->clear();
|
||||
{
|
||||
for(int i = 0; i < state.m_OM.RenderTargets.count; i++)
|
||||
@@ -1543,11 +1543,11 @@ void D3D12PipelineStateViewer::setState()
|
||||
ui->targetOutputs);
|
||||
}
|
||||
ui->targetOutputs->clearSelection();
|
||||
ui->targetOutputs->setUpdatesEnabled(true);
|
||||
ui->targetOutputs->endUpdate();
|
||||
ui->targetOutputs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ui->blends->verticalScrollBar()->value();
|
||||
ui->blends->setUpdatesEnabled(false);
|
||||
ui->blends->beginUpdate();
|
||||
ui->blends->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1591,7 +1591,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->blends->clearSelection();
|
||||
ui->blends->setUpdatesEnabled(true);
|
||||
ui->blends->endUpdate();
|
||||
ui->blends->verticalScrollBar()->setValue(vs);
|
||||
|
||||
ui->alphaToCoverage->setPixmap(state.m_OM.m_BlendState.AlphaToCoverage ? tick : cross);
|
||||
@@ -1612,7 +1612,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
ui->stencilWriteMask->setText(Formatter::Format(state.m_OM.m_State.StencilWriteMask, true));
|
||||
ui->stencilRef->setText(Formatter::Format(state.m_OM.m_State.StencilRef, true));
|
||||
|
||||
ui->stencils->setUpdatesEnabled(false);
|
||||
ui->stencils->beginUpdate();
|
||||
ui->stencils->clear();
|
||||
ui->stencils->addTopLevelItem(
|
||||
new RDTreeWidgetItem({tr("Front"), ToQStr(state.m_OM.m_State.m_FrontFace.Func),
|
||||
@@ -1624,7 +1624,7 @@ void D3D12PipelineStateViewer::setState()
|
||||
ToQStr(state.m_OM.m_State.m_BackFace.FailOp), ToQStr(state.m_OM.m_State.m_BackFace.DepthFailOp),
|
||||
ToQStr(state.m_OM.m_State.m_BackFace.PassOp)}));
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->setUpdatesEnabled(true);
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// highlight the appropriate stages in the flowchart
|
||||
if(draw == NULL)
|
||||
|
||||
@@ -612,10 +612,10 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
|
||||
// simultaneous update of resources and samplers
|
||||
vs = textures->verticalScrollBar()->value();
|
||||
textures->setUpdatesEnabled(false);
|
||||
textures->beginUpdate();
|
||||
textures->clear();
|
||||
vs2 = samplers->verticalScrollBar()->value();
|
||||
samplers->setUpdatesEnabled(false);
|
||||
samplers->beginUpdate();
|
||||
samplers->clear();
|
||||
|
||||
for(int i = 0; i < state.Textures.count; i++)
|
||||
@@ -788,14 +788,14 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
}
|
||||
|
||||
samplers->clearSelection();
|
||||
samplers->setUpdatesEnabled(true);
|
||||
samplers->endUpdate();
|
||||
samplers->verticalScrollBar()->setValue(vs2);
|
||||
textures->clearSelection();
|
||||
textures->setUpdatesEnabled(true);
|
||||
textures->endUpdate();
|
||||
textures->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ubos->verticalScrollBar()->value();
|
||||
ubos->setUpdatesEnabled(false);
|
||||
ubos->beginUpdate();
|
||||
ubos->clear();
|
||||
for(int i = 0; shaderDetails && i < shaderDetails->ConstantBlocks.count; i++)
|
||||
{
|
||||
@@ -869,22 +869,22 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
}
|
||||
}
|
||||
ubos->clearSelection();
|
||||
ubos->setUpdatesEnabled(true);
|
||||
ubos->endUpdate();
|
||||
ubos->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = subs->verticalScrollBar()->value();
|
||||
subs->setUpdatesEnabled(false);
|
||||
subs->beginUpdate();
|
||||
subs->clear();
|
||||
for(int i = 0; i < stage.Subroutines.count; i++)
|
||||
subs->addTopLevelItem(new RDTreeWidgetItem({i, stage.Subroutines[i]}));
|
||||
subs->clearSelection();
|
||||
subs->setUpdatesEnabled(true);
|
||||
subs->endUpdate();
|
||||
subs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
subs->parentWidget()->setVisible(!stage.Subroutines.empty());
|
||||
|
||||
vs = readwrites->verticalScrollBar()->value();
|
||||
readwrites->setUpdatesEnabled(false);
|
||||
readwrites->beginUpdate();
|
||||
readwrites->clear();
|
||||
for(int i = 0; shaderDetails && i < shaderDetails->ReadWriteResources.count; i++)
|
||||
{
|
||||
@@ -1017,7 +1017,7 @@ void GLPipelineStateViewer::setShaderState(const GLPipe::Shader &stage, QLabel *
|
||||
}
|
||||
}
|
||||
readwrites->clearSelection();
|
||||
readwrites->setUpdatesEnabled(true);
|
||||
readwrites->endUpdate();
|
||||
readwrites->verticalScrollBar()->setValue(vs);
|
||||
|
||||
readwrites->parentWidget()->setVisible(readwrites->invisibleRootItem()->childCount() > 0);
|
||||
@@ -1108,7 +1108,7 @@ void GLPipelineStateViewer::setState()
|
||||
int vs = 0;
|
||||
|
||||
vs = ui->viAttrs->verticalScrollBar()->value();
|
||||
ui->viAttrs->setUpdatesEnabled(false);
|
||||
ui->viAttrs->beginUpdate();
|
||||
ui->viAttrs->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1158,7 +1158,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->viAttrs->clearSelection();
|
||||
ui->viAttrs->setUpdatesEnabled(true);
|
||||
ui->viAttrs->endUpdate();
|
||||
ui->viAttrs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
Topology topo = draw ? draw->topology : Topology::Unknown;
|
||||
@@ -1192,7 +1192,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
|
||||
vs = ui->viBuffers->verticalScrollBar()->value();
|
||||
ui->viBuffers->setUpdatesEnabled(false);
|
||||
ui->viBuffers->beginUpdate();
|
||||
ui->viBuffers->clear();
|
||||
|
||||
if(state.m_VtxIn.ibuffer != ResourceId())
|
||||
@@ -1293,7 +1293,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->viBuffers->clearSelection();
|
||||
ui->viBuffers->setUpdatesEnabled(true);
|
||||
ui->viBuffers->endUpdate();
|
||||
ui->viBuffers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
setShaderState(state.m_VS, ui->vsShader, ui->vsTextures, ui->vsSamplers, ui->vsUBOs,
|
||||
@@ -1310,7 +1310,7 @@ void GLPipelineStateViewer::setState()
|
||||
ui->csSubroutines, ui->csReadWrite);
|
||||
|
||||
vs = ui->gsFeedback->verticalScrollBar()->value();
|
||||
ui->gsFeedback->setUpdatesEnabled(false);
|
||||
ui->gsFeedback->beginUpdate();
|
||||
ui->gsFeedback->clear();
|
||||
if(state.m_Feedback.Active)
|
||||
{
|
||||
@@ -1356,7 +1356,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
ui->gsFeedback->verticalScrollBar()->setValue(vs);
|
||||
ui->gsFeedback->clearSelection();
|
||||
ui->gsFeedback->setUpdatesEnabled(true);
|
||||
ui->gsFeedback->endUpdate();
|
||||
|
||||
ui->gsFeedback->setVisible(state.m_Feedback.Active);
|
||||
ui->xfbGroup->setVisible(state.m_Feedback.Active);
|
||||
@@ -1365,7 +1365,7 @@ void GLPipelineStateViewer::setState()
|
||||
// Rasterizer
|
||||
|
||||
vs = ui->viewports->verticalScrollBar()->value();
|
||||
ui->viewports->setUpdatesEnabled(false);
|
||||
ui->viewports->beginUpdate();
|
||||
ui->viewports->clear();
|
||||
|
||||
{
|
||||
@@ -1431,12 +1431,12 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
ui->viewports->verticalScrollBar()->setValue(vs);
|
||||
ui->viewports->clearSelection();
|
||||
ui->viewports->setUpdatesEnabled(true);
|
||||
ui->viewports->endUpdate();
|
||||
|
||||
bool anyScissorEnable = false;
|
||||
|
||||
vs = ui->scissors->verticalScrollBar()->value();
|
||||
ui->scissors->setUpdatesEnabled(false);
|
||||
ui->scissors->beginUpdate();
|
||||
ui->scissors->clear();
|
||||
{
|
||||
// accumulate identical scissors to save on visual repetition
|
||||
@@ -1507,7 +1507,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
ui->scissors->clearSelection();
|
||||
ui->scissors->verticalScrollBar()->setValue(vs);
|
||||
ui->scissors->setUpdatesEnabled(true);
|
||||
ui->scissors->endUpdate();
|
||||
|
||||
ui->fillMode->setText(ToQStr(state.m_Rasterizer.m_State.fillMode));
|
||||
ui->cullMode->setText(ToQStr(state.m_Rasterizer.m_State.cullMode));
|
||||
@@ -1610,7 +1610,7 @@ void GLPipelineStateViewer::setState()
|
||||
bool targets[32] = {};
|
||||
|
||||
vs = ui->framebuffer->verticalScrollBar()->value();
|
||||
ui->framebuffer->setUpdatesEnabled(false);
|
||||
ui->framebuffer->beginUpdate();
|
||||
ui->framebuffer->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1773,11 +1773,11 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
|
||||
ui->framebuffer->clearSelection();
|
||||
ui->framebuffer->setUpdatesEnabled(true);
|
||||
ui->framebuffer->endUpdate();
|
||||
ui->framebuffer->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ui->blends->verticalScrollBar()->value();
|
||||
ui->blends->setUpdatesEnabled(false);
|
||||
ui->blends->beginUpdate();
|
||||
ui->blends->clear();
|
||||
{
|
||||
bool logic = state.m_FB.m_Blending.Blends[0].Logic != LogicOp::NoOp;
|
||||
@@ -1841,7 +1841,7 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->blends->clearSelection();
|
||||
ui->blends->setUpdatesEnabled(true);
|
||||
ui->blends->endUpdate();
|
||||
ui->blends->verticalScrollBar()->setValue(vs);
|
||||
|
||||
ui->blendFactor->setText(QFormatStr("%1, %2, %3, %4")
|
||||
@@ -1866,7 +1866,7 @@ void GLPipelineStateViewer::setState()
|
||||
ui->depthBounds->setPixmap(cross);
|
||||
}
|
||||
|
||||
ui->stencils->setUpdatesEnabled(false);
|
||||
ui->stencils->beginUpdate();
|
||||
ui->stencils->clear();
|
||||
if(state.m_StencilState.StencilEnable)
|
||||
{
|
||||
@@ -1896,7 +1896,7 @@ void GLPipelineStateViewer::setState()
|
||||
{tr("Back"), lit("-"), lit("-"), lit("-"), lit("-"), lit("-"), lit("-"), lit("-")}));
|
||||
}
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->setUpdatesEnabled(true);
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// highlight the appropriate stages in the flowchart
|
||||
if(draw == NULL)
|
||||
|
||||
@@ -1234,7 +1234,7 @@ void VulkanPipelineStateViewer::setShaderState(const VKPipe::Shader &stage,
|
||||
ubos->hideColumn(0);
|
||||
|
||||
vs = resources->verticalScrollBar()->value();
|
||||
resources->setUpdatesEnabled(false);
|
||||
resources->beginUpdate();
|
||||
resources->clear();
|
||||
|
||||
QMap<ResourceId, SamplerData> samplers;
|
||||
@@ -1312,11 +1312,11 @@ void VulkanPipelineStateViewer::setShaderState(const VKPipe::Shader &stage,
|
||||
}
|
||||
|
||||
resources->clearSelection();
|
||||
resources->setUpdatesEnabled(true);
|
||||
resources->endUpdate();
|
||||
resources->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ubos->verticalScrollBar()->value();
|
||||
ubos->setUpdatesEnabled(false);
|
||||
ubos->beginUpdate();
|
||||
ubos->clear();
|
||||
for(int bindset = 0; bindset < pipe.DescSets.count; bindset++)
|
||||
{
|
||||
@@ -1386,7 +1386,7 @@ void VulkanPipelineStateViewer::setShaderState(const VKPipe::Shader &stage,
|
||||
}
|
||||
}
|
||||
ubos->clearSelection();
|
||||
ubos->setUpdatesEnabled(true);
|
||||
ubos->endUpdate();
|
||||
ubos->verticalScrollBar()->setValue(vs);
|
||||
}
|
||||
|
||||
@@ -1417,7 +1417,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
int vs = 0;
|
||||
|
||||
vs = ui->viAttrs->verticalScrollBar()->value();
|
||||
ui->viAttrs->setUpdatesEnabled(false);
|
||||
ui->viAttrs->beginUpdate();
|
||||
ui->viAttrs->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1458,7 +1458,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->viAttrs->clearSelection();
|
||||
ui->viAttrs->setUpdatesEnabled(true);
|
||||
ui->viAttrs->endUpdate();
|
||||
ui->viAttrs->verticalScrollBar()->setValue(vs);
|
||||
|
||||
m_BindNodes.clear();
|
||||
@@ -1480,7 +1480,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
ui->primRestart->setVisible(state.IA.primitiveRestartEnable);
|
||||
|
||||
vs = ui->viBuffers->verticalScrollBar()->value();
|
||||
ui->viBuffers->setUpdatesEnabled(false);
|
||||
ui->viBuffers->beginUpdate();
|
||||
ui->viBuffers->clear();
|
||||
|
||||
bool ibufferUsed = draw != NULL && (draw->flags & DrawFlags::UseIBuffer);
|
||||
@@ -1631,7 +1631,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->viBuffers->clearSelection();
|
||||
ui->viBuffers->setUpdatesEnabled(true);
|
||||
ui->viBuffers->endUpdate();
|
||||
ui->viBuffers->verticalScrollBar()->setValue(vs);
|
||||
|
||||
setShaderState(state.m_VS, state.graphics, ui->vsShader, ui->vsResources, ui->vsUBOs);
|
||||
@@ -1645,11 +1645,11 @@ void VulkanPipelineStateViewer::setState()
|
||||
// Rasterizer
|
||||
|
||||
vs = ui->viewports->verticalScrollBar()->value();
|
||||
ui->viewports->setUpdatesEnabled(false);
|
||||
ui->viewports->beginUpdate();
|
||||
ui->viewports->clear();
|
||||
|
||||
int vs2 = ui->scissors->verticalScrollBar()->value();
|
||||
ui->scissors->setUpdatesEnabled(false);
|
||||
ui->scissors->beginUpdate();
|
||||
ui->scissors->clear();
|
||||
|
||||
if(state.Pass.renderpass.obj != ResourceId())
|
||||
@@ -1685,8 +1685,8 @@ void VulkanPipelineStateViewer::setState()
|
||||
ui->scissors->clearSelection();
|
||||
ui->scissors->verticalScrollBar()->setValue(vs2);
|
||||
|
||||
ui->viewports->setUpdatesEnabled(true);
|
||||
ui->scissors->setUpdatesEnabled(true);
|
||||
ui->viewports->endUpdate();
|
||||
ui->scissors->endUpdate();
|
||||
|
||||
ui->fillMode->setText(ToQStr(state.RS.fillMode));
|
||||
ui->cullMode->setText(ToQStr(state.RS.cullMode));
|
||||
@@ -1711,7 +1711,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
bool targets[32] = {};
|
||||
|
||||
vs = ui->framebuffer->verticalScrollBar()->value();
|
||||
ui->framebuffer->setUpdatesEnabled(false);
|
||||
ui->framebuffer->beginUpdate();
|
||||
ui->framebuffer->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1828,11 +1828,11 @@ void VulkanPipelineStateViewer::setState()
|
||||
}
|
||||
|
||||
ui->framebuffer->clearSelection();
|
||||
ui->framebuffer->setUpdatesEnabled(true);
|
||||
ui->framebuffer->endUpdate();
|
||||
ui->framebuffer->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ui->blends->verticalScrollBar()->value();
|
||||
ui->blends->setUpdatesEnabled(false);
|
||||
ui->blends->beginUpdate();
|
||||
ui->blends->clear();
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1871,7 +1871,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
ui->blends->clearSelection();
|
||||
ui->blends->setUpdatesEnabled(true);
|
||||
ui->blends->endUpdate();
|
||||
ui->blends->verticalScrollBar()->setValue(vs);
|
||||
|
||||
ui->blendFactor->setText(QFormatStr("%1, %2, %3, %4")
|
||||
@@ -1898,7 +1898,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
ui->depthBounds->setPixmap(cross);
|
||||
}
|
||||
|
||||
ui->stencils->setUpdatesEnabled(false);
|
||||
ui->stencils->beginUpdate();
|
||||
ui->stencils->clear();
|
||||
if(state.DS.stencilTestEnable)
|
||||
{
|
||||
@@ -1923,7 +1923,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
{tr("Back"), lit("-"), lit("-"), lit("-"), lit("-"), lit("-"), lit("-"), lit("-")}));
|
||||
}
|
||||
ui->stencils->clearSelection();
|
||||
ui->stencils->setUpdatesEnabled(true);
|
||||
ui->stencils->endUpdate();
|
||||
|
||||
// highlight the appropriate stages in the flowchart
|
||||
if(draw == NULL)
|
||||
|
||||
@@ -1256,7 +1256,7 @@ void ShaderViewer::updateDebugging()
|
||||
new RDTreeWidgetItem({state.outputs[i].name, lit("output"), QString()}));
|
||||
}
|
||||
|
||||
ui->variables->setUpdatesEnabled(false);
|
||||
ui->variables->beginUpdate();
|
||||
|
||||
int v = 0;
|
||||
|
||||
@@ -1289,7 +1289,7 @@ void ShaderViewer::updateDebugging()
|
||||
node->setTag(QVariant::fromValue(VariableTag(VariableCategory::Outputs, i)));
|
||||
}
|
||||
|
||||
ui->variables->setUpdatesEnabled(true);
|
||||
ui->variables->endUpdate();
|
||||
|
||||
ui->watch->setUpdatesEnabled(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user