From 94b1ad52fa41aa763dd7a67b108bb8766b667d3d Mon Sep 17 00:00:00 2001 From: Ben Doherty Date: Tue, 3 Mar 2020 14:25:04 -0800 Subject: [PATCH] Add new Shadows uniform buffer (#2194) --- filament/backend/src/metal/MetalBuffer.mm | 1 - filament/src/Material.cpp | 1 + filament/src/View.cpp | 7 +++++++ filament/src/details/View.h | 3 +++ .../include/private/filament/EngineEnums.h | 4 ++-- .../include/private/filament/UibGenerator.h | 13 +++++++++++++ libs/filabridge/src/UibGenerator.cpp | 9 +++++++++ libs/filamat/src/shaders/ShaderGenerator.cpp | 4 ++++ 8 files changed, 39 insertions(+), 3 deletions(-) diff --git a/filament/backend/src/metal/MetalBuffer.mm b/filament/backend/src/metal/MetalBuffer.mm index 07b011e51b..8363e19070 100644 --- a/filament/backend/src/metal/MetalBuffer.mm +++ b/filament/backend/src/metal/MetalBuffer.mm @@ -24,7 +24,6 @@ namespace metal { MetalBuffer::MetalBuffer(MetalContext& context, size_t size, bool forceGpuBuffer) : mBufferSize(size), mContext(context) { - assert(size > 0); // If the buffer is less than 4K in size, we don't use an explicit buffer and instead use // immediate command encoder methods like setVertexBytes:length:atIndex:. // TODO: we shouldn't do this if the data persists for multiple uses. diff --git a/filament/src/Material.cpp b/filament/src/Material.cpp index 0ef0388529..09d05b11b8 100644 --- a/filament/src/Material.cpp +++ b/filament/src/Material.cpp @@ -332,6 +332,7 @@ backend::Handle FMaterial::getSurfaceProgramSlow(uint8_t var pb .setUniformBlock(BindingPoints::PER_VIEW, UibGenerator::getPerViewUib().getName()) .setUniformBlock(BindingPoints::LIGHTS, UibGenerator::getLightsUib().getName()) + .setUniformBlock(BindingPoints::SHADOW, UibGenerator::getShadowUib().getName()) .setUniformBlock(BindingPoints::PER_RENDERABLE, UibGenerator::getPerRenderableUib().getName()) .setUniformBlock(BindingPoints::PER_MATERIAL_INSTANCE, mUniformInterfaceBlock.getName()); diff --git a/filament/src/View.cpp b/filament/src/View.cpp index e29f7db881..90654b462d 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -56,6 +56,7 @@ namespace details { FView::FView(FEngine& engine) : mFroxelizer(engine), mPerViewUb(PerViewUib::getUib().getSize()), + mShadowUb(ShadowUib::getUib().getSize()), mPerViewSb(PerViewSib::SAMPLER_COUNT), mDirectionalShadowMap(engine) { DriverApi& driver = engine.getDriverApi(); @@ -77,6 +78,7 @@ FView::FView(FEngine& engine) // allocate ubos mPerViewUbh = driver.createUniformBuffer(mPerViewUb.getSize(), backend::BufferUsage::DYNAMIC); mLightUbh = driver.createUniformBuffer(CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib), backend::BufferUsage::DYNAMIC); + mShadowUbh = driver.createUniformBuffer(mShadowUb.getSize(), backend::BufferUsage::DYNAMIC); mIsDynamicResolutionSupported = driver.isFrameTimeSupported(); } @@ -88,6 +90,7 @@ void FView::terminate(FEngine& engine) { DriverApi& driver = engine.getDriverApi(); driver.destroyUniformBuffer(mPerViewUbh); driver.destroyUniformBuffer(mLightUbh); + driver.destroyUniformBuffer(mShadowUbh); driver.destroySamplerGroup(mPerViewSbh); driver.destroyUniformBuffer(mRenderableUbh); mDirectionalShadowMap.terminate(driver); @@ -691,6 +694,10 @@ void FView::commitUniforms(backend::DriverApi& driver) const noexcept { driver.loadUniformBuffer(mPerViewUbh, mPerViewUb.toBufferDescriptor(driver)); } + if (mShadowUb.isDirty()) { + driver.loadUniformBuffer(mShadowUbh, mShadowUb.toBufferDescriptor(driver)); + } + if (mPerViewSb.isDirty()) { driver.updateSamplerGroup(mPerViewSbh, std::move(mPerViewSb.toCommandStream())); } diff --git a/filament/src/details/View.h b/filament/src/details/View.h index 8b078dc41e..7f8b6d1602 100644 --- a/filament/src/details/View.h +++ b/filament/src/details/View.h @@ -338,6 +338,7 @@ private: void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept { driver.bindUniformBuffer(BindingPoints::PER_VIEW, mPerViewUbh); driver.bindUniformBuffer(BindingPoints::LIGHTS, mLightUbh); + driver.bindUniformBuffer(BindingPoints::SHADOW, mShadowUbh); driver.bindSamplers(BindingPoints::PER_VIEW, mPerViewSbh); } @@ -350,6 +351,7 @@ private: backend::Handle mPerViewSbh; backend::Handle mPerViewUbh; backend::Handle mLightUbh; + backend::Handle mShadowUbh; backend::Handle mRenderableUbh; backend::Handle getUsh() const noexcept { return mPerViewSbh; } @@ -399,6 +401,7 @@ private: RenderQuality mRenderQuality; mutable UniformBuffer mPerViewUb; + mutable UniformBuffer mShadowUb; mutable backend::SamplerGroup mPerViewSb; utils::CString mName; diff --git a/libs/filabridge/include/private/filament/EngineEnums.h b/libs/filabridge/include/private/filament/EngineEnums.h index d3b592429d..ac20b2d06f 100644 --- a/libs/filabridge/include/private/filament/EngineEnums.h +++ b/libs/filabridge/include/private/filament/EngineEnums.h @@ -35,7 +35,7 @@ namespace BindingPoints { constexpr uint8_t PER_RENDERABLE = 1; // uniforms/samplers updated per renderable constexpr uint8_t PER_RENDERABLE_BONES = 2; // bones data, per renderable constexpr uint8_t LIGHTS = 3; // lights data array - constexpr uint8_t POST_PROCESS_DEPRECATED = 4; // deprecated + constexpr uint8_t SHADOW = 4; // punctual shadow data constexpr uint8_t PER_MATERIAL_INSTANCE = 5; // uniforms/samplers updates per material constexpr uint8_t COUNT = 6; // These are limited by Program::UNIFORM_BINDING_COUNT (currently 6) @@ -53,7 +53,7 @@ constexpr size_t CONFIG_MAX_LIGHT_INDEX = CONFIG_MAX_LIGHT_COUNT - 1; // Light space coordinates are computed in the vertex shader and interpolated across fragments. // Thus, each additional shadow-casting spot light adds 4 additional varying components. Higher // values may cause the number of varyings to exceed the driver limit. -constexpr size_t CONFIG_MAX_SHADOW_CASTING_SPOTS = 0; +constexpr size_t CONFIG_MAX_SHADOW_CASTING_SPOTS = 2; // This value is also limited by UBO size, ES3.0 only guarantees 16 KiB. // We store 64 bytes per bone. diff --git a/libs/filabridge/include/private/filament/UibGenerator.h b/libs/filabridge/include/private/filament/UibGenerator.h index 91728b5aa5..947fdf35a7 100644 --- a/libs/filabridge/include/private/filament/UibGenerator.h +++ b/libs/filabridge/include/private/filament/UibGenerator.h @@ -21,6 +21,8 @@ #include #include +#include + namespace filament { class UniformInterfaceBlock; @@ -30,6 +32,7 @@ public: static UniformInterfaceBlock const& getPerViewUib() noexcept; static UniformInterfaceBlock const& getPerRenderableUib() noexcept; static UniformInterfaceBlock const& getLightsUib() noexcept; + static UniformInterfaceBlock const& getShadowUib() noexcept; static UniformInterfaceBlock const& getPerRenderableBonesUib() noexcept; }; @@ -112,6 +115,16 @@ struct LightsUib { filament::math::float4 spotScaleOffset; // { scale, offset, unused, unused } }; +// UBO for punctual (spot light) shadows. +struct ShadowUib { + static const UniformInterfaceBlock& getUib() noexcept { + return UibGenerator::getShadowUib(); + } + + filament::math::mat4f spotLightFromWorldMatrix[CONFIG_MAX_SHADOW_CASTING_SPOTS]; + filament::math::float4 directionShadowBias[CONFIG_MAX_SHADOW_CASTING_SPOTS]; // light direction, normal bias +}; + // This is not the UBO proper, but just an element of a bone array. struct PerRenderableUibBone { filament::math::quatf q = { 1, 0, 0, 0 }; diff --git a/libs/filabridge/src/UibGenerator.cpp b/libs/filabridge/src/UibGenerator.cpp index ebd2445d47..dbda6e9a43 100644 --- a/libs/filabridge/src/UibGenerator.cpp +++ b/libs/filabridge/src/UibGenerator.cpp @@ -107,6 +107,15 @@ UniformInterfaceBlock const& UibGenerator::getLightsUib() noexcept { return uib; } +UniformInterfaceBlock const& UibGenerator::getShadowUib() noexcept { + static UniformInterfaceBlock uib = UniformInterfaceBlock::Builder() + .name("ShadowUniforms") + .add("spotLightFromWorldMatrix", CONFIG_MAX_SHADOW_CASTING_SPOTS, UniformInterfaceBlock::Type::MAT4, Precision::HIGH) + .add("directionShadowBias", CONFIG_MAX_SHADOW_CASTING_SPOTS, UniformInterfaceBlock::Type::FLOAT4, Precision::HIGH) + .build(); + return uib; +} + UniformInterfaceBlock const& UibGenerator::getPerRenderableBonesUib() noexcept { static UniformInterfaceBlock uib = UniformInterfaceBlock::Builder() .name("BonesUniforms") diff --git a/libs/filamat/src/shaders/ShaderGenerator.cpp b/libs/filamat/src/shaders/ShaderGenerator.cpp index 332ce7cbb0..d5fa1bc50c 100644 --- a/libs/filamat/src/shaders/ShaderGenerator.cpp +++ b/libs/filamat/src/shaders/ShaderGenerator.cpp @@ -205,6 +205,10 @@ const std::string ShaderGenerator::createVertexProgram(filament::backend::Shader BindingPoints::PER_VIEW, UibGenerator::getPerViewUib()); cg.generateUniforms(vs, ShaderType::VERTEX, BindingPoints::PER_RENDERABLE, UibGenerator::getPerRenderableUib()); + if (litVariants && variant.hasShadowReceiver()) { + cg.generateUniforms(vs, ShaderType::VERTEX, + BindingPoints::SHADOW, UibGenerator::getShadowUib()); + } if (variant.hasSkinningOrMorphing()) { cg.generateUniforms(vs, ShaderType::VERTEX, BindingPoints::PER_RENDERABLE_BONES,