Instrumenting the GPU git status

This commit is contained in:
samcake 2016-07-15 17:47:54 -07:00
parent a3f6ed6a89
commit 076b8cd297
14 changed files with 145 additions and 82 deletions

View file

@ -14,7 +14,8 @@
using namespace gpu;
using namespace gpu::gl;
static bool timeElapsed = true;
// Eventually, we want to test with TIME_ELAPSED instead of TIMESTAMP
static bool timeElapsed = false;
void GLBackend::do_beginQuery(Batch& batch, size_t paramOffset) {
auto query = batch._queries.get(batch._params[paramOffset]._uint);

View file

@ -32,7 +32,7 @@ void DebugDeferredBufferConfig::setMode(int newMode) {
if (newMode == mode) {
return;
} else if (newMode > DebugDeferredBuffer::CustomMode || newMode < 0) {
mode = DebugDeferredBuffer::CustomMode;
mode = 0;
} else {
mode = newMode;
}
@ -347,6 +347,10 @@ void DebugDeferredBuffer::configure(const Config& config) {
}
void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& inputs) {
if (_mode == Off) {
return;
}
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;

View file

@ -50,7 +50,8 @@ protected:
enum Mode : uint8_t {
// Use Mode suffix to avoid collisions
DepthMode = 0,
Off = 0,
DepthMode,
AlbedoMode,
NormalMode,
RoughnessMode,
@ -70,18 +71,20 @@ protected:
ScatteringDebugMode,
AmbientOcclusionMode,
AmbientOcclusionBlurredMode,
CustomMode // Needs to stay last
CustomMode, // Needs to stay last
NumModes,
};
private:
Mode _mode;
Mode _mode{ Off };
glm::vec4 _size;
struct CustomPipeline {
gpu::PipelinePointer pipeline;
mutable QFileInfo info;
};
using StandardPipelines = std::array<gpu::PipelinePointer, CustomMode>;
using StandardPipelines = std::array<gpu::PipelinePointer, NumModes>;
using CustomPipelines = std::unordered_map<std::string, CustomPipeline>;
bool pipelineNeedsUpdate(Mode mode, std::string customFile = std::string()) const;

View file

@ -100,7 +100,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// GPU jobs: Start preparing the primary, deferred and lighting buffer
const auto primaryFramebuffer = addJob<PreparePrimaryFramebuffer>("PreparePrimaryBuffer");
const auto fullFrameRangeTimer = addJob<BeginGPURangeTimer>("BeginRangeTimer");
const auto opaqueRangeTimer = addJob<BeginGPURangeTimer>("BeginOpaqueRangeTimer");
const auto prepareDeferredInputs = SurfaceGeometryPass::Inputs(primaryFramebuffer, lightingModel).hasVarying();
const auto prepareDeferredOutputs = addJob<PrepareDeferred>("PrepareDeferred", prepareDeferredInputs);
const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0);
@ -113,6 +115,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// Once opaque is all rendered create stencil background
addJob<DrawStencilDeferred>("DrawOpaqueStencil", deferredFramebuffer);
addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
const auto curvatureRangeTimer = addJob<BeginGPURangeTimer>("BeginCurvatureRangeTimer");
// Opaque all rendered, generate surface geometry buffers
const auto surfaceGeometryPassInputs = SurfaceGeometryPass::Inputs(deferredFrameTransform, deferredFramebuffer).hasVarying();
@ -121,7 +126,6 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
const auto curvatureFramebuffer = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(1);
const auto linearDepthTexture = surfaceGeometryPassOutputs.getN<SurfaceGeometryPass::Outputs>(2);
const auto rangeTimer = addJob<BeginTimerGPU>("BeginTimerRange");
// TODO: Push this 2 diffusion stages into surfaceGeometryPass as they are working together
const auto diffuseCurvaturePassInputs = BlurGaussianDepthAware::Inputs(curvatureFramebuffer, linearDepthTexture).hasVarying();
@ -130,6 +134,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
const auto scatteringResource = addJob<SubsurfaceScattering>("Scattering");
addJob<EndGPURangeTimer>("CurvatureRangeTimer", curvatureRangeTimer);
// AO job
addJob<AmbientOcclusionEffect>("AmbientOcclusion");
@ -150,6 +156,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying();
addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber);
const auto toneAndPostRangeTimer = addJob<BeginGPURangeTimer>("BeginToneAndPostRangeTimer");
// Lighting Buffer ready for tone mapping
const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer));
addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
@ -188,11 +196,13 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
// AA job to be revisited
addJob<Antialiasing>("Antialiasing", primaryFramebuffer);
addJob<EndTimerGPU>("RangeTimer", rangeTimer);
addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
// Blit!
addJob<Blit>("Blit", primaryFramebuffer);
addJob<EndGPURangeTimer>("RangeTimer", fullFrameRangeTimer);
}
void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
@ -210,30 +220,19 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
RenderArgs* args = renderContext->args;
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
/* gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
_gpuTimer.begin(batch);
});*/
for (auto job : _jobs) {
job.run(sceneContext, renderContext);
}
/*gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
_gpuTimer.end(batch);
});*/
// config->gpuTime = _gpuTimer.getAverage();
}
void BeginTimerGPU::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) {
void BeginGPURangeTimer::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) {
timer = _gpuTimer;
gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) {
_gpuTimer->begin(batch);
});
}
void EndTimerGPU::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const gpu::RangeTimerPointer& timer) {
void EndGPURangeTimer::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const gpu::RangeTimerPointer& timer) {
gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) {
timer->end(batch);
});

View file

@ -17,11 +17,11 @@
#include "LightingModel.h"
class BeginTimerGPU {
class BeginGPURangeTimer {
public:
using JobModel = render::Job::ModelO<BeginTimerGPU, gpu::RangeTimerPointer>;
using JobModel = render::Job::ModelO<BeginGPURangeTimer, gpu::RangeTimerPointer>;
BeginTimerGPU() : _gpuTimer(std::make_shared<gpu::RangeTimer>()) {}
BeginGPURangeTimer() : _gpuTimer(std::make_shared<gpu::RangeTimer>()) {}
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer);
@ -30,23 +30,23 @@ protected:
};
class EndTimerGPUConfig : public render::Job::Config {
class GPURangeTimerConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(double gpuTime READ getGpuTime)
public:
double getGpuTime() { return gpuTime; }
protected:
friend class EndTimerGPU;
friend class EndGPURangeTimer;
double gpuTime;
};
class EndTimerGPU {
class EndGPURangeTimer {
public:
using Config = EndTimerGPUConfig;
using JobModel = render::Job::ModelI<EndTimerGPU, gpu::RangeTimerPointer, Config>;
using Config = GPURangeTimerConfig;
using JobModel = render::Job::ModelI<EndGPURangeTimer, gpu::RangeTimerPointer, Config>;
EndTimerGPU() {}
EndGPURangeTimer() {}
void configure(const Config& config) {}
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const gpu::RangeTimerPointer& timer);
@ -213,13 +213,13 @@ public:
class RenderDeferredTaskConfig : public render::Task::Config {
Q_OBJECT
Q_PROPERTY(quint64 gpuTime READ getGpuTime)
Q_PROPERTY(double gpuTime READ getGpuTime)
public:
quint64 getGpuTime() { return gpuTime; }
double getGpuTime() { return gpuTime; }
protected:
friend class RenderDeferredTask;
quint64 gpuTime;
double gpuTime;
};
class RenderDeferredTask : public render::Task {

View file

@ -45,14 +45,17 @@ void SurfaceGeometryFramebuffer::updatePrimaryDepth(const gpu::TexturePointer& d
}
if (reset) {
_linearDepthFramebuffer.reset();
_linearDepthTexture.reset();
_curvatureFramebuffer.reset();
_curvatureTexture.reset();
clear();
}
}
void SurfaceGeometryFramebuffer::clear() {
_linearDepthFramebuffer.reset();
_linearDepthTexture.reset();
_curvatureFramebuffer.reset();
_curvatureTexture.reset();
}
void SurfaceGeometryFramebuffer::allocate() {
auto width = _frameSize.x;
@ -62,12 +65,12 @@ void SurfaceGeometryFramebuffer::allocate() {
_linearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture);
// _linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
_linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
_curvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_curvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width >> getResolutionLevel(), height >> getResolutionLevel(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_curvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_curvatureFramebuffer->setRenderBuffer(0, _curvatureTexture);
// _curvatureFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
// _curvatureFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
}
gpu::FramebufferPointer SurfaceGeometryFramebuffer::getLinearDepthFramebuffer() {
@ -98,6 +101,12 @@ gpu::TexturePointer SurfaceGeometryFramebuffer::getCurvatureTexture() {
return _curvatureTexture;
}
void SurfaceGeometryFramebuffer::setResolutionLevel(int resolutionLevel) {
if (resolutionLevel != getResolutionLevel()) {
clear();
_resolutionLevel = resolutionLevel;
}
}
SurfaceGeometryPass::SurfaceGeometryPass() {
@ -106,7 +115,7 @@ SurfaceGeometryPass::SurfaceGeometryPass() {
}
void SurfaceGeometryPass::configure(const Config& config) {
if (config.depthThreshold != getCurvatureDepthThreshold()) {
_parametersBuffer.edit<Parameters>().curvatureInfo.x = config.depthThreshold;
}
@ -118,8 +127,14 @@ void SurfaceGeometryPass::configure(const Config& config) {
if (config.curvatureScale != getCurvatureScale()) {
_parametersBuffer.edit<Parameters>().curvatureInfo.w = config.curvatureScale;
}
if (!_surfaceGeometryFramebuffer) {
_surfaceGeometryFramebuffer = std::make_shared<SurfaceGeometryFramebuffer>();
}
_surfaceGeometryFramebuffer->setResolutionLevel(config.resolutionLevel);
}
void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& curvatureAndDepth) {
assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
@ -153,15 +168,17 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
// _gpuTimer.begin(batch);
// });
auto depthViewport = args->_viewport;
auto curvatureViewport = depthViewport >> _surfaceGeometryFramebuffer->getResolutionLevel();
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
_gpuTimer.begin(batch);
batch.enableStereo(false);
batch.setViewportTransform(args->_viewport);
batch.setViewportTransform(depthViewport);
batch.setProjectionTransform(glm::mat4());
batch.setViewTransform(Transform());
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_surfaceGeometryFramebuffer->getFrameSize(), args->_viewport));
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_surfaceGeometryFramebuffer->getDepthFrameSize(), depthViewport));
batch.setUniformBuffer(SurfaceGeometryPass_FrameTransformSlot, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(SurfaceGeometryPass_ParamsSlot, _parametersBuffer);
@ -172,9 +189,10 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
batch.setPipeline(linearDepthPipeline);
batch.setResourceTexture(SurfaceGeometryPass_DepthMapSlot, depthBuffer);
batch.draw(gpu::TRIANGLE_STRIP, 4);
_gpuTimer.end(batch);
batch.setViewportTransform(curvatureViewport);
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_surfaceGeometryFramebuffer->getCurvatureFrameSize(), curvatureViewport));
// Curvature pass
batch.setFramebuffer(curvatureFBO);
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0));
@ -185,7 +203,7 @@ void SurfaceGeometryPass::run(const render::SceneContextPointer& sceneContext, c
batch.setResourceTexture(SurfaceGeometryPass_DepthMapSlot, nullptr);
batch.setResourceTexture(SurfaceGeometryPass_NormalMapSlot, nullptr);
// _gpuTimer.end(batch);
_gpuTimer.end(batch);
});
// gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {

View file

@ -34,9 +34,14 @@ public:
// Update the depth buffer which will drive the allocation of all the other resources according to its size.
void updatePrimaryDepth(const gpu::TexturePointer& depthBuffer);
gpu::TexturePointer getPrimaryDepthTexture();
const glm::ivec2& getFrameSize() const { return _frameSize; }
const glm::ivec2& getDepthFrameSize() const { return _frameSize; }
glm::ivec2 getCurvatureFrameSize() const { return _frameSize >> _resolutionLevel; }
void setResolutionLevel(int level);
int getResolutionLevel() const { return _resolutionLevel; }
protected:
void clear();
void allocate();
gpu::TexturePointer _primaryDepthTexture;
@ -48,6 +53,7 @@ protected:
gpu::TexturePointer _curvatureTexture;
glm::ivec2 _frameSize;
int _resolutionLevel{ 0 };
};
using SurfaceGeometryFramebufferPointer = std::shared_ptr<SurfaceGeometryFramebuffer>;
@ -57,6 +63,7 @@ class SurfaceGeometryPassConfig : public render::Job::Config {
Q_PROPERTY(float depthThreshold MEMBER depthThreshold NOTIFY dirty)
Q_PROPERTY(float basisScale MEMBER basisScale NOTIFY dirty)
Q_PROPERTY(float curvatureScale MEMBER curvatureScale NOTIFY dirty)
Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel NOTIFY dirty)
Q_PROPERTY(double gpuTime READ getGpuTime)
public:
SurfaceGeometryPassConfig() : render::Job::Config(true) {}
@ -64,6 +71,7 @@ public:
float depthThreshold{ 0.02f }; // meters
float basisScale{ 1.0f };
float curvatureScale{ 10.0f };
int resolutionLevel{ 0 };
double getGpuTime() { return gpuTime; }

View file

@ -16,6 +16,8 @@ Item {
width: parent.width
height: 100
property int hitboxExtension : 20
// The title of the graph
property string title
@ -71,6 +73,11 @@ Item {
Component.onCompleted: {
createValues();
}
function resetMax() {
for (var i = 0; i < _values.length; i++) {
_values[i].valueMax *= 0.25 // Fast reduce the max value as we click
}
}
function pullFreshValues() {
// Wait until values are created to begin pulling
@ -125,6 +132,7 @@ Item {
Canvas {
id: mycanvas
anchors.fill:parent
onPaint: {
var lineHeight = 12;
@ -199,4 +207,19 @@ Item {
displayTitle(ctx, title, valueMax)
}
}
MouseArea {
id: hitbox
anchors.fill:mycanvas
anchors.topMargin: -hitboxExtension
anchors.bottomMargin: -hitboxExtension
anchors.leftMargin: -hitboxExtension
anchors.rightMargin: -hitboxExtension
onClicked: {
print("PerfPlot clicked!")
resetMax();
}
}
}

View file

@ -13,14 +13,15 @@ var qml = Script.resolvePath('deferredLighting.qml');
var window = new OverlayWindow({
title: 'Lighting',
source: qml,
width: 400, height:250,
width: 400, height:220,
});
window.setPosition(250, 800);a
window.setPosition(Window.innerWidth - 420, 50);
window.closed.connect(function() { Script.stop(); });
var DDB = Render.RenderDeferredTask.DebugDeferredBuffer;
DDB.enabled = true;
DDB.mode = 0;
// Debug buffer sizing
var resizing = false;
@ -36,7 +37,7 @@ Script.scriptEnding.connect(function () { DDB.enabled = false; });
function shouldStartResizing(eventX) {
var x = Math.abs(eventX - Window.innerWidth * (1.0 + DDB.size.x) / 2.0);
var mode = DDB.mode;
return mode !== -1 && x < 20;
return mode !== 0 && x < 20;
}
function setDebugBufferSize(x) {
@ -45,3 +46,4 @@ function setDebugBufferSize(x) {
DDB.size = { x: x, y: -1, z: 1, w: 1 };
}

View file

@ -13,8 +13,7 @@ import "configSlider"
Column {
spacing: 8
Row {
spacing: 8
Column {
@ -129,7 +128,7 @@ Column {
property var config: Render.getConfig("DebugDeferredBuffer")
function setDebugMode(mode) {
framebuffer.config.enabled = (mode != -1);
framebuffer.config.enabled = (mode != 0);
framebuffer.config.mode = mode;
}
@ -162,7 +161,7 @@ Column {
ListElement { text: "Custom"; color: "White" }
}
width: 200
onCurrentIndexChanged: { framebuffer.setDebugMode(currentIndex - 1) }
onCurrentIndexChanged: { framebuffer.setDebugMode(currentIndex) }
}
}
}

View file

@ -14,8 +14,8 @@ var qml = Script.resolvePath('statsGPU.qml');
var window = new OverlayWindow({
title: 'Render Stats GPU',
source: qml,
width: 320,
width: 400,
height: 200
});
window.setPosition(50, 20);
window.setPosition(Window.innerWidth - 420, 50 + 250 + 50);
window.closed.connect(function() { Script.stop(); });

View file

@ -242,22 +242,6 @@ Item {
}
]
}
PlotPerf {
title: "Timing"
height: parent.evalEvenHeight()
object: parent.drawOpaqueConfig
valueUnit: "ms"
valueScale: 1
valueNumDigits: "4"
plots: [
{
object: Render.getConfig("RenderDeferredTask"),
prop: "gpuTime",
label: "RenderFrameGPU",
color: "#00FFFF"
}
]
}
}
}

View file

@ -36,12 +36,23 @@ Item {
valueUnit: "ms"
valueScale: 1
valueNumDigits: "4"
plots: [
plots: [
{
object: Render.getConfig("OpaqueRangeTimer"),
prop: "gpuTime",
label: "Opaque",
color: "#0000FF"
},
{
object: Render.getConfig("SurfaceGeometry"),
prop: "gpuTime",
label: "SurfaceGeometryGPU",
label: "SurfaceGeometry",
color: "#00FFFF"
},{
object: Render.getConfig("CurvatureRangeTimer"),
prop: "gpuTime",
label: "Curvature",
color: "#00FF00"
},
{
object: Render.getConfig("RenderDeferred"),
@ -51,6 +62,12 @@ Item {
}
,
{
object: Render.getConfig("ToneAndPostRangeTimer"),
prop: "gpuTime",
label: "tone and post",
color: "#FF0000"
}
,{
object: Render.getConfig("RangeTimer"),
prop: "gpuTime",
label: "FrameGPU",

View file

@ -19,10 +19,15 @@ Column {
Column{
Repeater {
model: [ "Depth Threshold:depthThreshold:0.1", "Basis Scale:basisScale:2.0", "Curvature Scale:curvatureScale:100.0" ]
model: [
"Depth Threshold:depthThreshold:0.1:false",
"Basis Scale:basisScale:2.0:false",
"Curvature Scale:curvatureScale:100.0:false",
"Downscale:resolutionLevel:4:true"
]
ConfigSlider {
label: qsTr(modelData.split(":")[0])
integral: false
integral: (modelData.split(":")[3] == 'true')
config: Render.getConfig("SurfaceGeometry")
property: modelData.split(":")[1]
max: modelData.split(":")[2]