A morphing buffer must be bound when skinning is active
This is because we're using the same program variant for skinning and morphing, in the skinning-only case, the buffer won't be accessed in the shader, but it must be present. fixes #5085
This commit is contained in:
@@ -261,6 +261,20 @@ void FEngine::init() {
|
||||
.package(MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE)
|
||||
.build(*const_cast<FEngine*>(this)));
|
||||
|
||||
// create dummy textures we need throughout the engine
|
||||
|
||||
mDummyOneTexture = driverApi.createTexture(SamplerType::SAMPLER_2D, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mDummyOneTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mDummyZeroTexture = driverApi.createTexture(SamplerType::SAMPLER_2D, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
// dummy textures must be initialized before this call
|
||||
mDummyMorphingSamplerGroup = FMorphTargetBuffer::createDummySampleGroup(*this);
|
||||
|
||||
mPostProcessManager.init();
|
||||
mLightManager.init(*this);
|
||||
mDFG = std::make_unique<DFG>(*this);
|
||||
@@ -344,6 +358,11 @@ void FEngine::shutdown() {
|
||||
}
|
||||
cleanupResourceList(mFences);
|
||||
|
||||
driver.destroySamplerGroup(mDummyMorphingSamplerGroup);
|
||||
driver.destroyTexture(mDummyOneTexture);
|
||||
driver.destroyTexture(mDummyOneTextureArray);
|
||||
driver.destroyTexture(mDummyZeroTexture);
|
||||
|
||||
/*
|
||||
* Shutdown the backend...
|
||||
*/
|
||||
|
||||
@@ -118,10 +118,19 @@ void FMorphTargetBuffer::terminate(FEngine& engine) {
|
||||
driver.destroyTexture(mTbHandle);
|
||||
}
|
||||
|
||||
Handle<HwSamplerGroup> FMorphTargetBuffer::createDummySampleGroup(FEngine& engine) noexcept {
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
Handle<HwSamplerGroup> sgh = driver.createSamplerGroup(PerRenderPrimitiveMorphingSib::SAMPLER_COUNT);
|
||||
backend::SamplerGroup group(PerRenderPrimitiveMorphingSib::SAMPLER_COUNT);
|
||||
group.setSampler(PerRenderPrimitiveMorphingSib::TARGETS, engine.getOneTextureArray(), {});
|
||||
driver.updateSamplerGroup(sgh, std::move(group.toCommandStream()));
|
||||
return sgh;
|
||||
}
|
||||
|
||||
void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex, math::float3 const* positions, size_t count) {
|
||||
ASSERT_PRECONDITION(targetIndex < mCount, "targetIndex must be < count");
|
||||
|
||||
auto size = getSize(mVertexCount);
|
||||
const size_t size = getSize(mVertexCount);
|
||||
|
||||
ASSERT_PRECONDITION((int)sizeof(math::float3) * count <= size,
|
||||
"MorphTargetBuffer (size=%lu) overflow (size=%lu)",
|
||||
|
||||
@@ -253,15 +253,6 @@ void PostProcessManager::init() noexcept {
|
||||
registerPostProcessMaterial(info.name, info.data, info.size);
|
||||
}
|
||||
|
||||
mDummyOneTexture = driver.createTexture(SamplerType::SAMPLER_2D, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mDummyOneTextureArray = driver.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mDummyZeroTexture = driver.createTexture(SamplerType::SAMPLER_2D, 1,
|
||||
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
mStarburstTexture = driver.createTexture(SamplerType::SAMPLER_2D, 1,
|
||||
TextureFormat::R8, 1, 256, 1, 1, TextureUsage::DEFAULT);
|
||||
|
||||
@@ -277,17 +268,26 @@ void PostProcessManager::init() noexcept {
|
||||
float r = 0.5f + 0.5f * dist(gen);
|
||||
return uint8_t(r * 255.0f);
|
||||
});
|
||||
driver.update2DImage(mDummyOneTexture, 0, 0, 0, 1, 1, std::move(dataOne));
|
||||
driver.update3DImage(mDummyOneTextureArray, 0, 0, 0, 0, 1, 1, 1, std::move(dataOneArray));
|
||||
driver.update2DImage(mDummyZeroTexture, 0, 0, 0, 1, 1, std::move(dataZero));
|
||||
driver.update2DImage(mStarburstTexture, 0, 0, 0, 256, 1, std::move(dataStarburst));
|
||||
|
||||
driver.update2DImage(engine.getOneTexture(),
|
||||
0, 0, 0, 1, 1,
|
||||
std::move(dataOne));
|
||||
|
||||
driver.update3DImage(engine.getOneTextureArray(),
|
||||
0, 0, 0, 0, 1, 1, 1,
|
||||
std::move(dataOneArray));
|
||||
|
||||
driver.update2DImage(engine.getZeroTexture(),
|
||||
0, 0, 0, 1, 1,
|
||||
std::move(dataZero));
|
||||
|
||||
driver.update2DImage(mStarburstTexture,
|
||||
0, 0, 0, 256, 1,
|
||||
std::move(dataStarburst));
|
||||
}
|
||||
|
||||
void PostProcessManager::terminate(DriverApi& driver) noexcept {
|
||||
FEngine& engine = mEngine;
|
||||
driver.destroyTexture(mDummyOneTexture);
|
||||
driver.destroyTexture(mDummyOneTextureArray);
|
||||
driver.destroyTexture(mDummyZeroTexture);
|
||||
driver.destroyTexture(mStarburstTexture);
|
||||
auto first = mMaterialRegistry.begin();
|
||||
auto last = mMaterialRegistry.end();
|
||||
@@ -297,6 +297,18 @@ void PostProcessManager::terminate(DriverApi& driver) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> PostProcessManager::getOneTexture() const {
|
||||
return mEngine.getOneTexture();
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> PostProcessManager::getZeroTexture() const {
|
||||
return mEngine.getZeroTexture();
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> PostProcessManager::getOneTextureArray() const {
|
||||
return mEngine.getOneTextureArray();
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void PostProcessManager::commitAndRender(FrameGraphResources::RenderPassInfo const& out,
|
||||
PostProcessMaterial const& material, uint8_t variant, DriverApi& driver) const noexcept {
|
||||
|
||||
@@ -156,9 +156,9 @@ public:
|
||||
FrameGraphId<FrameGraphTexture> output, uint8_t dstLevel, uint8_t layer,
|
||||
bool reinhard, size_t kernelWidth, float sigma = 6.0f) noexcept;
|
||||
|
||||
backend::Handle<backend::HwTexture> getOneTexture() const { return mDummyOneTexture; }
|
||||
backend::Handle<backend::HwTexture> getZeroTexture() const { return mDummyZeroTexture; }
|
||||
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
|
||||
backend::Handle<backend::HwTexture> getOneTexture() const;
|
||||
backend::Handle<backend::HwTexture> getZeroTexture() const;
|
||||
backend::Handle<backend::HwTexture> getOneTextureArray() const;
|
||||
|
||||
math::float2 halton(size_t index) const noexcept {
|
||||
return mHaltonSamples[index & 0xFu];
|
||||
@@ -234,9 +234,6 @@ private:
|
||||
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> mDummyOneTextureArray;
|
||||
backend::Handle<backend::HwTexture> mDummyZeroTexture;
|
||||
backend::Handle<backend::HwTexture> mStarburstTexture;
|
||||
|
||||
std::uniform_real_distribution<float> mUniformDistribution{0.0f, 1.0f};
|
||||
|
||||
@@ -528,12 +528,13 @@ void RenderPass::Executor::execute(const char* name,
|
||||
engine.flush();
|
||||
|
||||
driver.beginRenderPass(renderTarget, params);
|
||||
recordDriverCommands(driver, mBegin, mEnd, mRenderableSoa);
|
||||
recordDriverCommands(engine, driver, mBegin, mEnd, mRenderableSoa);
|
||||
driver.endRenderPass();
|
||||
}
|
||||
|
||||
UTILS_NOINLINE // no need to be inlined
|
||||
void RenderPass::Executor::recordDriverCommands(backend::DriverApi& driver,
|
||||
void RenderPass::Executor::recordDriverCommands(FEngine& engine,
|
||||
backend::DriverApi& driver,
|
||||
const Command* first, const Command* last,
|
||||
FScene::RenderableSoa const& soa) const noexcept {
|
||||
SYSTRACE_CALL();
|
||||
@@ -589,6 +590,11 @@ void RenderPass::Executor::recordDriverCommands(backend::DriverApi& driver,
|
||||
skinning.handle,
|
||||
skinning.offset * sizeof(PerRenderableUibBone),
|
||||
CONFIG_MAX_BONE_COUNT * sizeof(PerRenderableUibBone));
|
||||
|
||||
if (!info.morphTargetBuffer) {
|
||||
driver.bindSamplers(BindingPoints::PER_RENDERABLE_MORPHING,
|
||||
engine.getDummyMorphingSamplerGroup());
|
||||
}
|
||||
}
|
||||
|
||||
if (UTILS_UNLIKELY(info.morphWeightBuffer)) {
|
||||
@@ -598,7 +604,7 @@ void RenderPass::Executor::recordDriverCommands(backend::DriverApi& driver,
|
||||
info.morphWeightBuffer);
|
||||
|
||||
// When only skinning is enabled, morphTargetBuffer isn't created.
|
||||
if (UTILS_UNLIKELY(info.morphTargetBuffer)) {
|
||||
if (info.morphTargetBuffer) {
|
||||
driver.bindSamplers(BindingPoints::PER_RENDERABLE_MORPHING,
|
||||
info.morphTargetBuffer);
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ public:
|
||||
assert_invariant(e <= pass->end());
|
||||
}
|
||||
|
||||
void recordDriverCommands(backend::DriverApi& driver,
|
||||
void recordDriverCommands(FEngine& engine, backend::DriverApi& driver,
|
||||
const Command* first, const Command* last,
|
||||
FScene::RenderableSoa const& soa) const noexcept;
|
||||
|
||||
|
||||
@@ -332,10 +332,15 @@ public:
|
||||
return mRandomEngine;
|
||||
}
|
||||
|
||||
void pumpMessageQueues() {
|
||||
void pumpMessageQueues() const {
|
||||
getDriver().purge();
|
||||
}
|
||||
|
||||
backend::Handle<backend::HwTexture> getOneTexture() const { return mDummyOneTexture; }
|
||||
backend::Handle<backend::HwTexture> getZeroTexture() const { return mDummyZeroTexture; }
|
||||
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
|
||||
backend::Handle<backend::HwSamplerGroup> getDummyMorphingSamplerGroup() const { return mDummyMorphingSamplerGroup; }
|
||||
|
||||
private:
|
||||
FEngine(Backend backend, Platform* platform, void* sharedGLContext);
|
||||
void init();
|
||||
@@ -424,6 +429,11 @@ private:
|
||||
mutable filaflat::ShaderBuilder mFragmentShaderBuilder;
|
||||
FDebugRegistry mDebugRegistry;
|
||||
|
||||
backend::Handle<backend::HwTexture> mDummyOneTexture;
|
||||
backend::Handle<backend::HwTexture> mDummyOneTextureArray;
|
||||
backend::Handle<backend::HwTexture> mDummyZeroTexture;
|
||||
backend::Handle<backend::HwSamplerGroup> mDummyMorphingSamplerGroup;
|
||||
|
||||
std::thread::id mMainThreadId{};
|
||||
|
||||
public:
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
inline size_t getVertexCount() const noexcept { return mVertexCount; }
|
||||
inline size_t getCount() const noexcept { return mCount; }
|
||||
|
||||
static backend::Handle<backend::HwSamplerGroup> createDummySampleGroup(FEngine& engine) noexcept;
|
||||
|
||||
private:
|
||||
friend class FView;
|
||||
friend class RenderPass;
|
||||
|
||||
Reference in New Issue
Block a user