attempt to reduce code size in PostProcessManager (#2880)

* attempt to reduce code size in PostProcessManager

The two main changes are:
- materials are now stored in a hash map which allows us to
  automatically destroy all of them using one loop -- instead of
  having to call terminate() for each of them.

- factored a very common sequence of code:
  commit()
  use()
  beginRenderPass()
  draw()
  endRenderPass()

  This makes the code easier to write and also results in less code.

There are also minor other changes, e.g. RenderPass constructor is not
inline anymore.
This commit is contained in:
Mathias Agopian
2020-07-29 13:01:23 -07:00
committed by GitHub
parent d15a906855
commit bd30abb168
14 changed files with 164 additions and 186 deletions

View File

@@ -57,7 +57,6 @@ PostProcessManager::PostProcessMaterial::PostProcessMaterial() noexcept {
mEngine = nullptr;
mData = nullptr;
mMaterial = nullptr; // aliased to mEngine
mMaterialInstance = nullptr; // aliased to mData
}
PostProcessManager::PostProcessMaterial::PostProcessMaterial(FEngine& engine,
@@ -94,46 +93,50 @@ PostProcessManager::PostProcessMaterial::~PostProcessMaterial() {
void PostProcessManager::PostProcessMaterial::terminate(FEngine& engine) noexcept {
if (mHasMaterial) {
engine.destroy(mMaterial);
// this is only needed for validation in the dtor in debug builds
#ifndef NDEBUG
mMaterial = nullptr;
mMaterialInstance = nullptr;
mHasMaterial = false;
} else {
mEngine = nullptr;
mData = nullptr;
#endif
}
}
void PostProcessManager::PostProcessMaterial::assertMaterial() const noexcept {
UTILS_NOINLINE
FMaterial* PostProcessManager::PostProcessMaterial::loadMaterial() const noexcept {
// TODO: After all materials using this class have been converted to the post-process material
// domain, load both OPAQUE and TRANSPARENT variants here.
mHasMaterial = true;
mMaterial = upcast(Material::Builder().package(mData, mSize).build(*mEngine));
return mMaterial;
}
FMaterial* PostProcessManager::PostProcessMaterial::assertMaterial() const noexcept {
if (UTILS_UNLIKELY(!mHasMaterial)) {
// TODO: After all materials using this class have been converted to the post-process material
// domain, load both OPAQUE and TRANSPARENT variants here.
mMaterial = upcast(Material::Builder().package(mData, mSize).build(*mEngine));
mMaterialInstance = mMaterial->getDefaultInstance();
mHasMaterial = true;
return loadMaterial();
}
return mMaterial;
}
PipelineState PostProcessManager::PostProcessMaterial::getPipelineState(uint8_t variant) const noexcept {
assertMaterial();
FMaterial* const material = assertMaterial();
return {
.program = mMaterial->getProgram(variant),
.rasterState = mMaterial->getRasterState(),
.scissor = mMaterialInstance->getScissor()
.program = material->getProgram(variant),
.rasterState = material->getRasterState(),
.scissor = material->getDefaultInstance()->getScissor()
};
}
PipelineState PostProcessManager::PostProcessMaterial::getPipelineState() const noexcept {
return getPipelineState(0);
}
FMaterial* PostProcessManager::PostProcessMaterial::getMaterial() const {
assertMaterial();
return mMaterial;
}
FMaterialInstance* PostProcessManager::PostProcessMaterial::getMaterialInstance() const {
assertMaterial();
return mMaterialInstance;
FMaterial* const material = assertMaterial();
return material->getDefaultInstance();
}
// ------------------------------------------------------------------------------------------------
@@ -141,33 +144,41 @@ FMaterialInstance* PostProcessManager::PostProcessMaterial::getMaterialInstance(
PostProcessManager::PostProcessManager(FEngine& engine) noexcept : mEngine(engine) {
}
UTILS_NOINLINE
void PostProcessManager::registerPostProcessMaterial(utils::StaticString name, uint8_t const* data, int size) {
mMaterialRegistry.try_emplace(name, mEngine, data, size);
}
PostProcessManager::PostProcessMaterial& PostProcessManager::getPostProcessMaterial(utils::StaticString name) noexcept {
assert(mMaterialRegistry.find(name) != mMaterialRegistry.end());
return mMaterialRegistry[name];
}
#define MATERIAL(n) MATERIALS_ ## n ## _DATA, MATERIALS_ ## n ## _SIZE
void PostProcessManager::init() noexcept {
auto& engine = mEngine;
DriverApi& driver = engine.getDriverApi();
mSSAO = { engine, MATERIAL(SAO) };
mMipmapDepth = { engine, MATERIAL(MIPMAPDEPTH) };
mBilateralBlur = { engine, MATERIAL(BILATERALBLUR) };
mSeparableGaussianBlur = { engine, MATERIAL(SEPARABLEGAUSSIANBLUR) };
mBloomDownsample = { engine, MATERIAL(BLOOMDOWNSAMPLE) };
mBloomUpsample = { engine, MATERIAL(BLOOMUPSAMPLE) };
mBlit[0] = { engine, MATERIAL(BLITLOW) };
mBlit[1] = { engine, MATERIAL(BLITMEDIUM) };
mBlit[2] = { engine, MATERIAL(BLITHIGH) };
mColorGrading = { engine, MATERIAL(COLORGRADING) };
mFxaa = { engine, MATERIAL(FXAA) };
mDoFDownsample = { engine, MATERIAL(DOFDOWNSAMPLE) };
mDoFMipmap = { engine, MATERIAL(DOFMIPMAP) };
mDoFTiles = { engine, MATERIAL(DOFTILES) };
mDoFDilate = { engine, MATERIAL(DOFDILATE) };
mDoF = { engine, MATERIAL(DOF) };
mDoFMedian = { engine, MATERIAL(DOFMEDIAN) };
mDoFCombine = { engine, MATERIAL(DOFCOMBINE) };
if (driver.isFrameBufferFetchSupported()) {
mColorGradingAsSubpass = { engine, MATERIAL(COLORGRADINGASSUBPASS) };
}
registerPostProcessMaterial("sao", MATERIAL(SAO));
registerPostProcessMaterial("mipmapDepth", MATERIAL(MIPMAPDEPTH));
registerPostProcessMaterial("bilateralBlur", MATERIAL(BILATERALBLUR));
registerPostProcessMaterial("separableGaussianBlur", MATERIAL(SEPARABLEGAUSSIANBLUR));
registerPostProcessMaterial("bloomDownsample", MATERIAL(BLOOMDOWNSAMPLE));
registerPostProcessMaterial("bloomUpsample", MATERIAL(BLOOMUPSAMPLE));
registerPostProcessMaterial("blitLow", MATERIAL(BLITLOW));
registerPostProcessMaterial("blitMedium", MATERIAL(BLITMEDIUM));
registerPostProcessMaterial("blitHigh", MATERIAL(BLITHIGH));
registerPostProcessMaterial("colorGrading", MATERIAL(COLORGRADING));
registerPostProcessMaterial("colorGradingAsSubpass", MATERIAL(COLORGRADINGASSUBPASS));
registerPostProcessMaterial("fxaa", MATERIAL(FXAA));
registerPostProcessMaterial("dofDownsample", MATERIAL(DOFDOWNSAMPLE));
registerPostProcessMaterial("dofMipmap", MATERIAL(DOFMIPMAP));
registerPostProcessMaterial("dofTiles", MATERIAL(DOFTILES));
registerPostProcessMaterial("dofDilate", MATERIAL(DOFDILATE));
registerPostProcessMaterial("dof", MATERIAL(DOF));
registerPostProcessMaterial("dofMedian", MATERIAL(DOFMEDIAN));
registerPostProcessMaterial("dofCombine", MATERIAL(DOFCOMBINE));
// UBO storage size.
// The effective kernel size is (kMaxPositiveKernelSize - 1) * 4 + 1.
@@ -175,7 +186,8 @@ void PostProcessManager::init() noexcept {
// taking advantage of linear filtering produces an effective kernel of 8+1+8=17 samples
// and because it's a separable filter, the effective 2D filter kernel size is 17*17
// The total number of samples needed over the two passes is 18.
mSeparableGaussianBlurKernelStorageSize = mSeparableGaussianBlur.getMaterial()->reflect("kernel")->size;
auto& separableGaussianBlur = getPostProcessMaterial("separableGaussianBlur");
mSeparableGaussianBlurKernelStorageSize = separableGaussianBlur.getMaterial()->reflect("kernel")->size;
mDummyOneTexture = driver.createTexture(SamplerType::SAMPLER_2D, 1,
TextureFormat::RGBA8, 0, 1, 1, 1, TextureUsage::DEFAULT);
@@ -195,25 +207,29 @@ void PostProcessManager::terminate(DriverApi& driver) noexcept {
FEngine& engine = mEngine;
driver.destroyTexture(mDummyOneTexture);
driver.destroyTexture(mDummyZeroTexture);
mSSAO.terminate(engine);
mMipmapDepth.terminate(engine);
mBilateralBlur.terminate(engine);
mSeparableGaussianBlur.terminate(engine);
mBloomDownsample.terminate(engine);
mBloomUpsample.terminate(engine);
mBlit[0].terminate(engine);
mBlit[1].terminate(engine);
mBlit[2].terminate(engine);
mColorGrading.terminate(engine);
mColorGradingAsSubpass.terminate(engine);
mFxaa.terminate(engine);
mDoFDownsample.terminate(engine);
mDoFMipmap.terminate(engine);
mDoFTiles.terminate(engine);
mDoFDilate.terminate(engine);
mDoF.terminate(engine);
mDoFMedian.terminate(engine);
mDoFCombine.terminate(engine);
auto first = mMaterialRegistry.begin();
auto last = mMaterialRegistry.end();
while (first != last) {
first.value().terminate(engine);
++first;
}
}
UTILS_NOINLINE
void PostProcessManager::commitAndRender(FrameGraphRenderTarget const& out,
PostProcessMaterial const& material, uint8_t variant, DriverApi& driver) const noexcept {
FMaterialInstance* const mi = material.getMaterialInstance();
mi->commit(driver);
mi->use(driver);
driver.beginRenderPass(out.target, out.params);
driver.draw(material.getPipelineState(variant), mEngine.getFullScreenRenderPrimitive());
driver.endRenderPass();
}
UTILS_ALWAYS_INLINE
void PostProcessManager::commitAndRender(FrameGraphRenderTarget const& out,
PostProcessMaterial const& material, DriverApi& driver) const noexcept {
commitAndRender(out, material, 0, driver);
}
// ------------------------------------------------------------------------------------------------
@@ -277,8 +293,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::structure(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> PostProcessManager::mipmapPass(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input, size_t level) noexcept {
Handle<HwRenderPrimitive> fullScreenRenderPrimitive = mEngine.getFullScreenRenderPrimitive();
struct DepthMipData {
FrameGraphId<FrameGraphTexture> in;
FrameGraphId<FrameGraphTexture> out;
@@ -300,15 +314,12 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::mipmapPass(FrameGraph& fg,
auto in = resources.getTexture(data.in);
auto out = resources.get(data.rt);
FMaterialInstance* const mi = mMipmapDepth.getMaterialInstance();
auto& material = getPostProcessMaterial("mipmapDepth");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("depth", in, { .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
mi->setParameter("level", uint32_t(level));
mi->commit(driver);
mi->use(driver);
driver.beginRenderPass(out.target, out.params);
driver.draw(mMipmapDepth.getPipelineState(), fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, driver);
});
return depthMipmapPass.getData().out;
@@ -405,7 +416,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::screenSpaceAmbientOclusion(
const auto invProjection = inverse(cameraInfo.projection);
const float inc = (1.0f / (sampleCount - 0.5f)) * spiralTurns * 2.0f * float(math::F_PI);
FMaterialInstance* const mi = mSSAO.getMaterialInstance();
auto& material = getPostProcessMaterial("sao");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("depth", depth, {
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST
});
@@ -429,7 +441,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::screenSpaceAmbientOclusion(
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(mSSAO.getPipelineState());
PipelineState pipeline(material.getPipelineState());
pipeline.rasterState.depthFunc = RasterState::DepthFunc::G;
driver.beginRenderPass(ssao.target, ssao.params);
@@ -499,14 +511,15 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bilateralBlurPass(
// TODO: "oneOverEdgeDistance" should be a user-settable parameter
// z-distance that constitute an edge for bilateral filtering
FMaterialInstance* const mi = mBilateralBlur.getMaterialInstance();
auto& material = getPostProcessMaterial("bilateralBlur");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("ssao", ssao, { /* only reads level 0 */ });
mi->setParameter("axis", axis / float2{desc.width, desc.height});
mi->setParameter("farPlaneOverEdgeDistance", -zf / 0.0625f);
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(mBilateralBlur.getPipelineState());
PipelineState pipeline(material.getPipelineState());
pipeline.rasterState.depthFunc = RasterState::DepthFunc::G;
driver.beginRenderPass(blurred.target, blurred.params);
@@ -611,7 +624,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
[=](FrameGraphPassResources const& resources,
auto const& data, DriverApi& driver) {
PostProcessMaterial const& separableGaussianBlur = mSeparableGaussianBlur;
auto const& separableGaussianBlur = getPostProcessMaterial("separableGaussianBlur");
FMaterialInstance* const mi = separableGaussianBlur.getMaterialInstance();
float2 kernel[64];
@@ -640,15 +653,11 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
float2{ 1.0f / FTexture::valueForLevel(srcLevel, inDesc.width), 0 });
mi->setParameter("count", (int32_t)m);
mi->setParameter("kernel", kernel, m);
mi->commit(driver);
mi->use(driver);
// The framegraph only computes discard flags at FrameGraphPass boundaries
hwTempRT.params.flags.discardEnd = TargetBufferFlags::NONE;
driver.beginRenderPass(hwTempRT.target, hwTempRT.params);
driver.draw(separableGaussianBlur.getPipelineState(), fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(hwTempRT, separableGaussianBlur, driver);
// vertical pass
auto width = FTexture::valueForLevel(dstLevel, outDesc.width);
@@ -665,6 +674,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
float4{ width, height, 1.0f / width, 1.0f / height });
mi->setParameter("axis", float2{ 0, 1.0f / tempDesc.height });
mi->commit(driver);
// we don't need to call use() here, since it's the same material
driver.beginRenderPass(hwOutRT.target, hwOutRT.params);
driver.draw(separableGaussianBlur.getPipelineState(), fullScreenRenderPrimitive);
@@ -772,18 +782,13 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto const& out = resources.get(data.rt);
auto color = resources.getTexture(data.color);
auto depth = resources.getTexture(data.depth);
PostProcessMaterial& material = mDoFDownsample;
auto const& material = getPostProcessMaterial("dofDownsample");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("color", color, { .filterMin = SamplerMinFilter::NEAREST });
mi->setParameter("depth", depth, { .filterMin = SamplerMinFilter::NEAREST });
mi->setParameter("cocParams", cocParams);
mi->setParameter("uvscale", float4{ width, height, 1.0f / colorDesc.width, 1.0f / colorDesc.height });
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(material.getPipelineState(variant));
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, driver);
});
/*
@@ -835,19 +840,20 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto inOutBackground = resources.getTexture(data.inOutBackground);
auto inOutCocFgBg = resources.getTexture(data.inOutCocFgBg);
PostProcessMaterial& material = mDoFMipmap;
auto const& material = getPostProcessMaterial("dofMipmap");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("foreground", inOutForeground, { .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
mi->setParameter("background", inOutBackground, { .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
mi->setParameter("cocFgBg", inOutCocFgBg, { .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
mi->use(driver);
const PipelineState pipeline(material.getPipelineState(variant));
for (size_t level = 0 ; level < mipmapCount - 1u ; level++) {
auto const& out = resources.get(data.rt[level]);
mi->setParameter("mip", uint32_t(level));
mi->setParameter("weightScale", 0.5f / float(1u<<level));
mi->commit(driver);
PipelineState pipeline(material.getPipelineState(variant));
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
@@ -895,16 +901,13 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto const& outputDesc = resources.getDescriptor(data.outTilesCocMaxMin);
auto const& out = resources.get(data.rt);
auto inCocMaxMin = resources.getTexture(data.inCocMaxMin);
PostProcessMaterial& material = mDoFTiles;
auto const& material = getPostProcessMaterial("dofTiles");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("cocMaxMin", inCocMaxMin, { .filterMin = SamplerMinFilter::NEAREST });
mi->setParameter("uvscale", float4{ outputDesc.width, outputDesc.height, 1.0f / inputDesc.width, 1.0f / inputDesc.height });
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(material.getPipelineState());
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
mi->setParameter("uvscale", float4{
outputDesc.width, outputDesc.height,
1.0f / inputDesc.width, 1.0f / inputDesc.height });
commitAndRender(out, material, driver);
});
inTilesCocMaxMin = ppDoFTiling.getData().outTilesCocMaxMin;
}
@@ -936,15 +939,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto const& data, DriverApi& driver) {
auto const& out = resources.get(data.rt);
auto inTilesCocMaxMin = resources.getTexture(data.inTilesCocMaxMin);
PostProcessMaterial& material = mDoFDilate;
auto const& material = getPostProcessMaterial("dofDilate");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("tiles", inTilesCocMaxMin, { .filterMin = SamplerMinFilter::NEAREST });
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(material.getPipelineState());
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, driver);
});
return ppDoFDilate.getData().outTilesCocMaxMin;
};
@@ -1007,7 +1005,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto const& outputDesc = resources.getDescriptor(data.outForeground);
auto const& tilesDesc = resources.getDescriptor(data.tilesCocMaxMin);
PostProcessMaterial& material = mDoF;
auto const& material = getPostProcessMaterial("dof");
FMaterialInstance* const mi = material.getMaterialInstance();
// it's not safe to use bilinear filtering in the general case (causes artifacts around edges)
mi->setParameter("foreground", foreground,
@@ -1028,12 +1026,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
outputDesc.height / (tileSize * 0.5f * tilesDesc.height)
});
mi->setParameter("bokehAngle", bokehAngle);
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(material.getPipelineState(variant));
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, driver);
});
/*
@@ -1077,7 +1070,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto const& outputDesc = resources.getDescriptor(data.outForeground);
auto const& tilesDesc = resources.getDescriptor(data.tilesCocMaxMin);
PostProcessMaterial& material = mDoFMedian;
auto const& material = getPostProcessMaterial("dofMedian");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("dof", inForeground, { .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
mi->setParameter("alpha", inAlpha, { .filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
@@ -1086,12 +1079,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
outputDesc.width / (tileSize * 0.5f * tilesDesc.width),
outputDesc.height / (tileSize * 0.5f * tilesDesc.height)
});
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(material.getPipelineState(variant));
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, driver);
});
@@ -1139,7 +1127,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
auto alpha = resources.getTexture(data.alpha);
auto tilesCocMaxMin = resources.getTexture(data.tilesCocMaxMin);
PostProcessMaterial& material = mDoFCombine;
auto const& material = getPostProcessMaterial("dofCombine");
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("color", color, { .filterMin = SamplerMinFilter::NEAREST });
mi->setParameter("dof", dof, { .filterMag = SamplerMagFilter::NEAREST });
@@ -1151,12 +1139,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::dof(FrameGraph& fg,
colorDesc.width / (tilesDesc.width * float(tileSize)),
colorDesc.height / (tilesDesc.height * float(tileSize))
});
mi->commit(driver);
mi->use(driver);
PipelineState pipeline(material.getPipelineState(variant));
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline, fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, driver);
});
return ppDoFCombine.getData().output;
@@ -1226,10 +1209,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bloomPass(FrameGraph& fg,
[=](FrameGraphPassResources const& resources,
auto const& data, DriverApi& driver) {
PostProcessMaterial const& bloomDownsample = mBloomDownsample;
FMaterialInstance* mi = bloomDownsample.getMaterialInstance();
auto const& material = getPostProcessMaterial("bloomDownsample");
FMaterialInstance* mi = material.getMaterialInstance();
const PipelineState pipeline(bloomDownsample.getPipelineState());
const PipelineState pipeline(material.getPipelineState());
auto hwIn = resources.getTexture(data.in);
auto hwOut = resources.getTexture(data.out);
@@ -1285,9 +1268,9 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bloomPass(FrameGraph& fg,
auto hwIn = resources.getTexture(data.in);
auto const& outDesc = resources.getDescriptor(data.out);
PostProcessMaterial const& bloomUpsample = mBloomUpsample;
FMaterialInstance* mi = bloomUpsample.getMaterialInstance();
PipelineState pipeline(bloomUpsample.getPipelineState());
auto const& material = getPostProcessMaterial("bloomUpsample");
FMaterialInstance* mi = material.getMaterialInstance();
PipelineState pipeline(material.getPipelineState());
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE;
@@ -1338,11 +1321,11 @@ static float4 getVignetteParameters(View::VignetteOptions options, uint32_t widt
// Factor to transform oval into circle
float aspect = mix(1.0f, float(width) / float(height), circle);
return float4{midPoint, radius, aspect, options.feather};
return float4{ midPoint, radius, aspect, options.feather };
}
// Set half-max to show disabled
return float4{std::numeric_limits<half>::max()};
return float4{ std::numeric_limits<half>::max() };
}
void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver,
@@ -1351,7 +1334,8 @@ void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver,
float4 vignetteParameters = getVignetteParameters(vignetteOptions, width, height);
FMaterialInstance* mi = mColorGradingAsSubpass.getMaterialInstance();
auto const& material = getPostProcessMaterial("colorGradingAsSubpass");
FMaterialInstance* mi = material.getMaterialInstance();
mi->setParameter("lut", colorGrading->getHwHandle(), {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
@@ -1367,12 +1351,13 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver, bool translucen
FEngine& engine = mEngine;
Handle<HwRenderPrimitive> const& fullScreenRenderPrimitive = engine.getFullScreenRenderPrimitive();
mColorGradingAsSubpass.getMaterialInstance()->use(driver);
auto const& material = getPostProcessMaterial("colorGradingAsSubpass");
material.getMaterialInstance()->use(driver);
const uint8_t variant = uint8_t(translucent ?
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE);
driver.nextSubpass();
driver.draw(mColorGradingAsSubpass.getPipelineState(variant), fullScreenRenderPrimitive);
driver.draw(material.getPipelineState(variant), fullScreenRenderPrimitive);
}
FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
@@ -1380,9 +1365,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
TextureFormat outFormat, bool translucent, bool fxaa, float2 scale,
View::BloomOptions bloomOptions, View::VignetteOptions vignetteOptions, bool dithering) noexcept {
FEngine& engine = mEngine;
Handle<HwRenderPrimitive> const& fullScreenRenderPrimitive = engine.getFullScreenRenderPrimitive();
struct PostProcessColorGrading {
FrameGraphId<FrameGraphTexture> input;
FrameGraphId<FrameGraphTexture> output;
@@ -1438,7 +1420,10 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
Handle<HwTexture> dirtTexture =
data.dirt.isValid() ? resources.getTexture(data.dirt) : getOneTexture();
FMaterialInstance* mi = mColorGrading.getMaterialInstance();
auto const& out = resources.get(data.rt);
auto const& material = getPostProcessMaterial("colorGrading");
FMaterialInstance* mi = material.getMaterialInstance();
mi->setParameter("lut", colorGrading->getHwHandle(), {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
@@ -1473,16 +1458,11 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
mi->setParameter("vignette", vignetteParameters);
mi->setParameter("vignetteColor", vignetteOptions.color);
mi->setParameter("fxaa", fxaa);
mi->commit(driver);
mi->use(driver);
const uint8_t variant = uint8_t(translucent ?
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE);
auto const& target = resources.get(data.rt);
driver.beginRenderPass(target.target, target.params);
driver.draw(mColorGrading.getPipelineState(variant), fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, variant, driver);
}
);
@@ -1493,9 +1473,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::fxaa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input,
TextureFormat outFormat, bool translucent) noexcept {
FEngine& engine = mEngine;
Handle<HwRenderPrimitive> const& fullScreenRenderPrimitive = engine.getFullScreenRenderPrimitive();
struct PostProcessFXAA {
FrameGraphId<FrameGraphTexture> input;
FrameGraphId<FrameGraphTexture> output;
@@ -1518,23 +1495,19 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::fxaa(FrameGraph& fg,
[=](FrameGraphPassResources const& resources,
auto const& data, DriverApi& driver) {
auto const& texture = resources.getTexture(data.input);
auto const& out = resources.get(data.rt);
FMaterialInstance* mi = mFxaa.getMaterialInstance();
auto const& material = getPostProcessMaterial("fxaa");
FMaterialInstance* mi = material.getMaterialInstance();
mi->setParameter("colorBuffer", texture, {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
});
mi->commit(driver);
mi->use(driver);
const uint8_t variant = uint8_t(translucent ?
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE);
auto const& target = resources.get(data.rt);
driver.beginRenderPass(target.target, target.params);
driver.draw(mFxaa.getPipelineState(variant), fullScreenRenderPrimitive);
driver.endRenderPass();
commitAndRender(out, material, variant, driver);
});
return ppFXAA.getData().output;
@@ -1620,8 +1593,9 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::blendBlit(
auto out = resources.get(data.drt);
auto const& desc = resources.getDescriptor(data.input);
const StaticString blitterNames[3] = { "blitLow", "blitMedium", "blitHigh" };
unsigned index = std::min(2u, (unsigned)quality);
PostProcessMaterial& material = mBlit[index];
auto& material = getPostProcessMaterial(blitterNames[index]);
FMaterialInstance* const mi = material.getMaterialInstance();
mi->setParameter("color", color, {
.filterMag = SamplerMagFilter::LINEAR,

View File

@@ -26,6 +26,10 @@
#include <backend/DriverEnums.h>
#include <filament/View.h>
#include <utils/CString.h>
#include <tsl/robin_map.h>
namespace filament {
class FColorGrading;
@@ -101,6 +105,7 @@ public:
private:
FEngine& mEngine;
class PostProcessMaterial;
FrameGraphId<FrameGraphTexture> mipmapPass(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input, size_t level) noexcept;
@@ -118,6 +123,13 @@ private:
FrameGraphId<FrameGraphTexture> input, backend::TextureFormat outFormat,
View::BloomOptions& bloomOptions, math::float2 scale) noexcept;
void commitAndRender(FrameGraphRenderTarget const& out,
PostProcessMaterial const& material, uint8_t variant,
backend::DriverApi& driver) const noexcept;
void commitAndRender(FrameGraphRenderTarget const& out,
PostProcessMaterial const& material,
backend::DriverApi& driver) const noexcept;
class PostProcessMaterial {
public:
@@ -137,16 +149,15 @@ private:
FMaterial* getMaterial() const;
FMaterialInstance* getMaterialInstance() const;
backend::PipelineState getPipelineState(uint8_t variant) const noexcept;
backend::PipelineState getPipelineState() const noexcept;
backend::PipelineState getPipelineState(uint8_t variant = 0u) const noexcept;
private:
void assertMaterial() const noexcept;
FMaterial* assertMaterial() const noexcept;
FMaterial* loadMaterial() const noexcept;
union {
struct {
mutable FMaterial* mMaterial;
mutable FMaterialInstance* mMaterialInstance;
};
struct {
FEngine* mEngine;
@@ -157,24 +168,10 @@ private:
mutable bool mHasMaterial{};
};
PostProcessMaterial mMipmapDepth;
tsl::robin_map<utils::StaticString, PostProcessMaterial> mMaterialRegistry;
PostProcessMaterial mSSAO;
PostProcessMaterial mBilateralBlur;
PostProcessMaterial mSeparableGaussianBlur;
PostProcessMaterial mDoFDownsample;
PostProcessMaterial mDoFMipmap;
PostProcessMaterial mDoF;
PostProcessMaterial mDoFTiles;
PostProcessMaterial mDoFDilate;
PostProcessMaterial mDoFMedian;
PostProcessMaterial mDoFCombine;
PostProcessMaterial mBloomDownsample;
PostProcessMaterial mBloomUpsample;
PostProcessMaterial mColorGradingAsSubpass;
PostProcessMaterial mColorGrading;
PostProcessMaterial mFxaa;
PostProcessMaterial mBlit[3];
void registerPostProcessMaterial(utils::StaticString name, uint8_t const* data, int size);
PostProcessMaterial& getPostProcessMaterial(utils::StaticString name) noexcept;
backend::Handle<backend::HwTexture> mDummyOneTexture;
backend::Handle<backend::HwTexture> mDummyZeroTexture;

View File

@@ -46,6 +46,10 @@ RenderPass::RenderPass(FEngine& engine,
mCustomCommands.reserve(8); // preallocate allocate a reasonable number of custom commands
}
RenderPass::RenderPass(RenderPass const& rhs) = default;
RenderPass::~RenderPass() noexcept = default;
void RenderPass::setGeometry(FScene::RenderableSoa const& soa, Range<uint32_t> vr,
backend::Handle<backend::HwUniformBuffer> uboHandle) noexcept {
mRenderableSoa = &soa;

View File

@@ -241,6 +241,9 @@ public:
RenderPass(FEngine& engine, utils::GrowingSlice<Command> commands) noexcept;
RenderPass(RenderPass const& rhs);
~RenderPass() noexcept;
void overridePolygonOffset(backend::PolygonOffset* polygonOffset) noexcept;
void setGeometry(FScene::RenderableSoa const& soa, utils::Range<uint32_t> vr,
backend::Handle<backend::HwUniformBuffer> uboHandle) noexcept;

View File

@@ -1,5 +1,5 @@
material {
name : blit,
name : blitHigh,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : blit,
name : blitLow,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : blit,
name : blitMedium,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfField,
name : dof,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfFieldCombine,
name : dofCombine,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfFieldDilate,
name : dofDilate,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfFieldDownsample,
name : dofDownsample,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfFieldMedian,
name : dofMedian,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfFieldMipmap,
name : dofMipmap,
parameters : [
{
type : sampler2d,

View File

@@ -1,5 +1,5 @@
material {
name : DepthOfFieldTiles,
name : dofTiles,
parameters : [
{
type : sampler2d,