no message
This commit is contained in:
173
cocos/renderer/GFXDeviceManager.h
Normal file
173
cocos/renderer/GFXDeviceManager.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "engine/EngineEvents.h"
|
||||
|
||||
#include "gfx-agent/DeviceAgent.h"
|
||||
#include "gfx-validator/DeviceValidator.h"
|
||||
#include "platform/BasePlatform.h"
|
||||
|
||||
// #undef CC_USE_NVN
|
||||
// #undef CC_USE_VULKAN
|
||||
// #undef CC_USE_METAL
|
||||
// #undef CC_USE_GLES3
|
||||
// #undef CC_USE_GLES2
|
||||
|
||||
#ifdef CC_USE_NVN
|
||||
#include "gfx-nvn/NVNDevice.h"
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_VULKAN
|
||||
#include "gfx-vulkan/VKDevice.h"
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_METAL
|
||||
#include "gfx-metal/MTLDevice.h"
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_GLES3
|
||||
#include "gfx-gles3/GLES3Device.h"
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_GLES2
|
||||
#include "gfx-gles2/GLES2Device.h"
|
||||
#endif
|
||||
|
||||
#include "gfx-empty/EmptyDevice.h"
|
||||
#include "renderer/pipeline/Define.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
class CC_DLL DeviceManager final {
|
||||
static constexpr bool DETACH_DEVICE_THREAD{true};
|
||||
static constexpr bool FORCE_DISABLE_VALIDATION{false};
|
||||
static constexpr bool FORCE_ENABLE_VALIDATION{false};
|
||||
|
||||
public:
|
||||
static Device *create() {
|
||||
DeviceInfo deviceInfo{pipeline::bindingMappingInfo};
|
||||
return DeviceManager::create(deviceInfo);
|
||||
}
|
||||
|
||||
static Device *create(const DeviceInfo &info) {
|
||||
if (Device::instance) return Device::instance;
|
||||
|
||||
Device *device = nullptr;
|
||||
|
||||
#ifdef CC_USE_NVN
|
||||
if (tryCreate<CCNVNDevice>(info, &device)) return device;
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_VULKAN
|
||||
bool skipVulkan = false;
|
||||
#if CC_PLATFORM == CC_PLATFORM_ANDROID
|
||||
auto sdkVersion = BasePlatform::getPlatform()->getSdkVersion();
|
||||
skipVulkan = sdkVersion <= 27; // Android 8
|
||||
#endif
|
||||
if (!skipVulkan && tryCreate<CCVKDevice>(info, &device)) return device;
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_METAL
|
||||
if (tryCreate<CCMTLDevice>(info, &device)) return device;
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_GLES3
|
||||
#if CC_USE_XR || CC_USE_AR_MODULE
|
||||
Device::isSupportDetachDeviceThread = false;
|
||||
#endif
|
||||
if (tryCreate<GLES3Device>(info, &device)) return device;
|
||||
#endif
|
||||
|
||||
#ifdef CC_USE_GLES2
|
||||
// arcore & arengine currently only supports gles, session update requires gl context
|
||||
#if CC_USE_AR_MODULE
|
||||
Device::isSupportDetachDeviceThread = false;
|
||||
#endif
|
||||
if (tryCreate<GLES2Device>(info, &device)) return device;
|
||||
#endif
|
||||
|
||||
#ifdef CC_EDITOR
|
||||
Device::isSupportDetachDeviceThread = false;
|
||||
#endif
|
||||
if (tryCreate<EmptyDevice>(info, &device)) return device;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool isDetachDeviceThread() {
|
||||
return DETACH_DEVICE_THREAD && Device::isSupportDetachDeviceThread;
|
||||
}
|
||||
|
||||
static ccstd::string getGFXName() {
|
||||
ccstd::string gfx = "unknown";
|
||||
#ifdef CC_USE_NVN
|
||||
gfx = "NVN";
|
||||
#elif defined(CC_USE_VULKAN)
|
||||
gfx = "Vulkan";
|
||||
#elif defined(CC_USE_METAL)
|
||||
gfx = "Metal";
|
||||
#elif defined(CC_USE_GLES3)
|
||||
gfx = "GLES3";
|
||||
#elif defined(CC_USE_GLES2)
|
||||
gfx = "GLES2";
|
||||
#else
|
||||
gfx = "Empty";
|
||||
#endif
|
||||
|
||||
return gfx;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename DeviceCtor, typename Enable = std::enable_if_t<std::is_base_of<Device, DeviceCtor>::value>>
|
||||
static bool tryCreate(const DeviceInfo &info, Device **pDevice) {
|
||||
Device *device = ccnew DeviceCtor;
|
||||
|
||||
if (isDetachDeviceThread()) {
|
||||
device = ccnew gfx::DeviceAgent(device);
|
||||
}
|
||||
|
||||
#if !defined(CC_SERVER_MODE)
|
||||
if (CC_DEBUG > 0 && !FORCE_DISABLE_VALIDATION || FORCE_ENABLE_VALIDATION) {
|
||||
device = ccnew gfx::DeviceValidator(device);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!device->initialize(info)) {
|
||||
CC_SAFE_DELETE(device);
|
||||
return false;
|
||||
}
|
||||
*pDevice = device;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef CC_DEBUG
|
||||
static constexpr int CC_DEBUG{0};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
116
cocos/renderer/core/MaterialInstance.cpp
Normal file
116
cocos/renderer/core/MaterialInstance.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
***************************************************************************/
|
||||
|
||||
#include "renderer/core/MaterialInstance.h"
|
||||
// #include "core/components/RenderableComponent.h"
|
||||
#include "renderer/core/PassInstance.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
MaterialInstance::MaterialInstance(const IMaterialInstanceInfo &info) {
|
||||
_parent = info.parent;
|
||||
// _owner = info.owner;
|
||||
_subModelIdx = info.subModelIdx;
|
||||
copy(_parent);
|
||||
}
|
||||
|
||||
void MaterialInstance::recompileShaders(const MacroRecord &overrides, index_t passIdx /* = CC_INVALID_INDEX */) {
|
||||
auto &passes = *_passes;
|
||||
if (passes.empty() || _effectAsset == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (passIdx == CC_INVALID_INDEX) {
|
||||
for (const auto &pass : passes) {
|
||||
pass->tryCompile(overrides);
|
||||
}
|
||||
} else {
|
||||
if (passIdx < passes.size()) {
|
||||
auto *pass = passes[passIdx].get();
|
||||
pass->tryCompile(overrides);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialInstance::overridePipelineStates(const PassOverrides &overrides, index_t passIdx /* = CC_INVALID_INDEX */) {
|
||||
auto &passes = *_passes;
|
||||
if (passes.empty() || _effectAsset == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ccstd::vector<IPassInfoFull> &passInfos = _effectAsset->_techniques[getTechniqueIndex()].passes;
|
||||
if (passIdx == CC_INVALID_INDEX) {
|
||||
for (size_t i = 0, len = passes.size(); i < len; i++) {
|
||||
auto *pass = passes[i].get();
|
||||
if (i >= _states.size()) {
|
||||
_states.resize(i + 1);
|
||||
}
|
||||
auto &state = _states[i];
|
||||
state.overrides(IPassInfoFull(overrides));
|
||||
pass->overridePipelineStates(passInfos[pass->getPassIndex()], state);
|
||||
}
|
||||
} else {
|
||||
if (passIdx >= _states.size()) {
|
||||
_states.resize(passIdx + 1);
|
||||
}
|
||||
auto &state = _states[passIdx];
|
||||
state.overrides(IPassInfoFull(overrides));
|
||||
passes[passIdx]->overridePipelineStates(passInfos[passIdx], state);
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialInstance::destroy() {
|
||||
doDestroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
ccstd::vector<IntrusivePtr<scene::Pass>> MaterialInstance::createPasses() {
|
||||
ccstd::vector<IntrusivePtr<scene::Pass>> passes;
|
||||
auto &parentPasses = _parent->getPasses();
|
||||
|
||||
passes.reserve(parentPasses->size());
|
||||
for (auto &parentPass : *parentPasses) {
|
||||
passes.emplace_back(ccnew PassInstance(parentPass, this));
|
||||
}
|
||||
return passes;
|
||||
}
|
||||
|
||||
void MaterialInstance::onPassStateChange(bool dontNotify) {
|
||||
_hash = Material::getHashForMaterial(this);
|
||||
if (!dontNotify) {
|
||||
if (_rebuildPSOCallback != nullptr) {
|
||||
_rebuildPSOCallback(_subModelIdx, this);
|
||||
}
|
||||
|
||||
// if (_owner != nullptr) {
|
||||
// _owner->onRebuildPSO(_subModelIdx, this);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialInstance::setRebuildPSOCallback(const RebuildPSOCallback &cb) {
|
||||
_rebuildPSOCallback = cb;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
90
cocos/renderer/core/MaterialInstance.h
Normal file
90
cocos/renderer/core/MaterialInstance.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/TypeDef.h"
|
||||
#include "base/std/optional.h"
|
||||
|
||||
#include "core/assets/Material.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
struct IMaterialInstanceInfo {
|
||||
Material *parent{nullptr};
|
||||
// RenderableComponent *owner{nullptr};
|
||||
index_t subModelIdx{0};
|
||||
};
|
||||
|
||||
class PassInstance;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 材质实例,当有材质修改需求时,根据材质资源创建的,可任意定制的实例。
|
||||
*/
|
||||
class MaterialInstance final : public Material {
|
||||
public:
|
||||
using Super = Material;
|
||||
|
||||
explicit MaterialInstance(const IMaterialInstanceInfo &info);
|
||||
|
||||
Material *getParent() const override {
|
||||
return _parent.get();
|
||||
}
|
||||
|
||||
// RenderableComponent *getOwner() const override {
|
||||
// return _owner;
|
||||
// }
|
||||
|
||||
void recompileShaders(const MacroRecord &overrides) override {
|
||||
MaterialInstance::recompileShaders(overrides, CC_INVALID_INDEX);
|
||||
}
|
||||
void recompileShaders(const MacroRecord &overrides, index_t passIdx) override;
|
||||
|
||||
void overridePipelineStates(const PassOverrides &overrides) override {
|
||||
MaterialInstance::overridePipelineStates(overrides, CC_INVALID_INDEX);
|
||||
}
|
||||
void overridePipelineStates(const PassOverrides &overrides, index_t passIdx) override;
|
||||
|
||||
bool destroy() override;
|
||||
|
||||
void onPassStateChange(bool dontNotify);
|
||||
|
||||
// For JS
|
||||
using RebuildPSOCallback = std::function<void(index_t index, Material *material)>;
|
||||
void setRebuildPSOCallback(const RebuildPSOCallback &cb);
|
||||
//
|
||||
|
||||
protected:
|
||||
ccstd::vector<IntrusivePtr<scene::Pass>> createPasses() override;
|
||||
|
||||
private:
|
||||
IntrusivePtr<Material> _parent;
|
||||
// RenderableComponent *_owner{nullptr};
|
||||
index_t _subModelIdx{0};
|
||||
|
||||
RebuildPSOCallback _rebuildPSOCallback{nullptr};
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
115
cocos/renderer/core/PassInstance.cpp
Normal file
115
cocos/renderer/core/PassInstance.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cocos/renderer/core/PassInstance.h"
|
||||
#include "cocos/renderer/core/MaterialInstance.h"
|
||||
#include "cocos/renderer/core/ProgramLib.h"
|
||||
#include "cocos/renderer/pipeline/InstancedBuffer.h"
|
||||
#include "cocos/renderer/pipeline/custom/RenderingModule.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
PassInstance::PassInstance(scene::Pass *parent, MaterialInstance *owner)
|
||||
: Super(parent->getRoot()), _parent(parent), _owner(owner) {
|
||||
doInit(_parent->getPassInfoFull());
|
||||
for (const auto &b : _shaderInfo->blocks) {
|
||||
scene::IBlockRef &block = _blocks[b.binding];
|
||||
const scene::IBlockRef &parentBlock = _parent->getBlocks()[b.binding];
|
||||
CC_ASSERT(block.count == parentBlock.count);
|
||||
memcpy(block.data, parentBlock.data, parentBlock.count * 4);
|
||||
}
|
||||
|
||||
_rootBufferDirty = true;
|
||||
gfx::DescriptorSet *parentDescriptorSet = _parent->getDescriptorSet();
|
||||
|
||||
auto *programLib = render::getProgramLibrary();
|
||||
if (programLib) {
|
||||
const auto &set = _shaderInfo->descriptors.at(
|
||||
static_cast<size_t>(pipeline::SetIndex::MATERIAL));
|
||||
for (const auto &samplerTexture : set.samplerTextures) {
|
||||
for (uint32_t i = 0; i < samplerTexture.count; ++i) {
|
||||
auto *sampler = parentDescriptorSet->getSampler(samplerTexture.binding, i);
|
||||
auto *texture = parentDescriptorSet->getTexture(samplerTexture.binding, i);
|
||||
_descriptorSet->bindSampler(samplerTexture.binding, sampler, i);
|
||||
_descriptorSet->bindTexture(samplerTexture.binding, texture, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto &samplerTexture : _shaderInfo->samplerTextures) {
|
||||
for (uint32_t i = 0; i < samplerTexture.count; ++i) {
|
||||
auto *sampler = parentDescriptorSet->getSampler(samplerTexture.binding, i);
|
||||
auto *texture = parentDescriptorSet->getTexture(samplerTexture.binding, i);
|
||||
_descriptorSet->bindSampler(samplerTexture.binding, sampler, i);
|
||||
_descriptorSet->bindTexture(samplerTexture.binding, texture, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Super::tryCompile();
|
||||
}
|
||||
|
||||
PassInstance::~PassInstance() = default;
|
||||
|
||||
scene::Pass *PassInstance::getParent() const {
|
||||
return _parent.get();
|
||||
}
|
||||
|
||||
void PassInstance::overridePipelineStates(const IPassInfo &original, const PassOverrides &override) {
|
||||
_blendState.reset();
|
||||
_rs.reset();
|
||||
_depthStencilState.reset();
|
||||
|
||||
scene::Pass::fillPipelineInfo(this, original);
|
||||
scene::Pass::fillPipelineInfo(this, IPassInfoFull(override));
|
||||
onStateChange();
|
||||
}
|
||||
|
||||
bool PassInstance::tryCompile(const ccstd::optional<MacroRecord> &defineOverrides) {
|
||||
if (defineOverrides.has_value()) {
|
||||
if (!overrideMacros(_defines, defineOverrides.value())) return false;
|
||||
}
|
||||
bool ret = Super::tryCompile();
|
||||
onStateChange();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PassInstance::beginChangeStatesSilently() {
|
||||
_dontNotify = true;
|
||||
}
|
||||
|
||||
void PassInstance::endChangeStatesSilently() {
|
||||
_dontNotify = false;
|
||||
}
|
||||
|
||||
void PassInstance::syncBatchingScheme() {
|
||||
_defines["USE_INSTANCING"] = false;
|
||||
_batchingScheme = scene::BatchingSchemes::NONE;
|
||||
}
|
||||
|
||||
void PassInstance::onStateChange() {
|
||||
_hash = scene::Pass::getPassHash(this);
|
||||
_owner->onPassStateChange(_dontNotify);
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
83
cocos/renderer/core/PassInstance.h
Normal file
83
cocos/renderer/core/PassInstance.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/std/optional.h"
|
||||
#include "scene/Pass.h"
|
||||
|
||||
namespace cc {
|
||||
class MaterialInstance;
|
||||
/**
|
||||
* @en A pass instance defines an variant version of the [[Pass]]
|
||||
* @zh 表示 [[Pass]] 的一种特殊实例
|
||||
*/
|
||||
class PassInstance final : public scene::Pass {
|
||||
public:
|
||||
using Super = scene::Pass;
|
||||
|
||||
PassInstance(scene::Pass *parent, MaterialInstance *owner);
|
||||
~PassInstance() override;
|
||||
/**
|
||||
* @en The parent pass
|
||||
* @zh 相关联的原始 Pass
|
||||
*/
|
||||
scene::Pass *getParent() const;
|
||||
|
||||
/**
|
||||
* @en Override pipeline states with the given pass override info.
|
||||
* This won't affect the original pass
|
||||
* @zh 重载当前 Pass 的管线状态。这不会影响原始 Pass
|
||||
* @param original The original pass info
|
||||
* @param value The override pipeline state info
|
||||
*/
|
||||
void overridePipelineStates(const IPassInfo &original, const PassOverrides &override) override;
|
||||
|
||||
bool tryCompile(const ccstd::optional<MacroRecord> &defineOverrides) override;
|
||||
|
||||
/**
|
||||
* @en Prepare to change states of the pass and do not notify the material to rebuild the pipeline state object
|
||||
* @zh 开始静默修改 Pass 相关状态,不会通知材质去重新构建管线状态对象。
|
||||
*/
|
||||
void beginChangeStatesSilently() override;
|
||||
|
||||
/**
|
||||
* @en End the silent states changing process, all state changes will be notified.
|
||||
* @zh 结束静默状态修改,所有修改将会开始通知材质。
|
||||
*/
|
||||
void endChangeStatesSilently() override;
|
||||
|
||||
protected:
|
||||
void syncBatchingScheme() override;
|
||||
|
||||
void onStateChange();
|
||||
|
||||
private:
|
||||
IntrusivePtr<scene::Pass> _parent;
|
||||
// Weak reference.
|
||||
MaterialInstance *_owner{nullptr};
|
||||
bool _dontNotify{false};
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
365
cocos/renderer/core/PassUtils.cpp
Normal file
365
cocos/renderer/core/PassUtils.cpp
Normal file
@@ -0,0 +1,365 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "renderer/core/PassUtils.h"
|
||||
#include <cstdint>
|
||||
#include "base/Log.h"
|
||||
#include "core/Types.h"
|
||||
#include "core/assets/TextureBase.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
const ccstd::unordered_map<gfx::Type, GFXTypeReaderCallback> type2reader = {
|
||||
{gfx::Type::UNKNOWN, [](const float * /*a*/, MaterialProperty & /*v*/, index_t /*idx*/) {
|
||||
CC_LOG_ERROR("type2reader unknown type");
|
||||
}},
|
||||
{gfx::Type::INT, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = static_cast<int32_t>(a[idx]);
|
||||
}},
|
||||
{gfx::Type::INT2, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = Vec2(a[idx], a[idx + 1]);
|
||||
}},
|
||||
{gfx::Type::INT3, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = Vec3(a[idx], a[idx + 1], a[idx + 2]);
|
||||
}},
|
||||
{gfx::Type::INT4, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = Vec4(a[idx], a[idx + 1], a[idx + 2], a[idx + 3]);
|
||||
}},
|
||||
{gfx::Type::FLOAT, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = a[idx];
|
||||
}},
|
||||
{gfx::Type::FLOAT2, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = Vec2(a[idx], a[idx + 1]);
|
||||
}},
|
||||
{gfx::Type::FLOAT3, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = Vec3(a[idx], a[idx + 1], a[idx + 2]);
|
||||
}},
|
||||
{gfx::Type::FLOAT4, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
v = Vec4(a[idx], a[idx + 1], a[idx + 2], a[idx + 3]);
|
||||
}},
|
||||
{gfx::Type::MAT3, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
Mat3 mat3;
|
||||
memcpy(&mat3.m[0], &a[idx], sizeof(Mat3));
|
||||
v = mat3;
|
||||
}},
|
||||
{gfx::Type::MAT4, [](const float *a, MaterialProperty &v, index_t idx) {
|
||||
Mat4 mat4;
|
||||
memcpy(&mat4.m[0], &a[idx], sizeof(Mat4));
|
||||
v = mat4;
|
||||
}},
|
||||
};
|
||||
|
||||
const ccstd::unordered_map<gfx::Type, GFXTypeWriterCallback> type2writer = {
|
||||
{gfx::Type::UNKNOWN, [](float * /*a*/, const MaterialProperty & /*v*/, index_t /*idx*/) {
|
||||
CC_LOG_ERROR("type2writer unknown type");
|
||||
}},
|
||||
{gfx::Type::INT, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const int32_t *p = ccstd::get_if<int32_t>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
a[idx] = static_cast<float>(*p);
|
||||
}},
|
||||
{gfx::Type::INT2, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const auto *p = ccstd::get_if<Vec2>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
a[idx] = p->x;
|
||||
a[idx + 1] = p->y;
|
||||
}},
|
||||
{gfx::Type::INT3, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const auto *p = ccstd::get_if<Vec3>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
a[idx] = p->x;
|
||||
a[idx + 1] = p->y;
|
||||
a[idx + 2] = p->z;
|
||||
}},
|
||||
{gfx::Type::INT4, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const auto *p = ccstd::get_if<Vec4>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
a[idx] = p->x;
|
||||
a[idx + 1] = p->y;
|
||||
a[idx + 2] = p->z;
|
||||
a[idx + 3] = p->w;
|
||||
}},
|
||||
{gfx::Type::FLOAT, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const float *p = ccstd::get_if<float>(&v);
|
||||
const int32_t *pInt = nullptr;
|
||||
if (p != nullptr) {
|
||||
a[idx] = *p;
|
||||
} else {
|
||||
pInt = ccstd::get_if<int32_t>(&v);
|
||||
if (pInt != nullptr) {
|
||||
a[idx] = static_cast<float>(*pInt);
|
||||
}
|
||||
}
|
||||
CC_ASSERT(p != nullptr || pInt != nullptr);
|
||||
}},
|
||||
{gfx::Type::FLOAT2, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const auto *p = ccstd::get_if<Vec2>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
a[idx] = p->x;
|
||||
a[idx + 1] = p->y;
|
||||
}},
|
||||
{gfx::Type::FLOAT3, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
if (ccstd::holds_alternative<Vec3>(v)) {
|
||||
const auto &vec3 = ccstd::get<Vec3>(v);
|
||||
a[idx] = vec3.x;
|
||||
a[idx + 1] = vec3.y;
|
||||
a[idx + 2] = vec3.z;
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
}},
|
||||
{gfx::Type::FLOAT4, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
if (ccstd::holds_alternative<Vec4>(v)) {
|
||||
const auto &vec4 = ccstd::get<Vec4>(v);
|
||||
a[idx] = vec4.x;
|
||||
a[idx + 1] = vec4.y;
|
||||
a[idx + 2] = vec4.z;
|
||||
a[idx + 3] = vec4.w;
|
||||
} else if (ccstd::holds_alternative<Color>(v)) {
|
||||
const auto &color = ccstd::get<Color>(v);
|
||||
Vec4 colorFloat{color.toVec4()};
|
||||
a[idx] = colorFloat.x;
|
||||
a[idx + 1] = colorFloat.y;
|
||||
a[idx + 2] = colorFloat.z;
|
||||
a[idx + 3] = colorFloat.w;
|
||||
} else if (ccstd::holds_alternative<Quaternion>(v)) {
|
||||
const auto &quat = ccstd::get<Quaternion>(v);
|
||||
a[idx] = quat.x;
|
||||
a[idx + 1] = quat.y;
|
||||
a[idx + 2] = quat.z;
|
||||
a[idx + 3] = quat.w;
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
}},
|
||||
{gfx::Type::MAT3, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const auto *p = ccstd::get_if<Mat3>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
memcpy(&a[idx], &p->m[0], sizeof(Mat3));
|
||||
}},
|
||||
{gfx::Type::MAT4, [](float *a, const MaterialProperty &v, index_t idx) {
|
||||
const auto *p = ccstd::get_if<Mat4>(&v);
|
||||
CC_ASSERT_NOT_NULL(p);
|
||||
memcpy(&a[idx], &p->m[0], sizeof(Mat4));
|
||||
}},
|
||||
};
|
||||
|
||||
const ccstd::unordered_map<gfx::Type, GFXTypeValidatorCallback> type2validator = {
|
||||
{gfx::Type::UNKNOWN, [](const MaterialProperty & /*v*/) -> bool {
|
||||
CC_LOG_ERROR("type2validator unknown type");
|
||||
return false;
|
||||
}},
|
||||
{gfx::Type::INT, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<int32_t>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::INT2, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Vec2>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::INT3, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Vec3>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::INT4, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Vec4>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::FLOAT, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<float>(&v);
|
||||
const auto *pInt = ccstd::get_if<int32_t>(&v);
|
||||
return p != nullptr || pInt != nullptr;
|
||||
}},
|
||||
{gfx::Type::FLOAT2, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Vec2>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::FLOAT3, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Vec3>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::FLOAT4, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Vec4>(&v);
|
||||
const auto *pColor = ccstd::get_if<Color>(&v);
|
||||
const auto *pQuat = ccstd::get_if<Quaternion>(&v);
|
||||
return p != nullptr || pColor != nullptr || pQuat != nullptr;
|
||||
}},
|
||||
{gfx::Type::MAT3, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Mat3>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
{gfx::Type::MAT4, [](const MaterialProperty &v) -> bool {
|
||||
const auto *p = ccstd::get_if<Mat4>(&v);
|
||||
return p != nullptr;
|
||||
}},
|
||||
};
|
||||
|
||||
const ccstd::vector<float> &getDefaultFloatArrayFromType(gfx::Type type) {
|
||||
static const ccstd::vector<float> DEFAULT_FLOAT_VALUES[] = {
|
||||
{0},
|
||||
{0, 0},
|
||||
{0, 0, 0, 0},
|
||||
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
|
||||
|
||||
switch (type) {
|
||||
case gfx::Type::BOOL:
|
||||
case gfx::Type::INT:
|
||||
case gfx::Type::UINT:
|
||||
case gfx::Type::FLOAT:
|
||||
return DEFAULT_FLOAT_VALUES[0];
|
||||
case gfx::Type::BOOL2:
|
||||
case gfx::Type::INT2:
|
||||
case gfx::Type::UINT2:
|
||||
case gfx::Type::FLOAT2:
|
||||
return DEFAULT_FLOAT_VALUES[1];
|
||||
case gfx::Type::BOOL4:
|
||||
case gfx::Type::INT4:
|
||||
case gfx::Type::UINT4:
|
||||
case gfx::Type::FLOAT4:
|
||||
return DEFAULT_FLOAT_VALUES[2];
|
||||
case gfx::Type::MAT4:
|
||||
return DEFAULT_FLOAT_VALUES[3];
|
||||
default:
|
||||
return DEFAULT_FLOAT_VALUES[0];
|
||||
}
|
||||
}
|
||||
|
||||
const ccstd::string &getDefaultStringFromType(gfx::Type type) {
|
||||
static const ccstd::string DEFAULT_TEXTURE_STR{"default-texture"};
|
||||
static const ccstd::string DEFAULT_CUBE_TEXTURE_STR{"default-cube-texture"};
|
||||
|
||||
switch (type) {
|
||||
case gfx::Type::SAMPLER2D:
|
||||
return DEFAULT_TEXTURE_STR;
|
||||
case gfx::Type::SAMPLER_CUBE:
|
||||
return DEFAULT_CUBE_TEXTURE_STR;
|
||||
default:
|
||||
return DEFAULT_TEXTURE_STR;
|
||||
}
|
||||
}
|
||||
|
||||
const ccstd::string &getStringFromType(gfx::Type type) {
|
||||
static const ccstd::string TEXTURE_2D_STR{"-texture"};
|
||||
static const ccstd::string TEXTURE_CUBE_STR{"-cube-texture"};
|
||||
static const ccstd::string TEXTURE_2D_ARRAY_STR{"-array-texture"};
|
||||
static const ccstd::string TEXTURE_3D_STR{"-3d-texture"};
|
||||
static const ccstd::string UNKNOWN_STR{"-unknown"};
|
||||
|
||||
switch (type) {
|
||||
case gfx::Type::SAMPLER2D:
|
||||
return TEXTURE_2D_STR;
|
||||
case gfx::Type::SAMPLER_CUBE:
|
||||
return TEXTURE_CUBE_STR;
|
||||
case gfx::Type::SAMPLER2D_ARRAY:
|
||||
return TEXTURE_2D_ARRAY_STR;
|
||||
case gfx::Type::SAMPLER3D:
|
||||
return TEXTURE_3D_STR;
|
||||
default:
|
||||
return UNKNOWN_STR;
|
||||
}
|
||||
}
|
||||
|
||||
bool overrideMacros(MacroRecord &target, const MacroRecord &source) {
|
||||
bool isDifferent = false;
|
||||
for (const auto &p : source) {
|
||||
if (target[p.first] != p.second) {
|
||||
target[p.first] = p.second;
|
||||
isDifferent = true;
|
||||
}
|
||||
}
|
||||
return isDifferent;
|
||||
}
|
||||
|
||||
MaterialProperty toMaterialProperty(gfx::Type type, const ccstd::vector<float> &vec) {
|
||||
MaterialProperty ret;
|
||||
size_t size = vec.size();
|
||||
|
||||
switch (type) {
|
||||
case gfx::Type::FLOAT:
|
||||
CC_ASSERT_GE(size, 1);
|
||||
ret = vec[0];
|
||||
break;
|
||||
case gfx::Type::FLOAT2:
|
||||
CC_ASSERT_GE(size, 2);
|
||||
ret = Vec2(vec[0], vec[1]);
|
||||
break;
|
||||
case gfx::Type::FLOAT3:
|
||||
CC_ASSERT_GE(size, 3);
|
||||
ret = Vec3(vec[0], vec[1], vec[2]);
|
||||
break;
|
||||
case gfx::Type::FLOAT4:
|
||||
CC_ASSERT_GE(size, 4);
|
||||
ret = Vec4(vec[0], vec[1], vec[2], vec[3]);
|
||||
break;
|
||||
case gfx::Type::MAT3:
|
||||
CC_ASSERT_GE(size, 9);
|
||||
ret = Mat3(vec.data());
|
||||
break;
|
||||
case gfx::Type::MAT4:
|
||||
CC_ASSERT_GE(size, 16);
|
||||
ret = Mat4(vec.data());
|
||||
break;
|
||||
case gfx::Type::INT:
|
||||
case gfx::Type::INT2:
|
||||
case gfx::Type::INT3:
|
||||
case gfx::Type::INT4:
|
||||
default:
|
||||
CC_ABORT();
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool macroRecordAsBool(const MacroRecord::mapped_type &v) {
|
||||
if (ccstd::holds_alternative<bool>(v)) {
|
||||
return ccstd::get<bool>(v);
|
||||
}
|
||||
|
||||
if (ccstd::holds_alternative<int32_t>(v)) {
|
||||
return ccstd::get<int32_t>(v) != 0;
|
||||
}
|
||||
|
||||
if (ccstd::holds_alternative<ccstd::string>(v)) {
|
||||
return ccstd::get<ccstd::string>(v) == "true";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ccstd::string macroRecordAsString(const MacroRecord::mapped_type &v) {
|
||||
if (ccstd::holds_alternative<ccstd::string>(v)) {
|
||||
return ccstd::get<ccstd::string>(v);
|
||||
}
|
||||
|
||||
if (ccstd::holds_alternative<bool>(v)) {
|
||||
return ccstd::get<bool>(v) ? "1" : "0";
|
||||
}
|
||||
|
||||
if (ccstd::holds_alternative<int32_t>(v)) {
|
||||
return std::to_string(ccstd::get<int32_t>(v));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}; // namespace cc
|
||||
118
cocos/renderer/core/PassUtils.h
Normal file
118
cocos/renderer/core/PassUtils.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Ptr.h"
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/vector.h"
|
||||
#include "base/std/variant.h"
|
||||
|
||||
#include "math/Color.h"
|
||||
#include "math/Mat3.h"
|
||||
#include "math/Mat4.h"
|
||||
#include "math/Quaternion.h"
|
||||
#include "math/Vec2.h"
|
||||
#include "math/Vec3.h"
|
||||
#include "math/Vec4.h"
|
||||
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
#include "renderer/gfx-base/GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class TextureBase;
|
||||
|
||||
constexpr uint32_t TYPE_MASK = 0xfc000000; // 6 bits => 64 types
|
||||
constexpr uint32_t BINDING_MASK = 0x03f00000; // 6 bits => 64 bindings
|
||||
constexpr uint32_t COUNT_MASK = 0x000ff000; // 8 bits => 256 vectors
|
||||
constexpr uint32_t OFFSET_MASK = 0x00000fff; // 12 bits => 1024 vectors
|
||||
|
||||
constexpr uint32_t genHandle(uint32_t binding, gfx::Type type, uint32_t count, uint32_t offset = 0) {
|
||||
return ((static_cast<uint32_t>(type) << 26) & TYPE_MASK) |
|
||||
((binding << 20) & BINDING_MASK) |
|
||||
((count << 12) & COUNT_MASK) |
|
||||
(offset & OFFSET_MASK);
|
||||
}
|
||||
|
||||
constexpr gfx::Type getTypeFromHandle(uint32_t handle) { return static_cast<gfx::Type>((handle & TYPE_MASK) >> 26); }
|
||||
constexpr uint32_t getBindingFromHandle(uint32_t handle) { return (handle & BINDING_MASK) >> 20; }
|
||||
constexpr uint32_t getCountFromHandle(uint32_t handle) { return (handle & COUNT_MASK) >> 12; }
|
||||
constexpr uint32_t getOffsetFromHandle(uint32_t handle) { return (handle & OFFSET_MASK); }
|
||||
constexpr uint32_t customizeType(uint32_t handle, gfx::Type type) {
|
||||
return (handle & ~TYPE_MASK) | ((static_cast<uint32_t>(type) << 26) & TYPE_MASK);
|
||||
}
|
||||
|
||||
using MacroValue = ccstd::variant<ccstd::monostate, int32_t, bool, ccstd::string>;
|
||||
|
||||
/**
|
||||
* @en Combination of preprocess macros
|
||||
* @zh 预处理宏组合
|
||||
*/
|
||||
using MacroRecord = ccstd::unordered_map<ccstd::string, MacroValue>;
|
||||
|
||||
using MaterialProperty = ccstd::variant<ccstd::monostate /*0*/, float /*1*/, int32_t /*2*/, Vec2 /*3*/, Vec3 /*4*/, Vec4 /*5*/, Color, /*6*/ Mat3 /*7*/, Mat4 /*8*/, Quaternion /*9*/, IntrusivePtr<TextureBase> /*10*/, IntrusivePtr<gfx::Texture> /*11*/>;
|
||||
|
||||
using MaterialPropertyList = ccstd::vector<MaterialProperty>;
|
||||
|
||||
using MaterialPropertyVariant = ccstd::variant<ccstd::monostate /*0*/, MaterialProperty /*1*/, MaterialPropertyList /*2*/>;
|
||||
|
||||
#define MATERIAL_PROPERTY_INDEX_SINGLE 1
|
||||
#define MATERIAL_PROPERTY_INDEX_LIST 2
|
||||
|
||||
using GFXTypeReaderCallback = void (*)(const float *, MaterialProperty &, index_t);
|
||||
using GFXTypeWriterCallback = void (*)(float *, const MaterialProperty &, index_t);
|
||||
using GFXTypeValidatorCallback = bool (*)(const MaterialProperty &);
|
||||
|
||||
extern const ccstd::unordered_map<gfx::Type, GFXTypeReaderCallback> type2reader; // NOLINT(readability-identifier-naming)
|
||||
extern const ccstd::unordered_map<gfx::Type, GFXTypeWriterCallback> type2writer; // NOLINT(readability-identifier-naming)
|
||||
extern const ccstd::unordered_map<gfx::Type, GFXTypeValidatorCallback> type2validator; // NOLINT(readability-identifier-naming)
|
||||
|
||||
/**
|
||||
* @en Gets the default values for the given type of uniform
|
||||
* @zh 根据指定的 Uniform 类型来获取默认值
|
||||
* @param type The type of the uniform
|
||||
*/
|
||||
const ccstd::vector<float> &getDefaultFloatArrayFromType(gfx::Type type);
|
||||
const ccstd::string &getDefaultStringFromType(gfx::Type type);
|
||||
const ccstd::string &getStringFromType(gfx::Type type);
|
||||
|
||||
/**
|
||||
* @en Combination of preprocess macros
|
||||
* @zh 预处理宏组合
|
||||
*/
|
||||
/**
|
||||
* @en Override the preprocess macros
|
||||
* @zh 覆写预处理宏
|
||||
* @param target Target preprocess macros to be overridden
|
||||
* @param source Preprocess macros used for override
|
||||
*/
|
||||
bool overrideMacros(MacroRecord &target, const MacroRecord &source);
|
||||
|
||||
MaterialProperty toMaterialProperty(gfx::Type type, const ccstd::vector<float> &vec);
|
||||
|
||||
bool macroRecordAsBool(const MacroRecord::mapped_type &v);
|
||||
ccstd::string macroRecordAsString(const MacroRecord::mapped_type &v);
|
||||
|
||||
} // namespace cc
|
||||
498
cocos/renderer/core/ProgramLib.cpp
Normal file
498
cocos/renderer/core/ProgramLib.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "renderer/core/ProgramLib.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
#include <ostream>
|
||||
#include "ProgramUtils.h"
|
||||
#include "base/Log.h"
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
#include "renderer/pipeline/custom/RenderInterfaceTypes.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
|
||||
void insertBuiltinBindings(const IProgramInfo &tmpl, ITemplateInfo &tmplInfo, const pipeline::DescriptorSetLayoutInfos &source,
|
||||
const ccstd::string &type, ccstd::vector<gfx::DescriptorSetLayoutBinding> *outBindings) {
|
||||
CC_ASSERT(type == "locals" || type == "globals");
|
||||
const auto &target = type == "globals" ? tmpl.builtins.globals : tmpl.builtins.locals;
|
||||
|
||||
// Blocks
|
||||
ccstd::vector<gfx::UniformBlock> tempBlocks{};
|
||||
for (const auto &b : target.blocks) {
|
||||
auto infoIt = source.blocks.find(b.name);
|
||||
if (infoIt == source.blocks.end()) {
|
||||
CC_LOG_WARNING("builtin UBO '%s' not available !", b.name.c_str());
|
||||
continue;
|
||||
}
|
||||
const auto &info = infoIt->second;
|
||||
const auto bindingsIter = std::find_if(source.bindings.begin(), source.bindings.end(), [&info](const auto &bd) -> bool { return bd.binding == info.binding; });
|
||||
if (bindingsIter == source.bindings.end()) {
|
||||
CC_LOG_WARNING("builtin UBO '%s' not available !", b.name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
tempBlocks.emplace_back(info);
|
||||
|
||||
if (outBindings != nullptr && std::count_if(outBindings->begin(), outBindings->end(), [&bindingsIter](const auto &b) { return b.binding == bindingsIter->binding; }) == 0) {
|
||||
outBindings->emplace_back(*bindingsIter);
|
||||
}
|
||||
}
|
||||
tmplInfo.shaderInfo.blocks.insert(tmplInfo.shaderInfo.blocks.begin(), tempBlocks.begin(), tempBlocks.end());
|
||||
|
||||
// SamplerTextures
|
||||
ccstd::vector<gfx::UniformSamplerTexture> tempSamplerTextures;
|
||||
for (const auto &s : target.samplerTextures) {
|
||||
auto infoIt = source.samplers.find(s.name);
|
||||
if (infoIt == source.samplers.end()) {
|
||||
CC_LOG_WARNING("builtin samplerTexture '%s' not available !", s.name.c_str());
|
||||
continue;
|
||||
}
|
||||
const auto &info = infoIt->second;
|
||||
const auto binding = std::find_if(source.bindings.begin(), source.bindings.end(), [&info](const auto &bd) {
|
||||
return bd.binding == info.binding;
|
||||
});
|
||||
if (binding == source.bindings.end() || !(binding->descriptorType & gfx::DESCRIPTOR_SAMPLER_TYPE)) {
|
||||
CC_LOG_WARNING("builtin samplerTexture '%s' not available !", s.name.c_str());
|
||||
continue;
|
||||
}
|
||||
tempSamplerTextures.emplace_back(info);
|
||||
if (outBindings != nullptr && std::count_if(outBindings->begin(), outBindings->end(), [&binding](const auto &b) { return b.binding == binding->binding; }) == 0) {
|
||||
outBindings->emplace_back(*binding);
|
||||
}
|
||||
}
|
||||
|
||||
tmplInfo.shaderInfo.samplerTextures.insert(tmplInfo.shaderInfo.samplerTextures.begin(), tempSamplerTextures.begin(), tempSamplerTextures.end());
|
||||
if (outBindings != nullptr) {
|
||||
std::stable_sort(outBindings->begin(), outBindings->end(), [](const auto &a, const auto &b) {
|
||||
return a.binding < b.binding;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int32_t getSize(const IBlockInfo &block) {
|
||||
auto s = 0;
|
||||
for (const auto &m : block.members) {
|
||||
s += static_cast<int>(getTypeSize(m.type) * m.count);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const char *getDeviceShaderVersion(const gfx::Device *device) {
|
||||
switch (device->getGfxAPI()) {
|
||||
case gfx::API::GLES2:
|
||||
case gfx::API::WEBGL:
|
||||
return "glsl1";
|
||||
case gfx::API::GLES3:
|
||||
case gfx::API::WEBGL2:
|
||||
return "glsl3";
|
||||
default:
|
||||
return "glsl4";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
static void copyDefines(const ccstd::vector<IDefineInfo> &from, ccstd::vector<IDefineRecord> &to) {
|
||||
to.resize(from.size());
|
||||
for (size_t i = 0, len = from.size(); i < len; ++i) {
|
||||
to[i].name = from[i].name;
|
||||
to[i].type = from[i].type;
|
||||
to[i].range = from[i].range;
|
||||
to[i].options = from[i].options;
|
||||
to[i].defaultVal = from[i].defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
// IProgramInfo
|
||||
void IProgramInfo::copyFrom(const IShaderInfo &o) {
|
||||
name = o.name;
|
||||
hash = o.hash;
|
||||
glsl4 = o.glsl4;
|
||||
glsl3 = o.glsl3;
|
||||
glsl1 = o.glsl1;
|
||||
builtins = o.builtins;
|
||||
copyDefines(o.defines, defines);
|
||||
blocks = o.blocks;
|
||||
samplerTextures = o.samplerTextures;
|
||||
attributes = o.attributes;
|
||||
samplers = o.samplers;
|
||||
textures = o.textures;
|
||||
buffers = o.buffers;
|
||||
images = o.images;
|
||||
subpassInputs = o.subpassInputs;
|
||||
descriptors = o.descriptors;
|
||||
}
|
||||
|
||||
ProgramLib::ProgramLib() {
|
||||
ProgramLib::instance = this;
|
||||
}
|
||||
|
||||
ProgramLib::~ProgramLib() {
|
||||
ProgramLib::instance = nullptr;
|
||||
#if CC_DEBUG
|
||||
for (const auto &cache : _cache) {
|
||||
if (cache.second->getRefCount() > 1) {
|
||||
CC_LOG_WARNING("ProgramLib cache: %s ref_count is %d and may leak", cache.second->getName().c_str(), cache.second->getRefCount());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
/*static*/
|
||||
|
||||
ProgramLib *ProgramLib::instance = nullptr;
|
||||
|
||||
ProgramLib *ProgramLib::getInstance() {
|
||||
return ProgramLib::instance;
|
||||
}
|
||||
|
||||
void ProgramLib::registerEffect(EffectAsset *effect) {
|
||||
for (auto &shader : effect->_shaders) {
|
||||
auto *tmpl = define(shader);
|
||||
tmpl->effectName = effect->getName();
|
||||
}
|
||||
render::addEffectDefaultProperties(*effect);
|
||||
}
|
||||
|
||||
IProgramInfo *ProgramLib::define(IShaderInfo &shader) {
|
||||
auto itCurrTmpl = _templates.find(shader.name);
|
||||
if (itCurrTmpl != _templates.end() && itCurrTmpl->second.hash == shader.hash) {
|
||||
return &itCurrTmpl->second;
|
||||
}
|
||||
|
||||
IProgramInfo &tmpl = _templates[shader.name];
|
||||
tmpl.copyFrom(shader);
|
||||
|
||||
render::populateMacros(tmpl);
|
||||
|
||||
if (_templateInfos.count(tmpl.hash) == 0) {
|
||||
ITemplateInfo tmplInfo{};
|
||||
// cache material-specific descriptor set layout
|
||||
tmplInfo.samplerStartBinding = static_cast<int32_t>(tmpl.blocks.size());
|
||||
tmplInfo.bindings = {};
|
||||
tmplInfo.blockSizes = {};
|
||||
for (const auto &block : tmpl.blocks) {
|
||||
tmplInfo.blockSizes.emplace_back(getSize(block));
|
||||
tmplInfo.bindings.emplace_back();
|
||||
auto &bindingsInfo = tmplInfo.bindings.back();
|
||||
bindingsInfo.binding = block.binding;
|
||||
bindingsInfo.descriptorType = gfx::DescriptorType::UNIFORM_BUFFER;
|
||||
bindingsInfo.count = 1;
|
||||
bindingsInfo.stageFlags = block.stageFlags;
|
||||
ccstd::vector<gfx::Uniform> uniforms;
|
||||
{
|
||||
// construct uniforms
|
||||
uniforms.reserve(block.members.size());
|
||||
for (const auto &member : block.members) {
|
||||
uniforms.emplace_back();
|
||||
auto &info = uniforms.back();
|
||||
info.name = member.name;
|
||||
info.type = member.type;
|
||||
info.count = member.count;
|
||||
}
|
||||
}
|
||||
tmplInfo.shaderInfo.blocks.emplace_back();
|
||||
auto &blocksInfo = tmplInfo.shaderInfo.blocks.back();
|
||||
blocksInfo.set = static_cast<uint32_t>(pipeline::SetIndex::MATERIAL);
|
||||
blocksInfo.binding = block.binding;
|
||||
blocksInfo.name = block.name;
|
||||
blocksInfo.members = uniforms;
|
||||
blocksInfo.count = 1; // effect compiler guarantees block count = 1
|
||||
}
|
||||
for (const auto &samplerTexture : tmpl.samplerTextures) {
|
||||
tmplInfo.bindings.emplace_back();
|
||||
auto &descriptorLayoutBindingInfo = tmplInfo.bindings.back();
|
||||
descriptorLayoutBindingInfo.binding = samplerTexture.binding;
|
||||
descriptorLayoutBindingInfo.descriptorType = gfx::DescriptorType::SAMPLER_TEXTURE;
|
||||
descriptorLayoutBindingInfo.count = samplerTexture.count;
|
||||
descriptorLayoutBindingInfo.stageFlags = samplerTexture.stageFlags;
|
||||
|
||||
tmplInfo.shaderInfo.samplerTextures.emplace_back();
|
||||
auto &samplerTextureInfo = tmplInfo.shaderInfo.samplerTextures.back();
|
||||
samplerTextureInfo.set = static_cast<uint32_t>(pipeline::SetIndex::MATERIAL);
|
||||
samplerTextureInfo.binding = samplerTexture.binding;
|
||||
samplerTextureInfo.name = samplerTexture.name;
|
||||
samplerTextureInfo.type = samplerTexture.type;
|
||||
samplerTextureInfo.count = samplerTexture.count;
|
||||
}
|
||||
|
||||
for (const auto &sampler : tmpl.samplers) {
|
||||
tmplInfo.bindings.emplace_back(gfx::DescriptorSetLayoutBinding{
|
||||
sampler.binding,
|
||||
gfx::DescriptorType::SAMPLER,
|
||||
sampler.count,
|
||||
sampler.stageFlags});
|
||||
|
||||
tmplInfo.shaderInfo.samplers.emplace_back(gfx::UniformSampler{
|
||||
static_cast<uint32_t>(pipeline::SetIndex::MATERIAL),
|
||||
sampler.binding,
|
||||
sampler.name,
|
||||
sampler.count,
|
||||
});
|
||||
}
|
||||
|
||||
for (const auto &texture : tmpl.textures) {
|
||||
tmplInfo.bindings.emplace_back(gfx::DescriptorSetLayoutBinding{
|
||||
texture.binding,
|
||||
gfx::DescriptorType::TEXTURE,
|
||||
texture.count,
|
||||
texture.stageFlags});
|
||||
|
||||
tmplInfo.shaderInfo.textures.emplace_back(gfx::UniformTexture{
|
||||
static_cast<uint32_t>(pipeline::SetIndex::MATERIAL),
|
||||
texture.binding,
|
||||
texture.name,
|
||||
texture.type,
|
||||
texture.count,
|
||||
});
|
||||
}
|
||||
|
||||
for (const auto &buffer : tmpl.buffers) {
|
||||
tmplInfo.bindings.emplace_back(gfx::DescriptorSetLayoutBinding{
|
||||
buffer.binding,
|
||||
gfx::DescriptorType::STORAGE_BUFFER,
|
||||
1,
|
||||
buffer.stageFlags});
|
||||
|
||||
tmplInfo.shaderInfo.buffers.emplace_back(gfx::UniformStorageBuffer{
|
||||
static_cast<uint32_t>(pipeline::SetIndex::MATERIAL),
|
||||
buffer.binding,
|
||||
buffer.name,
|
||||
1,
|
||||
buffer.memoryAccess}); // effect compiler guarantees buffer count = 1
|
||||
}
|
||||
|
||||
for (const auto &image : tmpl.images) {
|
||||
tmplInfo.bindings.emplace_back(gfx::DescriptorSetLayoutBinding{
|
||||
image.binding,
|
||||
gfx::DescriptorType::STORAGE_IMAGE,
|
||||
image.count,
|
||||
image.stageFlags});
|
||||
|
||||
tmplInfo.shaderInfo.images.emplace_back(gfx::UniformStorageImage{
|
||||
static_cast<uint32_t>(pipeline::SetIndex::MATERIAL),
|
||||
image.binding,
|
||||
image.name,
|
||||
image.type,
|
||||
image.count,
|
||||
image.memoryAccess});
|
||||
}
|
||||
|
||||
for (const auto &subpassInput : tmpl.subpassInputs) {
|
||||
tmplInfo.bindings.emplace_back(gfx::DescriptorSetLayoutBinding{
|
||||
subpassInput.binding,
|
||||
gfx::DescriptorType::INPUT_ATTACHMENT,
|
||||
subpassInput.count,
|
||||
subpassInput.stageFlags});
|
||||
|
||||
tmplInfo.shaderInfo.subpassInputs.emplace_back(gfx::UniformInputAttachment{
|
||||
static_cast<uint32_t>(pipeline::SetIndex::MATERIAL),
|
||||
subpassInput.binding,
|
||||
subpassInput.name,
|
||||
subpassInput.count});
|
||||
}
|
||||
|
||||
tmplInfo.gfxAttributes = {};
|
||||
for (auto &attr : tmpl.attributes) {
|
||||
tmplInfo.gfxAttributes.emplace_back();
|
||||
auto &info = tmplInfo.gfxAttributes.back();
|
||||
info.name = attr.name;
|
||||
info.format = attr.format;
|
||||
info.isNormalized = attr.isNormalized;
|
||||
info.stream = 0;
|
||||
info.isInstanced = attr.isInstanced;
|
||||
info.location = attr.location;
|
||||
}
|
||||
insertBuiltinBindings(tmpl, tmplInfo, pipeline::localDescriptorSetLayout, "locals", nullptr);
|
||||
|
||||
tmplInfo.shaderInfo.stages.emplace_back();
|
||||
auto &vertexShaderInfo = tmplInfo.shaderInfo.stages.back();
|
||||
vertexShaderInfo.stage = gfx::ShaderStageFlagBit::VERTEX;
|
||||
vertexShaderInfo.source = "";
|
||||
tmplInfo.shaderInfo.stages.emplace_back();
|
||||
auto &fragmentShaderInfo = tmplInfo.shaderInfo.stages.back();
|
||||
fragmentShaderInfo.stage = gfx::ShaderStageFlagBit::FRAGMENT;
|
||||
fragmentShaderInfo.source = "";
|
||||
tmplInfo.handleMap = render::genHandles(tmpl);
|
||||
tmplInfo.setLayouts = {};
|
||||
|
||||
_templateInfos[tmpl.hash] = tmplInfo;
|
||||
}
|
||||
return &tmpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the shader template with its name
|
||||
* @zh 通过名字获取 Shader 模板
|
||||
* @param name Target shader name
|
||||
*/
|
||||
|
||||
const IProgramInfo *ProgramLib::getTemplate(const ccstd::string &name) const {
|
||||
auto it = _templates.find(name);
|
||||
return it != _templates.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the shader template info with its name
|
||||
* @zh 通过名字获取 Shader 模版信息
|
||||
* @param name Target shader name
|
||||
*/
|
||||
|
||||
ITemplateInfo *ProgramLib::getTemplateInfo(const ccstd::string &name) {
|
||||
auto it = _templates.find(name);
|
||||
CC_ASSERT(it != _templates.end());
|
||||
auto hash = it->second.hash;
|
||||
auto itInfo = _templateInfos.find(hash);
|
||||
return itInfo != _templateInfos.end() ? &itInfo->second : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the pipeline layout of the shader template given its name
|
||||
* @zh 通过名字获取 Shader 模板相关联的管线布局
|
||||
* @param name Target shader name
|
||||
*/
|
||||
gfx::DescriptorSetLayout *ProgramLib::getDescriptorSetLayout(gfx::Device *device, const ccstd::string &name, bool isLocal) {
|
||||
auto itTmpl = _templates.find(name);
|
||||
CC_ASSERT(itTmpl != _templates.end());
|
||||
const auto &tmpl = itTmpl->second;
|
||||
auto itTplInfo = _templateInfos.find(tmpl.hash);
|
||||
if (itTplInfo == _templateInfos.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto &tmplInfo = itTplInfo->second;
|
||||
if (tmplInfo.setLayouts.empty()) {
|
||||
gfx::DescriptorSetLayoutInfo info;
|
||||
tmplInfo.setLayouts.resize(static_cast<size_t>(pipeline::SetIndex::COUNT));
|
||||
info.bindings = tmplInfo.bindings;
|
||||
tmplInfo.setLayouts.replace(static_cast<index_t>(pipeline::SetIndex::MATERIAL), device->createDescriptorSetLayout(info));
|
||||
info.bindings = pipeline::localDescriptorSetLayout.bindings;
|
||||
tmplInfo.setLayouts.replace(static_cast<index_t>(pipeline::SetIndex::LOCAL), device->createDescriptorSetLayout(info));
|
||||
}
|
||||
return tmplInfo.setLayouts.at(isLocal ? static_cast<uint32_t>(pipeline::SetIndex::LOCAL) : static_cast<uint32_t>(pipeline::SetIndex::MATERIAL));
|
||||
}
|
||||
|
||||
ccstd::string ProgramLib::getKey(const ccstd::string &name, const MacroRecord &defines) {
|
||||
auto itTpl = _templates.find(name);
|
||||
CC_ASSERT(itTpl != _templates.end());
|
||||
auto &tmpl = itTpl->second;
|
||||
return render::getVariantKey(tmpl, defines);
|
||||
}
|
||||
|
||||
void ProgramLib::destroyShaderByDefines(const MacroRecord &defines) {
|
||||
if (defines.empty()) return;
|
||||
ccstd::vector<ccstd::string> defineValues;
|
||||
for (const auto &i : defines) {
|
||||
defineValues.emplace_back(i.first + macroRecordAsString(i.second));
|
||||
}
|
||||
ccstd::vector<ccstd::string> matchedKeys;
|
||||
for (const auto &i : _cache) {
|
||||
bool matched = true;
|
||||
for (const auto &v : defineValues) {
|
||||
if (i.first.find(v) == ccstd::string::npos) {
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matched) {
|
||||
matchedKeys.emplace_back(i.first);
|
||||
}
|
||||
}
|
||||
for (const auto &key : matchedKeys) {
|
||||
CC_LOG_DEBUG("destroyed shader %s", key.c_str());
|
||||
_cache[key]->destroy();
|
||||
_cache.erase(key);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Shader *ProgramLib::getGFXShader(gfx::Device *device, const ccstd::string &name, MacroRecord &defines,
|
||||
render::PipelineRuntime *pipeline, ccstd::string *keyOut) {
|
||||
for (const auto &it : pipeline->getMacros()) {
|
||||
defines[it.first] = it.second;
|
||||
}
|
||||
|
||||
ccstd::string key;
|
||||
if (!keyOut) {
|
||||
key = getKey(name, defines);
|
||||
} else {
|
||||
key = *keyOut;
|
||||
}
|
||||
auto itRes = _cache.find(key);
|
||||
if (itRes != _cache.end()) {
|
||||
// CC_LOG_DEBUG("Found ProgramLib::_cache[%s]=%p, defines: %d", key.c_str(), itRes->second, defines.size());
|
||||
return itRes->second;
|
||||
}
|
||||
|
||||
auto itTpl = _templates.find(name);
|
||||
CC_ASSERT(itTpl != _templates.end());
|
||||
|
||||
const auto &tmpl = itTpl->second;
|
||||
const auto itTplInfo = _templateInfos.find(tmpl.hash);
|
||||
CC_ASSERT(itTplInfo != _templateInfos.end());
|
||||
auto &tmplInfo = itTplInfo->second;
|
||||
|
||||
if (!tmplInfo.pipelineLayout) {
|
||||
getDescriptorSetLayout(device, name); // ensure set layouts have been created
|
||||
insertBuiltinBindings(tmpl, tmplInfo, pipeline::globalDescriptorSetLayout, "globals", nullptr);
|
||||
tmplInfo.setLayouts.replace(static_cast<index_t>(pipeline::SetIndex::GLOBAL), pipeline->getDescriptorSetLayout());
|
||||
tmplInfo.pipelineLayout = device->createPipelineLayout(gfx::PipelineLayoutInfo{tmplInfo.setLayouts.get()});
|
||||
}
|
||||
|
||||
ccstd::vector<IMacroInfo> macroArray = render::prepareDefines(defines, tmpl.defines);
|
||||
std::stringstream ss;
|
||||
ss << std::endl;
|
||||
for (const auto &m : macroArray) {
|
||||
ss << "#define " << m.name << " " << m.value << std::endl;
|
||||
}
|
||||
auto prefix = pipeline->getConstantMacros() + tmpl.constantMacros + ss.str();
|
||||
|
||||
const IShaderSource *src = &tmpl.glsl3;
|
||||
const auto *deviceShaderVersion = getDeviceShaderVersion(device);
|
||||
if (deviceShaderVersion) {
|
||||
src = tmpl.getSource(deviceShaderVersion);
|
||||
} else {
|
||||
CC_LOG_ERROR("Invalid GFX API!");
|
||||
}
|
||||
tmplInfo.shaderInfo.stages[0].source = prefix + src->vert;
|
||||
tmplInfo.shaderInfo.stages[1].source = prefix + src->frag;
|
||||
|
||||
// strip out the active attributes only, instancing depend on this
|
||||
tmplInfo.shaderInfo.attributes = render::getActiveAttributes(tmpl, tmplInfo.gfxAttributes, defines);
|
||||
|
||||
tmplInfo.shaderInfo.name = render::getShaderInstanceName(name, macroArray);
|
||||
tmplInfo.shaderInfo.hash = tmpl.hash;
|
||||
auto *shader = device->createShader(tmplInfo.shaderInfo);
|
||||
_cache[key] = shader;
|
||||
// CC_LOG_DEBUG("ProgramLib::_cache[%s]=%p, defines: %d", key.c_str(), shader, defines.size());
|
||||
return shader;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
168
cocos/renderer/core/ProgramLib.h
Normal file
168
cocos/renderer/core/ProgramLib.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include "base/RefVector.h"
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "base/std/optional.h"
|
||||
#include "core/Types.h"
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "renderer/gfx-base/GFXDef-common.h"
|
||||
#include "renderer/pipeline/Define.h"
|
||||
#include "renderer/pipeline/RenderPipeline.h"
|
||||
|
||||
namespace cc {
|
||||
class EffectAsset;
|
||||
|
||||
namespace render {
|
||||
class PipelineRuntime;
|
||||
} // namespace render
|
||||
|
||||
struct IDefineRecord : public IDefineInfo {
|
||||
std::function<int32_t(const MacroValue &)> map{nullptr};
|
||||
int32_t offset{0};
|
||||
};
|
||||
struct IMacroInfo {
|
||||
ccstd::string name;
|
||||
ccstd::string value;
|
||||
bool isDefault{false};
|
||||
};
|
||||
|
||||
struct ITemplateInfo {
|
||||
ccstd::vector<gfx::Attribute> gfxAttributes;
|
||||
gfx::ShaderInfo shaderInfo;
|
||||
ccstd::vector<int32_t> blockSizes;
|
||||
RefVector<gfx::DescriptorSetLayout *> setLayouts;
|
||||
IntrusivePtr<gfx::PipelineLayout> pipelineLayout;
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> handleMap;
|
||||
ccstd::vector<gfx::DescriptorSetLayoutBinding> bindings;
|
||||
int32_t samplerStartBinding{-1};
|
||||
};
|
||||
|
||||
struct IProgramInfo : public IShaderInfo {
|
||||
ccstd::string effectName;
|
||||
ccstd::vector<IDefineRecord> defines;
|
||||
ccstd::string constantMacros;
|
||||
bool uber{false}; // macro number exceeds default limits, will fallback to string hash
|
||||
|
||||
void copyFrom(const IShaderInfo &o);
|
||||
};
|
||||
|
||||
const char *getDeviceShaderVersion(const gfx::Device *device);
|
||||
|
||||
/**
|
||||
* @en The global maintainer of all shader resources.
|
||||
* @zh 维护 shader 资源实例的全局管理器。
|
||||
*/
|
||||
class ProgramLib final {
|
||||
public:
|
||||
static ProgramLib *getInstance();
|
||||
|
||||
ProgramLib();
|
||||
~ProgramLib();
|
||||
|
||||
void registerEffect(EffectAsset *effect);
|
||||
|
||||
/**
|
||||
* @en Register the shader template with the given info
|
||||
* @zh 注册 shader 模板。
|
||||
*/
|
||||
IProgramInfo *define(IShaderInfo &shader);
|
||||
|
||||
/**
|
||||
* @en Gets the shader template with its name
|
||||
* @zh 通过名字获取 Shader 模板
|
||||
* @param name Target shader name
|
||||
*/
|
||||
|
||||
const IProgramInfo *getTemplate(const ccstd::string &name) const;
|
||||
|
||||
/**
|
||||
* @en Gets the shader template info with its name
|
||||
* @zh 通过名字获取 Shader 模版信息
|
||||
* @param name Target shader name
|
||||
*/
|
||||
|
||||
ITemplateInfo *getTemplateInfo(const ccstd::string &name);
|
||||
|
||||
/**
|
||||
* @en Gets the pipeline layout of the shader template given its name
|
||||
* @zh 通过名字获取 Shader 模板相关联的管线布局
|
||||
* @param name Target shader name
|
||||
*/
|
||||
gfx::DescriptorSetLayout *getDescriptorSetLayout(gfx::Device *device, const ccstd::string &name, bool isLocal = false);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Does this library has the specified program
|
||||
* @zh
|
||||
* 当前是否有已注册的指定名字的 shader
|
||||
* @param name Target shader name
|
||||
*/
|
||||
inline bool hasProgram(const ccstd::string &name) const {
|
||||
return _templates.count(name) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the shader key with the name and a macro combination
|
||||
* @zh 根据 shader 名和预处理宏列表获取 shader key。
|
||||
* @param name Target shader name
|
||||
* @param defines The combination of preprocess macros
|
||||
*/
|
||||
ccstd::string getKey(const ccstd::string &name, const MacroRecord &defines);
|
||||
|
||||
/**
|
||||
* @en Destroy all shader instance match the preprocess macros
|
||||
* @zh 销毁所有完全满足指定预处理宏特征的 shader 实例。
|
||||
* @param defines The preprocess macros as filter
|
||||
*/
|
||||
|
||||
void destroyShaderByDefines(const MacroRecord &defines);
|
||||
|
||||
/**
|
||||
* @en Gets the shader resource instance with given information
|
||||
* @zh 获取指定 shader 的渲染资源实例
|
||||
* @param name Shader name
|
||||
* @param defines Preprocess macros
|
||||
* @param pipeline The [[RenderPipeline]] which owns the render command
|
||||
* @param key The shader cache key, if already known
|
||||
*/
|
||||
gfx::Shader *getGFXShader(gfx::Device *device, const ccstd::string &name, MacroRecord &defines,
|
||||
render::PipelineRuntime *pipeline, ccstd::string *key = nullptr);
|
||||
|
||||
private:
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(ProgramLib);
|
||||
|
||||
static ProgramLib *instance;
|
||||
ccstd::unordered_map<ccstd::string, IProgramInfo> _templates; // per shader
|
||||
ccstd::unordered_map<ccstd::string, IntrusivePtr<gfx::Shader>> _cache;
|
||||
ccstd::unordered_map<uint64_t, ITemplateInfo> _templateInfos;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
264
cocos/renderer/core/ProgramUtils.cpp
Normal file
264
cocos/renderer/core/ProgramUtils.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "ProgramUtils.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
namespace {
|
||||
|
||||
int32_t getBitCount(int32_t cnt) {
|
||||
return std::ceil(std::log2(std::max(cnt, 2))); // std::max checks number types
|
||||
}
|
||||
|
||||
template <class ShaderInfoT>
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> genHandlesImpl(const ShaderInfoT &tmpl) {
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> handleMap{};
|
||||
// block member handles
|
||||
for (const auto &block : tmpl.blocks) {
|
||||
const auto members = block.members;
|
||||
uint32_t offset = 0;
|
||||
for (const auto &uniform : members) {
|
||||
handleMap[uniform.name] = genHandle(block.binding,
|
||||
uniform.type,
|
||||
uniform.count,
|
||||
offset);
|
||||
offset += (getTypeSize(uniform.type) >> 2) * uniform.count; // assumes no implicit padding, which is guaranteed by effect compiler
|
||||
}
|
||||
}
|
||||
// samplerTexture handles
|
||||
for (const auto &samplerTexture : tmpl.samplerTextures) {
|
||||
handleMap[samplerTexture.name] = genHandle(samplerTexture.binding,
|
||||
samplerTexture.type,
|
||||
samplerTexture.count);
|
||||
}
|
||||
return handleMap;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void populateMacros(IProgramInfo &tmpl) {
|
||||
// calculate option mask offset
|
||||
int32_t offset = 0;
|
||||
for (auto &def : tmpl.defines) {
|
||||
int32_t cnt = 1;
|
||||
if (def.type == "number") {
|
||||
auto &range = def.range.value();
|
||||
cnt = getBitCount(range[1] - range[0] + 1); // inclusive on both ends
|
||||
def.map = [=](const MacroValue &value) -> int32_t {
|
||||
if (ccstd::holds_alternative<int32_t>(value)) {
|
||||
return ccstd::get<int32_t>(value) - range[0];
|
||||
}
|
||||
if (ccstd::holds_alternative<bool>(value)) {
|
||||
return (ccstd::get<bool>(value) ? 1 : 0) - range[0];
|
||||
}
|
||||
CC_ABORT(); // We only support macro with int32_t type now.
|
||||
return 0;
|
||||
};
|
||||
} else if (def.type == "string") {
|
||||
cnt = getBitCount(static_cast<int32_t>(def.options.value().size()));
|
||||
def.map = [=](const MacroValue &value) -> int32_t {
|
||||
const auto *pValue = ccstd::get_if<ccstd::string>(&value);
|
||||
if (pValue != nullptr) {
|
||||
auto idx = static_cast<int32_t>(std::find(def.options.value().begin(), def.options.value().end(), *pValue) - def.options.value().begin());
|
||||
return std::max(0, idx);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
} else if (def.type == "boolean") {
|
||||
def.map = [](const MacroValue &value) -> int32_t {
|
||||
const auto *pBool = ccstd::get_if<bool>(&value);
|
||||
if (pBool != nullptr) {
|
||||
return *pBool ? 1 : 0;
|
||||
}
|
||||
const auto *pInt = ccstd::get_if<int32_t>(&value);
|
||||
if (pInt != nullptr) {
|
||||
return *pInt ? 1 : 0;
|
||||
}
|
||||
const auto *pString = ccstd::get_if<ccstd::string>(&value);
|
||||
if (pString != nullptr) {
|
||||
return *pString != "0" || !(*pString).empty() ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
def.offset = offset;
|
||||
offset += cnt;
|
||||
}
|
||||
if (offset > 31) {
|
||||
tmpl.uber = true;
|
||||
}
|
||||
// generate constant macros
|
||||
{
|
||||
tmpl.constantMacros.clear();
|
||||
std::stringstream ss;
|
||||
for (auto &key : tmpl.builtins.statistics) {
|
||||
ss << "#define " << key.first << " " << key.second << std::endl;
|
||||
}
|
||||
tmpl.constantMacros = ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> genHandles(const IProgramInfo &tmpl) {
|
||||
return genHandlesImpl(tmpl);
|
||||
}
|
||||
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> genHandles(const gfx::ShaderInfo &tmpl) {
|
||||
return genHandlesImpl(tmpl);
|
||||
}
|
||||
|
||||
ccstd::string getVariantKey(const IProgramInfo &tmpl, const MacroRecord &defines) {
|
||||
const auto &tmplDefs = tmpl.defines;
|
||||
if (tmpl.uber) {
|
||||
std::stringstream key;
|
||||
for (const auto &tmplDef : tmplDefs) {
|
||||
auto itDef = defines.find(tmplDef.name);
|
||||
if (itDef == defines.end() || !tmplDef.map) {
|
||||
continue;
|
||||
}
|
||||
const auto &value = itDef->second;
|
||||
auto mapped = tmplDef.map(value);
|
||||
auto offset = tmplDef.offset;
|
||||
key << offset << mapped << "|";
|
||||
}
|
||||
ccstd::string ret{key.str() + std::to_string(tmpl.hash)};
|
||||
return ret;
|
||||
}
|
||||
uint32_t key = 0;
|
||||
std::stringstream ss;
|
||||
for (const auto &tmplDef : tmplDefs) {
|
||||
auto itDef = defines.find(tmplDef.name);
|
||||
if (itDef == defines.end() || !tmplDef.map) {
|
||||
continue;
|
||||
}
|
||||
const auto &value = itDef->second;
|
||||
auto mapped = tmplDef.map(value);
|
||||
auto offset = tmplDef.offset;
|
||||
key |= (mapped << offset);
|
||||
}
|
||||
ss << std::hex << key << "|" << std::to_string(tmpl.hash);
|
||||
ccstd::string ret{ss.str()};
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
ccstd::string mapDefine(const IDefineInfo &info, const ccstd::optional<MacroRecord::mapped_type> &def) {
|
||||
if (info.type == "boolean") {
|
||||
return def.has_value() ? (macroRecordAsBool(def.value()) ? "1" : "0") : "0";
|
||||
}
|
||||
if (info.type == "string") {
|
||||
return def.has_value() ? macroRecordAsString(def.value()) : info.options.value()[0];
|
||||
}
|
||||
if (info.type == "number") {
|
||||
return def.has_value() ? macroRecordAsString(def.value()) : std::to_string(info.range.value()[0]);
|
||||
}
|
||||
CC_LOG_WARNING("unknown define type '%s', name: %s", info.type.c_str(), info.name.c_str());
|
||||
return "-1"; // should neven happen
|
||||
}
|
||||
|
||||
bool dependencyCheck(const ccstd::vector<ccstd::string> &dependencies, const MacroRecord &defines) {
|
||||
for (const auto &d : dependencies) { // NOLINT(readability-use-anyofallof)
|
||||
if (d[0] == '!') { // negative dependency
|
||||
if (defines.find(d.substr(1)) != defines.end()) {
|
||||
return false;
|
||||
}
|
||||
} else if (defines.count(d) == 0 ? true : !macroRecordAsBool(defines.at(d))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Vector>
|
||||
ccstd::vector<gfx::Attribute> getActiveAttributesImpl(
|
||||
const IProgramInfo &tmpl,
|
||||
const Vector &gfxAttributes, const MacroRecord &defines) {
|
||||
ccstd::vector<gfx::Attribute> out{};
|
||||
const auto &attributes = tmpl.attributes;
|
||||
for (auto i = 0; i < attributes.size(); i++) {
|
||||
if (!dependencyCheck(attributes[i].defines, defines)) {
|
||||
continue;
|
||||
}
|
||||
out.emplace_back(gfxAttributes[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ccstd::vector<IMacroInfo> prepareDefines(const MacroRecord &records, const ccstd::vector<IDefineRecord> &defList) {
|
||||
ccstd::vector<IMacroInfo> macros{};
|
||||
for (const auto &tmp : defList) {
|
||||
const auto &name = tmp.name;
|
||||
auto it = records.find(name);
|
||||
auto value = mapDefine(tmp, it == records.end() ? ccstd::nullopt : ccstd::optional<MacroValue>(it->second));
|
||||
bool isDefault = it == records.end() || (ccstd::holds_alternative<ccstd::string>(it->second) && ccstd::get<ccstd::string>(it->second) == "0");
|
||||
macros.emplace_back();
|
||||
auto &info = macros.back();
|
||||
info.name = name;
|
||||
info.value = value;
|
||||
info.isDefault = isDefault;
|
||||
}
|
||||
return macros;
|
||||
}
|
||||
|
||||
ccstd::vector<gfx::Attribute> getActiveAttributes(
|
||||
const IProgramInfo &tmpl,
|
||||
const ccstd::vector<gfx::Attribute> &gfxAttributes, const MacroRecord &defines) {
|
||||
return getActiveAttributesImpl(tmpl, gfxAttributes, defines);
|
||||
}
|
||||
|
||||
ccstd::vector<gfx::Attribute> getActiveAttributes(
|
||||
const IProgramInfo &tmpl,
|
||||
const ccstd::pmr::vector<gfx::Attribute> &gfxAttributes, const MacroRecord &defines) {
|
||||
return getActiveAttributesImpl(tmpl, gfxAttributes, defines);
|
||||
}
|
||||
|
||||
ccstd::string getShaderInstanceName(const ccstd::string &name, const ccstd::vector<IMacroInfo> ¯os) {
|
||||
std::stringstream ret;
|
||||
ret << name;
|
||||
for (const auto &cur : macros) {
|
||||
if (!cur.isDefault) {
|
||||
ret << "|" << cur.name << cur.value;
|
||||
}
|
||||
}
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
void addEffectDefaultProperties(EffectAsset &effect) {
|
||||
for (auto &tech : effect._techniques) {
|
||||
for (auto &pass : tech.passes) {
|
||||
// grab default property declaration if there is none
|
||||
if (pass.propertyIndex.has_value() && !pass.properties.has_value()) {
|
||||
pass.properties = tech.passes[pass.propertyIndex.value()].properties;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
55
cocos/renderer/core/ProgramUtils.h
Normal file
55
cocos/renderer/core/ProgramUtils.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "cocos/renderer/core/ProgramLib.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
void populateMacros(IProgramInfo& tmpl);
|
||||
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> genHandles(const IProgramInfo& tmpl);
|
||||
ccstd::unordered_map<ccstd::string, uint32_t> genHandles(const gfx::ShaderInfo& tmpl);
|
||||
ccstd::string getVariantKey(const IProgramInfo& tmpl, const MacroRecord& defines);
|
||||
ccstd::vector<IMacroInfo> prepareDefines(
|
||||
const MacroRecord& records, const ccstd::vector<IDefineRecord>& defList);
|
||||
|
||||
ccstd::vector<gfx::Attribute> getActiveAttributes(
|
||||
const IProgramInfo& tmpl,
|
||||
const ccstd::vector<gfx::Attribute>& gfxAttributes, const MacroRecord& defines);
|
||||
|
||||
ccstd::vector<gfx::Attribute> getActiveAttributes(
|
||||
const IProgramInfo& tmpl,
|
||||
const ccstd::pmr::vector<gfx::Attribute>& gfxAttributes, const MacroRecord& defines);
|
||||
|
||||
ccstd::string getShaderInstanceName(
|
||||
const ccstd::string& name, const ccstd::vector<IMacroInfo>& macros);
|
||||
|
||||
void addEffectDefaultProperties(EffectAsset& effect);
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
316
cocos/renderer/core/TextureBufferPool.cpp
Normal file
316
cocos/renderer/core/TextureBufferPool.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "renderer/core/TextureBufferPool.h"
|
||||
#include <cmath>
|
||||
#include "core/ArrayBuffer.h"
|
||||
#include "core/TypedArray.h"
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t roundUp(uint32_t n, uint32_t alignment) {
|
||||
return static_cast<uint32_t>(std::ceil(n / alignment)) * alignment;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace cc {
|
||||
|
||||
TextureBufferPool::TextureBufferPool() = default;
|
||||
|
||||
TextureBufferPool::TextureBufferPool(gfx::Device *device) {
|
||||
_device = device;
|
||||
}
|
||||
|
||||
TextureBufferPool::~TextureBufferPool() = default;
|
||||
|
||||
void TextureBufferPool::initialize(const ITextureBufferPoolInfo &info) {
|
||||
const auto &formatInfo = gfx::GFX_FORMAT_INFOS[static_cast<uint32_t>(info.format)];
|
||||
_format = info.format;
|
||||
_formatSize = formatInfo.size;
|
||||
_channels = formatInfo.count;
|
||||
_roundUpFn = info.roundUpFn.has_value() ? info.roundUpFn.value() : nullptr;
|
||||
_alignment = info.alignment.has_value() ? info.alignment.value() : 1;
|
||||
_useMcDonaldAlloc = info.alignment.has_value() && info.alignment.value();
|
||||
}
|
||||
|
||||
void TextureBufferPool::destroy() {
|
||||
for (auto &chunk : _chunks) {
|
||||
CC_SAFE_DESTROY_AND_DELETE(chunk.texture);
|
||||
}
|
||||
_chunks.clear();
|
||||
_handles.clear();
|
||||
}
|
||||
|
||||
ITextureBufferHandle TextureBufferPool::alloc(uint32_t size) {
|
||||
if (_useMcDonaldAlloc) {
|
||||
return mcDonaldAlloc(size);
|
||||
}
|
||||
|
||||
size = roundUp(size, _alignment);
|
||||
index_t index = CC_INVALID_INDEX;
|
||||
index_t start = CC_INVALID_INDEX;
|
||||
if (start < 0) {
|
||||
for (index_t i = 0; i < _chunkCount; ++i) {
|
||||
index = i;
|
||||
start = findAvailableSpace(size, index);
|
||||
if (start >= 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start >= 0) {
|
||||
auto chunk = _chunks[index];
|
||||
chunk.start += static_cast<index_t>(size);
|
||||
ITextureBufferHandle handle;
|
||||
handle.chunkIdx = index;
|
||||
handle.start = start;
|
||||
handle.end = static_cast<index_t>(start + size);
|
||||
handle.texture = chunk.texture;
|
||||
|
||||
_handles.emplace_back(handle);
|
||||
return handle;
|
||||
}
|
||||
// create a new one
|
||||
auto targetSize = static_cast<int32_t>(std::sqrt(size / _formatSize));
|
||||
uint32_t texLength = _roundUpFn ? _roundUpFn(targetSize, _formatSize) : std::max(1024, static_cast<int>(utils::nextPOT(targetSize)));
|
||||
auto newChunk = _chunks[createChunk(texLength)];
|
||||
|
||||
newChunk.start += static_cast<index_t>(size);
|
||||
ITextureBufferHandle texHandle;
|
||||
texHandle.chunkIdx = static_cast<index_t>(_chunkCount - 1);
|
||||
texHandle.start = 0;
|
||||
texHandle.end = static_cast<index_t>(size);
|
||||
texHandle.texture = newChunk.texture;
|
||||
_handles.emplace_back(texHandle);
|
||||
return texHandle;
|
||||
}
|
||||
|
||||
ITextureBufferHandle TextureBufferPool::alloc(uint32_t size, index_t chunkIdx) {
|
||||
size = roundUp(size, _alignment);
|
||||
index_t index = chunkIdx;
|
||||
index_t start = findAvailableSpace(size, index);
|
||||
|
||||
if (start < 0) {
|
||||
for (index_t i = 0; i < _chunkCount; ++i) {
|
||||
index = i;
|
||||
start = findAvailableSpace(size, index);
|
||||
if (start >= 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start >= 0) {
|
||||
auto chunk = _chunks[index];
|
||||
chunk.start += static_cast<index_t>(size);
|
||||
ITextureBufferHandle handle;
|
||||
handle.chunkIdx = index;
|
||||
handle.start = start;
|
||||
handle.end = static_cast<index_t>(start + size);
|
||||
handle.texture = chunk.texture;
|
||||
|
||||
_handles.emplace_back(handle);
|
||||
return handle;
|
||||
}
|
||||
// create a new one
|
||||
auto targetSize = static_cast<int32_t>(std::sqrt(size / _formatSize));
|
||||
uint32_t texLength = _roundUpFn ? _roundUpFn(targetSize, _formatSize) : std::max(1024, static_cast<int>(utils::nextPOT(targetSize)));
|
||||
auto newChunk = _chunks[createChunk(texLength)];
|
||||
|
||||
newChunk.start += static_cast<index_t>(size);
|
||||
ITextureBufferHandle texHandle;
|
||||
texHandle.chunkIdx = static_cast<index_t>(_chunkCount - 1);
|
||||
texHandle.start = 0;
|
||||
texHandle.end = static_cast<index_t>(size);
|
||||
texHandle.texture = newChunk.texture;
|
||||
_handles.emplace_back(texHandle);
|
||||
return texHandle;
|
||||
}
|
||||
|
||||
void TextureBufferPool::free(const ITextureBufferHandle &handle) {
|
||||
auto iter = std::find(_handles.begin(), _handles.end(), handle);
|
||||
if (iter != _handles.end()) {
|
||||
_chunks[handle.chunkIdx].end = handle.end;
|
||||
_handles.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TextureBufferPool::createChunk(uint32_t length) {
|
||||
uint32_t texSize = length * length * _formatSize;
|
||||
// debug(`TextureBufferPool: Allocate chunk $device->createTexture({gfx::TextureType::TEX2D,
|
||||
auto *texture = _device->createTexture({gfx::TextureType::TEX2D,
|
||||
gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_DST,
|
||||
_format,
|
||||
length,
|
||||
length});
|
||||
|
||||
ITextureBuffer chunk;
|
||||
chunk.texture = texture;
|
||||
chunk.size = texSize;
|
||||
chunk.start = 0;
|
||||
chunk.end = static_cast<index_t>(texSize);
|
||||
_chunks[_chunkCount] = chunk;
|
||||
return _chunkCount++;
|
||||
}
|
||||
|
||||
void TextureBufferPool::update(const ITextureBufferHandle &handle, ArrayBuffer *buffer) {
|
||||
gfx::BufferDataList buffers;
|
||||
uint8_t *bufferData = buffer->getData();
|
||||
gfx::BufferTextureCopyList regions;
|
||||
auto start = static_cast<int32_t>(handle.start / _formatSize);
|
||||
|
||||
uint32_t remainSize = buffer->byteLength() / _formatSize;
|
||||
int32_t offsetX = start % static_cast<int32_t>(handle.texture->getWidth());
|
||||
int32_t offsetY = std::floor(start / handle.texture->getWidth());
|
||||
uint32_t copySize = std::min(handle.texture->getWidth() - offsetX, remainSize);
|
||||
uint32_t begin = 0;
|
||||
|
||||
if (offsetX > 0) {
|
||||
_region0.texOffset.x = offsetX;
|
||||
_region0.texOffset.y = offsetY;
|
||||
_region0.texExtent.width = copySize;
|
||||
_region0.texExtent.height = 1;
|
||||
buffers.emplace_back(bufferData + begin * _formatSize);
|
||||
regions.emplace_back(_region0);
|
||||
offsetX = 0;
|
||||
offsetY += 1;
|
||||
remainSize -= copySize;
|
||||
begin += copySize;
|
||||
}
|
||||
|
||||
if (remainSize > 0) {
|
||||
_region1.texOffset.x = offsetX;
|
||||
_region1.texOffset.y = offsetY;
|
||||
|
||||
if (remainSize > handle.texture->getWidth()) {
|
||||
_region1.texExtent.width = handle.texture->getWidth();
|
||||
_region1.texExtent.height = std::floor(remainSize / handle.texture->getWidth());
|
||||
copySize = _region1.texExtent.width * _region1.texExtent.height;
|
||||
} else {
|
||||
copySize = remainSize;
|
||||
_region1.texExtent.width = copySize;
|
||||
_region1.texExtent.height = 1;
|
||||
}
|
||||
|
||||
buffers.emplace_back(bufferData + begin * _formatSize);
|
||||
regions.emplace_back(_region1);
|
||||
|
||||
offsetX = 0;
|
||||
offsetY += static_cast<int32_t>(_region1.texExtent.height);
|
||||
remainSize -= copySize;
|
||||
begin += copySize;
|
||||
}
|
||||
|
||||
if (remainSize > 0) {
|
||||
_region2.texOffset.x = offsetX;
|
||||
_region2.texOffset.y = offsetY;
|
||||
_region2.texExtent.width = remainSize;
|
||||
_region2.texExtent.height = 1;
|
||||
|
||||
buffers.emplace_back(bufferData + begin * _formatSize);
|
||||
regions.emplace_back(_region2);
|
||||
}
|
||||
_device->copyBuffersToTexture(buffers, handle.texture, regions);
|
||||
}
|
||||
|
||||
index_t TextureBufferPool::findAvailableSpace(uint32_t size, index_t chunkIdx) const {
|
||||
auto chunk = _chunks[chunkIdx];
|
||||
bool isFound = false;
|
||||
index_t start = chunk.start;
|
||||
if ((start + size) <= chunk.size) {
|
||||
isFound = true;
|
||||
} else {
|
||||
start = 0; // try to find from head again
|
||||
ccstd::vector<ITextureBufferHandle> handles;
|
||||
for (auto h : _handles) {
|
||||
if (h.chunkIdx == chunkIdx) {
|
||||
handles.emplace_back(h);
|
||||
}
|
||||
}
|
||||
std::sort(handles.begin(), handles.end(), [](const ITextureBufferHandle &a, const ITextureBufferHandle &b) { return a.start - b.start; });
|
||||
for (auto handle : handles) {
|
||||
if ((start + size) <= handle.start) {
|
||||
isFound = true;
|
||||
break;
|
||||
}
|
||||
start = handle.end;
|
||||
}
|
||||
if (!isFound && (start + size) <= chunk.size) {
|
||||
isFound = true;
|
||||
}
|
||||
}
|
||||
return isFound ? start : CC_INVALID_INDEX;
|
||||
}
|
||||
|
||||
ITextureBufferHandle TextureBufferPool::mcDonaldAlloc(uint32_t size) {
|
||||
size = roundUp(size, _alignment);
|
||||
for (index_t i = 0; i < _chunkCount; ++i) {
|
||||
auto chunk = _chunks[i];
|
||||
bool isFound = false;
|
||||
index_t start = chunk.start;
|
||||
if ((start + size) <= chunk.end) {
|
||||
isFound = true;
|
||||
} else if (start > chunk.end) {
|
||||
if ((start + size) <= chunk.size) {
|
||||
isFound = true;
|
||||
} else if (size <= chunk.end) {
|
||||
// Try to find from head again.
|
||||
start = 0;
|
||||
chunk.start = 0;
|
||||
isFound = true;
|
||||
}
|
||||
} else if (start == chunk.end) {
|
||||
start = 0;
|
||||
chunk.start = 0;
|
||||
chunk.end = static_cast<index_t>(chunk.size);
|
||||
if (size <= chunk.end) {
|
||||
isFound = true;
|
||||
}
|
||||
}
|
||||
if (isFound) {
|
||||
chunk.start += static_cast<index_t>(size);
|
||||
|
||||
ITextureBufferHandle handle;
|
||||
handle.chunkIdx = i;
|
||||
handle.start = start;
|
||||
handle.end = static_cast<index_t>(size);
|
||||
handle.texture = chunk.texture;
|
||||
_handles.emplace_back(handle);
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
// create a new one
|
||||
auto targetSize = static_cast<int32_t>(std::sqrt(size / _formatSize));
|
||||
uint32_t texLength = _roundUpFn ? _roundUpFn(targetSize, _formatSize) : std::max(1024, static_cast<int>(utils::nextPOT(targetSize)));
|
||||
auto newChunk = _chunks[createChunk(texLength)];
|
||||
|
||||
newChunk.start += static_cast<index_t>(size);
|
||||
ITextureBufferHandle texHandle;
|
||||
texHandle.chunkIdx = static_cast<index_t>(_chunkCount);
|
||||
texHandle.start = 0;
|
||||
texHandle.end = static_cast<index_t>(size),
|
||||
texHandle.texture = newChunk.texture;
|
||||
_handles.emplace_back(texHandle);
|
||||
return texHandle;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
97
cocos/renderer/core/TextureBufferPool.h
Normal file
97
cocos/renderer/core/TextureBufferPool.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "audio/android/PcmBufferProvider.h"
|
||||
#include "base/std/optional.h"
|
||||
#include "core/ArrayBuffer.h"
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
using roundUpType = std::function<uint32_t(uint32_t size, uint32_t formatSize)>;
|
||||
|
||||
struct ITextureBuffer {
|
||||
gfx::Texture *texture{nullptr};
|
||||
uint32_t size{0};
|
||||
index_t start{0};
|
||||
index_t end{0};
|
||||
};
|
||||
|
||||
struct ITextureBufferHandle {
|
||||
index_t chunkIdx{0};
|
||||
index_t start{0};
|
||||
index_t end{0};
|
||||
gfx::Texture *texture{nullptr};
|
||||
|
||||
bool operator==(const ITextureBufferHandle &handle) const {
|
||||
return chunkIdx == handle.chunkIdx && start == handle.start && end == handle.end && texture == handle.texture;
|
||||
}
|
||||
};
|
||||
|
||||
struct ITextureBufferPoolInfo {
|
||||
gfx::Format format{gfx::Format::UNKNOWN}; // target texture format
|
||||
ccstd::optional<bool> inOrderFree; // will the handles be freed exactly in the order of their allocation?
|
||||
ccstd::optional<uint32_t> alignment; // the data alignment for each handle allocated, in bytes
|
||||
ccstd::optional<roundUpType> roundUpFn; // given a target size, how will the actual texture size round up?
|
||||
};
|
||||
|
||||
class TextureBufferPool : public RefCounted {
|
||||
public:
|
||||
TextureBufferPool();
|
||||
explicit TextureBufferPool(gfx::Device *device);
|
||||
~TextureBufferPool() override;
|
||||
|
||||
void initialize(const ITextureBufferPoolInfo &info);
|
||||
void destroy();
|
||||
ITextureBufferHandle alloc(uint32_t size);
|
||||
ITextureBufferHandle alloc(uint32_t size, index_t chunkIdx);
|
||||
|
||||
void free(const ITextureBufferHandle &handle);
|
||||
uint32_t createChunk(uint32_t length);
|
||||
void update(const ITextureBufferHandle &handle, ArrayBuffer *buffer);
|
||||
|
||||
private:
|
||||
index_t findAvailableSpace(uint32_t size, index_t chunkIdx) const;
|
||||
|
||||
// [McDonald 12] Efficient Buffer Management
|
||||
ITextureBufferHandle mcDonaldAlloc(uint32_t size);
|
||||
|
||||
gfx::Device *_device{nullptr};
|
||||
gfx::Format _format{gfx::Format::UNKNOWN};
|
||||
uint32_t _formatSize{0};
|
||||
ccstd::vector<ITextureBuffer> _chunks;
|
||||
uint32_t _chunkCount{0};
|
||||
ccstd::vector<ITextureBufferHandle> _handles;
|
||||
gfx::BufferTextureCopy _region0;
|
||||
gfx::BufferTextureCopy _region1;
|
||||
gfx::BufferTextureCopy _region2;
|
||||
roundUpType _roundUpFn{nullptr};
|
||||
bool _useMcDonaldAlloc{false};
|
||||
uint32_t _channels{4};
|
||||
uint32_t _alignment{1};
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(TextureBufferPool);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
85
cocos/renderer/frame-graph/Blackboard.h
Normal file
85
cocos/renderer/frame-graph/Blackboard.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Handle.h"
|
||||
#include "base/Macros.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
template <typename KeyType, typename ValueType, ValueType InvalidValue>
|
||||
class Blackboard final {
|
||||
public:
|
||||
Blackboard() = default;
|
||||
~Blackboard() = default;
|
||||
Blackboard(const Blackboard &) = delete;
|
||||
Blackboard(Blackboard &&) noexcept = delete;
|
||||
Blackboard &operator=(const Blackboard &) = delete;
|
||||
Blackboard &operator=(Blackboard &&) noexcept = delete;
|
||||
|
||||
inline ValueType &operator[](const KeyType &name) noexcept;
|
||||
inline void put(const KeyType &name, ValueType handle) noexcept;
|
||||
inline ValueType get(const KeyType &name) const noexcept;
|
||||
inline void clear() noexcept;
|
||||
inline bool has(const KeyType &name) const noexcept;
|
||||
|
||||
private:
|
||||
using Container = ccstd::unordered_map<KeyType, ValueType, typename KeyType::Hasher>;
|
||||
Container _container;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename KeyType, typename ValueType, ValueType InvalidValue>
|
||||
ValueType &Blackboard<KeyType, ValueType, InvalidValue>::operator[](const KeyType &name) noexcept {
|
||||
const auto it = _container.find(name);
|
||||
return (it == _container.end() ? _container.emplace(name, InvalidValue).first : it)->second;
|
||||
}
|
||||
|
||||
template <typename KeyType, typename ValueType, ValueType InvalidValue>
|
||||
void Blackboard<KeyType, ValueType, InvalidValue>::put(const KeyType &name, ValueType const handle) noexcept {
|
||||
_container[name] = handle;
|
||||
}
|
||||
|
||||
template <typename KeyType, typename ValueType, ValueType InvalidValue>
|
||||
ValueType Blackboard<KeyType, ValueType, InvalidValue>::get(const KeyType &name) const noexcept {
|
||||
const auto it = _container.find(name);
|
||||
return it == _container.end() ? InvalidValue : it->second;
|
||||
}
|
||||
|
||||
template <typename KeyType, typename ValueType, ValueType InvalidValue>
|
||||
void Blackboard<KeyType, ValueType, InvalidValue>::clear() noexcept {
|
||||
_container.clear();
|
||||
}
|
||||
|
||||
template <typename KeyType, typename ValueType, ValueType InvalidValue>
|
||||
bool Blackboard<KeyType, ValueType, InvalidValue>::has(const KeyType &name) const noexcept {
|
||||
return _container.find(name) != _container.end();
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
81
cocos/renderer/frame-graph/CallbackPass.h
Normal file
81
cocos/renderer/frame-graph/CallbackPass.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DevicePassResourceTable.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class Executable {
|
||||
public:
|
||||
Executable() noexcept = default;
|
||||
virtual ~Executable() = default;
|
||||
Executable(const Executable &) = delete;
|
||||
Executable(Executable &&) noexcept = delete;
|
||||
Executable &operator=(const Executable &) = delete;
|
||||
Executable &operator=(Executable &&) noexcept = delete;
|
||||
|
||||
virtual void execute(const DevicePassResourceTable &resourceTable) noexcept = 0;
|
||||
};
|
||||
|
||||
template <typename Data, typename ExecuteMethodType>
|
||||
class CallbackPass final : public Executable {
|
||||
public:
|
||||
using ExecuteMethod = std::remove_reference_t<ExecuteMethodType>;
|
||||
|
||||
explicit CallbackPass(ExecuteMethod &execute) noexcept;
|
||||
explicit CallbackPass(ExecuteMethod &&execute) noexcept;
|
||||
|
||||
void execute(const DevicePassResourceTable &resourceTable) noexcept override;
|
||||
inline const Data &getData() const noexcept { return _data; }
|
||||
inline Data &getData() noexcept { return _data; }
|
||||
|
||||
private:
|
||||
Data _data;
|
||||
ExecuteMethod _execute;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Data, typename ExecuteMethod>
|
||||
CallbackPass<Data, ExecuteMethod>::CallbackPass(ExecuteMethod &execute) noexcept
|
||||
: Executable(),
|
||||
_execute(execute) {
|
||||
}
|
||||
|
||||
template <typename Data, typename ExecuteMethod>
|
||||
CallbackPass<Data, ExecuteMethod>::CallbackPass(ExecuteMethod &&execute) noexcept
|
||||
: Executable(),
|
||||
_execute(execute) {
|
||||
}
|
||||
|
||||
template <typename Data, typename ExecuteMethod>
|
||||
void CallbackPass<Data, ExecuteMethod>::execute(const DevicePassResourceTable &resourceTable) noexcept {
|
||||
_execute(_data, resourceTable);
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
427
cocos/renderer/frame-graph/DevicePass.cpp
Normal file
427
cocos/renderer/frame-graph/DevicePass.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "DevicePass.h"
|
||||
#include "CallbackPass.h"
|
||||
#include "DevicePassResourceTable.h"
|
||||
#include "FrameGraph.h"
|
||||
#include "PassNode.h"
|
||||
#include "ResourceNode.h"
|
||||
#include "base/Utils.h"
|
||||
#include "gfx-base/GFXCommandBuffer.h"
|
||||
#include "gfx-base/GFXDef-common.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
DevicePass::DevicePass(const FrameGraph &graph, ccstd::vector<PassNode *> const &subpassNodes) {
|
||||
ccstd::vector<RenderTargetAttachment> attachments;
|
||||
|
||||
uint32_t index = 0;
|
||||
for (const PassNode *passNode : subpassNodes) {
|
||||
append(graph, passNode, &attachments);
|
||||
_barriers.push_back(std::cref(passNode->getBarriers()));
|
||||
_subpasses.back().barrierID = index++;
|
||||
}
|
||||
|
||||
auto *device = gfx::Device::getInstance();
|
||||
// _enableAutoBarrier: auto barrier in framegraph
|
||||
// barrierDeduce: deduce barrier gfx internally
|
||||
// to avoid redundant instructions, either inside or outside
|
||||
device->enableAutoBarrier(!gfx::ENABLE_GRAPH_AUTO_BARRIER);
|
||||
|
||||
// Important Notice:
|
||||
// here attchment index has changed.
|
||||
// _attachments is flattened previously, and it is spliced into two parts here:
|
||||
// colorAttachments and depthStencilAttachment
|
||||
// As a result, the indices in subpasses are INVALIDATED.
|
||||
// So the attachment index in subpass should be recalculated.
|
||||
// there should be only ONE depth stencil in the entire Pass
|
||||
auto depthIndex = gfx::INVALID_BINDING;
|
||||
auto depthNewIndex = gfx::INVALID_BINDING;
|
||||
for (uint32_t id = 0; id != attachments.size(); ++id) {
|
||||
if (attachments[id].desc.usage != RenderTargetAttachment::Usage::COLOR) {
|
||||
CC_ASSERT_EQ(depthIndex, gfx::INVALID_BINDING);
|
||||
depthIndex = id;
|
||||
depthNewIndex = static_cast<uint32_t>(attachments.size() - 1);
|
||||
}
|
||||
}
|
||||
std::stable_sort(attachments.begin(), attachments.end(), RenderTargetAttachment::Sorter());
|
||||
|
||||
// update subpass index
|
||||
for (auto &subpass : _subpasses) {
|
||||
// reindex subpass attchment index
|
||||
auto &info = subpass.desc;
|
||||
for (auto &id : info.inputs) {
|
||||
if (id == depthIndex) {
|
||||
id = depthNewIndex;
|
||||
} else if (id > depthIndex) {
|
||||
--id;
|
||||
}
|
||||
}
|
||||
for (auto &id : info.resolves) {
|
||||
if (id == depthIndex) {
|
||||
id = depthNewIndex;
|
||||
} else if (id > depthIndex) {
|
||||
--id;
|
||||
}
|
||||
}
|
||||
for (auto &id : info.preserves) {
|
||||
if (id == depthIndex) {
|
||||
id = depthNewIndex;
|
||||
} else if (id > depthIndex) {
|
||||
--id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccstd::vector<const gfx::Texture *> renderTargets;
|
||||
|
||||
for (auto &attachment : attachments) {
|
||||
const ResourceNode &resourceNode = graph.getResourceNode(attachment.textureHandle);
|
||||
CC_ASSERT(resourceNode.virtualResource);
|
||||
|
||||
gfx::Texture *resource = static_cast<ResourceEntry<Texture> *>(resourceNode.virtualResource)->getDeviceResource();
|
||||
CC_ASSERT(resource);
|
||||
|
||||
_attachments.emplace_back();
|
||||
_attachments.back().attachment = attachment;
|
||||
_attachments.back().renderTarget = resource;
|
||||
renderTargets.emplace_back(resource);
|
||||
}
|
||||
|
||||
for (PassNode *const passNode : subpassNodes) {
|
||||
_resourceTable.extract(graph, passNode, renderTargets);
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePass::passDependency(gfx::RenderPassInfo &rpInfo) {
|
||||
if constexpr (gfx::ENABLE_GRAPH_AUTO_BARRIER) {
|
||||
uint32_t index = 0;
|
||||
|
||||
thread_local gfx::BufferBarrierList bufferBarriers;
|
||||
thread_local gfx::TextureBarrierList textureBarriers;
|
||||
thread_local gfx::BufferList buffers;
|
||||
thread_local gfx::TextureList textures;
|
||||
|
||||
bufferBarriers.clear();
|
||||
textureBarriers.clear();
|
||||
buffers.clear();
|
||||
textures.clear();
|
||||
|
||||
uint32_t lastBufferIndex{0};
|
||||
uint32_t lastTextureIndex{0};
|
||||
|
||||
auto mergeToDependency = [&](uint32_t barrierID, uint32_t subpassIndex) {
|
||||
for (const auto &frontBarrier : _barriers[barrierID].get().frontBarriers) {
|
||||
const auto &res = getBarrier(frontBarrier, &_resourceTable);
|
||||
if (frontBarrier.resourceType == ResourceType::BUFFER) {
|
||||
bufferBarriers.emplace_back(static_cast<gfx::BufferBarrier *>(res.first));
|
||||
buffers.emplace_back(static_cast<gfx::Buffer *>(res.second));
|
||||
} else if (frontBarrier.resourceType == ResourceType::TEXTURE) {
|
||||
textureBarriers.emplace_back(static_cast<gfx::TextureBarrier *>(res.first));
|
||||
textures.emplace_back(static_cast<gfx::Texture *>(res.second));
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
lastBufferIndex = static_cast<uint32_t>(buffers.size());
|
||||
lastTextureIndex = static_cast<uint32_t>(textures.size());
|
||||
|
||||
rpInfo.dependencies.emplace_back(gfx::SubpassDependency{
|
||||
subpassIndex > 1 ? subpassIndex - 1 : gfx::SUBPASS_EXTERNAL,
|
||||
subpassIndex,
|
||||
nullptr,
|
||||
{},
|
||||
{},
|
||||
});
|
||||
|
||||
for (const auto &rearBarrier : _barriers[barrierID].get().rearBarriers) {
|
||||
const auto &res = getBarrier(rearBarrier, &_resourceTable);
|
||||
if (rearBarrier.resourceType == ResourceType::BUFFER) {
|
||||
bufferBarriers.emplace_back(static_cast<gfx::BufferBarrier *>(res.first));
|
||||
buffers.emplace_back(static_cast<gfx::Buffer *>(res.second));
|
||||
} else if (rearBarrier.resourceType == ResourceType::TEXTURE) {
|
||||
textureBarriers.emplace_back(static_cast<gfx::TextureBarrier *>(res.first));
|
||||
textures.emplace_back(static_cast<gfx::Texture *>(res.second));
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!_subpasses.empty()) {
|
||||
for (const auto &subpass : _subpasses) {
|
||||
mergeToDependency(subpass.barrierID, index);
|
||||
++index;
|
||||
}
|
||||
} else {
|
||||
mergeToDependency(0, 0);
|
||||
}
|
||||
|
||||
if (textureBarriers.size() > lastTextureIndex || bufferBarriers.size() > lastBufferIndex) {
|
||||
rpInfo.dependencies.emplace_back(gfx::SubpassDependency{
|
||||
_subpasses.empty() ? 0 : static_cast<uint32_t>(_subpasses.size() - 1),
|
||||
gfx::SUBPASS_EXTERNAL,
|
||||
nullptr,
|
||||
{},
|
||||
{},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePass::execute() {
|
||||
auto *device = gfx::Device::getInstance();
|
||||
auto *cmdBuff = device->getCommandBuffer();
|
||||
|
||||
begin(cmdBuff);
|
||||
|
||||
for (uint32_t i = 0; i < utils::toUint(_subpasses.size()); ++i) {
|
||||
Subpass &subpass = _subpasses[i];
|
||||
_resourceTable._subpassIndex = i;
|
||||
|
||||
for (LogicPass &pass : subpass.logicPasses) {
|
||||
gfx::Viewport &viewport = pass.customViewport ? pass.viewport : _viewport;
|
||||
gfx::Rect &scissor = pass.customViewport ? pass.scissor : _scissor;
|
||||
|
||||
if (viewport != _curViewport) {
|
||||
cmdBuff->setViewport(viewport);
|
||||
_curViewport = viewport;
|
||||
}
|
||||
if (scissor != _curScissor) {
|
||||
cmdBuff->setScissor(scissor);
|
||||
_curScissor = scissor;
|
||||
}
|
||||
|
||||
pass.pass->execute(_resourceTable);
|
||||
}
|
||||
|
||||
if (i < _subpasses.size() - 1) next(cmdBuff);
|
||||
}
|
||||
|
||||
end(cmdBuff);
|
||||
}
|
||||
|
||||
void DevicePass::append(const FrameGraph &graph, const PassNode *passNode, ccstd::vector<RenderTargetAttachment> *attachments) {
|
||||
_subpasses.emplace_back();
|
||||
Subpass &subpass = _subpasses.back();
|
||||
|
||||
do {
|
||||
subpass.logicPasses.emplace_back();
|
||||
LogicPass &logicPass = subpass.logicPasses.back();
|
||||
logicPass.pass = passNode->_pass.get();
|
||||
logicPass.customViewport = passNode->_customViewport;
|
||||
logicPass.viewport = passNode->_viewport;
|
||||
logicPass.scissor = passNode->_scissor;
|
||||
|
||||
for (const auto &attachment : passNode->_attachments) {
|
||||
append(graph, attachment, attachments, &subpass.desc, passNode->_reads);
|
||||
}
|
||||
|
||||
for (const auto &handle : passNode->_reads) {
|
||||
const auto it = std::find_if(attachments->begin(), attachments->end(), [&handle](const RenderTargetAttachment &attachment) {
|
||||
return attachment.textureHandle == handle;
|
||||
});
|
||||
if (it != attachments->end()) {
|
||||
uint32_t input = utils::toUint(it - attachments->begin());
|
||||
if (std::find(subpass.desc.inputs.begin(), subpass.desc.inputs.end(), input) == subpass.desc.inputs.end()) {
|
||||
subpass.desc.inputs.push_back(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
passNode = passNode->_next;
|
||||
} while (passNode);
|
||||
}
|
||||
|
||||
void DevicePass::append(const FrameGraph &graph, const RenderTargetAttachment &attachment,
|
||||
ccstd::vector<RenderTargetAttachment> *attachments, gfx::SubpassInfo *subpass, const ccstd::vector<Handle> &reads) {
|
||||
std::ignore = reads;
|
||||
RenderTargetAttachment::Usage usage{attachment.desc.usage};
|
||||
uint32_t slot{attachment.desc.slot};
|
||||
if (attachment.desc.usage == RenderTargetAttachment::Usage::COLOR) {
|
||||
// should fetch actual color slot from current subpass
|
||||
slot = subpass->colors.size() > attachment.desc.slot ? subpass->colors[attachment.desc.slot] : gfx::INVALID_BINDING;
|
||||
}
|
||||
auto it = std::find_if(attachments->begin(), attachments->end(), [usage, slot](const RenderTargetAttachment &x) {
|
||||
return usage == x.desc.usage && slot == x.desc.slot;
|
||||
});
|
||||
|
||||
RenderTargetAttachment *output{nullptr};
|
||||
|
||||
if (it == attachments->end()) {
|
||||
attachments->emplace_back(attachment);
|
||||
output = &(attachments->back());
|
||||
if (attachment.desc.usage == RenderTargetAttachment::Usage::COLOR) {
|
||||
for (uint8_t i = 0; i < RenderTargetAttachment::DEPTH_STENCIL_SLOT_START; ++i) {
|
||||
if ((_usedRenderTargetSlotMask & (1 << i)) == 0) {
|
||||
attachments->back().desc.slot = i;
|
||||
_usedRenderTargetSlotMask |= 1 << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CC_ASSERT((_usedRenderTargetSlotMask & (1 << attachment.desc.slot)) == 0);
|
||||
_usedRenderTargetSlotMask |= 1 << attachment.desc.slot;
|
||||
}
|
||||
} else {
|
||||
const ResourceNode &resourceNodeA = graph.getResourceNode(it->textureHandle);
|
||||
const ResourceNode &resourceNodeB = graph.getResourceNode(attachment.textureHandle);
|
||||
|
||||
if (resourceNodeA.virtualResource == resourceNodeB.virtualResource) {
|
||||
output = &*it;
|
||||
if (attachment.storeOp != gfx::StoreOp::DISCARD) {
|
||||
output->storeOp = attachment.storeOp;
|
||||
output->desc.endAccesses = attachment.desc.endAccesses;
|
||||
}
|
||||
} else {
|
||||
CC_ASSERT(attachment.desc.usage == RenderTargetAttachment::Usage::COLOR);
|
||||
attachments->emplace_back(attachment);
|
||||
output = &(attachments->back());
|
||||
|
||||
for (uint8_t i = 0; i < RenderTargetAttachment::DEPTH_STENCIL_SLOT_START; ++i) {
|
||||
if ((_usedRenderTargetSlotMask & (1 << i)) == 0) {
|
||||
attachments->back().desc.slot = i;
|
||||
_usedRenderTargetSlotMask |= 1 << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attachment.desc.usage == RenderTargetAttachment::Usage::COLOR) {
|
||||
if (std::find(subpass->colors.begin(), subpass->colors.end(), output->desc.slot) == subpass->colors.end()) {
|
||||
subpass->colors.push_back(output->desc.slot);
|
||||
}
|
||||
} else {
|
||||
subpass->depthStencil = output->desc.slot;
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePass::begin(gfx::CommandBuffer *cmdBuff) {
|
||||
if (_attachments.empty()) return;
|
||||
|
||||
gfx::RenderPassInfo rpInfo;
|
||||
gfx::FramebufferInfo fboInfo;
|
||||
float clearDepth = 1.F;
|
||||
uint32_t clearStencil = 0;
|
||||
static ccstd::vector<gfx::Color> clearColors;
|
||||
clearColors.clear();
|
||||
|
||||
bool hasDefaultViewport{false};
|
||||
for (auto &subpass : _subpasses) {
|
||||
for (auto &pass : subpass.logicPasses) {
|
||||
if (!pass.customViewport) {
|
||||
hasDefaultViewport = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDefaultViewport) {
|
||||
_viewport = {};
|
||||
_scissor = {0, 0, UINT_MAX, UINT_MAX};
|
||||
} else { // if all passes use customize viewport
|
||||
_scissor = {INT_MAX, INT_MAX, 0, 0};
|
||||
|
||||
for (auto &subpass : _subpasses) {
|
||||
for (auto &pass : subpass.logicPasses) {
|
||||
// calculate the union of all viewports as render area
|
||||
_viewport.left = _scissor.x = std::min(_scissor.x, pass.viewport.left);
|
||||
_viewport.top = _scissor.y = std::min(_scissor.y, pass.viewport.top);
|
||||
_viewport.width = _scissor.width = std::max(_scissor.width, pass.viewport.width + pass.viewport.left - _scissor.x);
|
||||
_viewport.height = _scissor.height = std::max(_scissor.height, pass.viewport.height + pass.viewport.top - _scissor.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &attachElem : _attachments) {
|
||||
gfx::Texture *attachment = attachElem.renderTarget;
|
||||
if (attachElem.attachment.desc.usage == RenderTargetAttachment::Usage::COLOR) {
|
||||
rpInfo.colorAttachments.emplace_back();
|
||||
auto &attachmentInfo = rpInfo.colorAttachments.back();
|
||||
attachmentInfo.format = attachment->getFormat();
|
||||
attachmentInfo.loadOp = attachElem.attachment.desc.loadOp;
|
||||
attachmentInfo.storeOp = attachElem.attachment.storeOp;
|
||||
attachmentInfo.barrier = gfx::Device::getInstance()->getGeneralBarrier({attachElem.attachment.desc.beginAccesses, attachElem.attachment.desc.endAccesses});
|
||||
fboInfo.colorTextures.push_back(attachElem.renderTarget);
|
||||
clearColors.emplace_back(attachElem.attachment.desc.clearColor);
|
||||
} else {
|
||||
auto &attachmentInfo = rpInfo.depthStencilAttachment;
|
||||
attachmentInfo.format = attachment->getFormat();
|
||||
attachmentInfo.depthLoadOp = attachElem.attachment.desc.loadOp;
|
||||
attachmentInfo.stencilLoadOp = attachElem.attachment.desc.loadOp;
|
||||
attachmentInfo.depthStoreOp = attachElem.attachment.storeOp;
|
||||
attachmentInfo.stencilStoreOp = attachElem.attachment.storeOp;
|
||||
attachmentInfo.barrier = gfx::Device::getInstance()->getGeneralBarrier({attachElem.attachment.desc.beginAccesses, attachElem.attachment.desc.endAccesses});
|
||||
fboInfo.depthStencilTexture = attachElem.renderTarget;
|
||||
clearDepth = attachElem.attachment.desc.clearDepth;
|
||||
clearStencil = attachElem.attachment.desc.clearStencil;
|
||||
}
|
||||
if (hasDefaultViewport) {
|
||||
_viewport.width = _scissor.width = std::min(_scissor.width, attachment->getWidth());
|
||||
_viewport.height = _scissor.height = std::min(_scissor.height, attachment->getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &subpass : _subpasses) {
|
||||
rpInfo.subpasses.emplace_back(subpass.desc);
|
||||
}
|
||||
|
||||
passDependency(rpInfo);
|
||||
|
||||
_renderPass = RenderPass(rpInfo);
|
||||
_renderPass.createTransient();
|
||||
_resourceTable._renderPass = _renderPass.get();
|
||||
|
||||
fboInfo.renderPass = _renderPass.get();
|
||||
_fbo = Framebuffer(fboInfo);
|
||||
_fbo.createTransient();
|
||||
|
||||
cmdBuff->beginRenderPass(_renderPass.get(), _fbo.get(), _scissor, clearColors.data(), clearDepth, clearStencil);
|
||||
_curViewport = _viewport;
|
||||
_curScissor = _scissor;
|
||||
}
|
||||
|
||||
void DevicePass::next(gfx::CommandBuffer *cmdBuff) noexcept {
|
||||
if (!_renderPass.get() || !_fbo.get()) return;
|
||||
|
||||
cmdBuff->nextSubpass();
|
||||
}
|
||||
|
||||
void DevicePass::end(gfx::CommandBuffer *cmdBuff) {
|
||||
if (!_renderPass.get() || !_fbo.get()) return;
|
||||
|
||||
cmdBuff->endRenderPass();
|
||||
|
||||
_renderPass.destroyTransient();
|
||||
_fbo.destroyTransient();
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
93
cocos/renderer/frame-graph/DevicePass.h
Normal file
93
cocos/renderer/frame-graph/DevicePass.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include "CallbackPass.h"
|
||||
#include "ImmutableState.h"
|
||||
#include "RenderTargetAttachment.h"
|
||||
#include "base/std/container/string.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class DevicePass final {
|
||||
public:
|
||||
DevicePass() = delete;
|
||||
DevicePass(const FrameGraph &graph, ccstd::vector<PassNode *> const &subpassNodes);
|
||||
DevicePass(const DevicePass &) = delete;
|
||||
DevicePass(DevicePass &&) = delete;
|
||||
~DevicePass() = default;
|
||||
DevicePass &operator=(const DevicePass &) = delete;
|
||||
DevicePass &operator=(DevicePass &&) = delete;
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
struct LogicPass final {
|
||||
Executable *pass{nullptr};
|
||||
bool customViewport{false};
|
||||
gfx::Viewport viewport;
|
||||
gfx::Rect scissor;
|
||||
};
|
||||
|
||||
struct Subpass final {
|
||||
gfx::SubpassInfo desc;
|
||||
ccstd::vector<LogicPass> logicPasses{};
|
||||
uint32_t barrierID{0xFFFFFFFF};
|
||||
};
|
||||
|
||||
struct Attachment final {
|
||||
RenderTargetAttachment attachment;
|
||||
gfx::Texture *renderTarget{nullptr};
|
||||
};
|
||||
|
||||
void append(const FrameGraph &graph, const PassNode *passNode, ccstd::vector<RenderTargetAttachment> *attachments);
|
||||
void append(const FrameGraph &graph, const RenderTargetAttachment &attachment,
|
||||
ccstd::vector<RenderTargetAttachment> *attachments, gfx::SubpassInfo *subpass, const ccstd::vector<Handle> &reads);
|
||||
void begin(gfx::CommandBuffer *cmdBuff);
|
||||
void next(gfx::CommandBuffer *cmdBuff) noexcept;
|
||||
void end(gfx::CommandBuffer *cmdBuff);
|
||||
|
||||
void passDependency(gfx::RenderPassInfo &rpInfo);
|
||||
|
||||
ccstd::vector<Subpass> _subpasses{};
|
||||
ccstd::vector<Attachment> _attachments{};
|
||||
uint16_t _usedRenderTargetSlotMask{0};
|
||||
DevicePassResourceTable _resourceTable;
|
||||
|
||||
gfx::Viewport _viewport;
|
||||
gfx::Rect _scissor;
|
||||
gfx::Viewport _curViewport;
|
||||
gfx::Rect _curScissor;
|
||||
RenderPass _renderPass;
|
||||
Framebuffer _fbo;
|
||||
|
||||
std::vector<std::reference_wrapper<const PassBarrierPair>> _barriers;
|
||||
};
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
87
cocos/renderer/frame-graph/DevicePassResourceTable.cpp
Normal file
87
cocos/renderer/frame-graph/DevicePassResourceTable.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "DevicePassResourceTable.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "FrameGraph.h"
|
||||
#include "PassNode.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
gfx::GFXObject *DevicePassResourceTable::get(const ResourceDictionary &from, Handle handle) noexcept {
|
||||
const auto it = from.find(handle);
|
||||
return it == from.cend() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
void DevicePassResourceTable::extract(const FrameGraph &graph,
|
||||
const PassNode *passNode,
|
||||
ccstd::vector<const gfx::Texture *> const &renderTargets) noexcept {
|
||||
do {
|
||||
extract(graph, passNode->_reads, _reads, false, renderTargets);
|
||||
extract(graph, passNode->_writes, _writes, true, renderTargets);
|
||||
|
||||
passNode = passNode->_next;
|
||||
} while (passNode);
|
||||
}
|
||||
|
||||
void DevicePassResourceTable::extract(const FrameGraph &graph,
|
||||
ccstd::vector<Handle> const &from,
|
||||
ResourceDictionary &to,
|
||||
bool /*ignoreRenderTarget*/,
|
||||
ccstd::vector<const gfx::Texture *> const & /*renderTargets*/) noexcept {
|
||||
std::for_each(from.cbegin(), from.cend(), [&](const Handle handle) {
|
||||
if (to.find(handle) != to.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ResourceNode &resourceNode = graph.getResourceNode(handle);
|
||||
CC_ASSERT(resourceNode.virtualResource);
|
||||
gfx::GFXObject *const deviceResource = resourceNode.virtualResource->getDeviceResource();
|
||||
|
||||
if (!deviceResource) {
|
||||
return;
|
||||
}
|
||||
|
||||
//if (ignoreRenderTarget) {
|
||||
// bool const isRenderTarget =
|
||||
// std::find_if(
|
||||
// renderTargets.cbegin(),
|
||||
// renderTargets.cend(),
|
||||
// [&deviceResource](const gfx::Texture *const x) {
|
||||
// return deviceResource == x;
|
||||
// }) != renderTargets.cend();
|
||||
|
||||
// if (isRenderTarget) {
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
||||
to[handle] = deviceResource;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
88
cocos/renderer/frame-graph/DevicePassResourceTable.h
Normal file
88
cocos/renderer/frame-graph/DevicePassResourceTable.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Handle.h"
|
||||
#include "RenderTargetAttachment.h"
|
||||
#include "Resource.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class PassNode;
|
||||
class FrameGraph;
|
||||
class DevicePass;
|
||||
|
||||
class DevicePassResourceTable final {
|
||||
public:
|
||||
DevicePassResourceTable() = default;
|
||||
~DevicePassResourceTable() = default;
|
||||
DevicePassResourceTable(const DevicePassResourceTable &) = delete;
|
||||
DevicePassResourceTable(DevicePassResourceTable &&) = delete;
|
||||
DevicePassResourceTable &operator=(const DevicePassResourceTable &) = delete;
|
||||
DevicePassResourceTable &operator=(DevicePassResourceTable &&) = delete;
|
||||
|
||||
template <typename Type>
|
||||
std::enable_if_t<std::is_base_of<gfx::GFXObject, typename Type::DeviceResource>::value, typename Type::DeviceResource *>
|
||||
getRead(TypedHandle<Type> handle) const noexcept;
|
||||
|
||||
template <typename Type>
|
||||
std::enable_if_t<std::is_base_of<gfx::GFXObject, typename Type::DeviceResource>::value, typename Type::DeviceResource *>
|
||||
getWrite(TypedHandle<Type> handle) const noexcept;
|
||||
|
||||
gfx::RenderPass *getRenderPass() const { return _renderPass; }
|
||||
uint32_t getSubpassIndex() const { return _subpassIndex; }
|
||||
|
||||
private:
|
||||
using ResourceDictionary = ccstd::unordered_map<Handle, gfx::GFXObject *, Handle::Hasher>;
|
||||
|
||||
static gfx::GFXObject *get(const ResourceDictionary &from, Handle handle) noexcept;
|
||||
void extract(const FrameGraph &graph, const PassNode *passNode, ccstd::vector<const gfx::Texture *> const &renderTargets) noexcept;
|
||||
static void extract(const FrameGraph &graph, ccstd::vector<Handle> const &from, ResourceDictionary &to, bool ignoreRenderTarget, ccstd::vector<const gfx::Texture *> const &renderTargets) noexcept;
|
||||
|
||||
ResourceDictionary _reads{};
|
||||
ResourceDictionary _writes{};
|
||||
|
||||
gfx::RenderPass *_renderPass{nullptr};
|
||||
uint32_t _subpassIndex{0U};
|
||||
|
||||
friend class DevicePass;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
std::enable_if_t<std::is_base_of<gfx::GFXObject, typename Type::DeviceResource>::value, typename Type::DeviceResource *>
|
||||
DevicePassResourceTable::getRead(TypedHandle<Type> handle) const noexcept {
|
||||
return static_cast<typename Type::DeviceResource *>(get(_reads, handle));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
std::enable_if_t<std::is_base_of<gfx::GFXObject, typename Type::DeviceResource>::value, typename Type::DeviceResource *>
|
||||
DevicePassResourceTable::getWrite(TypedHandle<Type> handle) const noexcept {
|
||||
return static_cast<typename Type::DeviceResource *>(get(_writes, handle));
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
659
cocos/renderer/frame-graph/FrameGraph.cpp
Normal file
659
cocos/renderer/frame-graph/FrameGraph.cpp
Normal file
@@ -0,0 +1,659 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "FrameGraph.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include "PassNodeBuilder.h"
|
||||
#include "Resource.h"
|
||||
#include "base/StringUtil.h"
|
||||
#include "base/std/container/set.h"
|
||||
#include "frame-graph/ResourceEntry.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
namespace {
|
||||
// use function scoped static member
|
||||
// to ensure correct initialization order
|
||||
StringPool &getStringPool() {
|
||||
static StringPool pool;
|
||||
return pool;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
StringHandle FrameGraph::stringToHandle(const char *const name) {
|
||||
return getStringPool().stringToHandle(name);
|
||||
}
|
||||
|
||||
const char *FrameGraph::handleToString(const StringHandle &handle) noexcept {
|
||||
return getStringPool().handleToString(handle);
|
||||
}
|
||||
|
||||
void FrameGraph::present(const TextureHandle &input, gfx::Texture *target, bool useMoveSemantic) {
|
||||
static const StringHandle PRESENT_PASS{FrameGraph::stringToHandle("Present")};
|
||||
|
||||
const ResourceNode &resourceNode{getResourceNode(input)};
|
||||
CC_ASSERT(resourceNode.writer);
|
||||
|
||||
struct PassDataPresent {
|
||||
TextureHandle input;
|
||||
};
|
||||
|
||||
addPass<PassDataPresent>(
|
||||
resourceNode.writer->_insertPoint, PRESENT_PASS,
|
||||
[&](PassNodeBuilder &builder, PassDataPresent &data) {
|
||||
data.input = builder.read(input);
|
||||
builder.sideEffect();
|
||||
|
||||
if (useMoveSemantic) {
|
||||
// using a global map here so that the user don't need to worry about importing the targets every frame
|
||||
static ccstd::unordered_map<uint32_t, std::pair<StringHandle, Texture>> presentTargets;
|
||||
if (!presentTargets.count(target->getTypedID())) {
|
||||
auto name = FrameGraph::stringToHandle(StringUtil::format("Present Target %d", target->getTypedID()).c_str());
|
||||
presentTargets.emplace(std::piecewise_construct, std::forward_as_tuple(target->getTypedID()), std::forward_as_tuple(name, Texture{target}));
|
||||
}
|
||||
auto &resourceInfo{presentTargets[target->getTypedID()]};
|
||||
TextureHandle output{getBlackboard().get(resourceInfo.first)};
|
||||
if (!output.isValid()) {
|
||||
output = importExternal(resourceInfo.first, resourceInfo.second);
|
||||
getBlackboard().put(resourceInfo.first, output);
|
||||
}
|
||||
move(data.input, output, 0, 0, 0);
|
||||
data.input = output;
|
||||
}
|
||||
},
|
||||
[target](const PassDataPresent &data, const DevicePassResourceTable &table) {
|
||||
auto *cmdBuff = gfx::Device::getInstance()->getCommandBuffer();
|
||||
|
||||
gfx::Texture *input = table.getRead(data.input);
|
||||
if (input && input != target) {
|
||||
gfx::TextureBlit region;
|
||||
region.srcExtent.width = input->getWidth();
|
||||
region.srcExtent.height = input->getHeight();
|
||||
region.dstExtent.width = target->getWidth();
|
||||
region.dstExtent.height = target->getHeight();
|
||||
cmdBuff->blitTexture(input, target, ®ion, 1, gfx::Filter::POINT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FrameGraph::presentLastVersion(const VirtualResource *const virtualResource, gfx::Texture *target, bool useMoveSemantic) {
|
||||
const auto it = std::find_if(_resourceNodes.rbegin(), _resourceNodes.rend(), [&virtualResource](const ResourceNode &node) {
|
||||
return node.virtualResource == virtualResource;
|
||||
});
|
||||
|
||||
CC_ASSERT(it != _resourceNodes.rend());
|
||||
present(TextureHandle(static_cast<Handle::IndexType>(it.base() - _resourceNodes.begin() - 1)), target, useMoveSemantic);
|
||||
}
|
||||
|
||||
void FrameGraph::presentFromBlackboard(const StringHandle &inputName, gfx::Texture *target, bool useMoveSemantic) {
|
||||
present(TextureHandle(_blackboard.get(inputName)), target, useMoveSemantic);
|
||||
}
|
||||
|
||||
void FrameGraph::compile() {
|
||||
if (_passNodes.empty()) return;
|
||||
sort();
|
||||
cull();
|
||||
computeResourceLifetime();
|
||||
|
||||
if (_merge) {
|
||||
mergePassNodes();
|
||||
}
|
||||
|
||||
computeStoreActionAndMemoryless();
|
||||
generateDevicePasses();
|
||||
}
|
||||
|
||||
void FrameGraph::execute() noexcept {
|
||||
if (_passNodes.empty()) return;
|
||||
for (auto &pass : _devicePasses) {
|
||||
pass->execute();
|
||||
}
|
||||
}
|
||||
|
||||
void FrameGraph::reset() noexcept {
|
||||
_passNodes.clear();
|
||||
_resourceNodes.clear();
|
||||
_virtualResources.clear();
|
||||
_devicePasses.clear();
|
||||
_blackboard.clear();
|
||||
}
|
||||
|
||||
void FrameGraph::gc(uint32_t const unusedFrameCount) noexcept {
|
||||
Buffer::Allocator::getInstance().gc(unusedFrameCount);
|
||||
Framebuffer::Allocator::getInstance().gc(unusedFrameCount);
|
||||
RenderPass::Allocator::getInstance().gc(unusedFrameCount);
|
||||
Texture::Allocator::getInstance().gc(unusedFrameCount);
|
||||
}
|
||||
|
||||
void FrameGraph::move(const TextureHandle from, const TextureHandle to, uint8_t mipmapLevel, uint8_t faceId, uint8_t arrayPosition) noexcept {
|
||||
const ResourceNode &fromResourceNode = getResourceNode(from);
|
||||
const ResourceNode &toResourceNode = getResourceNode(to);
|
||||
|
||||
CC_ASSERT(!fromResourceNode.virtualResource->isImported());
|
||||
CC_ASSERT(fromResourceNode.writer);
|
||||
CC_ASSERT(!toResourceNode.writer);
|
||||
|
||||
const gfx::TextureInfo &toTextureDesc = static_cast<ResourceEntry<Texture> *>(toResourceNode.virtualResource)->get().getDesc();
|
||||
uint32_t const toTextureWidth = toTextureDesc.width >> mipmapLevel;
|
||||
uint32_t const toTextureHeight = toTextureDesc.height >> mipmapLevel;
|
||||
uint32_t const toTextureDepth = toTextureDesc.depth >> mipmapLevel;
|
||||
|
||||
CC_ASSERT(toTextureWidth && toTextureHeight && toTextureDepth);
|
||||
CC_ASSERT(toTextureDesc.levelCount > mipmapLevel && toTextureDesc.layerCount > arrayPosition);
|
||||
CC_ASSERT(toTextureDesc.type == gfx::TextureType::CUBE && faceId < 6 || faceId == 0);
|
||||
|
||||
for (ResourceNode &resourceNode : _resourceNodes) {
|
||||
if (resourceNode.virtualResource == fromResourceNode.virtualResource) {
|
||||
resourceNode.virtualResource = toResourceNode.virtualResource;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &passNode : _passNodes) {
|
||||
for (auto &attachment : passNode->_attachments) {
|
||||
const ResourceNode &attachmentResourceNode = getResourceNode(attachment.textureHandle);
|
||||
|
||||
if (attachmentResourceNode.virtualResource == toResourceNode.virtualResource) {
|
||||
const gfx::TextureInfo &attachmentTextureDesc = static_cast<ResourceEntry<Texture> *>(attachmentResourceNode.virtualResource)->get().getDesc();
|
||||
CC_ASSERT(attachmentTextureDesc.width >> attachment.level == toTextureWidth &&
|
||||
attachmentTextureDesc.height >> attachment.level == toTextureHeight &&
|
||||
attachmentTextureDesc.depth >> attachment.level == toTextureDepth);
|
||||
attachment.level = mipmapLevel;
|
||||
attachment.layer = faceId;
|
||||
attachment.index = arrayPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FrameGraph::hasPass(StringHandle handle) {
|
||||
return std::any_of(_passNodes.begin(), _passNodes.end(), [&](const auto &passNode) { return passNode->_name == handle; });
|
||||
}
|
||||
|
||||
Handle FrameGraph::create(VirtualResource *const virtualResource) {
|
||||
_virtualResources.emplace_back(virtualResource);
|
||||
return createResourceNode(virtualResource);
|
||||
}
|
||||
|
||||
PassNode &FrameGraph::createPassNode(const PassInsertPoint insertPoint, const StringHandle &name, Executable *const pass) {
|
||||
_passNodes.emplace_back(ccnew PassNode(insertPoint, name, static_cast<ID>(_passNodes.size()), pass));
|
||||
return *_passNodes.back();
|
||||
}
|
||||
|
||||
Handle FrameGraph::createResourceNode(VirtualResource *const virtualResource) {
|
||||
const size_t index = _resourceNodes.size();
|
||||
ResourceNode resourceNode;
|
||||
resourceNode.virtualResource = virtualResource;
|
||||
resourceNode.version = virtualResource->_version;
|
||||
_resourceNodes.emplace_back(resourceNode);
|
||||
|
||||
return Handle{static_cast<Handle::IndexType>(index)};
|
||||
}
|
||||
|
||||
void FrameGraph::sort() noexcept {
|
||||
std::stable_sort(_passNodes.begin(), _passNodes.end(), [](const auto &x, const auto &y) {
|
||||
return x->_insertPoint < y->_insertPoint;
|
||||
});
|
||||
}
|
||||
|
||||
void FrameGraph::cull() {
|
||||
for (const auto &passNode : _passNodes) {
|
||||
passNode->_refCount = static_cast<uint32_t>(passNode->_writes.size()) + passNode->_sideEffect;
|
||||
|
||||
for (const Handle handle : passNode->_reads) {
|
||||
CC_ASSERT(handle.isValid());
|
||||
++_resourceNodes[handle].readerCount;
|
||||
}
|
||||
}
|
||||
|
||||
static ccstd::vector<const ResourceNode *> stack;
|
||||
stack.clear();
|
||||
stack.reserve(_resourceNodes.size());
|
||||
|
||||
for (ResourceNode &resourceNode : _resourceNodes) {
|
||||
if (resourceNode.readerCount == 0 && resourceNode.writer) {
|
||||
stack.push_back(&resourceNode);
|
||||
}
|
||||
}
|
||||
|
||||
while (!stack.empty()) {
|
||||
PassNode *const writerPassNode = stack.back()->writer;
|
||||
stack.pop_back();
|
||||
|
||||
if (writerPassNode) {
|
||||
CC_ASSERT(writerPassNode->_refCount);
|
||||
|
||||
if (--writerPassNode->_refCount == 0) {
|
||||
CC_ASSERT(!writerPassNode->_sideEffect);
|
||||
|
||||
for (const Handle handle : writerPassNode->_reads) {
|
||||
ResourceNode &resourceNode = _resourceNodes[handle];
|
||||
|
||||
if (--resourceNode.readerCount == 0) {
|
||||
stack.push_back(&resourceNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const ResourceNode &resourceNode : _resourceNodes) {
|
||||
resourceNode.virtualResource->_refCount += resourceNode.readerCount;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameGraph::computeResourceLifetime() {
|
||||
for (const auto &passNode : _passNodes) {
|
||||
if (passNode->_refCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const Handle handle : passNode->_reads) {
|
||||
_resourceNodes[handle].virtualResource->updateLifetime(passNode.get());
|
||||
}
|
||||
|
||||
for (const Handle handle : passNode->_writes) {
|
||||
_resourceNodes[handle].virtualResource->updateLifetime(passNode.get());
|
||||
++_resourceNodes[handle].virtualResource->_writerCount;
|
||||
}
|
||||
|
||||
std::sort(passNode->_attachments.begin(), passNode->_attachments.end(), RenderTargetAttachment::Sorter());
|
||||
}
|
||||
|
||||
for (const auto &resource : _virtualResources) {
|
||||
CC_ASSERT(!resource->_firstUsePass == !resource->_lastUsePass);
|
||||
|
||||
if (!resource->_firstUsePass || !resource->_lastUsePass) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resource->_refCount == 0 && !resource->_lastUsePass->getRenderTargetAttachment(*this, resource.get())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
resource->_firstUsePass->_resourceRequestArray.push_back(resource.get());
|
||||
resource->_lastUsePass->_resourceReleaseArray.push_back(resource.get());
|
||||
}
|
||||
}
|
||||
|
||||
void FrameGraph::mergePassNodes() noexcept {
|
||||
const size_t count = _passNodes.size();
|
||||
size_t currentPassId = 0;
|
||||
size_t lastPassId = 0;
|
||||
|
||||
while (currentPassId < count) {
|
||||
const auto ¤tPassNode = _passNodes[currentPassId];
|
||||
|
||||
if (currentPassNode->_refCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
++currentPassId;
|
||||
}
|
||||
|
||||
lastPassId = currentPassId;
|
||||
|
||||
while (++currentPassId < count) {
|
||||
const auto ¤tPassNode = _passNodes[currentPassId];
|
||||
|
||||
if (currentPassNode->_refCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &lastPassNode = _passNodes[lastPassId];
|
||||
|
||||
if (lastPassNode->canMerge(*this, *currentPassNode)) {
|
||||
auto *prevPassNode = lastPassNode.get();
|
||||
|
||||
uint16_t distance = 1;
|
||||
|
||||
while (prevPassNode->_next) {
|
||||
prevPassNode = prevPassNode->_next;
|
||||
++distance;
|
||||
}
|
||||
|
||||
prevPassNode->_next = currentPassNode.get();
|
||||
currentPassNode->_head = lastPassNode.get();
|
||||
currentPassNode->_distanceToHead = distance;
|
||||
currentPassNode->_refCount = 0;
|
||||
|
||||
const size_t attachmentCount = lastPassNode->_attachments.size();
|
||||
|
||||
for (size_t i = 0; i < attachmentCount; ++i) {
|
||||
const RenderTargetAttachment &attachmentInLastPassNode = lastPassNode->_attachments[i];
|
||||
const RenderTargetAttachment &attachmentInCurrentPassNode = currentPassNode->_attachments[i];
|
||||
|
||||
ResourceNode &resourceNode = _resourceNodes[attachmentInLastPassNode.textureHandle];
|
||||
uint16_t &writeCount = resourceNode.virtualResource->_writerCount;
|
||||
CC_ASSERT_GT(writeCount, 1);
|
||||
--writeCount;
|
||||
|
||||
resourceNode.readerCount += _resourceNodes[attachmentInCurrentPassNode.textureHandle].readerCount;
|
||||
resourceNode.readerCount -= attachmentInCurrentPassNode.desc.loadOp == gfx::LoadOp::LOAD;
|
||||
}
|
||||
} else {
|
||||
lastPassId = currentPassId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FrameGraph::computeStoreActionAndMemoryless() {
|
||||
ID passId = 0;
|
||||
bool lastPassSubpassEnable = false;
|
||||
|
||||
for (const auto &passNode : _passNodes) {
|
||||
if (passNode->_refCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ID const oldPassId = passId;
|
||||
passId += !passNode->_subpass || lastPassSubpassEnable != passNode->_subpass;
|
||||
passId += oldPassId == passId ? passNode->_hasClearedAttachment * !passNode->_clearActionIgnorable : 0;
|
||||
passNode->setDevicePassId(passId);
|
||||
lastPassSubpassEnable = passNode->_subpass && !passNode->_subpassEnd;
|
||||
}
|
||||
|
||||
static ccstd::set<VirtualResource *> renderTargets;
|
||||
renderTargets.clear();
|
||||
|
||||
for (const auto &passNode : _passNodes) {
|
||||
if (passNode->_refCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (RenderTargetAttachment &attachment : passNode->_attachments) {
|
||||
CC_ASSERT(attachment.textureHandle.isValid());
|
||||
ResourceNode &resourceNode = getResourceNode(attachment.textureHandle);
|
||||
|
||||
if (resourceNode.virtualResource->isImported() || resourceNode.readerCount) {
|
||||
if (passNode->_subpass) {
|
||||
if (passNode->_devicePassId != resourceNode.virtualResource->_lastUsePass->_devicePassId) {
|
||||
attachment.storeOp = gfx::StoreOp::STORE;
|
||||
}
|
||||
} else {
|
||||
if (attachment.desc.writeMask) {
|
||||
attachment.storeOp = gfx::StoreOp::STORE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (passNode->_subpass && attachment.desc.loadOp == gfx::LoadOp::LOAD && resourceNode.version > 1) {
|
||||
ResourceNode *const resourceNodePrevVersion = getResourceNode(resourceNode.virtualResource, resourceNode.version - 1);
|
||||
CC_ASSERT(resourceNodePrevVersion);
|
||||
|
||||
if (resourceNodePrevVersion->writer->_devicePassId == passNode->_devicePassId) {
|
||||
attachment.desc.loadOp = gfx::LoadOp::DISCARD;
|
||||
resourceNodePrevVersion->writer->getRenderTargetAttachment(*this, resourceNodePrevVersion->virtualResource)->storeOp = gfx::StoreOp::DISCARD;
|
||||
}
|
||||
}
|
||||
|
||||
if (attachment.desc.loadOp == gfx::LoadOp::LOAD) {
|
||||
resourceNode.virtualResource->_neverLoaded = false;
|
||||
}
|
||||
|
||||
if (attachment.storeOp == gfx::StoreOp::STORE) {
|
||||
resourceNode.virtualResource->_neverStored = false;
|
||||
}
|
||||
|
||||
renderTargets.emplace(resourceNode.virtualResource);
|
||||
}
|
||||
}
|
||||
|
||||
for (VirtualResource *const renderTarget : renderTargets) {
|
||||
const gfx::TextureInfo &textureDesc = static_cast<ResourceEntry<Texture> *>(renderTarget)->get().getDesc();
|
||||
|
||||
renderTarget->_memoryless = renderTarget->_neverLoaded && renderTarget->_neverStored;
|
||||
renderTarget->_memorylessMSAA = textureDesc.samples != gfx::SampleCount::X1 && renderTarget->_writerCount < 2;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameGraph::generateDevicePasses() {
|
||||
Buffer::Allocator::getInstance().tick();
|
||||
Framebuffer::Allocator::getInstance().tick();
|
||||
RenderPass::Allocator::getInstance().tick();
|
||||
Texture::Allocator::getInstance().tick();
|
||||
|
||||
ID passId = 1;
|
||||
|
||||
static ccstd::vector<PassNode *> subpassNodes;
|
||||
subpassNodes.clear();
|
||||
|
||||
for (const auto &passNode : _passNodes) {
|
||||
if (passNode->_refCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passId != passNode->_devicePassId) {
|
||||
_devicePasses.emplace_back(ccnew DevicePass(*this, subpassNodes));
|
||||
|
||||
for (PassNode *const p : subpassNodes) {
|
||||
p->releaseTransientResources();
|
||||
}
|
||||
|
||||
subpassNodes.clear();
|
||||
passId = passNode->_devicePassId;
|
||||
}
|
||||
|
||||
passNode->requestTransientResources();
|
||||
subpassNodes.emplace_back(passNode.get());
|
||||
}
|
||||
|
||||
CC_ASSERT(subpassNodes.size() == 1);
|
||||
|
||||
_devicePasses.emplace_back(ccnew DevicePass(*this, subpassNodes));
|
||||
|
||||
for (PassNode *const p : subpassNodes) {
|
||||
p->releaseTransientResources();
|
||||
}
|
||||
}
|
||||
|
||||
// https://dreampuf.github.io/GraphvizOnline/
|
||||
void FrameGraph::exportGraphViz(const ccstd::string &path) {
|
||||
std::ofstream out(path, std::ios::out | std::ios::binary);
|
||||
//out.imbue(std::locale("chs", std::locale::ctype));
|
||||
|
||||
if (out.fail()) {
|
||||
return;
|
||||
}
|
||||
|
||||
out << "digraph framegraph {\n";
|
||||
out << "rankdir = LR\n";
|
||||
out << "bgcolor = black\n";
|
||||
out << "node [shape=rectangle, fontname=\"helvetica\", fontsize=10]\n\n";
|
||||
|
||||
for (const auto &node : _passNodes) {
|
||||
if (node->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out << "\"P" << node->_id << "\" [label=\"" << node->_name.str();
|
||||
|
||||
const PassNode *currPassNode = node.get();
|
||||
|
||||
if (currPassNode->_head) {
|
||||
out << "\\n(merged by pass " << currPassNode->_head->_name.str() << ")";
|
||||
} else {
|
||||
while (currPassNode->_next) {
|
||||
currPassNode = currPassNode->_next;
|
||||
out << " & " << currPassNode->_name.str();
|
||||
}
|
||||
}
|
||||
|
||||
out << "\\nrefs: " << node->_refCount
|
||||
<< "\\nseq: " << node->_id
|
||||
<< "\\ndevice pass id: " << node->_devicePassId
|
||||
<< "\", style=filled, fillcolor="
|
||||
<< (node->_refCount ? "darkorange" : "darkorange4") << "]\n";
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
|
||||
for (const ResourceNode &node : _resourceNodes) {
|
||||
if (node.writer && node.writer->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out << "\"R" << node.virtualResource->_id << "_" << +node.version << "\""
|
||||
"[label=\""
|
||||
<< node.virtualResource->_name.str() << "\\n(version: " << +node.version << ")"
|
||||
<< "\\nrefs:" << node.virtualResource->_refCount;
|
||||
|
||||
if (node.virtualResource->_memoryless) {
|
||||
out << "\\nMemoryless";
|
||||
}
|
||||
|
||||
if (node.virtualResource->_memorylessMSAA) {
|
||||
out << "\\nMemorylessMSAA";
|
||||
}
|
||||
|
||||
PassNode *const writer = (node.writer && node.writer->_head) ? node.writer->_head : node.writer;
|
||||
|
||||
if (writer) {
|
||||
out << "\\n";
|
||||
const RenderTargetAttachment *const attachment = writer->getRenderTargetAttachment(*this, node.virtualResource);
|
||||
|
||||
if (attachment) {
|
||||
switch (attachment->desc.loadOp) {
|
||||
case gfx::LoadOp::DISCARD:
|
||||
out << "DontCare";
|
||||
break;
|
||||
case gfx::LoadOp::CLEAR:
|
||||
out << "Clear";
|
||||
break;
|
||||
default:
|
||||
out << "Load";
|
||||
break;
|
||||
}
|
||||
out << ", ";
|
||||
out << (attachment->storeOp == gfx::StoreOp::DISCARD ? "DontCare" : "Store");
|
||||
out << "\\nWriteMask: 0x" << std::hex << static_cast<uint32_t>(attachment->desc.writeMask) << std::dec;
|
||||
} else {
|
||||
out << "Transfer";
|
||||
}
|
||||
}
|
||||
|
||||
out << "\", style=filled, fillcolor="
|
||||
<< ((node.virtualResource->isImported())
|
||||
? (node.virtualResource->_refCount ? "palegreen" : "palegreen4")
|
||||
: (node.version == 0 ? "pink" : (node.virtualResource->_refCount ? "skyblue" : "skyblue4")))
|
||||
<< "]\n";
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
|
||||
for (const auto &node : _passNodes) {
|
||||
if (node->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out << "P" << node->_id << " -> { ";
|
||||
|
||||
for (const Handle writer : node->_writes) {
|
||||
out << "R" << _resourceNodes[writer].virtualResource->_id << "_" << +_resourceNodes[writer].version << " ";
|
||||
}
|
||||
|
||||
out << "} [color=red]\n";
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
|
||||
for (const ResourceNode &node : _resourceNodes) {
|
||||
if (node.writer && node.writer->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out << "R" << node.virtualResource->_id << "_" << +node.version << " -> { ";
|
||||
|
||||
for (const auto &passNode : _passNodes) {
|
||||
if (passNode->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Handle read : passNode->_reads) {
|
||||
const ResourceNode *readResourceNode = &_resourceNodes[read];
|
||||
|
||||
if (readResourceNode->writer && readResourceNode->writer->_head) {
|
||||
const Handle resourceNodeHandlePrevVersion = readResourceNode->writer->_head->getWriteResourceNodeHandle(*this, readResourceNode->virtualResource);
|
||||
CC_ASSERT(resourceNodeHandlePrevVersion.isValid());
|
||||
readResourceNode = &getResourceNode(resourceNodeHandlePrevVersion);
|
||||
}
|
||||
|
||||
if (readResourceNode->virtualResource->_id == node.virtualResource->_id &&
|
||||
readResourceNode->version == node.version) {
|
||||
out << "P" << passNode->_id << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << "} [color=green]\n";
|
||||
}
|
||||
|
||||
for (const ResourceNode &node : _resourceNodes) {
|
||||
if (node.writer && node.writer->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out << "R" << node.virtualResource->_id << "_" << +node.version << " -> { ";
|
||||
|
||||
for (const auto &passNode : _passNodes) {
|
||||
if (passNode->_head) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const RenderTargetAttachment &attachment : passNode->_attachments) {
|
||||
const ResourceNode *readResourceNode = &_resourceNodes[attachment.textureHandle];
|
||||
uint16_t const distanceToHead = readResourceNode->writer->_distanceToHead;
|
||||
|
||||
if (readResourceNode->writer && readResourceNode->writer->_head) {
|
||||
const Handle resourceNodeHandleHead = readResourceNode->writer->_head->getWriteResourceNodeHandle(*this, readResourceNode->virtualResource);
|
||||
CC_ASSERT(resourceNodeHandleHead.isValid());
|
||||
readResourceNode = &getResourceNode(resourceNodeHandleHead);
|
||||
}
|
||||
|
||||
if (readResourceNode->virtualResource == node.virtualResource &&
|
||||
readResourceNode->version == node.version + 1 - distanceToHead) {
|
||||
out << "P" << passNode->_id << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << "} [color=red4]\n";
|
||||
}
|
||||
|
||||
out << "}" << std::endl;
|
||||
out.close();
|
||||
}
|
||||
|
||||
ResourceNode *FrameGraph::getResourceNode(const VirtualResource *const virtualResource, uint8_t version) noexcept {
|
||||
const auto it = std::find_if(_resourceNodes.begin(), _resourceNodes.end(), [&](const ResourceNode &node) {
|
||||
return node.version == version && node.virtualResource == virtualResource;
|
||||
});
|
||||
|
||||
return it == _resourceNodes.end() ? nullptr : &(*it);
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
144
cocos/renderer/frame-graph/FrameGraph.h
Normal file
144
cocos/renderer/frame-graph/FrameGraph.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Blackboard.h"
|
||||
#include "CallbackPass.h"
|
||||
#include "DevicePass.h"
|
||||
#include "PassNode.h"
|
||||
#include "PassNodeBuilder.h"
|
||||
#include "ResourceEntry.h"
|
||||
#include "ResourceNode.h"
|
||||
#include "base/std/container/string.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class FrameGraph final {
|
||||
public:
|
||||
using ResourceHandleBlackboard = Blackboard<StringHandle, Handle::IndexType, Handle::UNINITIALIZED>;
|
||||
|
||||
FrameGraph() = default;
|
||||
~FrameGraph() = default;
|
||||
FrameGraph(const FrameGraph &) = delete;
|
||||
FrameGraph(FrameGraph &&) noexcept = delete;
|
||||
FrameGraph &operator=(const FrameGraph &) = delete;
|
||||
FrameGraph &operator=(FrameGraph &&) noexcept = delete;
|
||||
|
||||
static StringHandle stringToHandle(const char *name);
|
||||
static const char *handleToString(const StringHandle &handle) noexcept;
|
||||
|
||||
void present(const TextureHandle &input, gfx::Texture *target, bool useMoveSemantic = true);
|
||||
void presentLastVersion(const VirtualResource *virtualResource, gfx::Texture *target, bool useMoveSemantic = true);
|
||||
void presentFromBlackboard(const StringHandle &inputName, gfx::Texture *target, bool useMoveSemantic = true);
|
||||
void compile();
|
||||
void execute() noexcept;
|
||||
void reset() noexcept;
|
||||
static void gc(uint32_t unusedFrameCount = 30) noexcept;
|
||||
|
||||
template <typename Data, typename SetupMethod, typename ExecuteMethod>
|
||||
const CallbackPass<Data, ExecuteMethod> &addPass(PassInsertPoint insertPoint, const StringHandle &name, SetupMethod setup, ExecuteMethod &&execute) noexcept;
|
||||
|
||||
template <typename DescriptorType, typename ResourceType = typename ResourceTypeLookupTable<DescriptorType>::Resource>
|
||||
TypedHandle<ResourceType> create(const StringHandle &name, const DescriptorType &desc) noexcept;
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> importExternal(const StringHandle &name, ResourceType &resource) noexcept;
|
||||
void move(TextureHandle from, TextureHandle to, uint8_t mipmapLevel, uint8_t faceId, uint8_t arrayPosition) noexcept;
|
||||
|
||||
inline ResourceNode &getResourceNode(const Handle handle) noexcept { return _resourceNodes[handle]; }
|
||||
inline const ResourceNode &getResourceNode(const Handle handle) const noexcept { return _resourceNodes[handle]; }
|
||||
inline ResourceHandleBlackboard &getBlackboard() noexcept { return _blackboard; }
|
||||
|
||||
void exportGraphViz(const ccstd::string &path);
|
||||
inline void enableMerge(bool enable) noexcept;
|
||||
bool hasPass(StringHandle handle);
|
||||
|
||||
private:
|
||||
Handle create(VirtualResource *virtualResource);
|
||||
PassNode &createPassNode(PassInsertPoint insertPoint, const StringHandle &name, Executable *pass);
|
||||
Handle createResourceNode(VirtualResource *virtualResource);
|
||||
void sort() noexcept;
|
||||
void cull();
|
||||
void computeResourceLifetime();
|
||||
void mergePassNodes() noexcept;
|
||||
void computeStoreActionAndMemoryless();
|
||||
void generateDevicePasses();
|
||||
ResourceNode *getResourceNode(const VirtualResource *virtualResource, uint8_t version) noexcept;
|
||||
|
||||
ccstd::vector<std::unique_ptr<PassNode>> _passNodes{};
|
||||
ccstd::vector<ResourceNode> _resourceNodes{};
|
||||
ccstd::vector<std::unique_ptr<VirtualResource>> _virtualResources{};
|
||||
ccstd::vector<std::unique_ptr<DevicePass>> _devicePasses{};
|
||||
ResourceHandleBlackboard _blackboard;
|
||||
bool _merge{true};
|
||||
|
||||
friend class PassNode;
|
||||
friend class PassNodeBuilder;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Data, typename SetupMethod, typename ExecuteMethod>
|
||||
const CallbackPass<Data, ExecuteMethod> &FrameGraph::addPass(const PassInsertPoint insertPoint, const StringHandle &name, SetupMethod setup, ExecuteMethod &&execute) noexcept {
|
||||
static_assert(sizeof(ExecuteMethod) < 1024, "Execute() lambda is capturing too much data.");
|
||||
auto *const pass = ccnew CallbackPass<Data, ExecuteMethod>(std::forward<ExecuteMethod>(execute));
|
||||
PassNode &passNode = createPassNode(insertPoint, name, pass);
|
||||
PassNodeBuilder builder(*this, passNode);
|
||||
setup(builder, pass->getData());
|
||||
return *pass;
|
||||
}
|
||||
|
||||
template <typename DescriptorType, typename ResourceType>
|
||||
TypedHandle<ResourceType> FrameGraph::create(const StringHandle &name, const DescriptorType &desc) noexcept {
|
||||
auto *const virtualResource = ccnew ResourceEntry<ResourceType>(name, static_cast<ID>(_virtualResources.size()), desc);
|
||||
return TypedHandle<ResourceType>(create(virtualResource));
|
||||
}
|
||||
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> FrameGraph::importExternal(const StringHandle &name, ResourceType &resource) noexcept {
|
||||
CC_ASSERT(resource.get());
|
||||
auto *const virtualResource = ccnew ResourceEntry<ResourceType>(name, static_cast<ID>(_virtualResources.size()), resource);
|
||||
return TypedHandle<ResourceType>(create(virtualResource));
|
||||
}
|
||||
|
||||
void FrameGraph::enableMerge(bool const enable) noexcept {
|
||||
_merge = enable;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename DescriptorType, typename ResourceType>
|
||||
TypedHandle<ResourceType> PassNodeBuilder::create(const StringHandle &name, const DescriptorType &desc) const noexcept {
|
||||
return _graph.create(name, desc);
|
||||
}
|
||||
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> PassNodeBuilder::importExternal(const StringHandle &name, ResourceType &resource) const noexcept {
|
||||
return _graph.importExternal(name, resource);
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
45
cocos/renderer/frame-graph/Handle.h
Normal file
45
cocos/renderer/frame-graph/Handle.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/IndexHandle.h"
|
||||
#include "base/StringPool.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
using Handle = cc::IndexHandle<uint16_t>;
|
||||
using StringHandle = cc::StringHandle;
|
||||
using StringPool = cc::StringPool<false>;
|
||||
|
||||
template <typename T>
|
||||
class TypedHandle final : public Handle {
|
||||
public:
|
||||
using Type = T;
|
||||
using Handle::Handle;
|
||||
};
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
101
cocos/renderer/frame-graph/ImmutableState.cpp
Normal file
101
cocos/renderer/frame-graph/ImmutableState.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ImmutableState.h"
|
||||
#include <vector>
|
||||
#include "DevicePassResourceTable.h"
|
||||
#include "gfx-base/GFXBarrier.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
using gfx::AccessFlags;
|
||||
using gfx::BufferUsage;
|
||||
using gfx::hasFlag;
|
||||
using gfx::MemoryAccess;
|
||||
using gfx::MemoryUsage;
|
||||
using gfx::ShaderStageFlags;
|
||||
using gfx::TextureUsage;
|
||||
|
||||
namespace {
|
||||
|
||||
AccessFlags getAccessFlags(BufferUsage usage, MemoryUsage memUsage, const AccessStatus& status) noexcept {
|
||||
return gfx::getAccessFlags(usage, memUsage, status.access, status.visibility);
|
||||
}
|
||||
|
||||
AccessFlags getAccessFlags(TextureUsage usage, const AccessStatus& status) noexcept {
|
||||
return gfx::getAccessFlags(usage, status.access, status.visibility);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::pair<gfx::GFXObject*, gfx::GFXObject*> getBarrier(const ResourceBarrier& barrierInfo, const DevicePassResourceTable* dictPtr) noexcept {
|
||||
std::pair<gfx::GFXObject*, gfx::GFXObject*> res;
|
||||
|
||||
const auto& dict = *dictPtr;
|
||||
if (barrierInfo.resourceType == ResourceType::BUFFER) {
|
||||
gfx::Buffer* gfxBuffer{nullptr};
|
||||
if (hasFlag(barrierInfo.endStatus.access, MemoryAccess::WRITE_ONLY)) {
|
||||
gfxBuffer = dict.getWrite(static_cast<BufferHandle>(barrierInfo.handle));
|
||||
} else {
|
||||
gfxBuffer = dict.getRead(static_cast<BufferHandle>(barrierInfo.handle));
|
||||
}
|
||||
auto usage = gfxBuffer->getUsage();
|
||||
auto memUsage = gfxBuffer->getMemUsage();
|
||||
gfx::BufferBarrierInfo info;
|
||||
info.prevAccesses = getAccessFlags(usage, memUsage, barrierInfo.beginStatus);
|
||||
info.nextAccesses = getAccessFlags(usage, memUsage, barrierInfo.endStatus);
|
||||
info.offset = static_cast<uint32_t>(barrierInfo.bufferRange.base);
|
||||
info.size = static_cast<uint32_t>(barrierInfo.bufferRange.len);
|
||||
info.type = barrierInfo.barrierType;
|
||||
|
||||
res.first = gfx::Device::getInstance()->getBufferBarrier(info);
|
||||
res.second = gfxBuffer;
|
||||
} else if (barrierInfo.resourceType == ResourceType::TEXTURE) {
|
||||
gfx::Texture* gfxTexture{nullptr};
|
||||
if (hasFlag(barrierInfo.beginStatus.access, MemoryAccess::WRITE_ONLY)) {
|
||||
gfxTexture = dict.getWrite(static_cast<TextureHandle>(barrierInfo.handle));
|
||||
} else {
|
||||
gfxTexture = dict.getRead(static_cast<TextureHandle>(barrierInfo.handle));
|
||||
}
|
||||
auto usage = gfxTexture->getInfo().usage;
|
||||
gfx::TextureBarrierInfo info;
|
||||
info.type = barrierInfo.barrierType;
|
||||
info.prevAccesses = getAccessFlags(usage, barrierInfo.beginStatus);
|
||||
info.nextAccesses = getAccessFlags(usage, barrierInfo.endStatus);
|
||||
info.range.mipLevel = static_cast<uint32_t>(barrierInfo.mipRange.base);
|
||||
info.range.levelCount = static_cast<uint32_t>(barrierInfo.mipRange.len);
|
||||
info.range.firstSlice = static_cast<uint32_t>(barrierInfo.layerRange.base);
|
||||
info.range.numSlices = static_cast<uint32_t>(barrierInfo.layerRange.len);
|
||||
|
||||
res.first = gfx::Device::getInstance()->getTextureBarrier(info);
|
||||
res.second = gfxTexture;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
84
cocos/renderer/frame-graph/ImmutableState.h
Normal file
84
cocos/renderer/frame-graph/ImmutableState.h
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "frame-graph/Resource.h"
|
||||
#include "gfx-base/GFXDef-common.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class DevicePassResourceTable;
|
||||
|
||||
struct Range {
|
||||
size_t base{0};
|
||||
size_t len{0};
|
||||
};
|
||||
|
||||
struct AccessStatus {
|
||||
gfx::PassType passType{gfx::PassType::RASTER};
|
||||
gfx::ShaderStageFlagBit visibility{gfx::ShaderStageFlagBit::NONE};
|
||||
gfx::MemoryAccessBit access{gfx::MemoryAccessBit::NONE};
|
||||
};
|
||||
|
||||
enum class ResourceType : uint32_t {
|
||||
UNKNOWN,
|
||||
BUFFER,
|
||||
TEXTURE,
|
||||
};
|
||||
|
||||
struct ResourceBarrier {
|
||||
ResourceType resourceType{ResourceType::UNKNOWN};
|
||||
gfx::BarrierType barrierType{gfx::BarrierType::FULL};
|
||||
|
||||
Handle handle;
|
||||
|
||||
AccessStatus beginStatus;
|
||||
AccessStatus endStatus;
|
||||
Range layerRange;
|
||||
|
||||
union {
|
||||
Range mipRange;
|
||||
Range bufferRange;
|
||||
};
|
||||
};
|
||||
|
||||
struct PassBarrierPair {
|
||||
ccstd::vector<ResourceBarrier> frontBarriers;
|
||||
ccstd::vector<ResourceBarrier> rearBarriers;
|
||||
};
|
||||
|
||||
using BarriersList = std::vector<PassBarrierPair>;
|
||||
|
||||
struct PassBarriers {
|
||||
PassBarrierPair blockBarrier;
|
||||
BarriersList subpassBarriers;
|
||||
};
|
||||
|
||||
std::pair<gfx::GFXObject* /*barrier*/, gfx::GFXObject* /*resource*/> getBarrier(const ResourceBarrier& barrierInfo, const DevicePassResourceTable* dict) noexcept;
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
57
cocos/renderer/frame-graph/PassInsertPointManager.cpp
Normal file
57
cocos/renderer/frame-graph/PassInsertPointManager.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "PassInsertPointManager.h"
|
||||
#include "base/Macros.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
PassInsertPointManager &PassInsertPointManager::getInstance() {
|
||||
static PassInsertPointManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
PassInsertPoint PassInsertPointManager::record(const char *const name, const PassInsertPoint point) {
|
||||
StringHandle nameHandle = _stringPool.find(name);
|
||||
|
||||
if (nameHandle.isValid()) {
|
||||
CC_ASSERT(point == get(nameHandle));
|
||||
return get(nameHandle);
|
||||
}
|
||||
|
||||
nameHandle = _stringPool.stringToHandle(name);
|
||||
CC_ASSERT(nameHandle == _insertPoints.size());
|
||||
_insertPoints.emplace_back(point);
|
||||
return point;
|
||||
}
|
||||
|
||||
PassInsertPoint PassInsertPointManager::get(const char *const name) const {
|
||||
const StringHandle nameHandle = _stringPool.find(name);
|
||||
CC_ASSERT(nameHandle.isValid());
|
||||
return get(nameHandle);
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
64
cocos/renderer/frame-graph/PassInsertPointManager.h
Normal file
64
cocos/renderer/frame-graph/PassInsertPointManager.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Handle.h"
|
||||
#include "base/Macros.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
using PassInsertPoint = uint16_t;
|
||||
|
||||
class PassInsertPointManager final {
|
||||
public:
|
||||
PassInsertPointManager(const PassInsertPointManager &) = delete;
|
||||
PassInsertPointManager(PassInsertPointManager &&) noexcept = delete;
|
||||
PassInsertPointManager &operator=(const PassInsertPointManager &) = delete;
|
||||
PassInsertPointManager &operator=(PassInsertPointManager &&) noexcept = delete;
|
||||
|
||||
static PassInsertPointManager &getInstance();
|
||||
|
||||
PassInsertPoint record(const char *name, PassInsertPoint point);
|
||||
PassInsertPoint get(const char *name) const;
|
||||
|
||||
private:
|
||||
PassInsertPointManager() = default;
|
||||
~PassInsertPointManager() = default;
|
||||
|
||||
inline PassInsertPoint get(StringHandle name) const;
|
||||
|
||||
StringPool _stringPool;
|
||||
ccstd::vector<PassInsertPoint> _insertPoints{};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PassInsertPoint PassInsertPointManager::get(const StringHandle name) const {
|
||||
return _insertPoints[name];
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
191
cocos/renderer/frame-graph/PassNode.cpp
Normal file
191
cocos/renderer/frame-graph/PassNode.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "PassNode.h"
|
||||
#include <algorithm>
|
||||
#include "FrameGraph.h"
|
||||
#include "ResourceNode.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
PassNode::PassNode(const PassInsertPoint inserPoint, const StringHandle name, const ID &id, Executable *pass)
|
||||
: _pass(pass),
|
||||
_name(name),
|
||||
_id(id),
|
||||
_insertPoint(inserPoint) {
|
||||
CC_ASSERT(_name.isValid());
|
||||
}
|
||||
|
||||
Handle PassNode::read(FrameGraph & /*graph*/, const Handle &input) {
|
||||
const auto it = std::find_if(_reads.begin(), _reads.end(), [input](const Handle handle) {
|
||||
return input == handle;
|
||||
});
|
||||
|
||||
if (it == _reads.end()) {
|
||||
_reads.push_back(input);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
Handle PassNode::write(FrameGraph &graph, const Handle &output) {
|
||||
CC_ASSERT(std::find_if(_writes.begin(), _writes.end(), [output](const Handle handle) {
|
||||
return output == handle;
|
||||
}) == _writes.end());
|
||||
|
||||
const ResourceNode &nodeOldVersion = graph.getResourceNode(output);
|
||||
nodeOldVersion.virtualResource->newVersion();
|
||||
_sideEffect = _sideEffect || nodeOldVersion.virtualResource->isImported();
|
||||
const Handle handle = graph.createResourceNode(nodeOldVersion.virtualResource);
|
||||
ResourceNode &nodeNewVersion = graph.getResourceNode(handle);
|
||||
nodeNewVersion.writer = this;
|
||||
_writes.push_back(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void PassNode::createRenderTargetAttachment(RenderTargetAttachment &&attachment) {
|
||||
if (attachment.desc.usage == RenderTargetAttachment::Usage::COLOR) {
|
||||
if (attachment.desc.slot == 0xff) {
|
||||
for (uint8_t i = 0; i < RenderTargetAttachment::DEPTH_STENCIL_SLOT_START; ++i) {
|
||||
if ((_usedRenderTargetSlotMask & (1 << i)) == 0) {
|
||||
attachment.desc.slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CC_ASSERT(attachment.desc.slot < RenderTargetAttachment::DEPTH_STENCIL_SLOT_START);
|
||||
}
|
||||
} else {
|
||||
attachment.desc.slot = RenderTargetAttachment::DEPTH_STENCIL_SLOT_START + static_cast<uint8_t>(attachment.desc.usage) - 1;
|
||||
|
||||
if (attachment.desc.usage == RenderTargetAttachment::Usage::DEPTH_STENCIL) {
|
||||
CC_ASSERT((_usedRenderTargetSlotMask & (1 << (RenderTargetAttachment::DEPTH_STENCIL_SLOT_START + static_cast<uint8_t>(RenderTargetAttachment::Usage::DEPTH) - 1))) == 0);
|
||||
CC_ASSERT((_usedRenderTargetSlotMask & (1 << (RenderTargetAttachment::DEPTH_STENCIL_SLOT_START + static_cast<uint8_t>(RenderTargetAttachment::Usage::STENCIL) - 1))) == 0);
|
||||
} else {
|
||||
CC_ASSERT((_usedRenderTargetSlotMask & (1 << (RenderTargetAttachment::DEPTH_STENCIL_SLOT_START + static_cast<uint8_t>(attachment.desc.usage) - 1))) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
CC_ASSERT((_usedRenderTargetSlotMask & (1 << attachment.desc.slot)) == 0);
|
||||
_usedRenderTargetSlotMask |= (1 << attachment.desc.slot);
|
||||
|
||||
_attachments.emplace_back(attachment);
|
||||
_hasClearedAttachment = _hasClearedAttachment || (attachment.desc.loadOp == gfx::LoadOp::CLEAR);
|
||||
}
|
||||
|
||||
bool PassNode::canMerge(const FrameGraph &graph, const PassNode &passNode) const {
|
||||
const size_t attachmentCount = _attachments.size();
|
||||
|
||||
if (passNode._hasClearedAttachment || attachmentCount != passNode._attachments.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < attachmentCount; ++i) {
|
||||
const RenderTargetAttachment &attachmentInPassNodeA = _attachments[i];
|
||||
const RenderTargetAttachment &attachmentInPassNodeB = passNode._attachments[i];
|
||||
|
||||
if (attachmentInPassNodeA.desc.usage != attachmentInPassNodeB.desc.usage ||
|
||||
attachmentInPassNodeA.desc.slot != attachmentInPassNodeB.desc.slot ||
|
||||
attachmentInPassNodeA.desc.writeMask != attachmentInPassNodeB.desc.writeMask ||
|
||||
attachmentInPassNodeA.level != attachmentInPassNodeB.level ||
|
||||
attachmentInPassNodeA.layer != attachmentInPassNodeB.layer ||
|
||||
attachmentInPassNodeA.index != attachmentInPassNodeB.index ||
|
||||
graph.getResourceNode(attachmentInPassNodeA.textureHandle).virtualResource != graph.getResourceNode(attachmentInPassNodeB.textureHandle).virtualResource) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderTargetAttachment *PassNode::getRenderTargetAttachment(const Handle &handle) {
|
||||
const auto it = std::find_if(_attachments.begin(), _attachments.end(), [&handle](const RenderTargetAttachment &attachment) {
|
||||
return attachment.textureHandle == handle;
|
||||
});
|
||||
|
||||
return it == _attachments.end() ? nullptr : &(*it);
|
||||
}
|
||||
|
||||
RenderTargetAttachment *PassNode::getRenderTargetAttachment(const FrameGraph &graph, const VirtualResource *const resource) {
|
||||
const auto it = std::find_if(_attachments.begin(), _attachments.end(), [&](const RenderTargetAttachment &attachment) {
|
||||
return graph.getResourceNode(attachment.textureHandle).virtualResource == resource;
|
||||
});
|
||||
|
||||
return it == _attachments.end() ? nullptr : &(*it);
|
||||
}
|
||||
|
||||
void PassNode::requestTransientResources() {
|
||||
PassNode *it = this;
|
||||
|
||||
do {
|
||||
std::for_each(it->_resourceRequestArray.begin(), it->_resourceRequestArray.end(), [](VirtualResource *const resource) {
|
||||
if (!resource->isImported()) {
|
||||
resource->request();
|
||||
}
|
||||
});
|
||||
|
||||
it = it->_next;
|
||||
} while (it);
|
||||
}
|
||||
|
||||
void PassNode::releaseTransientResources() {
|
||||
PassNode *it = this;
|
||||
|
||||
do {
|
||||
// resources should be release in the reverse order to stabilize usages between frames
|
||||
std::for_each(it->_resourceReleaseArray.rbegin(), it->_resourceReleaseArray.rend(), [](VirtualResource *const resource) {
|
||||
if (!resource->isImported()) {
|
||||
resource->release();
|
||||
}
|
||||
});
|
||||
|
||||
it = it->_next;
|
||||
} while (it);
|
||||
}
|
||||
|
||||
void PassNode::setDevicePassId(ID const id) {
|
||||
PassNode *it = this;
|
||||
|
||||
do {
|
||||
it->_devicePassId = id;
|
||||
|
||||
it = it->_next;
|
||||
} while (it);
|
||||
}
|
||||
|
||||
Handle PassNode::getWriteResourceNodeHandle(const FrameGraph &graph, const VirtualResource *const resource) const {
|
||||
const auto it = std::find_if(_writes.begin(), _writes.end(), [&](const Handle handle) {
|
||||
return graph.getResourceNode(handle).virtualResource == resource;
|
||||
});
|
||||
|
||||
return it == _writes.end() ? Handle{} : *it;
|
||||
}
|
||||
|
||||
void PassNode::setBarrier(const PassBarrierPair &barrier) {
|
||||
_barriers = barrier;
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
124
cocos/renderer/frame-graph/PassNode.h
Normal file
124
cocos/renderer/frame-graph/PassNode.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "CallbackPass.h"
|
||||
#include "Handle.h"
|
||||
#include "ImmutableState.h"
|
||||
#include "PassInsertPointManager.h"
|
||||
#include "RenderTargetAttachment.h"
|
||||
#include "VirtualResource.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class FrameGraph;
|
||||
|
||||
class PassNode final {
|
||||
public:
|
||||
PassNode(PassInsertPoint inserPoint, StringHandle name, const ID &id, Executable *pass);
|
||||
~PassNode() = default;
|
||||
PassNode(PassNode &&) noexcept = default;
|
||||
PassNode(const PassNode &) = delete;
|
||||
PassNode &operator=(const PassNode &) = delete;
|
||||
PassNode &operator=(PassNode &&) noexcept = delete;
|
||||
|
||||
Handle read(FrameGraph &graph, const Handle &input);
|
||||
Handle write(FrameGraph &graph, const Handle &output);
|
||||
void createRenderTargetAttachment(RenderTargetAttachment &&attachment);
|
||||
void setBarrier(const PassBarrierPair &barrier);
|
||||
|
||||
inline void sideEffect();
|
||||
inline void subpass(bool end, bool clearActionIgnorable);
|
||||
inline void setViewport(const gfx::Viewport &viewport, const gfx::Rect &scissor);
|
||||
inline const PassBarrierPair &getBarriers() const;
|
||||
|
||||
private:
|
||||
bool canMerge(const FrameGraph &graph, const PassNode &passNode) const;
|
||||
RenderTargetAttachment *getRenderTargetAttachment(const Handle &handle);
|
||||
RenderTargetAttachment *getRenderTargetAttachment(const FrameGraph &graph, const VirtualResource *resource);
|
||||
void requestTransientResources();
|
||||
void releaseTransientResources();
|
||||
void setDevicePassId(ID id);
|
||||
Handle getWriteResourceNodeHandle(const FrameGraph &graph, const VirtualResource *resource) const;
|
||||
|
||||
std::unique_ptr<Executable> _pass{nullptr};
|
||||
ccstd::vector<Handle> _reads{};
|
||||
ccstd::vector<Handle> _writes{};
|
||||
ccstd::vector<RenderTargetAttachment> _attachments{};
|
||||
ccstd::vector<VirtualResource *> _resourceRequestArray{};
|
||||
ccstd::vector<VirtualResource *> _resourceReleaseArray{};
|
||||
const StringHandle _name;
|
||||
uint32_t _refCount{0};
|
||||
PassNode *_head{nullptr};
|
||||
PassNode *_next{nullptr};
|
||||
uint16_t _distanceToHead{0};
|
||||
uint16_t _usedRenderTargetSlotMask{0};
|
||||
ID const _id{0};
|
||||
ID _devicePassId{0};
|
||||
const PassInsertPoint _insertPoint{0};
|
||||
bool _sideEffect{false};
|
||||
bool _subpass{false};
|
||||
bool _subpassEnd{false};
|
||||
bool _hasClearedAttachment{false};
|
||||
bool _clearActionIgnorable{false};
|
||||
|
||||
bool _customViewport{false};
|
||||
gfx::Viewport _viewport;
|
||||
gfx::Rect _scissor;
|
||||
|
||||
PassBarrierPair _barriers;
|
||||
|
||||
friend class FrameGraph;
|
||||
friend class DevicePass;
|
||||
friend class DevicePassResourceTable;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const PassBarrierPair &PassNode::getBarriers() const {
|
||||
return _barriers;
|
||||
}
|
||||
|
||||
void PassNode::sideEffect() {
|
||||
_sideEffect = true;
|
||||
}
|
||||
|
||||
void PassNode::subpass(bool end, bool clearActionIgnorable) {
|
||||
_subpass = true;
|
||||
_subpassEnd = end;
|
||||
_clearActionIgnorable = clearActionIgnorable;
|
||||
}
|
||||
|
||||
void PassNode::setViewport(const gfx::Viewport &viewport, const gfx::Rect &scissor) {
|
||||
_customViewport = true;
|
||||
_viewport = viewport;
|
||||
_scissor = scissor;
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
71
cocos/renderer/frame-graph/PassNodeBuilder.cpp
Normal file
71
cocos/renderer/frame-graph/PassNodeBuilder.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "PassNodeBuilder.h"
|
||||
#include "FrameGraph.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
PassNodeBuilder::PassNodeBuilder(FrameGraph &graph, PassNode &passNode) noexcept
|
||||
: _graph(graph),
|
||||
_passNode(passNode) {
|
||||
}
|
||||
|
||||
Handle PassNodeBuilder::read(const Handle &input) const noexcept {
|
||||
return _passNode.read(_graph, input);
|
||||
}
|
||||
|
||||
TextureHandle PassNodeBuilder::write(const TextureHandle &output, uint8_t mipmapLevel, uint8_t faceId, uint8_t arrayPosition, const RenderTargetAttachment::Descriptor &attachmentDesc) const noexcept {
|
||||
const TextureHandle handle(_passNode.write(_graph, output));
|
||||
RenderTargetAttachment attachment;
|
||||
attachment.textureHandle = handle;
|
||||
attachment.desc = attachmentDesc;
|
||||
attachment.level = mipmapLevel;
|
||||
attachment.layer = faceId;
|
||||
attachment.index = arrayPosition;
|
||||
_passNode.createRenderTargetAttachment(std::forward<RenderTargetAttachment>(attachment));
|
||||
|
||||
if (attachmentDesc.loadOp == gfx::LoadOp::LOAD) {
|
||||
ResourceNode &outputResourceNode = _graph.getResourceNode(output);
|
||||
++outputResourceNode.readerCount;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
TextureHandle PassNodeBuilder::write(const TextureHandle &output, const RenderTargetAttachment::Descriptor &attachmentDesc) const noexcept {
|
||||
return write(output, 0, 0, 0, attachmentDesc);
|
||||
}
|
||||
|
||||
void PassNodeBuilder::writeToBlackboard(const StringHandle &name, const Handle &handle) const noexcept {
|
||||
_graph.getBlackboard().put(name, handle);
|
||||
}
|
||||
|
||||
Handle PassNodeBuilder::readFromBlackboard(const StringHandle &name) const noexcept {
|
||||
return Handle(_graph.getBlackboard().get(name));
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
103
cocos/renderer/frame-graph/PassNodeBuilder.h
Normal file
103
cocos/renderer/frame-graph/PassNodeBuilder.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PassNode.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class PassNodeBuilder final {
|
||||
public:
|
||||
PassNodeBuilder(FrameGraph &graph, PassNode &passNode) noexcept;
|
||||
PassNodeBuilder() = delete;
|
||||
~PassNodeBuilder() = default;
|
||||
PassNodeBuilder(const PassNodeBuilder &) = delete;
|
||||
PassNodeBuilder(PassNodeBuilder &&) = delete;
|
||||
PassNodeBuilder &operator=(const PassNodeBuilder &) = delete;
|
||||
PassNodeBuilder &operator=(PassNodeBuilder &&) = delete;
|
||||
|
||||
template <typename DescriptorType, typename ResourceType = typename ResourceTypeLookupTable<DescriptorType>::Resource>
|
||||
TypedHandle<ResourceType> create(const StringHandle &name, const DescriptorType &desc) const noexcept;
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> importExternal(const StringHandle &name, ResourceType &resource) const noexcept;
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> read(TypedHandle<ResourceType> const &input) const noexcept;
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> write(TypedHandle<ResourceType> const &output) const noexcept;
|
||||
TextureHandle write(const TextureHandle &output, uint8_t mipmapLevel, uint8_t faceId, uint8_t arrayPosition, const RenderTargetAttachment::Descriptor &attachmentDesc) const noexcept;
|
||||
TextureHandle write(const TextureHandle &output, const RenderTargetAttachment::Descriptor &attachmentDesc) const noexcept;
|
||||
|
||||
inline void sideEffect() const noexcept;
|
||||
inline void subpass(bool end = false, bool clearActionIgnorable = true) const noexcept;
|
||||
inline void setViewport(const gfx::Rect &scissor) noexcept;
|
||||
inline void setViewport(const gfx::Viewport &viewport, const gfx::Rect &scissor) noexcept;
|
||||
inline void setBarrier(const PassBarrierPair &barrier);
|
||||
|
||||
void writeToBlackboard(const StringHandle &name, const Handle &handle) const noexcept;
|
||||
Handle readFromBlackboard(const StringHandle &name) const noexcept;
|
||||
|
||||
private:
|
||||
Handle read(const Handle &input) const noexcept;
|
||||
|
||||
FrameGraph &_graph;
|
||||
PassNode &_passNode;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> PassNodeBuilder::read(TypedHandle<ResourceType> const &input) const noexcept {
|
||||
return TypedHandle<ResourceType>(read(static_cast<const Handle &>(input)));
|
||||
}
|
||||
|
||||
template <typename ResourceType>
|
||||
TypedHandle<ResourceType> PassNodeBuilder::write(TypedHandle<ResourceType> const &output) const noexcept {
|
||||
return TypedHandle<ResourceType>(_passNode.write(_graph, output));
|
||||
}
|
||||
|
||||
void PassNodeBuilder::sideEffect() const noexcept {
|
||||
_passNode.sideEffect();
|
||||
}
|
||||
|
||||
void PassNodeBuilder::subpass(bool end, bool clearActionIgnorable) const noexcept {
|
||||
_passNode.subpass(end, clearActionIgnorable);
|
||||
}
|
||||
|
||||
void PassNodeBuilder::setViewport(const gfx::Rect &scissor) noexcept {
|
||||
gfx::Viewport viewport{scissor.x, scissor.y, scissor.width, scissor.height, 0.F, 1.F};
|
||||
_passNode.setViewport(viewport, scissor);
|
||||
}
|
||||
|
||||
void PassNodeBuilder::setViewport(const gfx::Viewport &viewport, const gfx::Rect &scissor) noexcept {
|
||||
_passNode.setViewport(viewport, scissor);
|
||||
}
|
||||
|
||||
void PassNodeBuilder::setBarrier(const PassBarrierPair &barrier) {
|
||||
_passNode.setBarrier(barrier);
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
79
cocos/renderer/frame-graph/RenderTargetAttachment.h
Normal file
79
cocos/renderer/frame-graph/RenderTargetAttachment.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
struct RenderTargetAttachment final {
|
||||
using StoreOp = gfx::StoreOp;
|
||||
using LoadOp = gfx::LoadOp;
|
||||
using Color = gfx::Color;
|
||||
|
||||
enum class Usage : uint8_t {
|
||||
COLOR,
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
DEPTH_STENCIL,
|
||||
};
|
||||
|
||||
struct Descriptor final {
|
||||
Usage usage{Usage::COLOR};
|
||||
uint8_t slot{0xff};
|
||||
uint8_t writeMask{0xff};
|
||||
LoadOp loadOp{LoadOp::DISCARD};
|
||||
Color clearColor;
|
||||
float clearDepth{1.F};
|
||||
uint8_t clearStencil{0U};
|
||||
|
||||
gfx::AccessFlags beginAccesses{gfx::AccessFlagBit::NONE};
|
||||
gfx::AccessFlags endAccesses{gfx::AccessFlagBit::NONE};
|
||||
};
|
||||
|
||||
struct Sorter {
|
||||
inline bool operator()(const RenderTargetAttachment &a1, const RenderTargetAttachment &a2) const noexcept;
|
||||
};
|
||||
|
||||
static constexpr uint8_t DEPTH_STENCIL_SLOT_START{13};
|
||||
|
||||
TextureHandle textureHandle{};
|
||||
Descriptor desc;
|
||||
uint8_t level{0};
|
||||
uint8_t layer{0};
|
||||
uint8_t index{0};
|
||||
StoreOp storeOp{StoreOp::DISCARD};
|
||||
};
|
||||
|
||||
inline bool RenderTargetAttachment::Sorter::operator()(const RenderTargetAttachment &a1, const RenderTargetAttachment &a2) const noexcept {
|
||||
if (a1.desc.usage == a2.desc.usage) {
|
||||
return a1.desc.slot < a2.desc.slot;
|
||||
}
|
||||
return a1.desc.usage < a2.desc.usage;
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
155
cocos/renderer/frame-graph/Resource.h
Normal file
155
cocos/renderer/frame-graph/Resource.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ResourceAllocator.h"
|
||||
|
||||
#include "Handle.h"
|
||||
#include "renderer/gfx-base/GFXBuffer.h"
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
#include "renderer/gfx-base/GFXFramebuffer.h"
|
||||
#include "renderer/gfx-base/GFXRenderPass.h"
|
||||
#include "renderer/gfx-base/GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType>
|
||||
struct DeviceResourceCreator final {
|
||||
inline DeviceResourceType *operator()(const DescriptorType & /*desc*/) const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DescriptorType>
|
||||
struct ResourceTypeLookupTable final {};
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType,
|
||||
typename DeviceResourceCreatorType = DeviceResourceCreator<DeviceResourceType, DescriptorType>>
|
||||
class Resource final {
|
||||
public:
|
||||
using Allocator = ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>;
|
||||
using DeviceResource = DeviceResourceType;
|
||||
using Descriptor = DescriptorType;
|
||||
|
||||
Resource() = default;
|
||||
explicit Resource(const Descriptor &desc);
|
||||
~Resource() = default;
|
||||
Resource(const Resource &) = default;
|
||||
Resource(Resource &&) noexcept = default;
|
||||
Resource &operator=(const Resource &) = default;
|
||||
Resource &operator=(Resource &&) noexcept = default;
|
||||
|
||||
void createTransient() noexcept;
|
||||
void createPersistent() noexcept;
|
||||
|
||||
void destroyTransient() noexcept;
|
||||
void destroyPersistent() noexcept;
|
||||
inline DeviceResourceType *get() const noexcept;
|
||||
inline const Descriptor &getDesc() const noexcept;
|
||||
|
||||
private:
|
||||
explicit Resource(DeviceResourceType *external);
|
||||
|
||||
Descriptor _desc;
|
||||
DeviceResourceType *_deviceObject{nullptr};
|
||||
|
||||
friend class FrameGraph;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::Resource(const Descriptor &desc)
|
||||
: _desc(desc) {
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::Resource(DeviceResourceType *external)
|
||||
: _desc(external->getInfo()), _deviceObject(external) {
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::createTransient() noexcept {
|
||||
_deviceObject = Allocator::getInstance().alloc(_desc);
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::createPersistent() noexcept {
|
||||
if (!_deviceObject) {
|
||||
DeviceResourceCreatorType creator;
|
||||
_deviceObject = creator(_desc);
|
||||
_deviceObject->addRef();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::destroyTransient() noexcept {
|
||||
Allocator::getInstance().free(_deviceObject);
|
||||
_deviceObject = nullptr;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::destroyPersistent() noexcept {
|
||||
if (_deviceObject) {
|
||||
_deviceObject->release();
|
||||
_deviceObject = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
DeviceResourceType *Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::get() const noexcept {
|
||||
return _deviceObject;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
const DescriptorType &Resource<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::getDesc() const noexcept {
|
||||
return _desc;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DEFINE_GFX_RESOURCE(Type) \
|
||||
template <> \
|
||||
struct DeviceResourceCreator<gfx::Type, gfx::Type##Info> final { \
|
||||
inline gfx::Type *operator()(const gfx::Type##Info &desc) const { \
|
||||
return gfx::Device::getInstance()->create##Type(desc); \
|
||||
} \
|
||||
}; \
|
||||
using Type = Resource<gfx::Type, gfx::Type##Info>; \
|
||||
using Type##Handle = TypedHandle<Type>; \
|
||||
template <> \
|
||||
struct ResourceTypeLookupTable<gfx::Type##Info> final { \
|
||||
using Resource = Type; \
|
||||
};
|
||||
|
||||
// Descriptors must have std::hash specialization and == operators
|
||||
DEFINE_GFX_RESOURCE(Buffer)
|
||||
DEFINE_GFX_RESOURCE(Framebuffer)
|
||||
DEFINE_GFX_RESOURCE(RenderPass)
|
||||
DEFINE_GFX_RESOURCE(Texture)
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
269
cocos/renderer/frame-graph/ResourceAllocator.h
Normal file
269
cocos/renderer/frame-graph/ResourceAllocator.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include "base/RefVector.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
class ResourceAllocator final {
|
||||
public:
|
||||
using DeviceResourceCreator = DeviceResourceCreatorType;
|
||||
|
||||
ResourceAllocator(const ResourceAllocator &) = delete;
|
||||
ResourceAllocator(ResourceAllocator &&) noexcept = delete;
|
||||
ResourceAllocator &operator=(const ResourceAllocator &) = delete;
|
||||
ResourceAllocator &operator=(ResourceAllocator &&) noexcept = delete;
|
||||
|
||||
static ResourceAllocator &getInstance() noexcept;
|
||||
DeviceResourceType *alloc(const DescriptorType &desc) noexcept;
|
||||
void free(DeviceResourceType *resource) noexcept;
|
||||
inline void tick() noexcept;
|
||||
void gc(uint32_t unusedFrameCount) noexcept;
|
||||
|
||||
private:
|
||||
using DeviceResourcePool = RefVector<DeviceResourceType *>;
|
||||
|
||||
ResourceAllocator() noexcept = default;
|
||||
~ResourceAllocator() = default;
|
||||
|
||||
ccstd::unordered_map<DescriptorType, DeviceResourcePool, gfx::Hasher<DescriptorType>> _pool{};
|
||||
ccstd::unordered_map<DeviceResourceType *, int64_t> _ages{};
|
||||
uint64_t _age{0};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType> &
|
||||
ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::getInstance() noexcept {
|
||||
static ResourceAllocator instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
DeviceResourceType *ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::alloc(const DescriptorType &desc) noexcept {
|
||||
DeviceResourcePool &pool{_pool[desc]};
|
||||
|
||||
DeviceResourceType *resource{nullptr};
|
||||
for (DeviceResourceType *res : pool) {
|
||||
if (_ages[res] >= 0) {
|
||||
resource = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!resource) {
|
||||
DeviceResourceCreator creator;
|
||||
resource = creator(desc);
|
||||
pool.pushBack(resource);
|
||||
}
|
||||
|
||||
_ages[resource] = -1;
|
||||
return resource;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::free(DeviceResourceType *const resource) noexcept {
|
||||
CC_ASSERT(_ages.count(resource) && _ages[resource] < 0);
|
||||
_ages[resource] = _age;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::tick() noexcept {
|
||||
++_age;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DescriptorType, typename DeviceResourceCreatorType>
|
||||
void ResourceAllocator<DeviceResourceType, DescriptorType, DeviceResourceCreatorType>::gc(uint32_t const unusedFrameCount) noexcept {
|
||||
for (auto &pair : _pool) {
|
||||
DeviceResourcePool &pool = pair.second;
|
||||
|
||||
auto count = static_cast<int>(pool.size());
|
||||
|
||||
if (!count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int destroyBegin = count - 1;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int64_t ageI = _ages[pool.at(i)];
|
||||
if (ageI < 0 || _age - ageI < unusedFrameCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int j = destroyBegin;
|
||||
|
||||
for (; j > i; --j) {
|
||||
int64_t ageJ = _ages[pool.at(j)];
|
||||
if (ageJ < 0 || _age - ageJ < unusedFrameCount) {
|
||||
std::swap(pool.at(i), pool.at(j));
|
||||
destroyBegin = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= j) {
|
||||
destroyBegin = i - 1;
|
||||
}
|
||||
|
||||
if (i >= destroyBegin) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (++destroyBegin < count) {
|
||||
auto *resource = pool.back();
|
||||
_ages.erase(resource);
|
||||
pool.popBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DeviceResourceCreatorType>
|
||||
class ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType> final {
|
||||
public:
|
||||
using DeviceResourceCreator = DeviceResourceCreatorType;
|
||||
|
||||
ResourceAllocator(const ResourceAllocator &) = delete;
|
||||
ResourceAllocator(ResourceAllocator &&) noexcept = delete;
|
||||
ResourceAllocator &operator=(const ResourceAllocator &) = delete;
|
||||
ResourceAllocator &operator=(ResourceAllocator &&) noexcept = delete;
|
||||
|
||||
static ResourceAllocator &getInstance() noexcept;
|
||||
DeviceResourceType *alloc(const gfx::FramebufferInfo &desc) noexcept;
|
||||
void free(DeviceResourceType *resource) noexcept;
|
||||
inline void tick() noexcept;
|
||||
void gc(uint32_t unusedFrameCount) noexcept;
|
||||
|
||||
private:
|
||||
using DeviceResourcePool = RefVector<DeviceResourceType *>;
|
||||
|
||||
ResourceAllocator() noexcept = default;
|
||||
~ResourceAllocator() = default;
|
||||
|
||||
std::unordered_map<ccstd::hash_t, DeviceResourcePool> _pool{};
|
||||
std::unordered_map<DeviceResourceType *, int64_t> _ages{};
|
||||
uint64_t _age{0};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename DeviceResourceType, typename DeviceResourceCreatorType>
|
||||
ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType> &
|
||||
ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType>::getInstance() noexcept {
|
||||
static ResourceAllocator instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DeviceResourceCreatorType>
|
||||
DeviceResourceType *ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType>::alloc(const gfx::FramebufferInfo &desc) noexcept {
|
||||
ccstd::hash_t hash = gfx::Hasher<gfx::FramebufferInfo>()(desc);
|
||||
DeviceResourcePool &pool{_pool[hash]};
|
||||
|
||||
DeviceResourceType *resource{nullptr};
|
||||
for (DeviceResourceType *res : pool) {
|
||||
if (_ages[res] >= 0) {
|
||||
resource = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!resource) {
|
||||
DeviceResourceCreator creator;
|
||||
resource = creator(desc);
|
||||
pool.pushBack(resource);
|
||||
}
|
||||
|
||||
_ages[resource] = -1;
|
||||
return resource;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DeviceResourceCreatorType>
|
||||
void ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType>::free(DeviceResourceType *const resource) noexcept {
|
||||
CC_ASSERT(_ages.count(resource) && _ages[resource] < 0);
|
||||
_ages[resource] = _age;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DeviceResourceCreatorType>
|
||||
void ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType>::tick() noexcept {
|
||||
++_age;
|
||||
}
|
||||
|
||||
template <typename DeviceResourceType, typename DeviceResourceCreatorType>
|
||||
void ResourceAllocator<DeviceResourceType, gfx::FramebufferInfo, DeviceResourceCreatorType>::gc(uint32_t const unusedFrameCount) noexcept {
|
||||
for (auto &pair : _pool) {
|
||||
DeviceResourcePool &pool = pair.second;
|
||||
|
||||
auto count = static_cast<int>(pool.size());
|
||||
|
||||
if (!count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int destroyBegin = count - 1;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int64_t ageI = _ages[pool.at(i)];
|
||||
if (ageI < 0 || _age - ageI < unusedFrameCount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int j = destroyBegin;
|
||||
|
||||
for (; j > i; --j) {
|
||||
int64_t ageJ = _ages[pool.at(j)];
|
||||
if (ageJ < 0 || _age - ageJ < unusedFrameCount) {
|
||||
std::swap(pool.at(i), pool.at(j));
|
||||
destroyBegin = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= j) {
|
||||
destroyBegin = i - 1;
|
||||
}
|
||||
|
||||
if (i >= destroyBegin) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (++destroyBegin < count) {
|
||||
auto *resource = pool.back();
|
||||
// delete resource;
|
||||
_ages.erase(resource);
|
||||
pool.popBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
84
cocos/renderer/frame-graph/ResourceEntry.h
Normal file
84
cocos/renderer/frame-graph/ResourceEntry.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VirtualResource.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
template <typename ResourceType, typename Enable = std::enable_if_t<std::is_base_of<gfx::GFXObject, typename ResourceType::DeviceResource>::value>>
|
||||
class ResourceEntry final : public VirtualResource {
|
||||
public:
|
||||
explicit ResourceEntry(StringHandle name, ID id, const typename ResourceType::Descriptor &desc) noexcept;
|
||||
ResourceEntry(StringHandle name, ID id, const ResourceType &resource) noexcept;
|
||||
ResourceEntry() = delete;
|
||||
~ResourceEntry() override = default;
|
||||
ResourceEntry(const ResourceEntry &) = delete;
|
||||
ResourceEntry(ResourceEntry &&) noexcept = delete;
|
||||
ResourceEntry &operator=(const ResourceEntry &) = delete;
|
||||
ResourceEntry &operator=(ResourceEntry &&) noexcept = delete;
|
||||
|
||||
void request() noexcept override;
|
||||
void release() noexcept override;
|
||||
typename ResourceType::DeviceResource *getDeviceResource() const noexcept override;
|
||||
|
||||
inline const ResourceType &get() const noexcept { return _resource; }
|
||||
|
||||
private:
|
||||
ResourceType _resource;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename ResourceType, typename Enable>
|
||||
ResourceEntry<ResourceType, Enable>::ResourceEntry(const StringHandle name, ID const id, const typename ResourceType::Descriptor &desc) noexcept
|
||||
: VirtualResource(name, id, false),
|
||||
_resource(desc) {
|
||||
}
|
||||
|
||||
template <typename ResourceType, typename Enable>
|
||||
ResourceEntry<ResourceType, Enable>::ResourceEntry(const StringHandle name, ID const id, const ResourceType &resource) noexcept
|
||||
: VirtualResource(name, id, true),
|
||||
_resource(resource) {
|
||||
}
|
||||
|
||||
template <typename ResourceType, typename Enable>
|
||||
void ResourceEntry<ResourceType, Enable>::request() noexcept {
|
||||
_resource.createTransient();
|
||||
}
|
||||
|
||||
template <typename ResourceType, typename Enable>
|
||||
void ResourceEntry<ResourceType, Enable>::release() noexcept {
|
||||
_resource.destroyTransient();
|
||||
}
|
||||
|
||||
template <typename ResourceType, typename Enable>
|
||||
typename ResourceType::DeviceResource *ResourceEntry<ResourceType, Enable>::getDeviceResource() const noexcept {
|
||||
return _resource.get();
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
40
cocos/renderer/frame-graph/ResourceNode.h
Normal file
40
cocos/renderer/frame-graph/ResourceNode.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VirtualResource.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
struct ResourceNode final {
|
||||
VirtualResource *virtualResource{nullptr};
|
||||
PassNode *writer{nullptr};
|
||||
uint32_t readerCount{0};
|
||||
uint8_t version{0};
|
||||
};
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
43
cocos/renderer/frame-graph/VirtualResource.cpp
Normal file
43
cocos/renderer/frame-graph/VirtualResource.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "VirtualResource.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
VirtualResource::VirtualResource(const StringHandle name, ID const id, bool const imported) noexcept
|
||||
: _name(name),
|
||||
_id(id),
|
||||
_imported(imported) {
|
||||
CC_ASSERT(_name.isValid());
|
||||
}
|
||||
|
||||
void VirtualResource::updateLifetime(PassNode *const passNode) noexcept {
|
||||
_firstUsePass = _firstUsePass ? _firstUsePass : passNode;
|
||||
_lastUsePass = passNode;
|
||||
}
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
73
cocos/renderer/frame-graph/VirtualResource.h
Normal file
73
cocos/renderer/frame-graph/VirtualResource.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Handle.h"
|
||||
#include "renderer/gfx-base/GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace framegraph {
|
||||
|
||||
class PassNode;
|
||||
|
||||
using ID = uint16_t;
|
||||
|
||||
class VirtualResource {
|
||||
public:
|
||||
VirtualResource(StringHandle name, ID id, bool imported) noexcept;
|
||||
VirtualResource() noexcept = delete;
|
||||
virtual ~VirtualResource() = default;
|
||||
VirtualResource(const VirtualResource &) = delete;
|
||||
VirtualResource(VirtualResource &&) noexcept = delete;
|
||||
VirtualResource &operator=(const VirtualResource &) = delete;
|
||||
VirtualResource &operator=(VirtualResource &&) noexcept = delete;
|
||||
|
||||
virtual void request() noexcept = 0;
|
||||
virtual void release() noexcept = 0;
|
||||
bool isImported() const noexcept { return _imported; }
|
||||
void updateLifetime(PassNode *passNode) noexcept;
|
||||
void newVersion() noexcept { ++_version; }
|
||||
|
||||
virtual gfx::GFXObject *getDeviceResource() const noexcept = 0;
|
||||
|
||||
private:
|
||||
PassNode *_firstUsePass{nullptr};
|
||||
PassNode *_lastUsePass{nullptr};
|
||||
const StringHandle _name;
|
||||
uint32_t _refCount{0};
|
||||
uint16_t _writerCount{0};
|
||||
ID _id{0};
|
||||
uint8_t _version{0};
|
||||
bool const _imported{false};
|
||||
bool _neverLoaded{true};
|
||||
bool _neverStored{true};
|
||||
bool _memoryless{false};
|
||||
bool _memorylessMSAA{false};
|
||||
|
||||
friend class FrameGraph;
|
||||
};
|
||||
|
||||
} // namespace framegraph
|
||||
} // namespace cc
|
||||
170
cocos/renderer/gfx-agent/BufferAgent.cpp
Normal file
170
cocos/renderer/gfx-agent/BufferAgent.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "BufferAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
BufferAgent::BufferAgent(Buffer *actor)
|
||||
: Agent<Buffer>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
BufferAgent::~BufferAgent() {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
BufferDestruct,
|
||||
actor, _actor,
|
||||
stagingBuffer, std::move(_stagingBuffer),
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::doInit(const BufferInfo &info) {
|
||||
uint32_t size = getSize();
|
||||
if (hasFlag(info.flags, BufferFlagBit::ENABLE_STAGING_WRITE) || (size > STAGING_BUFFER_THRESHOLD && hasFlag(_memUsage, MemoryUsageBit::HOST))) {
|
||||
_stagingBuffer = std::make_unique<uint8_t[]>(size * DeviceAgent::MAX_FRAME_INDEX);
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
BufferInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::doInit(const BufferViewInfo &info) {
|
||||
BufferViewInfo actorInfo = info;
|
||||
actorInfo.buffer = static_cast<BufferAgent *>(info.buffer)->getActor();
|
||||
|
||||
// buffer views don't need staging buffers
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
BufferViewInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::doResize(uint32_t size, uint32_t /*count*/) {
|
||||
auto *mq = DeviceAgent::getInstance()->getMessageQueue();
|
||||
|
||||
if (_stagingBuffer) {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
mq, BufferFreeStagingBuffer,
|
||||
stagingBuffer, std::move(_stagingBuffer),
|
||||
{});
|
||||
}
|
||||
|
||||
if (hasFlag(_flags, BufferFlagBit::ENABLE_STAGING_WRITE) || (size > STAGING_BUFFER_THRESHOLD && hasFlag(_memUsage, MemoryUsageBit::HOST))) {
|
||||
_stagingBuffer = std::make_unique<uint8_t[]>(size * DeviceAgent::MAX_FRAME_INDEX);
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
mq, BufferResize,
|
||||
actor, getActor(),
|
||||
size, size,
|
||||
{
|
||||
actor->resize(size);
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::doDestroy() {
|
||||
auto *mq = DeviceAgent::getInstance()->getMessageQueue();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
mq, BufferDestroy,
|
||||
actor, getActor(),
|
||||
stagingBuffer, std::move(_stagingBuffer),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::update(const void *buffer, uint32_t size) {
|
||||
uint8_t *actorBuffer{nullptr};
|
||||
bool needFreeing{false};
|
||||
auto *mq{DeviceAgent::getInstance()->getMessageQueue()};
|
||||
|
||||
getActorBuffer(this, mq, size, &actorBuffer, &needFreeing);
|
||||
memcpy(actorBuffer, buffer, size);
|
||||
|
||||
ENQUEUE_MESSAGE_4(
|
||||
mq, BufferUpdate,
|
||||
actor, getActor(),
|
||||
buffer, actorBuffer,
|
||||
size, size,
|
||||
needFreeing, needFreeing,
|
||||
{
|
||||
actor->update(buffer, size);
|
||||
if (needFreeing) free(buffer);
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::flush(const uint8_t *buffer) {
|
||||
auto *mq = DeviceAgent::getInstance()->getMessageQueue();
|
||||
ENQUEUE_MESSAGE_3(
|
||||
mq, BufferUpdate,
|
||||
actor, getActor(),
|
||||
buffer, buffer,
|
||||
size, _size,
|
||||
{
|
||||
actor->update(buffer, size);
|
||||
});
|
||||
}
|
||||
|
||||
void BufferAgent::getActorBuffer(const BufferAgent *buffer, MessageQueue *mq, uint32_t size, uint8_t **pActorBuffer, bool *pNeedFreeing) {
|
||||
if (buffer->_stagingBuffer) { // for frequent updates on big buffers
|
||||
uint32_t frameIndex = DeviceAgent::getInstance()->getCurrentIndex();
|
||||
*pActorBuffer = buffer->_stagingBuffer.get() + frameIndex * buffer->_size;
|
||||
} else if (size > STAGING_BUFFER_THRESHOLD) { // less frequent updates on big buffers
|
||||
*pActorBuffer = reinterpret_cast<uint8_t *>(malloc(size));
|
||||
*pNeedFreeing = true;
|
||||
} else { // for small enough buffers
|
||||
*pActorBuffer = mq->allocate<uint8_t>(size);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *BufferAgent::getStagingAddress() const {
|
||||
if (!_stagingBuffer) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t frameIndex = DeviceAgent::getInstance()->getCurrentIndex();
|
||||
return _stagingBuffer.get() + _size * frameIndex;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
61
cocos/renderer/gfx-agent/BufferAgent.h
Normal file
61
cocos/renderer/gfx-agent/BufferAgent.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
#include "gfx-base/GFXBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class ThreadSafeLinearAllocator;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL BufferAgent final : public Agent<Buffer> {
|
||||
public:
|
||||
explicit BufferAgent(Buffer *actor);
|
||||
~BufferAgent() override;
|
||||
|
||||
void update(const void *buffer, uint32_t size) override;
|
||||
|
||||
static void getActorBuffer(const BufferAgent *buffer, MessageQueue *mq, uint32_t size, uint8_t **pActorBuffer, bool *pNeedFreeing);
|
||||
|
||||
private:
|
||||
void doInit(const BufferInfo &info) override;
|
||||
void doInit(const BufferViewInfo &info) override;
|
||||
void doResize(uint32_t size, uint32_t count) override;
|
||||
void doDestroy() override;
|
||||
|
||||
void flush(const uint8_t *buffer) override;
|
||||
uint8_t *getStagingAddress() const override;
|
||||
|
||||
static constexpr uint32_t STAGING_BUFFER_THRESHOLD = MessageQueue::MEMORY_CHUNK_SIZE / 2;
|
||||
|
||||
std::unique_ptr<uint8_t[]> _stagingBuffer;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
595
cocos/renderer/gfx-agent/CommandBufferAgent.cpp
Normal file
595
cocos/renderer/gfx-agent/CommandBufferAgent.cpp
Normal file
@@ -0,0 +1,595 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "CommandBufferAgent.h"
|
||||
#include <cstring>
|
||||
#include "BufferAgent.h"
|
||||
#include "DescriptorSetAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "FramebufferAgent.h"
|
||||
#include "InputAssemblerAgent.h"
|
||||
#include "PipelineStateAgent.h"
|
||||
#include "QueryPoolAgent.h"
|
||||
#include "QueueAgent.h"
|
||||
#include "RenderPassAgent.h"
|
||||
#include "TextureAgent.h"
|
||||
#include "base/Utils.h"
|
||||
#include "base/job-system/JobSystem.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
#include "base/threading/ThreadSafeLinearAllocator.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
CommandBufferAgent::CommandBufferAgent(CommandBuffer *actor)
|
||||
: Agent<CommandBuffer>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
void CommandBufferAgent::flushCommands(uint32_t count, CommandBufferAgent *const *cmdBuffs, bool multiThreaded) {
|
||||
// don't even touch the job system if we are only recording sequentially
|
||||
if (count == 1) {
|
||||
cmdBuffs[0]->getMessageQueue()->flushMessages();
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t jobThreadCount = JobSystem::getInstance()->threadCount();
|
||||
uint32_t workForThisThread = (count - 1) / jobThreadCount + 1; // ceil(count / jobThreadCount)
|
||||
|
||||
if (count > workForThisThread + 1 && multiThreaded) { // more than one job to dispatch
|
||||
JobGraph g(JobSystem::getInstance());
|
||||
g.createForEachIndexJob(workForThisThread, count, 1U, [cmdBuffs](uint32_t i) {
|
||||
cmdBuffs[i]->getMessageQueue()->flushMessages();
|
||||
});
|
||||
g.run();
|
||||
|
||||
for (uint32_t i = 0U; i < workForThisThread; ++i) {
|
||||
cmdBuffs[i]->getMessageQueue()->flushMessages();
|
||||
}
|
||||
g.waitForAll();
|
||||
} else {
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
cmdBuffs[i]->getMessageQueue()->flushMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CommandBufferAgent::~CommandBufferAgent() {
|
||||
destroyMessageQueue();
|
||||
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), CommandBufferDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::initMessageQueue() {
|
||||
DeviceAgent *device = DeviceAgent::getInstance();
|
||||
device->_cmdBuffRefs.insert(this);
|
||||
|
||||
_messageQueue = ccnew MessageQueue;
|
||||
if (device->_multithreaded) _messageQueue->setImmediateMode(false);
|
||||
}
|
||||
|
||||
void CommandBufferAgent::destroyMessageQueue() {
|
||||
DeviceAgent::getInstance()->getMessageQueue()->kickAndWait();
|
||||
|
||||
CC_SAFE_DELETE(_messageQueue);
|
||||
|
||||
DeviceAgent::getInstance()->_cmdBuffRefs.erase(this);
|
||||
}
|
||||
|
||||
void CommandBufferAgent::initAgent() {
|
||||
initMessageQueue();
|
||||
}
|
||||
|
||||
void CommandBufferAgent::destroyAgent() {
|
||||
destroyMessageQueue();
|
||||
}
|
||||
|
||||
void CommandBufferAgent::doInit(const CommandBufferInfo &info) {
|
||||
initMessageQueue();
|
||||
|
||||
CommandBufferInfo actorInfo = info;
|
||||
actorInfo.queue = static_cast<QueueAgent *>(info.queue)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), CommandBufferInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::doDestroy() {
|
||||
destroyMessageQueue();
|
||||
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), CommandBufferDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::begin(RenderPass *renderPass, uint32_t subpass, Framebuffer *frameBuffer) {
|
||||
ENQUEUE_MESSAGE_4(
|
||||
_messageQueue,
|
||||
CommandBufferBegin,
|
||||
actor, getActor(),
|
||||
renderPass, renderPass ? static_cast<RenderPassAgent *>(renderPass)->getActor() : nullptr,
|
||||
subpass, subpass,
|
||||
frameBuffer, frameBuffer ? static_cast<FramebufferAgent *>(frameBuffer)->getActor() : nullptr,
|
||||
{
|
||||
actor->begin(renderPass, subpass, frameBuffer);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::end() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_messageQueue, CommandBufferEnd,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->end();
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) {
|
||||
auto attachmentCount = utils::toUint(renderPass->getColorAttachments().size());
|
||||
Color *actorColors = nullptr;
|
||||
if (attachmentCount) {
|
||||
actorColors = _messageQueue->allocate<Color>(attachmentCount);
|
||||
memcpy(actorColors, colors, sizeof(Color) * attachmentCount);
|
||||
}
|
||||
|
||||
CommandBuffer **actorSecondaryCBs = nullptr;
|
||||
if (secondaryCBCount) {
|
||||
actorSecondaryCBs = _messageQueue->allocate<CommandBuffer *>(secondaryCBCount);
|
||||
for (uint32_t i = 0; i < secondaryCBCount; ++i) {
|
||||
actorSecondaryCBs[i] = static_cast<CommandBufferAgent *>(secondaryCBs[i])->getActor();
|
||||
}
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_9(
|
||||
_messageQueue, CommandBufferBeginRenderPass,
|
||||
actor, getActor(),
|
||||
renderPass, static_cast<RenderPassAgent *>(renderPass)->getActor(),
|
||||
fbo, static_cast<FramebufferAgent *>(fbo)->getActor(),
|
||||
renderArea, renderArea,
|
||||
colors, actorColors,
|
||||
depth, depth,
|
||||
stencil, stencil,
|
||||
secondaryCBCount, secondaryCBCount,
|
||||
secondaryCBs, actorSecondaryCBs,
|
||||
{
|
||||
actor->beginRenderPass(renderPass, fbo, renderArea, colors, depth, stencil, secondaryCBs, secondaryCBCount);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::endRenderPass() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_messageQueue, CommandBufferEndRenderPass,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->endRenderPass();
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::insertMarker(const MarkerInfo &marker) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferInsertMarker,
|
||||
actor, getActor(),
|
||||
marker, marker,
|
||||
{
|
||||
actor->insertMarker(marker);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::beginMarker(const MarkerInfo &marker) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferBeginMarker,
|
||||
actor, getActor(),
|
||||
marker, marker,
|
||||
{
|
||||
actor->beginMarker(marker);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::endMarker() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_messageQueue, CommandBufferEndMarker,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->endMarker();
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::execute(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
if (!count) return;
|
||||
|
||||
auto **actorCmdBuffs = _messageQueue->allocate<CommandBuffer *>(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
actorCmdBuffs[i] = static_cast<CommandBufferAgent *>(cmdBuffs[i])->getActor();
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_3(
|
||||
_messageQueue, CommandBufferExecute,
|
||||
actor, getActor(),
|
||||
cmdBuffs, actorCmdBuffs,
|
||||
count, count,
|
||||
{
|
||||
actor->execute(cmdBuffs, count);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::bindPipelineState(PipelineState *pso) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferBindPipelineState,
|
||||
actor, getActor(),
|
||||
pso, static_cast<PipelineStateAgent *>(pso)->getActor(),
|
||||
{
|
||||
actor->bindPipelineState(pso);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) {
|
||||
uint32_t *actorDynamicOffsets = nullptr;
|
||||
if (dynamicOffsetCount) {
|
||||
actorDynamicOffsets = _messageQueue->allocate<uint32_t>(dynamicOffsetCount);
|
||||
memcpy(actorDynamicOffsets, dynamicOffsets, dynamicOffsetCount * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_5(
|
||||
_messageQueue, CommandBufferBindDescriptorSet,
|
||||
actor, getActor(),
|
||||
set, set,
|
||||
descriptorSet, static_cast<DescriptorSetAgent *>(descriptorSet)->getActor(),
|
||||
dynamicOffsetCount, dynamicOffsetCount,
|
||||
dynamicOffsets, actorDynamicOffsets,
|
||||
{
|
||||
actor->bindDescriptorSet(set, descriptorSet, dynamicOffsetCount, dynamicOffsets);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::bindInputAssembler(InputAssembler *ia) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferBindInputAssembler,
|
||||
actor, getActor(),
|
||||
ia, static_cast<InputAssemblerAgent *>(ia)->getActor(),
|
||||
{
|
||||
actor->bindInputAssembler(ia);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setViewport(const Viewport &vp) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferSetViewport,
|
||||
actor, getActor(),
|
||||
vp, vp,
|
||||
{
|
||||
actor->setViewport(vp);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setScissor(const Rect &rect) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferSetScissor,
|
||||
actor, getActor(),
|
||||
rect, rect,
|
||||
{
|
||||
actor->setScissor(rect);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setLineWidth(float width) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferSetLineWidth,
|
||||
actor, getActor(),
|
||||
width, width,
|
||||
{
|
||||
actor->setLineWidth(width);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setDepthBias(float constant, float clamp, float slope) {
|
||||
ENQUEUE_MESSAGE_4(
|
||||
_messageQueue, CommandBufferSetDepthBias,
|
||||
actor, getActor(),
|
||||
constant, constant,
|
||||
clamp, clamp,
|
||||
slope, slope,
|
||||
{
|
||||
actor->setDepthBias(constant, clamp, slope);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setBlendConstants(const Color &constants) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferSetBlendConstants,
|
||||
actor, getActor(),
|
||||
constants, constants,
|
||||
{
|
||||
actor->setBlendConstants(constants);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setDepthBound(float minBounds, float maxBounds) {
|
||||
ENQUEUE_MESSAGE_3(
|
||||
_messageQueue, CommandBufferSetDepthBound,
|
||||
actor, getActor(),
|
||||
minBounds, minBounds,
|
||||
maxBounds, maxBounds,
|
||||
{
|
||||
actor->setDepthBound(minBounds, maxBounds);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setStencilWriteMask(StencilFace face, uint32_t mask) {
|
||||
ENQUEUE_MESSAGE_3(
|
||||
_messageQueue, CommandBufferSetStencilWriteMask,
|
||||
actor, getActor(),
|
||||
face, face,
|
||||
mask, mask,
|
||||
{
|
||||
actor->setStencilWriteMask(face, mask);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) {
|
||||
ENQUEUE_MESSAGE_4(
|
||||
_messageQueue, CommandBufferSetStencilCompareMask,
|
||||
actor, getActor(),
|
||||
face, face,
|
||||
ref, ref,
|
||||
mask, mask,
|
||||
{
|
||||
actor->setStencilCompareMask(face, ref, mask);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::nextSubpass() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_messageQueue, CommandBufferNextSubpass,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->nextSubpass();
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::draw(const DrawInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferDraw,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->draw(info);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::updateBuffer(Buffer *buff, const void *data, uint32_t size) {
|
||||
auto *bufferAgent = static_cast<BufferAgent *>(buff);
|
||||
|
||||
uint8_t *actorBuffer{nullptr};
|
||||
bool needFreeing{false};
|
||||
|
||||
BufferAgent::getActorBuffer(bufferAgent, _messageQueue, size, &actorBuffer, &needFreeing);
|
||||
memcpy(actorBuffer, data, size);
|
||||
|
||||
ENQUEUE_MESSAGE_5(
|
||||
_messageQueue, CommandBufferUpdateBuffer,
|
||||
actor, getActor(),
|
||||
buff, bufferAgent->getActor(),
|
||||
data, actorBuffer,
|
||||
size, size,
|
||||
needFreeing, needFreeing,
|
||||
{
|
||||
actor->updateBuffer(buff, data, size);
|
||||
if (needFreeing) free(data);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
Texture *actorSrcTexture = nullptr;
|
||||
Texture *actorDstTexture = nullptr;
|
||||
if (srcTexture) actorSrcTexture = static_cast<TextureAgent *>(srcTexture)->getActor();
|
||||
if (dstTexture) actorDstTexture = static_cast<TextureAgent *>(dstTexture)->getActor();
|
||||
|
||||
auto *actorRegions = _messageQueue->allocate<TextureCopy>(count);
|
||||
memcpy(actorRegions, regions, count * sizeof(TextureCopy));
|
||||
|
||||
ENQUEUE_MESSAGE_5(
|
||||
_messageQueue, CommandBufferBlitTexture,
|
||||
actor, getActor(),
|
||||
srcTexture, actorSrcTexture,
|
||||
dstTexture, actorDstTexture,
|
||||
regions, actorRegions,
|
||||
count, count,
|
||||
{
|
||||
actor->resolveTexture(srcTexture, dstTexture, regions, count);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
Texture *actorSrcTexture = nullptr;
|
||||
Texture *actorDstTexture = nullptr;
|
||||
if (srcTexture) actorSrcTexture = static_cast<TextureAgent *>(srcTexture)->getActor();
|
||||
if (dstTexture) actorDstTexture = static_cast<TextureAgent *>(dstTexture)->getActor();
|
||||
|
||||
auto *actorRegions = _messageQueue->allocate<TextureCopy>(count);
|
||||
memcpy(actorRegions, regions, count * sizeof(TextureCopy));
|
||||
|
||||
ENQUEUE_MESSAGE_5(
|
||||
_messageQueue, CommandBufferBlitTexture,
|
||||
actor, getActor(),
|
||||
srcTexture, actorSrcTexture,
|
||||
dstTexture, actorDstTexture,
|
||||
regions, actorRegions,
|
||||
count, count,
|
||||
{
|
||||
actor->copyTexture(srcTexture, dstTexture, regions, count);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) {
|
||||
Texture *actorSrcTexture = nullptr;
|
||||
Texture *actorDstTexture = nullptr;
|
||||
if (srcTexture) actorSrcTexture = static_cast<TextureAgent *>(srcTexture)->getActor();
|
||||
if (dstTexture) actorDstTexture = static_cast<TextureAgent *>(dstTexture)->getActor();
|
||||
|
||||
auto *actorRegions = _messageQueue->allocate<TextureBlit>(count);
|
||||
memcpy(actorRegions, regions, count * sizeof(TextureBlit));
|
||||
|
||||
ENQUEUE_MESSAGE_6(
|
||||
_messageQueue, CommandBufferBlitTexture,
|
||||
actor, getActor(),
|
||||
srcTexture, actorSrcTexture,
|
||||
dstTexture, actorDstTexture,
|
||||
regions, actorRegions,
|
||||
count, count,
|
||||
filter, filter,
|
||||
{
|
||||
actor->blitTexture(srcTexture, dstTexture, regions, count, filter);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::dispatch(const DispatchInfo &info) {
|
||||
DispatchInfo actorInfo = info;
|
||||
if (info.indirectBuffer) actorInfo.indirectBuffer = static_cast<BufferAgent *>(info.indirectBuffer)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferDispatch,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->dispatch(info);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) {
|
||||
TextureBarrier **actorTextureBarriers = nullptr;
|
||||
Texture **actorTextures = nullptr;
|
||||
|
||||
BufferBarrier **actorBufferBarriers = nullptr;
|
||||
Buffer **actorBuffers = nullptr;
|
||||
|
||||
if (textureBarrierCount) {
|
||||
actorTextureBarriers = _messageQueue->allocate<TextureBarrier *>(textureBarrierCount);
|
||||
memcpy(actorTextureBarriers, textureBarriers, textureBarrierCount * sizeof(uintptr_t));
|
||||
|
||||
actorTextures = _messageQueue->allocate<Texture *>(textureBarrierCount);
|
||||
for (uint32_t i = 0U; i < textureBarrierCount; ++i) {
|
||||
actorTextures[i] = textures[i] ? static_cast<const TextureAgent *>(textures[i])->getActor() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufferBarrierCount) {
|
||||
actorBufferBarriers = _messageQueue->allocateAndZero<BufferBarrier *>(bufferBarrierCount);
|
||||
memcpy(actorBufferBarriers, bufferBarriers, bufferBarrierCount * sizeof(uintptr_t));
|
||||
|
||||
actorBuffers = _messageQueue->allocate<Buffer *>(bufferBarrierCount);
|
||||
for (uint32_t i = 0; i < bufferBarrierCount; ++i) {
|
||||
actorBuffers[i] = buffers[i] ? static_cast<const BufferAgent *>(buffers[i])->getActor() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_8(
|
||||
_messageQueue, CommandBufferPipelineBarrier,
|
||||
actor, getActor(),
|
||||
barrier, barrier,
|
||||
bufferBarriers, actorBufferBarriers,
|
||||
buffers, actorBuffers,
|
||||
bufferBarrierCount, bufferBarrierCount,
|
||||
textureBarriers, actorTextureBarriers,
|
||||
textures, actorTextures,
|
||||
textureBarrierCount, textureBarrierCount,
|
||||
{
|
||||
actor->pipelineBarrier(barrier, bufferBarriers, buffers, bufferBarrierCount, textureBarriers, textures, textureBarrierCount);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::beginQuery(QueryPool *queryPool, uint32_t id) {
|
||||
auto *actorQueryPool = static_cast<QueryPoolAgent *>(queryPool)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_3(
|
||||
_messageQueue, CommandBufferBeginQuery,
|
||||
actor, getActor(),
|
||||
queryPool, actorQueryPool,
|
||||
id, id,
|
||||
{
|
||||
actor->beginQuery(queryPool, id);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::endQuery(QueryPool *queryPool, uint32_t id) {
|
||||
auto *actorQueryPool = static_cast<QueryPoolAgent *>(queryPool)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_3(
|
||||
_messageQueue, CommandBufferEndQuery,
|
||||
actor, getActor(),
|
||||
queryPool, actorQueryPool,
|
||||
id, id,
|
||||
{
|
||||
actor->endQuery(queryPool, id);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::resetQueryPool(QueryPool *queryPool) {
|
||||
auto *actorQueryPool = static_cast<QueryPoolAgent *>(queryPool)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferResetQueryPool,
|
||||
actor, getActor(),
|
||||
queryPool, actorQueryPool,
|
||||
{
|
||||
actor->resetQueryPool(queryPool);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::completeQueryPool(QueryPool *queryPool) {
|
||||
auto *actorQueryPool = static_cast<QueryPoolAgent *>(queryPool)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferCompleteQueryPool,
|
||||
actor, getActor(),
|
||||
queryPool, actorQueryPool,
|
||||
{
|
||||
actor->completeQueryPool(queryPool);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandBufferAgent::customCommand(CustomCommand &&cmd) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_messageQueue, CommandBufferCompleteQueryPool,
|
||||
actor, getActor(),
|
||||
cmd, cmd,
|
||||
{
|
||||
actor->customCommand(std::move(cmd));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
98
cocos/renderer/gfx-agent/CommandBufferAgent.h
Normal file
98
cocos/renderer/gfx-agent/CommandBufferAgent.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXCommandBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class MessageQueue;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL CommandBufferAgent final : public Agent<CommandBuffer> {
|
||||
public:
|
||||
explicit CommandBufferAgent(CommandBuffer *actor);
|
||||
~CommandBufferAgent() override;
|
||||
|
||||
static void flushCommands(uint32_t count, CommandBufferAgent *const *cmdBuffs, bool multiThreaded);
|
||||
|
||||
void begin(RenderPass *renderPass, uint32_t subpass, Framebuffer *frameBuffer) override;
|
||||
void end() override;
|
||||
void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override;
|
||||
void endRenderPass() override;
|
||||
void insertMarker(const MarkerInfo &marker) override;
|
||||
void beginMarker(const MarkerInfo &marker) override;
|
||||
void endMarker() override;
|
||||
void bindPipelineState(PipelineState *pso) override;
|
||||
void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override;
|
||||
void bindInputAssembler(InputAssembler *ia) override;
|
||||
void setViewport(const Viewport &vp) override;
|
||||
void setScissor(const Rect &rect) override;
|
||||
void setLineWidth(float width) override;
|
||||
void setDepthBias(float constant, float clamp, float slope) override;
|
||||
void setBlendConstants(const Color &constants) override;
|
||||
void setDepthBound(float minBounds, float maxBounds) override;
|
||||
void setStencilWriteMask(StencilFace face, uint32_t mask) override;
|
||||
void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) override;
|
||||
void nextSubpass() override;
|
||||
void draw(const DrawInfo &info) override;
|
||||
void updateBuffer(Buffer *buff, const void *data, uint32_t size) override;
|
||||
void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) override;
|
||||
void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) override;
|
||||
void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override;
|
||||
void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override;
|
||||
void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override;
|
||||
void dispatch(const DispatchInfo &info) override;
|
||||
void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override;
|
||||
void beginQuery(QueryPool *queryPool, uint32_t id) override;
|
||||
void endQuery(QueryPool *queryPool, uint32_t id) override;
|
||||
void resetQueryPool(QueryPool *queryPool) override;
|
||||
void completeQueryPool(QueryPool *queryPool) override;
|
||||
void customCommand(CustomCommand &&cmd) override;
|
||||
|
||||
uint32_t getNumDrawCalls() const override { return _actor->getNumDrawCalls(); }
|
||||
uint32_t getNumInstances() const override { return _actor->getNumInstances(); }
|
||||
uint32_t getNumTris() const override { return _actor->getNumTris(); }
|
||||
|
||||
inline MessageQueue *getMessageQueue() { return _messageQueue; }
|
||||
|
||||
protected:
|
||||
friend class DeviceAgent;
|
||||
|
||||
void initAgent();
|
||||
void destroyAgent();
|
||||
|
||||
void doInit(const CommandBufferInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
void initMessageQueue();
|
||||
void destroyMessageQueue();
|
||||
MessageQueue *_messageQueue = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
149
cocos/renderer/gfx-agent/DescriptorSetAgent.cpp
Normal file
149
cocos/renderer/gfx-agent/DescriptorSetAgent.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "BufferAgent.h"
|
||||
#include "DescriptorSetAgent.h"
|
||||
#include "DescriptorSetLayoutAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "TextureAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DescriptorSetAgent::DescriptorSetAgent(DescriptorSet *actor)
|
||||
: Agent<DescriptorSet>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
DescriptorSetAgent::~DescriptorSetAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::doInit(const DescriptorSetInfo &info) {
|
||||
DescriptorSetInfo actorInfo;
|
||||
actorInfo.layout = static_cast<const DescriptorSetLayoutAgent *>(info.layout)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::update() {
|
||||
// Avoid enqueueing unnecessary command
|
||||
if (!_isDirty) return;
|
||||
|
||||
_isDirty = false;
|
||||
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetUpdate,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->update();
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::forceUpdate() {
|
||||
_isDirty = false;
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetForceUpdate,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->forceUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) {
|
||||
DescriptorSet::bindBuffer(binding, buffer, index, flags);
|
||||
|
||||
ENQUEUE_MESSAGE_5(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetBindBuffer,
|
||||
actor, getActor(),
|
||||
binding, binding,
|
||||
buffer, static_cast<BufferAgent *>(buffer)->getActor(),
|
||||
index, index,
|
||||
flags, flags,
|
||||
{
|
||||
actor->bindBuffer(binding, buffer, index, flags);
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) {
|
||||
DescriptorSet::bindTexture(binding, texture, index, flags);
|
||||
|
||||
ENQUEUE_MESSAGE_5(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetBindTexture,
|
||||
actor, getActor(),
|
||||
binding, binding,
|
||||
texture, static_cast<TextureAgent *>(texture)->getActor(),
|
||||
index, index,
|
||||
flags, flags,
|
||||
{
|
||||
actor->bindTexture(binding, texture, index, flags);
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetAgent::bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) {
|
||||
DescriptorSet::bindSampler(binding, sampler, index);
|
||||
|
||||
ENQUEUE_MESSAGE_4(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetBindSampler,
|
||||
actor, getActor(),
|
||||
binding, binding,
|
||||
sampler, sampler,
|
||||
index, index,
|
||||
{
|
||||
actor->bindSampler(binding, sampler, index);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
51
cocos/renderer/gfx-agent/DescriptorSetAgent.h
Normal file
51
cocos/renderer/gfx-agent/DescriptorSetAgent.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXDescriptorSet.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL DescriptorSetAgent final : public Agent<DescriptorSet> {
|
||||
public:
|
||||
explicit DescriptorSetAgent(DescriptorSet *actor);
|
||||
~DescriptorSetAgent() override;
|
||||
|
||||
void update() override;
|
||||
void forceUpdate() override;
|
||||
|
||||
void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) override;
|
||||
void bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) override;
|
||||
void bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) override;
|
||||
|
||||
protected:
|
||||
void doInit(const DescriptorSetInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
70
cocos/renderer/gfx-agent/DescriptorSetLayoutAgent.cpp
Normal file
70
cocos/renderer/gfx-agent/DescriptorSetLayoutAgent.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DescriptorSetLayoutAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DescriptorSetLayoutAgent::DescriptorSetLayoutAgent(DescriptorSetLayout *actor)
|
||||
: Agent<DescriptorSetLayout>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
DescriptorSetLayoutAgent::~DescriptorSetLayoutAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetLayoutDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetLayoutAgent::doInit(const DescriptorSetLayoutInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetLayoutInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void DescriptorSetLayoutAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
DescriptorSetLayoutDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/DescriptorSetLayoutAgent.h
Normal file
44
cocos/renderer/gfx-agent/DescriptorSetLayoutAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXDescriptorSetLayout.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL DescriptorSetLayoutAgent final : public Agent<DescriptorSetLayout> {
|
||||
public:
|
||||
explicit DescriptorSetLayoutAgent(DescriptorSetLayout *actor);
|
||||
~DescriptorSetLayoutAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const DescriptorSetLayoutInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
463
cocos/renderer/gfx-agent/DeviceAgent.cpp
Normal file
463
cocos/renderer/gfx-agent/DeviceAgent.cpp
Normal file
@@ -0,0 +1,463 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <boost/align/align_up.hpp>
|
||||
#include <cstring>
|
||||
#include "application/ApplicationManager.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
#include "base/threading/ThreadSafeLinearAllocator.h"
|
||||
#include "platform/interfaces/modules/IXRInterface.h"
|
||||
|
||||
#include "BufferAgent.h"
|
||||
#include "CommandBufferAgent.h"
|
||||
#include "DescriptorSetAgent.h"
|
||||
#include "DescriptorSetLayoutAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "FramebufferAgent.h"
|
||||
#include "InputAssemblerAgent.h"
|
||||
#include "PipelineLayoutAgent.h"
|
||||
#include "PipelineStateAgent.h"
|
||||
#include "QueryPoolAgent.h"
|
||||
#include "QueueAgent.h"
|
||||
#include "RenderPassAgent.h"
|
||||
#include "ShaderAgent.h"
|
||||
#include "SwapchainAgent.h"
|
||||
#include "TextureAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DeviceAgent *DeviceAgent::instance = nullptr;
|
||||
|
||||
DeviceAgent *DeviceAgent::getInstance() {
|
||||
return DeviceAgent::instance;
|
||||
}
|
||||
|
||||
DeviceAgent::DeviceAgent(Device *device) : Agent(device) {
|
||||
DeviceAgent::instance = this;
|
||||
}
|
||||
|
||||
DeviceAgent::~DeviceAgent() {
|
||||
CC_SAFE_DELETE(_actor);
|
||||
DeviceAgent::instance = nullptr;
|
||||
}
|
||||
|
||||
bool DeviceAgent::doInit(const DeviceInfo &info) {
|
||||
if (!_actor->initialize(info)) {
|
||||
return false;
|
||||
}
|
||||
_xr = CC_GET_XR_INTERFACE();
|
||||
_api = _actor->getGfxAPI();
|
||||
_deviceName = _actor->getDeviceName();
|
||||
_queue = ccnew QueueAgent(_actor->getQueue());
|
||||
_queryPool = ccnew QueryPoolAgent(_actor->getQueryPool());
|
||||
_cmdBuff = ccnew CommandBufferAgent(_actor->getCommandBuffer());
|
||||
_renderer = _actor->getRenderer();
|
||||
_vendor = _actor->getVendor();
|
||||
_caps = _actor->_caps;
|
||||
memcpy(_features.data(), _actor->_features.data(), static_cast<uint32_t>(Feature::COUNT) * sizeof(bool));
|
||||
memcpy(_formatFeatures.data(), _actor->_formatFeatures.data(), static_cast<uint32_t>(Format::COUNT) * sizeof(FormatFeatureBit));
|
||||
|
||||
_mainMessageQueue = ccnew MessageQueue;
|
||||
|
||||
static_cast<CommandBufferAgent *>(_cmdBuff)->_queue = _queue;
|
||||
static_cast<CommandBufferAgent *>(_cmdBuff)->initAgent();
|
||||
|
||||
setMultithreaded(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeviceAgent::doDestroy() {
|
||||
if (!_mainMessageQueue) {
|
||||
_actor->destroy();
|
||||
} else {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_mainMessageQueue, DeviceDestroy,
|
||||
actor, _actor,
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
if (_cmdBuff) {
|
||||
static_cast<CommandBufferAgent *>(_cmdBuff)->destroyAgent();
|
||||
static_cast<CommandBufferAgent *>(_cmdBuff)->_actor = nullptr;
|
||||
delete _cmdBuff;
|
||||
_cmdBuff = nullptr;
|
||||
}
|
||||
if (_queryPool) {
|
||||
static_cast<QueryPoolAgent *>(_queryPool)->_actor = nullptr;
|
||||
delete _queryPool;
|
||||
_queryPool = nullptr;
|
||||
}
|
||||
if (_queue) {
|
||||
static_cast<QueueAgent *>(_queue)->_actor = nullptr;
|
||||
delete _queue;
|
||||
_queue = nullptr;
|
||||
}
|
||||
|
||||
if (_mainMessageQueue) {
|
||||
_mainMessageQueue->terminateConsumerThread();
|
||||
|
||||
delete _mainMessageQueue;
|
||||
_mainMessageQueue = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceAgent::acquire(Swapchain *const *swapchains, uint32_t count) {
|
||||
auto *actorSwapchains = _mainMessageQueue->allocate<Swapchain *>(count);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
actorSwapchains[i] = static_cast<SwapchainAgent *>(swapchains[i])->getActor();
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_4(
|
||||
_mainMessageQueue, DevicePresent,
|
||||
device, this,
|
||||
actor, _actor,
|
||||
swapchains, actorSwapchains,
|
||||
count, count,
|
||||
{
|
||||
if (device->_onAcquire) device->_onAcquire->execute();
|
||||
actor->acquire(swapchains, count);
|
||||
});
|
||||
}
|
||||
|
||||
void DeviceAgent::present() {
|
||||
if (_xr) {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_mainMessageQueue, DevicePresent,
|
||||
actor, _actor,
|
||||
{
|
||||
actor->present();
|
||||
});
|
||||
} else {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_mainMessageQueue, DevicePresent,
|
||||
actor, _actor,
|
||||
frameBoundarySemaphore, &_frameBoundarySemaphore,
|
||||
{
|
||||
actor->present();
|
||||
frameBoundarySemaphore->signal();
|
||||
});
|
||||
|
||||
MessageQueue::freeChunksInFreeQueue(_mainMessageQueue);
|
||||
_mainMessageQueue->finishWriting();
|
||||
_currentIndex = (_currentIndex + 1) % MAX_FRAME_INDEX;
|
||||
_frameBoundarySemaphore.wait();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceAgent::setMultithreaded(bool multithreaded) {
|
||||
if (multithreaded == _multithreaded) return;
|
||||
_multithreaded = multithreaded;
|
||||
|
||||
if (multithreaded) {
|
||||
_mainMessageQueue->setImmediateMode(false);
|
||||
_actor->bindContext(false);
|
||||
_mainMessageQueue->runConsumerThread();
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_mainMessageQueue, DeviceMakeCurrentTrue,
|
||||
actor, _actor,
|
||||
{
|
||||
actor->bindContext(true);
|
||||
CC_LOG_INFO("Device thread detached.");
|
||||
});
|
||||
for (CommandBufferAgent *cmdBuff : _cmdBuffRefs) {
|
||||
cmdBuff->_messageQueue->setImmediateMode(false);
|
||||
}
|
||||
} else {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_mainMessageQueue, DeviceMakeCurrentFalse,
|
||||
actor, _actor,
|
||||
{
|
||||
actor->bindContext(false);
|
||||
});
|
||||
_mainMessageQueue->terminateConsumerThread();
|
||||
_mainMessageQueue->setImmediateMode(true);
|
||||
_actor->bindContext(true);
|
||||
for (CommandBufferAgent *cmdBuff : _cmdBuffRefs) {
|
||||
cmdBuff->_messageQueue->setImmediateMode(true);
|
||||
}
|
||||
CC_LOG_INFO("Device thread joined.");
|
||||
}
|
||||
}
|
||||
|
||||
CommandBuffer *DeviceAgent::createCommandBuffer(const CommandBufferInfo &info, bool /*hasAgent*/) {
|
||||
CommandBuffer *actor = _actor->createCommandBuffer(info, true);
|
||||
return ccnew CommandBufferAgent(actor);
|
||||
}
|
||||
|
||||
Queue *DeviceAgent::createQueue() {
|
||||
Queue *actor = _actor->createQueue();
|
||||
return ccnew QueueAgent(actor);
|
||||
}
|
||||
|
||||
QueryPool *DeviceAgent::createQueryPool() {
|
||||
QueryPool *actor = _actor->createQueryPool();
|
||||
return ccnew QueryPoolAgent(actor);
|
||||
}
|
||||
|
||||
Swapchain *DeviceAgent::createSwapchain() {
|
||||
Swapchain *actor = _actor->createSwapchain();
|
||||
return ccnew SwapchainAgent(actor);
|
||||
}
|
||||
|
||||
Buffer *DeviceAgent::createBuffer() {
|
||||
Buffer *actor = _actor->createBuffer();
|
||||
return ccnew BufferAgent(actor);
|
||||
}
|
||||
|
||||
Texture *DeviceAgent::createTexture() {
|
||||
Texture *actor = _actor->createTexture();
|
||||
return ccnew TextureAgent(actor);
|
||||
}
|
||||
|
||||
Shader *DeviceAgent::createShader() {
|
||||
Shader *actor = _actor->createShader();
|
||||
return ccnew ShaderAgent(actor);
|
||||
}
|
||||
|
||||
InputAssembler *DeviceAgent::createInputAssembler() {
|
||||
InputAssembler *actor = _actor->createInputAssembler();
|
||||
return ccnew InputAssemblerAgent(actor);
|
||||
}
|
||||
|
||||
RenderPass *DeviceAgent::createRenderPass() {
|
||||
RenderPass *actor = _actor->createRenderPass();
|
||||
return ccnew RenderPassAgent(actor);
|
||||
}
|
||||
|
||||
Framebuffer *DeviceAgent::createFramebuffer() {
|
||||
Framebuffer *actor = _actor->createFramebuffer();
|
||||
return ccnew FramebufferAgent(actor);
|
||||
}
|
||||
|
||||
DescriptorSet *DeviceAgent::createDescriptorSet() {
|
||||
DescriptorSet *actor = _actor->createDescriptorSet();
|
||||
return ccnew DescriptorSetAgent(actor);
|
||||
}
|
||||
|
||||
DescriptorSetLayout *DeviceAgent::createDescriptorSetLayout() {
|
||||
DescriptorSetLayout *actor = _actor->createDescriptorSetLayout();
|
||||
return ccnew DescriptorSetLayoutAgent(actor);
|
||||
}
|
||||
|
||||
PipelineLayout *DeviceAgent::createPipelineLayout() {
|
||||
PipelineLayout *actor = _actor->createPipelineLayout();
|
||||
return ccnew PipelineLayoutAgent(actor);
|
||||
}
|
||||
|
||||
PipelineState *DeviceAgent::createPipelineState() {
|
||||
PipelineState *actor = _actor->createPipelineState();
|
||||
return ccnew PipelineStateAgent(actor);
|
||||
}
|
||||
|
||||
Sampler *DeviceAgent::getSampler(const SamplerInfo &info) {
|
||||
return _actor->getSampler(info);
|
||||
}
|
||||
|
||||
GeneralBarrier *DeviceAgent::getGeneralBarrier(const GeneralBarrierInfo &info) {
|
||||
return _actor->getGeneralBarrier(info);
|
||||
}
|
||||
|
||||
TextureBarrier *DeviceAgent::getTextureBarrier(const TextureBarrierInfo &info) {
|
||||
return _actor->getTextureBarrier(info);
|
||||
}
|
||||
|
||||
BufferBarrier *DeviceAgent::getBufferBarrier(const BufferBarrierInfo &info) {
|
||||
return _actor->getBufferBarrier(info);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void doBufferTextureCopy(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count, MessageQueue *mq, T *actor) {
|
||||
uint32_t bufferCount = 0U;
|
||||
for (uint32_t i = 0U; i < count; i++) {
|
||||
bufferCount += regions[i].texSubres.layerCount;
|
||||
}
|
||||
|
||||
Format format = texture->getFormat();
|
||||
constexpr uint32_t alignment = 16;
|
||||
|
||||
size_t totalSize = boost::alignment::align_up(sizeof(BufferTextureCopy) * count + sizeof(uint8_t *) * bufferCount, alignment);
|
||||
for (uint32_t i = 0U; i < count; i++) {
|
||||
const BufferTextureCopy ®ion = regions[i];
|
||||
|
||||
uint32_t size = formatSize(texture->getFormat(), region.texExtent.width, region.texExtent.height, region.texExtent.depth);
|
||||
totalSize += boost::alignment::align_up(size, alignment) * region.texSubres.layerCount;
|
||||
}
|
||||
|
||||
auto *allocator = ccnew ThreadSafeLinearAllocator(totalSize, alignment);
|
||||
|
||||
auto *actorRegions = allocator->allocate<BufferTextureCopy>(count);
|
||||
memcpy(actorRegions, regions, count * sizeof(BufferTextureCopy));
|
||||
|
||||
const auto **actorBuffers = allocator->allocate<const uint8_t *>(bufferCount);
|
||||
const auto blockHeight = formatAlignment(format).second;
|
||||
for (uint32_t i = 0U, n = 0U; i < count; i++) {
|
||||
const BufferTextureCopy ®ion = regions[i];
|
||||
uint32_t width = region.texExtent.width;
|
||||
uint32_t height = region.texExtent.height;
|
||||
uint32_t depth = region.texExtent.depth;
|
||||
|
||||
uint32_t rowStride = region.buffStride > 0 ? region.buffStride : region.texExtent.width;
|
||||
uint32_t heightStride = region.buffTexHeight > 0 ? region.buffTexHeight : region.texExtent.height;
|
||||
|
||||
uint32_t rowStrideSize = formatSize(format, rowStride, 1, 1);
|
||||
uint32_t sliceStrideSize = formatSize(format, rowStride, heightStride, 1);
|
||||
uint32_t destRowStrideSize = formatSize(format, width, 1, 1);
|
||||
uint32_t size = formatSize(format, width, height, depth);
|
||||
|
||||
for (uint32_t l = 0; l < region.texSubres.layerCount; l++) {
|
||||
auto *buffer = allocator->allocate<uint8_t>(size, alignment);
|
||||
uint32_t destOffset = 0;
|
||||
uint32_t buffOffset = 0;
|
||||
for (uint32_t d = 0; d < depth; d++) {
|
||||
buffOffset = region.buffOffset + sliceStrideSize * d;
|
||||
for (uint32_t h = 0; h < height; h += blockHeight) {
|
||||
memcpy(buffer + destOffset, buffers[n] + buffOffset, destRowStrideSize);
|
||||
destOffset += destRowStrideSize;
|
||||
buffOffset += rowStrideSize;
|
||||
}
|
||||
}
|
||||
actorBuffers[n++] = buffer;
|
||||
}
|
||||
actorRegions[i].buffOffset = 0;
|
||||
actorRegions[i].buffStride = 0;
|
||||
actorRegions[i].buffTexHeight = 0;
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_6(
|
||||
mq, DeviceCopyBuffersToTexture,
|
||||
actor, actor,
|
||||
buffers, actorBuffers,
|
||||
dst, static_cast<TextureAgent *>(texture)->getActor(),
|
||||
regions, actorRegions,
|
||||
count, count,
|
||||
allocator, allocator,
|
||||
{
|
||||
actor->copyBuffersToTexture(buffers, dst, regions, count);
|
||||
delete allocator;
|
||||
});
|
||||
}
|
||||
|
||||
void DeviceAgent::copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) {
|
||||
doBufferTextureCopy(buffers, dst, regions, count, _mainMessageQueue, _actor);
|
||||
}
|
||||
|
||||
void CommandBufferAgent::copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) {
|
||||
doBufferTextureCopy(buffers, texture, regions, count, _messageQueue, _actor);
|
||||
}
|
||||
|
||||
void DeviceAgent::copyTextureToBuffers(Texture *srcTexture, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count) {
|
||||
ENQUEUE_MESSAGE_5(
|
||||
_mainMessageQueue,
|
||||
DeviceCopyTextureToBuffers,
|
||||
actor, getActor(),
|
||||
src, static_cast<TextureAgent *>(srcTexture)->getActor(),
|
||||
buffers, buffers,
|
||||
regions, regions,
|
||||
count, count,
|
||||
{
|
||||
actor->copyTextureToBuffers(src, buffers, regions, count);
|
||||
});
|
||||
|
||||
_mainMessageQueue->kickAndWait();
|
||||
}
|
||||
|
||||
void DeviceAgent::flushCommands(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
if (!_multithreaded) return; // all command buffers are immediately executed
|
||||
|
||||
auto **agentCmdBuffs = _mainMessageQueue->allocate<CommandBufferAgent *>(count);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
agentCmdBuffs[i] = static_cast<CommandBufferAgent *const>(cmdBuffs[i]);
|
||||
MessageQueue::freeChunksInFreeQueue(agentCmdBuffs[i]->_messageQueue);
|
||||
agentCmdBuffs[i]->_messageQueue->finishWriting();
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_3(
|
||||
_mainMessageQueue, DeviceFlushCommands,
|
||||
count, count,
|
||||
cmdBuffs, agentCmdBuffs,
|
||||
multiThreaded, _actor->_multithreadedCommandRecording,
|
||||
{
|
||||
CommandBufferAgent::flushCommands(count, cmdBuffs, multiThreaded);
|
||||
});
|
||||
}
|
||||
|
||||
void DeviceAgent::getQueryPoolResults(QueryPool *queryPool) {
|
||||
QueryPool *actorQueryPool = static_cast<QueryPoolAgent *>(queryPool)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_mainMessageQueue, DeviceGetQueryPoolResults,
|
||||
actor, getActor(),
|
||||
queryPool, actorQueryPool,
|
||||
{
|
||||
actor->getQueryPoolResults(queryPool);
|
||||
});
|
||||
|
||||
auto *actorQueryPoolAgent = static_cast<QueryPoolAgent *>(actorQueryPool);
|
||||
auto *queryPoolAgent = static_cast<QueryPoolAgent *>(queryPool);
|
||||
std::lock_guard<std::mutex> lock(actorQueryPoolAgent->_mutex);
|
||||
queryPoolAgent->_results = actorQueryPoolAgent->_results;
|
||||
}
|
||||
|
||||
void DeviceAgent::enableAutoBarrier(bool en) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
_mainMessageQueue, enableAutoBarrier,
|
||||
actor, getActor(),
|
||||
en, en,
|
||||
{
|
||||
actor->enableAutoBarrier(en);
|
||||
});
|
||||
}
|
||||
|
||||
void DeviceAgent::presentSignal() {
|
||||
_frameBoundarySemaphore.signal();
|
||||
}
|
||||
|
||||
void DeviceAgent::presentWait() {
|
||||
MessageQueue::freeChunksInFreeQueue(_mainMessageQueue);
|
||||
_mainMessageQueue->finishWriting();
|
||||
_currentIndex = (_currentIndex + 1) % MAX_FRAME_INDEX;
|
||||
_frameBoundarySemaphore.wait();
|
||||
}
|
||||
|
||||
void DeviceAgent::frameSync() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
_mainMessageQueue, FrameSync,
|
||||
actor, _actor,
|
||||
{
|
||||
actor->frameSync();
|
||||
});
|
||||
}
|
||||
|
||||
SampleCount DeviceAgent::getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const {
|
||||
return _actor->getMaxSampleCount(format, usage, flags);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
136
cocos/renderer/gfx-agent/DeviceAgent.h
Normal file
136
cocos/renderer/gfx-agent/DeviceAgent.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "base/std/container/unordered_set.h"
|
||||
#include "base/threading/Semaphore.h"
|
||||
#include "gfx-base/GFXDevice.h"
|
||||
|
||||
namespace cc {
|
||||
class IXRInterface;
|
||||
class MessageQueue;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
class CommandBuffer;
|
||||
class CommandBufferAgent;
|
||||
|
||||
class CC_DLL DeviceAgent final : public Agent<Device> {
|
||||
public:
|
||||
static DeviceAgent *getInstance();
|
||||
static constexpr uint32_t MAX_CPU_FRAME_AHEAD = 1;
|
||||
static constexpr uint32_t MAX_FRAME_INDEX = MAX_CPU_FRAME_AHEAD + 1;
|
||||
|
||||
~DeviceAgent() override;
|
||||
|
||||
using Device::copyBuffersToTexture;
|
||||
using Device::createBuffer;
|
||||
using Device::createCommandBuffer;
|
||||
using Device::createDescriptorSet;
|
||||
using Device::createDescriptorSetLayout;
|
||||
using Device::createFramebuffer;
|
||||
using Device::createGeneralBarrier;
|
||||
using Device::createInputAssembler;
|
||||
using Device::createPipelineLayout;
|
||||
using Device::createPipelineState;
|
||||
using Device::createQueryPool;
|
||||
using Device::createQueue;
|
||||
using Device::createRenderPass;
|
||||
using Device::createSampler;
|
||||
using Device::createShader;
|
||||
using Device::createTexture;
|
||||
using Device::createTextureBarrier;
|
||||
|
||||
void frameSync() override;
|
||||
void acquire(Swapchain *const *swapchains, uint32_t count) override;
|
||||
void present() override;
|
||||
|
||||
CommandBuffer *createCommandBuffer(const CommandBufferInfo &info, bool hasAgent) override;
|
||||
Queue *createQueue() override;
|
||||
QueryPool *createQueryPool() override;
|
||||
Swapchain *createSwapchain() override;
|
||||
Buffer *createBuffer() override;
|
||||
Texture *createTexture() override;
|
||||
Shader *createShader() override;
|
||||
InputAssembler *createInputAssembler() override;
|
||||
RenderPass *createRenderPass() override;
|
||||
Framebuffer *createFramebuffer() override;
|
||||
DescriptorSet *createDescriptorSet() override;
|
||||
DescriptorSetLayout *createDescriptorSetLayout() override;
|
||||
PipelineLayout *createPipelineLayout() override;
|
||||
PipelineState *createPipelineState() override;
|
||||
|
||||
Sampler *getSampler(const SamplerInfo &info) override;
|
||||
GeneralBarrier *getGeneralBarrier(const GeneralBarrierInfo &info) override;
|
||||
TextureBarrier *getTextureBarrier(const TextureBarrierInfo &info) override;
|
||||
BufferBarrier *getBufferBarrier(const BufferBarrierInfo &info) override;
|
||||
|
||||
void copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) override;
|
||||
void copyTextureToBuffers(Texture *src, uint8_t *const *buffers, const BufferTextureCopy *region, uint32_t count) override;
|
||||
void flushCommands(CommandBuffer *const *cmdBuffs, uint32_t count) override;
|
||||
void getQueryPoolResults(QueryPool *queryPool) override;
|
||||
MemoryStatus &getMemoryStatus() override { return _actor->getMemoryStatus(); }
|
||||
uint32_t getNumDrawCalls() const override { return _actor->getNumDrawCalls(); }
|
||||
uint32_t getNumInstances() const override { return _actor->getNumInstances(); }
|
||||
uint32_t getNumTris() const override { return _actor->getNumTris(); }
|
||||
|
||||
uint32_t getCurrentIndex() const { return _currentIndex; }
|
||||
void setMultithreaded(bool multithreaded);
|
||||
|
||||
inline MessageQueue *getMessageQueue() const { return _mainMessageQueue; }
|
||||
|
||||
void presentWait();
|
||||
void presentSignal();
|
||||
|
||||
void enableAutoBarrier(bool en) override;
|
||||
SampleCount getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const override;
|
||||
protected:
|
||||
static DeviceAgent *instance;
|
||||
|
||||
friend class DeviceManager;
|
||||
friend class CommandBufferAgent;
|
||||
|
||||
explicit DeviceAgent(Device *device);
|
||||
|
||||
bool doInit(const DeviceInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _multithreaded{false};
|
||||
MessageQueue *_mainMessageQueue{nullptr};
|
||||
|
||||
uint32_t _currentIndex = 0U;
|
||||
#if CC_USE_XR
|
||||
Semaphore _frameBoundarySemaphore{0};
|
||||
#else
|
||||
Semaphore _frameBoundarySemaphore{MAX_CPU_FRAME_AHEAD};
|
||||
#endif
|
||||
|
||||
ccstd::unordered_set<CommandBufferAgent *> _cmdBuffRefs;
|
||||
IXRInterface *_xr{nullptr};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
86
cocos/renderer/gfx-agent/FramebufferAgent.cpp
Normal file
86
cocos/renderer/gfx-agent/FramebufferAgent.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceAgent.h"
|
||||
#include "FramebufferAgent.h"
|
||||
#include "RenderPassAgent.h"
|
||||
#include "TextureAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
FramebufferAgent::FramebufferAgent(Framebuffer *actor)
|
||||
: Agent<Framebuffer>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
FramebufferAgent::~FramebufferAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
FramebufferDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void FramebufferAgent::doInit(const FramebufferInfo &info) {
|
||||
FramebufferInfo actorInfo = info;
|
||||
for (uint32_t i = 0U; i < info.colorTextures.size(); ++i) {
|
||||
if (info.colorTextures[i]) {
|
||||
actorInfo.colorTextures[i] = static_cast<TextureAgent *>(info.colorTextures[i])->getActor();
|
||||
}
|
||||
}
|
||||
if (info.depthStencilTexture) {
|
||||
actorInfo.depthStencilTexture = static_cast<TextureAgent *>(info.depthStencilTexture)->getActor();
|
||||
}
|
||||
if (info.depthStencilResolveTexture) {
|
||||
actorInfo.depthStencilResolveTexture = static_cast<TextureAgent *>(info.depthStencilResolveTexture)->getActor();
|
||||
}
|
||||
actorInfo.renderPass = static_cast<RenderPassAgent *>(info.renderPass)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
FramebufferInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void FramebufferAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
FramebufferDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/FramebufferAgent.h
Normal file
44
cocos/renderer/gfx-agent/FramebufferAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXFramebuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL FramebufferAgent final : public Agent<Framebuffer> {
|
||||
public:
|
||||
explicit FramebufferAgent(Framebuffer *actor);
|
||||
~FramebufferAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const FramebufferInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
82
cocos/renderer/gfx-agent/InputAssemblerAgent.cpp
Normal file
82
cocos/renderer/gfx-agent/InputAssemblerAgent.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "BufferAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "InputAssemblerAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
InputAssemblerAgent::InputAssemblerAgent(InputAssembler *actor)
|
||||
: Agent<InputAssembler>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
InputAssemblerAgent::~InputAssemblerAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
InputAssemblerDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void InputAssemblerAgent::doInit(const InputAssemblerInfo &info) {
|
||||
InputAssemblerInfo actorInfo = info;
|
||||
for (auto &vertexBuffer : actorInfo.vertexBuffers) {
|
||||
vertexBuffer = static_cast<BufferAgent *>(vertexBuffer)->getActor();
|
||||
}
|
||||
if (actorInfo.indexBuffer) {
|
||||
actorInfo.indexBuffer = static_cast<BufferAgent *>(actorInfo.indexBuffer)->getActor();
|
||||
}
|
||||
if (actorInfo.indirectBuffer) {
|
||||
actorInfo.indirectBuffer = static_cast<BufferAgent *>(actorInfo.indirectBuffer)->getActor();
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
InputAssemblerInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void InputAssemblerAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
InputAssemblerDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/InputAssemblerAgent.h
Normal file
44
cocos/renderer/gfx-agent/InputAssemblerAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXInputAssembler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL InputAssemblerAgent final : public Agent<InputAssembler> {
|
||||
public:
|
||||
explicit InputAssemblerAgent(InputAssembler *actor);
|
||||
~InputAssemblerAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const InputAssemblerInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
77
cocos/renderer/gfx-agent/PipelineLayoutAgent.cpp
Normal file
77
cocos/renderer/gfx-agent/PipelineLayoutAgent.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DescriptorSetLayoutAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "PipelineLayoutAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
PipelineLayoutAgent::PipelineLayoutAgent(PipelineLayout *actor)
|
||||
: Agent<PipelineLayout>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
PipelineLayoutAgent::~PipelineLayoutAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
PipelineLayoutDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void PipelineLayoutAgent::doInit(const PipelineLayoutInfo &info) {
|
||||
PipelineLayoutInfo actorInfo;
|
||||
actorInfo.setLayouts.resize(info.setLayouts.size());
|
||||
for (uint32_t i = 0U; i < info.setLayouts.size(); i++) {
|
||||
actorInfo.setLayouts[i] = static_cast<DescriptorSetLayoutAgent *>(info.setLayouts[i])->getActor();
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
PipelineLayoutInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void PipelineLayoutAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
PipelineLayoutDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/PipelineLayoutAgent.h
Normal file
44
cocos/renderer/gfx-agent/PipelineLayoutAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXPipelineLayout.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL PipelineLayoutAgent final : public Agent<PipelineLayout> {
|
||||
public:
|
||||
explicit PipelineLayoutAgent(PipelineLayout *actor);
|
||||
~PipelineLayoutAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const PipelineLayoutInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
78
cocos/renderer/gfx-agent/PipelineStateAgent.cpp
Normal file
78
cocos/renderer/gfx-agent/PipelineStateAgent.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceAgent.h"
|
||||
#include "PipelineLayoutAgent.h"
|
||||
#include "PipelineStateAgent.h"
|
||||
#include "RenderPassAgent.h"
|
||||
#include "ShaderAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
PipelineStateAgent::PipelineStateAgent(PipelineState *actor)
|
||||
: Agent<PipelineState>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
PipelineStateAgent::~PipelineStateAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
PipelineStateDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void PipelineStateAgent::doInit(const PipelineStateInfo &info) {
|
||||
PipelineStateInfo actorInfo = info;
|
||||
actorInfo.shader = static_cast<ShaderAgent *>(info.shader)->getActor();
|
||||
actorInfo.pipelineLayout = static_cast<PipelineLayoutAgent *>(info.pipelineLayout)->getActor();
|
||||
if (info.renderPass) actorInfo.renderPass = static_cast<RenderPassAgent *>(info.renderPass)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
PipelineStateInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void PipelineStateAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
PipelineStateDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/PipelineStateAgent.h
Normal file
44
cocos/renderer/gfx-agent/PipelineStateAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXPipelineState.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL PipelineStateAgent final : public Agent<PipelineState> {
|
||||
public:
|
||||
explicit PipelineStateAgent(PipelineState *actor);
|
||||
~PipelineStateAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const PipelineStateInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
74
cocos/renderer/gfx-agent/QueryPoolAgent.cpp
Normal file
74
cocos/renderer/gfx-agent/QueryPoolAgent.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/job-system/JobSystem.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "CommandBufferAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "QueryPoolAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
QueryPoolAgent::QueryPoolAgent(QueryPool *actor)
|
||||
: Agent<QueryPool>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
_type = actor->getType();
|
||||
_maxQueryObjects = actor->getMaxQueryObjects();
|
||||
}
|
||||
|
||||
QueryPoolAgent::~QueryPoolAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueryDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void QueryPoolAgent::doInit(const QueryPoolInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueryInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void QueryPoolAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueryDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
46
cocos/renderer/gfx-agent/QueryPoolAgent.h
Normal file
46
cocos/renderer/gfx-agent/QueryPoolAgent.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXQueryPool.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL QueryPoolAgent final : public Agent<QueryPool> {
|
||||
public:
|
||||
explicit QueryPoolAgent(QueryPool *actor);
|
||||
~QueryPoolAgent() override;
|
||||
|
||||
protected:
|
||||
friend class DeviceAgent;
|
||||
|
||||
void doInit(const QueryPoolInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
103
cocos/renderer/gfx-agent/QueueAgent.cpp
Normal file
103
cocos/renderer/gfx-agent/QueueAgent.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/job-system/JobSystem.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "CommandBufferAgent.h"
|
||||
#include "DeviceAgent.h"
|
||||
#include "QueueAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
QueueAgent::QueueAgent(Queue *actor)
|
||||
: Agent<Queue>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
QueueAgent::~QueueAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueueDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void QueueAgent::doInit(const QueueInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueueInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void QueueAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueueDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
void QueueAgent::submit(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
if (!count) return;
|
||||
|
||||
MessageQueue *msgQ = DeviceAgent::getInstance()->getMessageQueue();
|
||||
auto **actorCmdBuffs = msgQ->allocate<CommandBuffer *>(count);
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
actorCmdBuffs[i] = static_cast<CommandBufferAgent *>(cmdBuffs[i])->getActor();
|
||||
}
|
||||
|
||||
ENQUEUE_MESSAGE_3(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
QueueSubmit,
|
||||
actor, getActor(),
|
||||
actorCmdBuffs, actorCmdBuffs,
|
||||
count, count,
|
||||
{
|
||||
//auto startTime = std::chrono::steady_clock::now();
|
||||
|
||||
//auto endTime = std::chrono::steady_clock::now();
|
||||
//float dt = std::chrono::duration_cast<std::chrono::nanoseconds>(endTime - startTime).count() / 1e6;
|
||||
//static float timeAcc = 0.f;
|
||||
//if (!timeAcc) timeAcc = dt;
|
||||
//else timeAcc = timeAcc * 0.95f + dt * 0.05f;
|
||||
//CC_LOG_INFO("---------- %.2fms", timeAcc);
|
||||
|
||||
//CC_LOG_INFO("======== one round ========");
|
||||
|
||||
actor->submit(actorCmdBuffs, count);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-agent/QueueAgent.h
Normal file
50
cocos/renderer/gfx-agent/QueueAgent.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXQueue.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL QueueAgent final : public Agent<Queue> {
|
||||
public:
|
||||
using Queue::submit;
|
||||
|
||||
explicit QueueAgent(Queue *actor);
|
||||
~QueueAgent() override;
|
||||
|
||||
void submit(CommandBuffer *const *cmdBuffs, uint32_t count) override;
|
||||
|
||||
protected:
|
||||
friend class DeviceAgent;
|
||||
|
||||
void doInit(const QueueInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
70
cocos/renderer/gfx-agent/RenderPassAgent.cpp
Normal file
70
cocos/renderer/gfx-agent/RenderPassAgent.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceAgent.h"
|
||||
#include "RenderPassAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
RenderPassAgent::RenderPassAgent(RenderPass *actor)
|
||||
: Agent<RenderPass>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
RenderPassAgent::~RenderPassAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
RenderPassDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void RenderPassAgent::doInit(const RenderPassInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
RenderPassInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void RenderPassAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
RenderPassDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/RenderPassAgent.h
Normal file
44
cocos/renderer/gfx-agent/RenderPassAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXRenderPass.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL RenderPassAgent final : public Agent<RenderPass> {
|
||||
public:
|
||||
explicit RenderPassAgent(RenderPass *actor);
|
||||
~RenderPassAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const RenderPassInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
70
cocos/renderer/gfx-agent/ShaderAgent.cpp
Normal file
70
cocos/renderer/gfx-agent/ShaderAgent.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceAgent.h"
|
||||
#include "ShaderAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
ShaderAgent::ShaderAgent(Shader *actor)
|
||||
: Agent<Shader>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
ShaderAgent::~ShaderAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
ShaderDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void ShaderAgent::doInit(const ShaderInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
ShaderInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void ShaderAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
ShaderDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
44
cocos/renderer/gfx-agent/ShaderAgent.h
Normal file
44
cocos/renderer/gfx-agent/ShaderAgent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXShader.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL ShaderAgent final : public Agent<Shader> {
|
||||
public:
|
||||
explicit ShaderAgent(Shader *actor);
|
||||
~ShaderAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const ShaderInfo &info) override;
|
||||
void doDestroy() override;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
151
cocos/renderer/gfx-agent/SwapchainAgent.cpp
Normal file
151
cocos/renderer/gfx-agent/SwapchainAgent.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceAgent.h"
|
||||
#include "SwapchainAgent.h"
|
||||
#include "gfx-agent/TextureAgent.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
SwapchainAgent::SwapchainAgent(Swapchain *actor)
|
||||
: Agent<Swapchain>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
_preRotationEnabled = static_cast<SwapchainAgent *>(actor)->_preRotationEnabled;
|
||||
}
|
||||
|
||||
SwapchainAgent::~SwapchainAgent() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), SwapchainDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
|
||||
void SwapchainAgent::doInit(const SwapchainInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), SwapchainInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
|
||||
DeviceAgent::getInstance()->getMessageQueue()->kickAndWait();
|
||||
|
||||
auto *colorTexture = ccnew TextureAgent(_actor->getColorTexture());
|
||||
colorTexture->renounceOwnership();
|
||||
_colorTexture = colorTexture;
|
||||
|
||||
auto *depthStencilTexture = ccnew TextureAgent(_actor->getDepthStencilTexture());
|
||||
depthStencilTexture->renounceOwnership();
|
||||
_depthStencilTexture = depthStencilTexture;
|
||||
|
||||
SwapchainTextureInfo textureInfo;
|
||||
textureInfo.swapchain = this;
|
||||
textureInfo.format = _actor->getColorTexture()->getFormat();
|
||||
textureInfo.width = _actor->getWidth();
|
||||
textureInfo.height = _actor->getHeight();
|
||||
initTexture(textureInfo, _colorTexture);
|
||||
|
||||
textureInfo.format = _actor->getDepthStencilTexture()->getFormat();
|
||||
initTexture(textureInfo, _depthStencilTexture);
|
||||
|
||||
_transform = _actor->getSurfaceTransform();
|
||||
}
|
||||
|
||||
void SwapchainAgent::doDestroy() {
|
||||
_depthStencilTexture = nullptr;
|
||||
_colorTexture = nullptr;
|
||||
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), SwapchainDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
void SwapchainAgent::doResize(uint32_t width, uint32_t height, SurfaceTransform transform) {
|
||||
auto *mq = DeviceAgent::getInstance()->getMessageQueue();
|
||||
|
||||
ENQUEUE_MESSAGE_4(
|
||||
mq, SwapchainResize,
|
||||
actor, getActor(),
|
||||
width, width,
|
||||
height, height,
|
||||
transform, transform,
|
||||
{
|
||||
actor->resize(width, height, transform);
|
||||
});
|
||||
|
||||
mq->kickAndWait();
|
||||
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
void SwapchainAgent::updateInfo() {
|
||||
_generation = _actor->getGeneration();
|
||||
SwapchainTextureInfo textureInfo;
|
||||
textureInfo.swapchain = this;
|
||||
textureInfo.format = _actor->getColorTexture()->getFormat();
|
||||
textureInfo.width = _actor->getWidth();
|
||||
textureInfo.height = _actor->getHeight();
|
||||
updateTextureInfo(textureInfo, _colorTexture);
|
||||
|
||||
textureInfo.format = _actor->getDepthStencilTexture()->getFormat();
|
||||
updateTextureInfo(textureInfo, _depthStencilTexture);
|
||||
|
||||
_transform = _actor->getSurfaceTransform();
|
||||
}
|
||||
|
||||
void SwapchainAgent::doDestroySurface() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), SwapchaindestroySurface,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroySurface();
|
||||
});
|
||||
|
||||
DeviceAgent::getInstance()->getMessageQueue()->kickAndWait();
|
||||
}
|
||||
|
||||
void SwapchainAgent::doCreateSurface(void *windowHandle) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(), SwapchaincreateSurface,
|
||||
actor, getActor(),
|
||||
windowHandle, windowHandle,
|
||||
{
|
||||
actor->createSurface(windowHandle);
|
||||
});
|
||||
DeviceAgent::getInstance()->getMessageQueue()->kickAndWait();
|
||||
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-agent/SwapchainAgent.h
Normal file
48
cocos/renderer/gfx-agent/SwapchainAgent.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXSwapchain.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL SwapchainAgent final : public Agent<Swapchain> {
|
||||
public:
|
||||
explicit SwapchainAgent(Swapchain *actor);
|
||||
~SwapchainAgent() override;
|
||||
|
||||
protected:
|
||||
void doInit(const SwapchainInfo &info) override;
|
||||
void doDestroy() override;
|
||||
void doResize(uint32_t width, uint32_t height, SurfaceTransform transform) override;
|
||||
void doDestroySurface() override;
|
||||
void doCreateSurface(void *windowHandle) override;
|
||||
void updateInfo();
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
104
cocos/renderer/gfx-agent/TextureAgent.cpp
Normal file
104
cocos/renderer/gfx-agent/TextureAgent.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceAgent.h"
|
||||
#include "TextureAgent.h"
|
||||
#include "gfx-agent/SwapchainAgent.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
TextureAgent::TextureAgent(Texture *actor)
|
||||
: Agent<Texture>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
TextureAgent::~TextureAgent() {
|
||||
if (_ownTheActor) {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
TextureDestruct,
|
||||
actor, _actor,
|
||||
{
|
||||
CC_SAFE_DELETE(actor);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TextureAgent::doInit(const TextureInfo &info) {
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
TextureInit,
|
||||
actor, getActor(),
|
||||
info, info,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void TextureAgent::doInit(const TextureViewInfo &info) {
|
||||
TextureViewInfo actorInfo = info;
|
||||
actorInfo.texture = static_cast<TextureAgent *>(info.texture)->getActor();
|
||||
|
||||
ENQUEUE_MESSAGE_2(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
TextureViewInit,
|
||||
actor, getActor(),
|
||||
info, actorInfo,
|
||||
{
|
||||
actor->initialize(info);
|
||||
});
|
||||
}
|
||||
|
||||
void TextureAgent::doInit(const SwapchainTextureInfo &info) {
|
||||
// the actor is already initialized
|
||||
}
|
||||
|
||||
void TextureAgent::doDestroy() {
|
||||
ENQUEUE_MESSAGE_1(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
TextureDestroy,
|
||||
actor, getActor(),
|
||||
{
|
||||
actor->destroy();
|
||||
});
|
||||
}
|
||||
|
||||
void TextureAgent::doResize(uint32_t width, uint32_t height, uint32_t /*size*/) {
|
||||
ENQUEUE_MESSAGE_3(
|
||||
DeviceAgent::getInstance()->getMessageQueue(),
|
||||
TextureResize,
|
||||
actor, getActor(),
|
||||
width, width,
|
||||
height, height,
|
||||
{
|
||||
actor->resize(width, height);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
57
cocos/renderer/gfx-agent/TextureAgent.h
Normal file
57
cocos/renderer/gfx-agent/TextureAgent.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Agent.h"
|
||||
#include "gfx-base/GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL TextureAgent : public Agent<Texture> {
|
||||
public:
|
||||
explicit TextureAgent(Texture *actor);
|
||||
~TextureAgent() override;
|
||||
|
||||
inline void renounceOwnership() { _ownTheActor = false; }
|
||||
|
||||
const Texture *getRaw() const override { return _actor->getRaw(); }
|
||||
|
||||
uint32_t getGLTextureHandle() const noexcept override { return _actor->getGLTextureHandle(); }
|
||||
|
||||
protected:
|
||||
friend class SwapchainAgent;
|
||||
|
||||
void doInit(const TextureInfo &info) override;
|
||||
void doInit(const TextureViewInfo &info) override;
|
||||
void doInit(const SwapchainTextureInfo &info) override;
|
||||
void doDestroy() override;
|
||||
void doResize(uint32_t width, uint32_t height, uint32_t size) override;
|
||||
|
||||
bool _ownTheActor = true;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
905
cocos/renderer/gfx-base/GFXBarrier.cpp
Normal file
905
cocos/renderer/gfx-base/GFXBarrier.cpp
Normal file
@@ -0,0 +1,905 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXBarrier.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace gfx {
|
||||
|
||||
namespace {
|
||||
|
||||
template <unsigned char... indices>
|
||||
constexpr uint64_t setbit() {
|
||||
return ((1ULL << indices) | ... | 0ULL);
|
||||
}
|
||||
|
||||
template <typename T, size_t... indices>
|
||||
constexpr uint64_t setbits(const std::integer_sequence<T, indices...>& intSeq) {
|
||||
std::ignore = intSeq;
|
||||
return setbit<indices...>();
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
constexpr uint64_t setbits() {
|
||||
using index_seq = std::make_index_sequence<N>;
|
||||
return setbits(index_seq{});
|
||||
}
|
||||
|
||||
template <unsigned char first, unsigned char end>
|
||||
constexpr uint64_t setbitBetween() {
|
||||
static_assert(first >= end);
|
||||
return setbits<first>() ^ setbits<end>();
|
||||
}
|
||||
|
||||
template <uint32_t N>
|
||||
constexpr uint8_t highestBitPosOffset() {
|
||||
if constexpr (N == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return highestBitPosOffset<(N >> 1)>() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
enum class ResourceType : uint32_t {
|
||||
UNKNOWN,
|
||||
BUFFER,
|
||||
TEXTURE,
|
||||
};
|
||||
|
||||
enum class CommonUsage : uint32_t {
|
||||
NONE = 0,
|
||||
COPY_SRC = 1 << 1,
|
||||
COPY_DST = 1 << 2,
|
||||
ROM = 1 << 3, // sampled or UNIFORM
|
||||
STORAGE = 1 << 4,
|
||||
IB_OR_CA = 1 << 5,
|
||||
VB_OR_DS = 1 << 6,
|
||||
INDIRECT_OR_INPUT = 1 << 7,
|
||||
SHADING_RATE = 1 << 8,
|
||||
|
||||
LAST_ONE = SHADING_RATE,
|
||||
};
|
||||
CC_ENUM_BITWISE_OPERATORS(CommonUsage);
|
||||
|
||||
constexpr CommonUsage textureUsageToCommonUsage(TextureUsage usage) {
|
||||
CommonUsage res{0};
|
||||
if (hasFlag(usage, TextureUsage::TRANSFER_SRC)) {
|
||||
res |= CommonUsage::COPY_SRC;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::TRANSFER_DST)) {
|
||||
res |= CommonUsage::COPY_DST;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::SAMPLED)) {
|
||||
res |= CommonUsage::ROM;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::STORAGE)) {
|
||||
res |= CommonUsage::STORAGE;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::COLOR_ATTACHMENT)) {
|
||||
res |= CommonUsage::IB_OR_CA;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::DEPTH_STENCIL_ATTACHMENT)) {
|
||||
res |= CommonUsage::VB_OR_DS;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::INPUT_ATTACHMENT)) {
|
||||
res |= CommonUsage::INDIRECT_OR_INPUT;
|
||||
}
|
||||
if (hasFlag(usage, TextureUsage::SHADING_RATE)) {
|
||||
res |= CommonUsage::SHADING_RATE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr CommonUsage bufferUsageToCommonUsage(BufferUsage usage) {
|
||||
CommonUsage res{0};
|
||||
if (hasFlag(usage, BufferUsage::NONE)) {
|
||||
res |= CommonUsage::NONE;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::TRANSFER_SRC)) {
|
||||
res |= CommonUsage::COPY_SRC;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::TRANSFER_DST)) {
|
||||
res |= CommonUsage::COPY_DST;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::UNIFORM)) {
|
||||
res |= CommonUsage::ROM;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::STORAGE)) {
|
||||
res |= CommonUsage::STORAGE;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::INDEX)) {
|
||||
res |= CommonUsage::IB_OR_CA;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::VERTEX)) {
|
||||
res |= CommonUsage::VB_OR_DS;
|
||||
}
|
||||
if (hasFlag(usage, BufferUsage::INDIRECT)) {
|
||||
res |= CommonUsage::INDIRECT_OR_INPUT;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct AccessElem {
|
||||
uint32_t mask{0xFFFFFFFF};
|
||||
uint32_t key{0xFFFFFFFF};
|
||||
AccessFlags access{AccessFlags::NONE};
|
||||
uint32_t mutex{0x0}; // optional mutually exclusive flag
|
||||
};
|
||||
|
||||
#define OPERABLE(val) static_cast<std::underlying_type<decltype(val)>::type>(val)
|
||||
|
||||
constexpr uint8_t COMMON_USAGE_COUNT = highestBitPosOffset<OPERABLE(CommonUsage::LAST_ONE)>();
|
||||
constexpr uint8_t SHADER_STAGE_RESERVE_COUNT = 6;
|
||||
constexpr uint8_t RESOURCE_TYPE_COUNT = 2;
|
||||
constexpr uint8_t MEM_TYPE_COUNT = 2;
|
||||
constexpr uint8_t ACCESS_TYPE_COUNT = 2;
|
||||
|
||||
constexpr auto CMN_NONE = OPERABLE(CommonUsage::NONE);
|
||||
constexpr auto CMN_COPY_SRC = OPERABLE(CommonUsage::COPY_SRC);
|
||||
constexpr auto CMN_COPY_DST = OPERABLE(CommonUsage::COPY_DST);
|
||||
constexpr auto CMN_ROM = OPERABLE(CommonUsage::ROM);
|
||||
constexpr auto CMN_STORAGE = OPERABLE(CommonUsage::STORAGE);
|
||||
constexpr auto CMN_IB_OR_CA = OPERABLE(CommonUsage::IB_OR_CA);
|
||||
constexpr auto CMN_VB_OR_DS = OPERABLE(CommonUsage::VB_OR_DS);
|
||||
constexpr auto CMN_INDIRECT_OR_INPUT = OPERABLE(CommonUsage::INDIRECT_OR_INPUT);
|
||||
constexpr auto CMN_SHADING_RATE = OPERABLE(CommonUsage::SHADING_RATE);
|
||||
|
||||
constexpr auto SHADER_STAGE_BIT_POPS = COMMON_USAGE_COUNT;
|
||||
constexpr auto SHADERSTAGE_NONE = 0;
|
||||
constexpr auto SHADERSTAGE_VERT = 1 << (0 + SHADER_STAGE_BIT_POPS);
|
||||
constexpr auto SHADERSTAGE_CTRL = 1 << (1 + SHADER_STAGE_BIT_POPS);
|
||||
constexpr auto SHADERSTAGE_EVAL = 1 << (2 + SHADER_STAGE_BIT_POPS);
|
||||
constexpr auto SHADERSTAGE_GEOM = 1 << (3 + SHADER_STAGE_BIT_POPS);
|
||||
constexpr auto SHADERSTAGE_FRAG = 1 << (4 + SHADER_STAGE_BIT_POPS);
|
||||
constexpr auto SHADERSTAGE_COMP = 1 << (5 + SHADER_STAGE_BIT_POPS);
|
||||
|
||||
constexpr auto RESOURCE_TYPE_BIT_POS = COMMON_USAGE_COUNT + SHADER_STAGE_RESERVE_COUNT;
|
||||
constexpr auto RES_TEXTURE = OPERABLE(ResourceType::TEXTURE) << RESOURCE_TYPE_BIT_POS;
|
||||
constexpr auto RES_BUFFER = OPERABLE(ResourceType::BUFFER) << RESOURCE_TYPE_BIT_POS;
|
||||
|
||||
constexpr auto MEM_TYPE_BIT_POS = COMMON_USAGE_COUNT + SHADER_STAGE_RESERVE_COUNT + RESOURCE_TYPE_COUNT;
|
||||
constexpr auto MEM_HOST = OPERABLE(MemoryUsage::HOST) << MEM_TYPE_BIT_POS;
|
||||
constexpr auto MEM_DEVICE = OPERABLE(MemoryUsage::DEVICE) << MEM_TYPE_BIT_POS;
|
||||
|
||||
constexpr auto ACCESS_TYPE_BIT_POS = COMMON_USAGE_COUNT + SHADER_STAGE_RESERVE_COUNT + RESOURCE_TYPE_COUNT + MEM_TYPE_COUNT;
|
||||
constexpr auto ACCESS_WRITE = OPERABLE(MemoryAccess::WRITE_ONLY) << ACCESS_TYPE_BIT_POS;
|
||||
constexpr auto ACCESS_READ = OPERABLE(MemoryAccess::READ_ONLY) << ACCESS_TYPE_BIT_POS;
|
||||
|
||||
constexpr uint8_t USED_BIT_COUNT = COMMON_USAGE_COUNT + SHADER_STAGE_RESERVE_COUNT + RESOURCE_TYPE_COUNT + MEM_TYPE_COUNT + ACCESS_TYPE_COUNT;
|
||||
// 20 and above :reserved
|
||||
// 18 ~ 19: MemoryAccess
|
||||
// 16 ~ 17: MemoryUsage
|
||||
// 14 ~ 15: ResourceType
|
||||
// 8 ~ 13: ShaderStageFlags
|
||||
// 0 ~ 7: CommonUsage
|
||||
|
||||
constexpr uint32_t CARE_NONE = 0x0;
|
||||
constexpr uint32_t CARE_CMNUSAGE = setbitBetween<SHADER_STAGE_BIT_POPS, 0>();
|
||||
constexpr uint32_t CARE_SHADERSTAGE = setbitBetween<RESOURCE_TYPE_BIT_POS, SHADER_STAGE_BIT_POPS>();
|
||||
constexpr uint32_t CARE_RESTYPE = setbitBetween<MEM_TYPE_BIT_POS, RESOURCE_TYPE_BIT_POS>();
|
||||
constexpr uint32_t CARE_MEMUSAGE = setbitBetween<ACCESS_TYPE_BIT_POS, MEM_TYPE_BIT_POS>();
|
||||
constexpr uint32_t CARE_MEMACCESS = setbitBetween<USED_BIT_COUNT, ACCESS_TYPE_BIT_POS>();
|
||||
|
||||
constexpr uint32_t IGNORE_NONE = 0xFFFFFFFF;
|
||||
constexpr uint32_t IGNORE_CMNUSAGE = ~CARE_CMNUSAGE;
|
||||
constexpr uint32_t IGNORE_SHADERSTAGE = ~CARE_SHADERSTAGE;
|
||||
constexpr uint32_t IGNORE_RESTYPE = ~CARE_RESTYPE;
|
||||
constexpr uint32_t IGNORE_MEMUSAGE = ~CARE_MEMUSAGE;
|
||||
constexpr uint32_t IGNORE_MEMACCESS = ~CARE_MEMACCESS;
|
||||
|
||||
constexpr AccessElem ACCESS_MAP[] = {
|
||||
{CARE_MEMACCESS,
|
||||
0x0,
|
||||
AccessFlags::NONE},
|
||||
|
||||
{CARE_MEMUSAGE,
|
||||
0x0,
|
||||
AccessFlags::NONE},
|
||||
|
||||
{CARE_RESTYPE | CARE_CMNUSAGE,
|
||||
RES_BUFFER | CMN_INDIRECT_OR_INPUT,
|
||||
AccessFlags::INDIRECT_BUFFER},
|
||||
|
||||
{CARE_RESTYPE | CARE_CMNUSAGE,
|
||||
RES_BUFFER | CMN_IB_OR_CA,
|
||||
AccessFlags::INDEX_BUFFER}, // buffer usage indicates what it is, so shader stage ignored.
|
||||
|
||||
{CARE_RESTYPE | CARE_CMNUSAGE,
|
||||
ACCESS_READ | RES_BUFFER | CMN_VB_OR_DS,
|
||||
AccessFlags::VERTEX_BUFFER}, // ditto
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_BUFFER | SHADERSTAGE_VERT | CMN_ROM,
|
||||
AccessFlags::VERTEX_SHADER_READ_UNIFORM_BUFFER},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_TEXTURE | SHADERSTAGE_VERT | CMN_ROM,
|
||||
AccessFlags::VERTEX_SHADER_READ_TEXTURE},
|
||||
|
||||
{IGNORE_MEMUSAGE & IGNORE_RESTYPE,
|
||||
ACCESS_READ | ACCESS_WRITE | SHADERSTAGE_VERT | CMN_STORAGE,
|
||||
AccessFlags::VERTEX_SHADER_READ_OTHER},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_BUFFER | SHADERSTAGE_FRAG | CMN_ROM,
|
||||
AccessFlags::FRAGMENT_SHADER_READ_UNIFORM_BUFFER},
|
||||
|
||||
{CARE_MEMACCESS | CARE_RESTYPE | CARE_SHADERSTAGE | CARE_CMNUSAGE,
|
||||
ACCESS_READ | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_ROM,
|
||||
AccessFlags::FRAGMENT_SHADER_READ_TEXTURE,
|
||||
CMN_VB_OR_DS},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_IB_OR_CA | CMN_INDIRECT_OR_INPUT,
|
||||
AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_VB_OR_DS | CMN_INDIRECT_OR_INPUT,
|
||||
AccessFlags::FRAGMENT_SHADER_READ_DEPTH_STENCIL_INPUT_ATTACHMENT},
|
||||
|
||||
{IGNORE_MEMUSAGE & IGNORE_RESTYPE,
|
||||
ACCESS_READ | ACCESS_WRITE | SHADERSTAGE_FRAG | CMN_STORAGE,
|
||||
AccessFlags::FRAGMENT_SHADER_READ_OTHER,
|
||||
CMN_SHADING_RATE},
|
||||
|
||||
//{IGNORE_MEMUSAGE,
|
||||
// ACCESS_READ | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_IB_OR_CA,
|
||||
// AccessFlags::COLOR_ATTACHMENT_READ},
|
||||
|
||||
{CARE_MEMACCESS | CARE_RESTYPE | CARE_CMNUSAGE | CARE_SHADERSTAGE,
|
||||
ACCESS_READ | RES_TEXTURE | CMN_VB_OR_DS | CMN_ROM,
|
||||
AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_BUFFER | SHADERSTAGE_COMP | CMN_ROM,
|
||||
AccessFlags::COMPUTE_SHADER_READ_UNIFORM_BUFFER},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_READ | RES_TEXTURE | SHADERSTAGE_COMP | CMN_ROM,
|
||||
AccessFlags::COMPUTE_SHADER_READ_TEXTURE,
|
||||
CMN_VB_OR_DS},
|
||||
|
||||
// shading rate has its own flag
|
||||
{CARE_MEMACCESS | CARE_SHADERSTAGE | CARE_CMNUSAGE,
|
||||
ACCESS_READ | ACCESS_WRITE | SHADERSTAGE_COMP | CMN_STORAGE,
|
||||
AccessFlags::COMPUTE_SHADER_READ_OTHER,
|
||||
CMN_ROM},
|
||||
|
||||
{CARE_MEMACCESS | CARE_CMNUSAGE,
|
||||
ACCESS_READ | CMN_COPY_SRC,
|
||||
AccessFlags::TRANSFER_READ},
|
||||
|
||||
{CARE_MEMACCESS | CARE_MEMUSAGE,
|
||||
ACCESS_READ | MEM_HOST,
|
||||
AccessFlags::HOST_READ},
|
||||
|
||||
{CARE_MEMACCESS | CARE_SHADERSTAGE | CARE_CMNUSAGE,
|
||||
ACCESS_READ | SHADERSTAGE_FRAG | CMN_SHADING_RATE,
|
||||
AccessFlags::SHADING_RATE},
|
||||
|
||||
//{CARE_CMNUSAGE | CARE_RESTYPE,
|
||||
// RES_TEXTURE | CMN_NONE,
|
||||
// AccessFlags::PRESENT},
|
||||
|
||||
{CARE_MEMACCESS | CARE_SHADERSTAGE | CARE_CMNUSAGE,
|
||||
ACCESS_WRITE | SHADERSTAGE_VERT | CMN_STORAGE,
|
||||
AccessFlags::VERTEX_SHADER_WRITE},
|
||||
|
||||
{CARE_MEMACCESS | CARE_SHADERSTAGE | CARE_CMNUSAGE,
|
||||
ACCESS_WRITE | SHADERSTAGE_FRAG | CMN_STORAGE,
|
||||
AccessFlags::FRAGMENT_SHADER_WRITE},
|
||||
|
||||
{IGNORE_MEMUSAGE,
|
||||
ACCESS_WRITE | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_IB_OR_CA,
|
||||
AccessFlags::COLOR_ATTACHMENT_WRITE},
|
||||
|
||||
{IGNORE_NONE,
|
||||
ACCESS_WRITE | MEM_DEVICE | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_VB_OR_DS,
|
||||
AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE},
|
||||
|
||||
{CARE_MEMACCESS | CARE_SHADERSTAGE | CARE_CMNUSAGE,
|
||||
ACCESS_WRITE | SHADERSTAGE_COMP | CMN_STORAGE,
|
||||
AccessFlags::COMPUTE_SHADER_WRITE},
|
||||
|
||||
{CARE_MEMACCESS | CARE_CMNUSAGE,
|
||||
ACCESS_WRITE | CMN_COPY_DST,
|
||||
AccessFlags::TRANSFER_WRITE},
|
||||
|
||||
{CARE_MEMACCESS | CARE_MEMUSAGE,
|
||||
ACCESS_WRITE | MEM_HOST,
|
||||
AccessFlags::HOST_WRITE},
|
||||
};
|
||||
|
||||
constexpr bool validateAccess(ResourceType type, CommonUsage usage, MemoryAccess access, ShaderStageFlags visibility) {
|
||||
bool res = true;
|
||||
if (type == ResourceType::BUFFER) {
|
||||
uint32_t conflicts[] = {
|
||||
hasFlag(usage, CommonUsage::ROM) && hasFlag(access, MemoryAccess::WRITE_ONLY), // uniform has write access.
|
||||
hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS) && !hasFlag(visibility, ShaderStageFlags::VERTEX), // color/ds/input not in fragment
|
||||
hasAllFlags(usage, CommonUsage::ROM | CommonUsage::STORAGE), // storage ^ sampled
|
||||
hasFlag(usage, CommonUsage::COPY_SRC) && hasAllFlags(MemoryAccess::READ_ONLY, access), // transfer src ==> read_only
|
||||
hasFlag(usage, CommonUsage::COPY_DST) && hasAllFlags(MemoryAccess::WRITE_ONLY, access), // transfer dst ==> write_only
|
||||
hasAllFlags(usage, CommonUsage::COPY_SRC | CommonUsage::COPY_DST), // both src and dst
|
||||
hasFlag(usage, CommonUsage::VB_OR_DS) && hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::INDIRECT_OR_INPUT),
|
||||
hasFlag(usage, CommonUsage::IB_OR_CA) && hasAnyFlags(usage, CommonUsage::VB_OR_DS | CommonUsage::INDIRECT_OR_INPUT),
|
||||
hasFlag(usage, CommonUsage::INDIRECT_OR_INPUT) && hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS),
|
||||
// exlusive
|
||||
};
|
||||
res = !(*std::max_element(std::begin(conflicts), std::end(conflicts)));
|
||||
} else if (type == ResourceType::TEXTURE) {
|
||||
uint32_t conflicts[] = {
|
||||
// hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS | CommonUsage::INDIRECT_OR_INPUT) && !hasFlag(visibility, ShaderStageFlags::FRAGMENT), // color/ds/input not in fragment
|
||||
hasFlag(usage, CommonUsage::INDIRECT_OR_INPUT) && !hasFlag(access, MemoryAccess::READ_ONLY), // input needs read
|
||||
hasAllFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::STORAGE), // storage ^ sampled
|
||||
hasFlag(usage, CommonUsage::COPY_SRC) && !hasAllFlags(MemoryAccess::READ_ONLY, access), // transfer src ==> read_only
|
||||
hasFlag(usage, CommonUsage::COPY_DST) && !hasAllFlags(MemoryAccess::WRITE_ONLY, access),
|
||||
hasFlag(usage, CommonUsage::INDIRECT_OR_INPUT) && !hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS), // input needs to specify color or ds // transfer dst ==> write_only
|
||||
hasAllFlags(usage, CommonUsage::COPY_SRC | CommonUsage::COPY_DST), // both src and dst
|
||||
};
|
||||
res = !(*std::max_element(std::begin(conflicts), std::end(conflicts)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr AccessFlags getAccessFlagsImpl(
|
||||
BufferUsage usage, MemoryUsage memUsage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) noexcept {
|
||||
AccessFlags flags{AccessFlags::NONE};
|
||||
CommonUsage cmnUsage = bufferUsageToCommonUsage(usage);
|
||||
if (validateAccess(ResourceType::BUFFER, cmnUsage, access, visibility)) {
|
||||
uint32_t info = 0xFFFFFFFF;
|
||||
info &= ((OPERABLE(access) << ACCESS_TYPE_BIT_POS) | IGNORE_MEMACCESS);
|
||||
info &= ((OPERABLE(memUsage) << MEM_TYPE_BIT_POS) | IGNORE_MEMUSAGE);
|
||||
info &= ((OPERABLE(ResourceType::TEXTURE) << RESOURCE_TYPE_BIT_POS) | IGNORE_RESTYPE);
|
||||
info &= ((OPERABLE(visibility) << SHADER_STAGE_BIT_POPS) | IGNORE_SHADERSTAGE);
|
||||
info &= OPERABLE(cmnUsage) | IGNORE_CMNUSAGE;
|
||||
|
||||
for (const auto& elem : ACCESS_MAP) {
|
||||
auto testFlag = info & elem.mask;
|
||||
// hasKey
|
||||
if ((testFlag & elem.key) == elem.key) {
|
||||
flags |= elem.access;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
flags = INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
constexpr AccessFlags getAccessFlagsImpl(
|
||||
TextureUsage usage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) noexcept {
|
||||
AccessFlags flags{AccessFlags::NONE};
|
||||
CommonUsage cmnUsage = textureUsageToCommonUsage(usage);
|
||||
if (validateAccess(ResourceType::TEXTURE, cmnUsage, access, visibility)) {
|
||||
if (usage == gfx::TextureUsageBit::NONE) {
|
||||
return gfx::AccessFlagBit::PRESENT;
|
||||
}
|
||||
uint32_t info = 0xFFFFFFFF;
|
||||
info &= ((OPERABLE(access) << ACCESS_TYPE_BIT_POS) | IGNORE_MEMACCESS);
|
||||
info &= ((OPERABLE(MemoryUsage::DEVICE) << MEM_TYPE_BIT_POS) | IGNORE_MEMUSAGE);
|
||||
info &= ((OPERABLE(ResourceType::TEXTURE) << RESOURCE_TYPE_BIT_POS) | IGNORE_RESTYPE);
|
||||
info &= ((OPERABLE(visibility) << (SHADER_STAGE_BIT_POPS)) | IGNORE_SHADERSTAGE);
|
||||
info &= OPERABLE(cmnUsage) | IGNORE_CMNUSAGE;
|
||||
|
||||
for (const auto& elem : ACCESS_MAP) {
|
||||
auto testFlag = info & elem.mask;
|
||||
// hasKey && no mutex flag
|
||||
if (((testFlag & elem.key) == elem.key) && ((testFlag & elem.mutex) == 0)) {
|
||||
flags |= elem.access;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
flags = INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
|
||||
// CC_ASSERT(flags != INVALID_ACCESS_FLAGS);
|
||||
return flags;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AccessFlags getAccessFlags(
|
||||
BufferUsage usage, MemoryUsage memUsage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) noexcept {
|
||||
return getAccessFlagsImpl(usage, memUsage, access, visibility);
|
||||
}
|
||||
|
||||
AccessFlags getAccessFlags(
|
||||
TextureUsage usage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) noexcept {
|
||||
return getAccessFlagsImpl(usage, access, visibility);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr AccessFlags getDeviceAccessFlagsImpl(
|
||||
TextureUsage usage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) {
|
||||
// Special Present Usage
|
||||
if (usage == TextureUsage::NONE) {
|
||||
return AccessFlags::PRESENT;
|
||||
}
|
||||
|
||||
// not read or write access
|
||||
if (access == MemoryAccess::NONE) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
|
||||
// input attachment requires color or depth stencil
|
||||
if (hasAnyFlags(usage, TextureUsage::INPUT_ATTACHMENT) &&
|
||||
!hasAnyFlags(usage, TextureUsage::COLOR_ATTACHMENT | TextureUsage::DEPTH_STENCIL_ATTACHMENT)) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
|
||||
const bool bWrite = hasAnyFlags(access, MemoryAccess::WRITE_ONLY);
|
||||
const bool bRead = hasAnyFlags(access, MemoryAccess::READ_ONLY);
|
||||
|
||||
if (bWrite) { // single write
|
||||
const auto writeMask =
|
||||
TextureUsage::TRANSFER_DST |
|
||||
TextureUsage::STORAGE |
|
||||
TextureUsage::COLOR_ATTACHMENT |
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT;
|
||||
|
||||
const auto usage1 = usage & writeMask;
|
||||
// see https://stackoverflow.com/questions/51094594/how-to-check-if-exactly-one-bit-is-set-in-an-int
|
||||
constexpr auto hasOnebit = [](uint32_t bits) -> bool {
|
||||
return bits && !(bits & (bits - 1));
|
||||
};
|
||||
if (!hasOnebit(static_cast<uint32_t>(usage1))) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
|
||||
const auto readMask =
|
||||
TextureUsage::SAMPLED |
|
||||
TextureUsage::TRANSFER_SRC;
|
||||
|
||||
if (hasAnyFlags(usage, readMask)) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
}
|
||||
|
||||
auto flags = AccessFlags::NONE;
|
||||
|
||||
if (hasAnyFlags(usage, TextureUsage::COLOR_ATTACHMENT)) {
|
||||
if (hasAnyFlags(visibility, ShaderStageFlags::ALL & ~ShaderStageFlags::FRAGMENT)) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
if (bWrite) {
|
||||
flags |= AccessFlags::COLOR_ATTACHMENT_WRITE;
|
||||
}
|
||||
if (bRead) {
|
||||
flags |= AccessFlags::COLOR_ATTACHMENT_READ;
|
||||
}
|
||||
if (hasAnyFlags(usage, TextureUsage::INPUT_ATTACHMENT)) {
|
||||
if (!bRead) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
flags |= AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT;
|
||||
}
|
||||
if (bWrite) {
|
||||
return flags;
|
||||
}
|
||||
} else if (hasAnyFlags(usage, TextureUsage::DEPTH_STENCIL_ATTACHMENT)) {
|
||||
if (hasAnyFlags(visibility, ShaderStageFlags::ALL & ~ShaderStageFlags::FRAGMENT)) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
if (bWrite) {
|
||||
flags |= AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE;
|
||||
}
|
||||
if (bRead) {
|
||||
flags |= AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ;
|
||||
}
|
||||
if (hasAnyFlags(usage, TextureUsage::INPUT_ATTACHMENT)) {
|
||||
if (!bRead) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
flags |= AccessFlags::FRAGMENT_SHADER_READ_DEPTH_STENCIL_INPUT_ATTACHMENT;
|
||||
}
|
||||
if (bWrite) {
|
||||
return flags;
|
||||
}
|
||||
} else if (bWrite) {
|
||||
if (hasAnyFlags(usage, TextureUsage::SAMPLED)) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
const bool bUnorderedAccess = hasAnyFlags(usage, TextureUsage::STORAGE);
|
||||
const bool bCopyTarget = hasAnyFlags(usage, TextureUsage::TRANSFER_DST);
|
||||
if (!(bUnorderedAccess ^ bCopyTarget)) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
if (bCopyTarget) {
|
||||
if (bRead || hasAnyFlags(usage, TextureUsage::TRANSFER_SRC)) {
|
||||
return INVALID_ACCESS_FLAGS; // both copy source and target
|
||||
}
|
||||
flags |= AccessFlags::TRANSFER_WRITE;
|
||||
} else {
|
||||
if (hasAnyFlags(visibility, ShaderStageFlags::VERTEX)) {
|
||||
flags |= AccessFlags::VERTEX_SHADER_WRITE;
|
||||
if (bRead) {
|
||||
flags |= AccessFlags::VERTEX_SHADER_READ_TEXTURE;
|
||||
}
|
||||
} else if (hasAnyFlags(visibility, ShaderStageFlags::FRAGMENT)) {
|
||||
flags |= AccessFlags::FRAGMENT_SHADER_WRITE;
|
||||
if (bRead) {
|
||||
flags |= AccessFlags::FRAGMENT_SHADER_READ_TEXTURE;
|
||||
}
|
||||
} else if (hasAnyFlags(visibility, ShaderStageFlags::COMPUTE)) {
|
||||
flags |= AccessFlags::COMPUTE_SHADER_WRITE;
|
||||
if (bRead) {
|
||||
flags |= AccessFlags::COMPUTE_SHADER_READ_TEXTURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
if (bWrite) {
|
||||
return INVALID_ACCESS_FLAGS;
|
||||
}
|
||||
|
||||
// ReadOnly
|
||||
if (hasAnyFlags(usage, TextureUsage::TRANSFER_SRC)) {
|
||||
flags |= AccessFlags::TRANSFER_READ;
|
||||
}
|
||||
|
||||
if (hasAnyFlags(usage, TextureUsage::SAMPLED | TextureUsage::STORAGE)) {
|
||||
if (hasAnyFlags(visibility, ShaderStageFlags::VERTEX)) {
|
||||
flags |= AccessFlags::VERTEX_SHADER_READ_TEXTURE;
|
||||
}
|
||||
if (hasAnyFlags(visibility, ShaderStageFlags::FRAGMENT)) {
|
||||
flags |= AccessFlags::FRAGMENT_SHADER_READ_TEXTURE;
|
||||
}
|
||||
if (hasAnyFlags(visibility, ShaderStageFlags::COMPUTE)) {
|
||||
flags |= AccessFlags::COMPUTE_SHADER_READ_TEXTURE;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::VERTEX_SHADER_WRITE | AccessFlags::VERTEX_SHADER_READ_OTHER) ==
|
||||
getAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::VERTEX));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::FRAGMENT_SHADER_WRITE | AccessFlags::FRAGMENT_SHADER_READ_OTHER) ==
|
||||
getAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COMPUTE_SHADER_WRITE | AccessFlags::COMPUTE_SHADER_READ_OTHER) ==
|
||||
getAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::COMPUTE));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT | TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT | TextureUsage::SAMPLED | TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::TRANSFER_WRITE | AccessFlags::COLOR_ATTACHMENT_WRITE) ==
|
||||
getAccessFlagsImpl(
|
||||
TextureUsage::TRANSFER_DST | TextureUsage::COLOR_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::ALL));
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
// VERTEX_SHADER_WRITE
|
||||
static_assert(
|
||||
AccessFlags::VERTEX_SHADER_WRITE ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::VERTEX));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::VERTEX_SHADER_WRITE | AccessFlags::VERTEX_SHADER_READ_TEXTURE) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::VERTEX));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE | TextureUsage::SAMPLED, // both storage write and sampling
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::VERTEX));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::SAMPLED, // Sampled cannot be write
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::VERTEX));
|
||||
|
||||
// FRAGMENT_SHADER_WRITE
|
||||
static_assert(
|
||||
AccessFlags::FRAGMENT_SHADER_WRITE ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::FRAGMENT_SHADER_WRITE | AccessFlags::FRAGMENT_SHADER_READ_TEXTURE) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
// COLOR_ATTACHMENT_WRITE
|
||||
static_assert(
|
||||
AccessFlags::COLOR_ATTACHMENT_WRITE ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::VERTEX)); // not fragment stage
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::SAMPLED, // both color attachment and sampled texture
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_WRITE | AccessFlags::COLOR_ATTACHMENT_READ) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
AccessFlags::COLOR_ATTACHMENT_READ ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_WRITE | AccessFlags::COLOR_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY, // INPUT_ATTACHMENT needs read access
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
// DEPTH_STENCIL_ATTACHMENT_WRITE
|
||||
static_assert(
|
||||
AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::VERTEX)); // not fragment stage
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT | TextureUsage::SAMPLED, // both color attachment and sampled texture
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_DEPTH_STENCIL_INPUT_ATTACHMENT) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_DEPTH_STENCIL_INPUT_ATTACHMENT) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::DEPTH_STENCIL_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT,
|
||||
MemoryAccess::WRITE_ONLY, // INPUT_ATTACHMENT needs read access
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
// COMPUTE_SHADER_WRITE
|
||||
static_assert(
|
||||
AccessFlags::COMPUTE_SHADER_WRITE ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::COMPUTE));
|
||||
static_assert(
|
||||
(AccessFlags::COMPUTE_SHADER_WRITE | AccessFlags::COMPUTE_SHADER_READ_TEXTURE) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::COMPUTE));
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE | TextureUsage::SAMPLED, // cannot be sampled
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::COMPUTE));
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::STORAGE | TextureUsage::SAMPLED, // cannot be sampled
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::COMPUTE));
|
||||
|
||||
// TRANSFER_WRITE
|
||||
static_assert(
|
||||
AccessFlags::TRANSFER_WRITE ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::TRANSFER_DST,
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::ALL)); // ShaderStageFlags not used
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::TRANSFER_DST,
|
||||
MemoryAccess::READ_WRITE,
|
||||
ShaderStageFlags::ALL)); // ShaderStageFlags not used
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::TRANSFER_DST | TextureUsage::TRANSFER_SRC, // both source and target
|
||||
MemoryAccess::READ_WRITE, // both read and write
|
||||
ShaderStageFlags::ALL));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::TRANSFER_DST | TextureUsage::TRANSFER_SRC, // both source and target
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::ALL));
|
||||
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::TRANSFER_DST | TextureUsage::COLOR_ATTACHMENT, // cannot be sampled
|
||||
MemoryAccess::WRITE_ONLY,
|
||||
ShaderStageFlags::ALL));
|
||||
|
||||
// Read
|
||||
// COLOR_ATTACHMENT_READ
|
||||
static_assert(
|
||||
INVALID_ACCESS_FLAGS ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::INPUT_ATTACHMENT, // INPUT_ATTACHMENT needs COLOR_ATTACHMENT or DEPTH_STENCIL_ATTACHMENT
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT | AccessFlags::FRAGMENT_SHADER_READ_TEXTURE) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT | TextureUsage::SAMPLED,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT | AccessFlags::FRAGMENT_SHADER_READ_TEXTURE) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT | TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT | AccessFlags::FRAGMENT_SHADER_READ_TEXTURE) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT | TextureUsage::SAMPLED | TextureUsage::STORAGE,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
static_assert(
|
||||
(AccessFlags::COLOR_ATTACHMENT_READ | AccessFlags::FRAGMENT_SHADER_READ_COLOR_INPUT_ATTACHMENT | AccessFlags::TRANSFER_READ) ==
|
||||
getDeviceAccessFlagsImpl(
|
||||
TextureUsage::COLOR_ATTACHMENT | TextureUsage::INPUT_ATTACHMENT | TextureUsage::TRANSFER_SRC,
|
||||
MemoryAccess::READ_ONLY,
|
||||
ShaderStageFlags::FRAGMENT));
|
||||
|
||||
} // namespace
|
||||
|
||||
AccessFlags getDeviceAccessFlags(
|
||||
TextureUsage usage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) {
|
||||
return getDeviceAccessFlagsImpl(usage, access, visibility);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
} // namespace cc
|
||||
51
cocos/renderer/gfx-base/GFXBarrier.h
Normal file
51
cocos/renderer/gfx-base/GFXBarrier.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "GFXDef-common.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace gfx {
|
||||
|
||||
AccessFlags getAccessFlags(
|
||||
BufferUsage usage, MemoryUsage memUsage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) noexcept;
|
||||
|
||||
AccessFlags getAccessFlags(
|
||||
TextureUsage usage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility) noexcept;
|
||||
|
||||
constexpr AccessFlags INVALID_ACCESS_FLAGS = static_cast<AccessFlags>(0xFFFFFFFF);
|
||||
|
||||
AccessFlags getDeviceAccessFlags(
|
||||
TextureUsage usage,
|
||||
MemoryAccess access,
|
||||
ShaderStageFlags visibility);
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
} // namespace cc
|
||||
106
cocos/renderer/gfx-base/GFXBuffer.cpp
Normal file
106
cocos/renderer/gfx-base/GFXBuffer.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXBuffer.h"
|
||||
#include "GFXDevice.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
Buffer::Buffer()
|
||||
: GFXObject(ObjectType::BUFFER) {
|
||||
}
|
||||
|
||||
Buffer::~Buffer() = default;
|
||||
|
||||
ccstd::hash_t Buffer::computeHash(const BufferInfo &info) {
|
||||
return Hasher<BufferInfo>()(info);
|
||||
}
|
||||
|
||||
void Buffer::initialize(const BufferInfo &info) {
|
||||
_usage = info.usage;
|
||||
_memUsage = info.memUsage;
|
||||
_size = info.size;
|
||||
_flags = info.flags;
|
||||
_stride = std::max(info.stride, 1U);
|
||||
_count = _size / _stride;
|
||||
|
||||
doInit(info);
|
||||
|
||||
if (hasFlag(info.flags, BufferFlagBit::ENABLE_STAGING_WRITE) && getStagingAddress() == nullptr) {
|
||||
_data = std::make_unique<uint8_t[]>(_size);
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::initialize(const BufferViewInfo &info) {
|
||||
_usage = info.buffer->getUsage();
|
||||
_memUsage = info.buffer->getMemUsage();
|
||||
_flags = info.buffer->getFlags();
|
||||
_offset = info.offset;
|
||||
_size = _stride = info.range;
|
||||
_count = 1U;
|
||||
_isBufferView = true;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void Buffer::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_offset = _size = _stride = _count = 0U;
|
||||
}
|
||||
|
||||
void Buffer::resize(uint32_t size) {
|
||||
if (size != _size) {
|
||||
uint32_t count = size / _stride;
|
||||
doResize(size, count);
|
||||
|
||||
_size = size;
|
||||
_count = count;
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::write(const uint8_t *value, uint32_t offset, uint32_t size) const {
|
||||
CC_ASSERT(hasFlag(_flags, BufferFlagBit::ENABLE_STAGING_WRITE));
|
||||
uint8_t *dst = getStagingAddress();
|
||||
if (dst == nullptr || offset + size > _size) {
|
||||
return;
|
||||
}
|
||||
memcpy(dst + offset, value, size);
|
||||
}
|
||||
|
||||
void Buffer::update() {
|
||||
flush(getStagingAddress());
|
||||
}
|
||||
|
||||
uint8_t *Buffer::getBufferStagingAddress(Buffer *buffer) {
|
||||
return buffer->getStagingAddress();
|
||||
}
|
||||
|
||||
void Buffer::flushBuffer(Buffer *buffer, const uint8_t *data) {
|
||||
buffer->flush(data);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
91
cocos/renderer/gfx-base/GFXBuffer.h
Normal file
91
cocos/renderer/gfx-base/GFXBuffer.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL Buffer : public GFXObject, public RefCounted {
|
||||
public:
|
||||
Buffer();
|
||||
~Buffer() override;
|
||||
|
||||
static ccstd::hash_t computeHash(const BufferInfo &info);
|
||||
|
||||
void initialize(const BufferInfo &info);
|
||||
void initialize(const BufferViewInfo &info);
|
||||
void resize(uint32_t size);
|
||||
void destroy();
|
||||
|
||||
template <typename T>
|
||||
void write(const T &value, uint32_t offset) const {
|
||||
write(reinterpret_cast<const uint8_t *>(&value), offset, sizeof(T));
|
||||
}
|
||||
|
||||
void write(const uint8_t *value, uint32_t offset, uint32_t size) const;
|
||||
|
||||
virtual void update(const void *buffer, uint32_t size) = 0;
|
||||
|
||||
inline void update(const void *buffer) { update(buffer, _size); }
|
||||
|
||||
void update();
|
||||
|
||||
inline BufferUsage getUsage() const { return _usage; }
|
||||
inline MemoryUsage getMemUsage() const { return _memUsage; }
|
||||
inline uint32_t getStride() const { return _stride; }
|
||||
inline uint32_t getCount() const { return _count; }
|
||||
inline uint32_t getSize() const { return _size; }
|
||||
inline BufferFlags getFlags() const { return _flags; }
|
||||
inline bool isBufferView() const { return _isBufferView; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const BufferInfo &info) = 0;
|
||||
virtual void doInit(const BufferViewInfo &info) = 0;
|
||||
virtual void doResize(uint32_t size, uint32_t count) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
static uint8_t *getBufferStagingAddress(Buffer *buffer);
|
||||
static void flushBuffer(Buffer *buffer, const uint8_t *data);
|
||||
|
||||
virtual void flush(const uint8_t *data) { update(reinterpret_cast<const void *>(data), _size); }
|
||||
virtual uint8_t *getStagingAddress() const { return _data.get(); }
|
||||
|
||||
BufferUsage _usage = BufferUsageBit::NONE;
|
||||
MemoryUsage _memUsage = MemoryUsageBit::NONE;
|
||||
uint32_t _stride = 0U;
|
||||
uint32_t _count = 0U;
|
||||
uint32_t _size = 0U;
|
||||
uint32_t _offset = 0U;
|
||||
BufferFlags _flags = BufferFlagBit::NONE;
|
||||
bool _isBufferView = false;
|
||||
uint8_t _rsv[3] = {0};
|
||||
std::unique_ptr<uint8_t[]> _data;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
52
cocos/renderer/gfx-base/GFXCommandBuffer.cpp
Normal file
52
cocos/renderer/gfx-base/GFXCommandBuffer.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXCommandBuffer.h"
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
CommandBuffer::CommandBuffer()
|
||||
: GFXObject(ObjectType::COMMAND_BUFFER) {
|
||||
}
|
||||
|
||||
CommandBuffer::~CommandBuffer() = default;
|
||||
|
||||
void CommandBuffer::initialize(const CommandBufferInfo &info) {
|
||||
_type = info.type;
|
||||
_queue = info.queue;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void CommandBuffer::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_type = CommandBufferType::PRIMARY;
|
||||
_queue = nullptr;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
194
cocos/renderer/gfx-base/GFXCommandBuffer.h
Normal file
194
cocos/renderer/gfx-base/GFXCommandBuffer.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXBuffer.h"
|
||||
#include "GFXInputAssembler.h"
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/Utils.h"
|
||||
#include "base/std/container/vector.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL CommandBuffer : public GFXObject, public RefCounted {
|
||||
public:
|
||||
CommandBuffer();
|
||||
~CommandBuffer() override;
|
||||
|
||||
void initialize(const CommandBufferInfo &info);
|
||||
void destroy();
|
||||
|
||||
virtual void begin(RenderPass *renderPass, uint32_t subpass, Framebuffer *frameBuffer) = 0;
|
||||
virtual void end() = 0;
|
||||
virtual void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) = 0;
|
||||
virtual void endRenderPass() = 0;
|
||||
virtual void insertMarker(const MarkerInfo &marker) = 0;
|
||||
virtual void beginMarker(const MarkerInfo &marker) = 0;
|
||||
virtual void endMarker() = 0;
|
||||
virtual void bindPipelineState(PipelineState *pso) = 0;
|
||||
virtual void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) = 0;
|
||||
virtual void bindInputAssembler(InputAssembler *ia) = 0;
|
||||
virtual void setViewport(const Viewport &vp) = 0;
|
||||
virtual void setScissor(const Rect &rect) = 0;
|
||||
virtual void setLineWidth(float width) = 0;
|
||||
virtual void setDepthBias(float constant, float clamp, float slope) = 0;
|
||||
virtual void setBlendConstants(const Color &constants) = 0;
|
||||
virtual void setDepthBound(float minBounds, float maxBounds) = 0;
|
||||
virtual void setStencilWriteMask(StencilFace face, uint32_t mask) = 0;
|
||||
virtual void setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) = 0;
|
||||
virtual void nextSubpass() = 0;
|
||||
virtual void draw(const DrawInfo &info) = 0;
|
||||
virtual void updateBuffer(Buffer *buff, const void *data, uint32_t size) = 0;
|
||||
virtual void copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) = 0;
|
||||
virtual void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) = 0;
|
||||
virtual void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) = 0;
|
||||
virtual void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) = 0;
|
||||
virtual void execute(CommandBuffer *const *cmdBuffs, uint32_t count) = 0;
|
||||
virtual void dispatch(const DispatchInfo &info) = 0;
|
||||
virtual void beginQuery(QueryPool *queryPool, uint32_t id) = 0;
|
||||
virtual void endQuery(QueryPool *queryPool, uint32_t id) = 0;
|
||||
virtual void resetQueryPool(QueryPool *queryPool) = 0;
|
||||
virtual void completeQueryPool(QueryPool *queryPool) {}
|
||||
|
||||
using CustomCommand = std::function<void(void *)>;
|
||||
virtual void customCommand(CustomCommand &&cmd) {}
|
||||
|
||||
// barrier: excutionBarrier
|
||||
// bufferBarriers: array of BufferBarrier*, descriptions of access of buffers
|
||||
// buffers: array of MTL/VK/GLES buffers
|
||||
// bufferBarrierCount: number of barrier, should be equal to number of buffers
|
||||
// textureBarriers: array of TextureBarrier*, descriptions of access of textures
|
||||
// textures: array of MTL/VK/GLES textures
|
||||
// textureBarrierCount: number of barrier, should be equal to number of textures
|
||||
virtual void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) = 0;
|
||||
|
||||
inline void begin();
|
||||
inline void begin(RenderPass *renderPass);
|
||||
inline void begin(RenderPass *renderPass, uint32_t subpass);
|
||||
|
||||
inline void updateBuffer(Buffer *buff, const void *data);
|
||||
|
||||
inline void execute(const CommandBufferList &cmdBuffs, uint32_t count);
|
||||
|
||||
inline void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet);
|
||||
inline void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, const ccstd::vector<uint32_t> &dynamicOffsets);
|
||||
|
||||
inline void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const ColorList &colors, float depth, uint32_t stencil, const CommandBufferList &secondaryCBs);
|
||||
inline void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const ColorList &colors, float depth, uint32_t stencil);
|
||||
inline void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil);
|
||||
|
||||
inline void draw(InputAssembler *ia);
|
||||
inline void copyBuffersToTexture(const BufferDataList &buffers, Texture *texture, const BufferTextureCopyList ®ions);
|
||||
|
||||
inline void blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlitList ®ions, Filter filter);
|
||||
|
||||
inline void pipelineBarrier(const GeneralBarrier *barrier);
|
||||
inline void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrierList &bufferBarriers, const BufferList &buffers, const TextureBarrierList &textureBarriers, const TextureList &textures);
|
||||
|
||||
inline Queue *getQueue() const { return _queue; }
|
||||
inline CommandBufferType getType() const { return _type; }
|
||||
|
||||
virtual uint32_t getNumDrawCalls() const { return _numDrawCalls; }
|
||||
virtual uint32_t getNumInstances() const { return _numInstances; }
|
||||
virtual uint32_t getNumTris() const { return _numTriangles; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const CommandBufferInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
Queue *_queue = nullptr;
|
||||
CommandBufferType _type = CommandBufferType::PRIMARY;
|
||||
|
||||
uint32_t _numDrawCalls = 0;
|
||||
uint32_t _numInstances = 0;
|
||||
uint32_t _numTriangles = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CommandBuffer::begin() {
|
||||
begin(nullptr, 0, nullptr);
|
||||
}
|
||||
|
||||
void CommandBuffer::begin(RenderPass *renderPass) {
|
||||
begin(renderPass, 0, nullptr);
|
||||
}
|
||||
|
||||
void CommandBuffer::begin(RenderPass *renderPass, uint32_t subpass) {
|
||||
begin(renderPass, subpass, nullptr);
|
||||
}
|
||||
|
||||
void CommandBuffer::updateBuffer(Buffer *buff, const void *data) {
|
||||
updateBuffer(buff, data, buff->getSize());
|
||||
}
|
||||
|
||||
void CommandBuffer::execute(const CommandBufferList &cmdBuffs, uint32_t count) {
|
||||
execute(cmdBuffs.data(), count);
|
||||
}
|
||||
|
||||
void CommandBuffer::bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet) {
|
||||
bindDescriptorSet(set, descriptorSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void CommandBuffer::bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, const ccstd::vector<uint32_t> &dynamicOffsets) {
|
||||
bindDescriptorSet(set, descriptorSet, utils::toUint(dynamicOffsets.size()), dynamicOffsets.data());
|
||||
}
|
||||
|
||||
void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const ColorList &colors, float depth, uint32_t stencil, const CommandBufferList &secondaryCBs) {
|
||||
beginRenderPass(renderPass, fbo, renderArea, colors.data(), depth, stencil, secondaryCBs.data(), utils::toUint(secondaryCBs.size()));
|
||||
}
|
||||
|
||||
void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const ColorList &colors, float depth, uint32_t stencil) {
|
||||
beginRenderPass(renderPass, fbo, renderArea, colors.data(), depth, stencil, nullptr, 0);
|
||||
}
|
||||
|
||||
void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil) {
|
||||
beginRenderPass(renderPass, fbo, renderArea, colors, depth, stencil, nullptr, 0);
|
||||
}
|
||||
|
||||
void CommandBuffer::draw(InputAssembler *ia) {
|
||||
draw(ia->getDrawInfo());
|
||||
}
|
||||
|
||||
void CommandBuffer::copyBuffersToTexture(const BufferDataList &buffers, Texture *texture, const BufferTextureCopyList ®ions) {
|
||||
copyBuffersToTexture(buffers.data(), texture, regions.data(), utils::toUint(regions.size()));
|
||||
}
|
||||
|
||||
void CommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlitList ®ions, Filter filter) {
|
||||
blitTexture(srcTexture, dstTexture, regions.data(), utils::toUint(regions.size()), filter);
|
||||
}
|
||||
|
||||
void CommandBuffer::pipelineBarrier(const GeneralBarrier *barrier) {
|
||||
pipelineBarrier(barrier, nullptr, nullptr, 0, nullptr, nullptr, 0U);
|
||||
}
|
||||
|
||||
void CommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrierList &bufferBarriers, const BufferList &buffers, const TextureBarrierList &textureBarriers, const TextureList &textures) {
|
||||
pipelineBarrier(barrier, bufferBarriers.data(), buffers.data(), utils::toUint(bufferBarriers.size()), textureBarriers.data(), textures.data(), utils::toUint(textureBarriers.size()));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
1629
cocos/renderer/gfx-base/GFXDef-common.h
Normal file
1629
cocos/renderer/gfx-base/GFXDef-common.h
Normal file
File diff suppressed because it is too large
Load Diff
664
cocos/renderer/gfx-base/GFXDef.cpp
Normal file
664
cocos/renderer/gfx-base/GFXDef.cpp
Normal file
@@ -0,0 +1,664 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/Utils.h"
|
||||
#include "base/std/container/array.h"
|
||||
#include "base/std/hash/hash.h"
|
||||
|
||||
#include "GFXDef.h"
|
||||
#include "GFXRenderPass.h"
|
||||
#include "GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
// T must have no implicit padding
|
||||
template <typename T>
|
||||
ccstd::hash_t quickHashTrivialStruct(const T *info, size_t count = 1) {
|
||||
static_assert(std::is_trivially_copyable<T>::value && sizeof(T) % 8 == 0, "T must be 8 bytes aligned and trivially copyable");
|
||||
return ccstd::hash_range(reinterpret_cast<const uint64_t *>(info), reinterpret_cast<const uint64_t *>(info + count));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<ColorAttachment>::operator()(const ColorAttachment &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const ColorAttachment &lhs, const ColorAttachment &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(ColorAttachment));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<DepthStencilAttachment>::operator()(const DepthStencilAttachment &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const DepthStencilAttachment &lhs, const DepthStencilAttachment &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(DepthStencilAttachment));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<SubpassDependency>::operator()(const SubpassDependency &info) const {
|
||||
ccstd::hash_t seed = 8;
|
||||
ccstd::hash_combine(seed, info.dstSubpass);
|
||||
ccstd::hash_combine(seed, info.srcSubpass);
|
||||
ccstd::hash_combine(seed, info.generalBarrier);
|
||||
ccstd::hash_combine(seed, info.prevAccesses);
|
||||
ccstd::hash_combine(seed, info.nextAccesses);
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool operator==(const SubpassDependency &lhs, const SubpassDependency &rhs) {
|
||||
return lhs.srcSubpass == rhs.srcSubpass &&
|
||||
lhs.dstSubpass == rhs.dstSubpass &&
|
||||
lhs.generalBarrier == rhs.generalBarrier &&
|
||||
lhs.prevAccesses == rhs.prevAccesses &&
|
||||
lhs.nextAccesses == rhs.nextAccesses;
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<SubpassInfo>::operator()(const SubpassInfo &info) const {
|
||||
ccstd::hash_t seed = 8;
|
||||
ccstd::hash_combine(seed, info.inputs);
|
||||
ccstd::hash_combine(seed, info.colors);
|
||||
ccstd::hash_combine(seed, info.resolves);
|
||||
ccstd::hash_combine(seed, info.preserves);
|
||||
ccstd::hash_combine(seed, info.depthStencil);
|
||||
ccstd::hash_combine(seed, info.depthStencilResolve);
|
||||
ccstd::hash_combine(seed, info.depthResolveMode);
|
||||
ccstd::hash_combine(seed, info.stencilResolveMode);
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool operator==(const SubpassInfo &lhs, const SubpassInfo &rhs) {
|
||||
return lhs.inputs == rhs.inputs &&
|
||||
lhs.colors == rhs.colors &&
|
||||
lhs.resolves == rhs.resolves &&
|
||||
lhs.preserves == rhs.preserves &&
|
||||
lhs.depthStencil == rhs.depthStencil &&
|
||||
lhs.depthStencilResolve == rhs.depthStencilResolve &&
|
||||
lhs.depthResolveMode == rhs.depthResolveMode &&
|
||||
lhs.stencilResolveMode == rhs.stencilResolveMode;
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<RenderPassInfo>::operator()(const RenderPassInfo &info) const {
|
||||
ccstd::hash_t seed = 4;
|
||||
ccstd::hash_combine(seed, info.colorAttachments);
|
||||
ccstd::hash_combine(seed, info.depthStencilAttachment);
|
||||
ccstd::hash_combine(seed, info.depthStencilResolveAttachment);
|
||||
ccstd::hash_combine(seed, info.subpasses);
|
||||
ccstd::hash_combine(seed, info.dependencies);
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool operator==(const RenderPassInfo &lhs, const RenderPassInfo &rhs) {
|
||||
return lhs.colorAttachments == rhs.colorAttachments &&
|
||||
lhs.depthStencilAttachment == rhs.depthStencilAttachment &&
|
||||
lhs.depthStencilResolveAttachment == rhs.depthStencilResolveAttachment &&
|
||||
lhs.subpasses == rhs.subpasses &&
|
||||
lhs.dependencies == rhs.dependencies;
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<FramebufferInfo>::operator()(const FramebufferInfo &info) const {
|
||||
// render pass is mostly irrelevant
|
||||
ccstd::hash_t seed = static_cast<ccstd::hash_t>(info.colorTextures.size()) +
|
||||
static_cast<ccstd::hash_t>(info.depthStencilTexture != nullptr) +
|
||||
static_cast<ccstd::hash_t>(info.depthStencilResolveTexture != nullptr);
|
||||
if (info.depthStencilTexture) {
|
||||
ccstd::hash_combine(seed, info.depthStencilTexture->getObjectID());
|
||||
ccstd::hash_combine(seed, info.depthStencilTexture->getHash());
|
||||
}
|
||||
if (info.depthStencilResolveTexture) {
|
||||
ccstd::hash_combine(seed, info.depthStencilResolveTexture->getObjectID());
|
||||
ccstd::hash_combine(seed, info.depthStencilResolveTexture->getHash());
|
||||
}
|
||||
for (auto *colorTexture : info.colorTextures) {
|
||||
ccstd::hash_combine(seed, colorTexture->getObjectID());
|
||||
ccstd::hash_combine(seed, colorTexture->getHash());
|
||||
}
|
||||
ccstd::hash_combine(seed, info.renderPass->getHash());
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool operator==(const FramebufferInfo &lhs, const FramebufferInfo &rhs) {
|
||||
// render pass is mostly irrelevant
|
||||
bool res = false;
|
||||
res = lhs.colorTextures == rhs.colorTextures;
|
||||
|
||||
if (res) {
|
||||
res = lhs.depthStencilTexture == rhs.depthStencilTexture;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
res = lhs.depthStencilResolveTexture == rhs.depthStencilResolveTexture;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
for (size_t i = 0; i < lhs.colorTextures.size(); ++i) {
|
||||
res = lhs.colorTextures[i]->getRaw() == rhs.colorTextures[i]->getRaw() &&
|
||||
lhs.colorTextures[i]->getHash() == rhs.colorTextures[i]->getHash();
|
||||
if (!res) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
res = lhs.renderPass->getHash() == rhs.renderPass->getHash();
|
||||
if (res) {
|
||||
res = lhs.depthStencilTexture->getRaw() == rhs.depthStencilTexture->getRaw() &&
|
||||
lhs.depthStencilTexture->getHash() == rhs.depthStencilTexture->getHash();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<TextureInfo>::operator()(const TextureInfo &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const TextureInfo &lhs, const TextureInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(TextureInfo));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<TextureViewInfo>::operator()(const TextureViewInfo &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const TextureViewInfo &lhs, const TextureViewInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(TextureViewInfo));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<BufferInfo>::operator()(const BufferInfo &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const BufferInfo &lhs, const BufferInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(BufferInfo));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<SamplerInfo>::operator()(const SamplerInfo &info) const {
|
||||
// return quickHashTrivialStruct(&info);
|
||||
|
||||
// the hash may be used to reconstruct the original struct
|
||||
auto hash = static_cast<uint32_t>(info.minFilter);
|
||||
hash |= static_cast<uint32_t>(info.magFilter) << 2;
|
||||
hash |= static_cast<uint32_t>(info.mipFilter) << 4;
|
||||
hash |= static_cast<uint32_t>(info.addressU) << 6;
|
||||
hash |= static_cast<uint32_t>(info.addressV) << 8;
|
||||
hash |= static_cast<uint32_t>(info.addressW) << 10;
|
||||
hash |= static_cast<uint32_t>(info.maxAnisotropy) << 12;
|
||||
hash |= static_cast<uint32_t>(info.cmpFunc) << 16;
|
||||
return static_cast<ccstd::hash_t>(hash);
|
||||
}
|
||||
|
||||
bool operator==(const SamplerInfo &lhs, const SamplerInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(SamplerInfo));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<GeneralBarrierInfo>::operator()(const GeneralBarrierInfo &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const GeneralBarrierInfo &lhs, const GeneralBarrierInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(GeneralBarrierInfo));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<TextureBarrierInfo>::operator()(const TextureBarrierInfo &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const TextureBarrierInfo &lhs, const TextureBarrierInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(TextureBarrierInfo));
|
||||
}
|
||||
|
||||
template <>
|
||||
ccstd::hash_t Hasher<BufferBarrierInfo>::operator()(const BufferBarrierInfo &info) const {
|
||||
return quickHashTrivialStruct(&info);
|
||||
}
|
||||
|
||||
bool operator==(const BufferBarrierInfo &lhs, const BufferBarrierInfo &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(BufferBarrierInfo));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool operator==(const Viewport &lhs, const Viewport &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(Viewport));
|
||||
}
|
||||
|
||||
bool operator==(const Rect &lhs, const Rect &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(Rect));
|
||||
}
|
||||
|
||||
bool operator==(const Color &lhs, const Color &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(Color));
|
||||
}
|
||||
|
||||
bool operator==(const Offset &lhs, const Offset &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(Offset));
|
||||
}
|
||||
|
||||
bool operator==(const Extent &lhs, const Extent &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(Extent));
|
||||
}
|
||||
|
||||
bool operator==(const Size &lhs, const Size &rhs) {
|
||||
return !memcmp(&lhs, &rhs, sizeof(Size));
|
||||
}
|
||||
|
||||
const FormatInfo GFX_FORMAT_INFOS[] = {
|
||||
{"UNKNOWN", 0, 0, FormatType::NONE, false, false, false, false},
|
||||
{"A8", 1, 1, FormatType::UNORM, true, false, false, false},
|
||||
{"L8", 1, 1, FormatType::UNORM, false, false, false, false},
|
||||
{"LA8", 1, 2, FormatType::UNORM, false, false, false, false},
|
||||
|
||||
{"R8", 1, 1, FormatType::UNORM, false, false, false, false},
|
||||
{"R8SN", 1, 1, FormatType::SNORM, false, false, false, false},
|
||||
{"R8UI", 1, 1, FormatType::UINT, false, false, false, false},
|
||||
{"R8I", 1, 1, FormatType::INT, false, false, false, false},
|
||||
{"R16F", 2, 1, FormatType::FLOAT, false, false, false, false},
|
||||
{"R16UI", 2, 1, FormatType::UINT, false, false, false, false},
|
||||
{"R16I", 2, 1, FormatType::INT, false, false, false, false},
|
||||
{"R32F", 4, 1, FormatType::FLOAT, false, false, false, false},
|
||||
{"R32UI", 4, 1, FormatType::UINT, false, false, false, false},
|
||||
{"R32I", 4, 1, FormatType::INT, false, false, false, false},
|
||||
|
||||
{"RG8", 2, 2, FormatType::UNORM, false, false, false, false},
|
||||
{"RG8SN", 2, 2, FormatType::SNORM, false, false, false, false},
|
||||
{"RG8UI", 2, 2, FormatType::UINT, false, false, false, false},
|
||||
{"RG8I", 2, 2, FormatType::INT, false, false, false, false},
|
||||
{"RG16F", 4, 2, FormatType::FLOAT, false, false, false, false},
|
||||
{"RG16UI", 4, 2, FormatType::UINT, false, false, false, false},
|
||||
{"RG16I", 4, 2, FormatType::INT, false, false, false, false},
|
||||
{"RG32F", 8, 2, FormatType::FLOAT, false, false, false, false},
|
||||
{"RG32UI", 8, 2, FormatType::UINT, false, false, false, false},
|
||||
{"RG32I", 8, 2, FormatType::INT, false, false, false, false},
|
||||
|
||||
{"RGB8", 3, 3, FormatType::UNORM, false, false, false, false},
|
||||
{"SRGB8", 3, 3, FormatType::UNORM, false, false, false, false},
|
||||
{"RGB8SN", 3, 3, FormatType::SNORM, false, false, false, false},
|
||||
{"RGB8UI", 3, 3, FormatType::UINT, false, false, false, false},
|
||||
{"RGB8I", 3, 3, FormatType::INT, false, false, false, false},
|
||||
{"RGB16F", 6, 3, FormatType::FLOAT, false, false, false, false},
|
||||
{"RGB16UI", 6, 3, FormatType::UINT, false, false, false, false},
|
||||
{"RGB16I", 6, 3, FormatType::INT, false, false, false, false},
|
||||
{"RGB32F", 12, 3, FormatType::FLOAT, false, false, false, false},
|
||||
{"RGB32UI", 12, 3, FormatType::UINT, false, false, false, false},
|
||||
{"RGB32I", 12, 3, FormatType::INT, false, false, false, false},
|
||||
|
||||
{"RGBA8", 4, 4, FormatType::UNORM, true, false, false, false},
|
||||
{"BGRA8", 4, 4, FormatType::UNORM, true, false, false, false},
|
||||
{"SRGB8_A8", 4, 4, FormatType::UNORM, true, false, false, false},
|
||||
{"RGBA8SN", 4, 4, FormatType::SNORM, true, false, false, false},
|
||||
{"RGBA8UI", 4, 4, FormatType::UINT, true, false, false, false},
|
||||
{"RGBA8I", 4, 4, FormatType::INT, true, false, false, false},
|
||||
{"RGBA16F", 8, 4, FormatType::FLOAT, true, false, false, false},
|
||||
{"RGBA16UI", 8, 4, FormatType::UINT, true, false, false, false},
|
||||
{"RGBA16I", 8, 4, FormatType::INT, true, false, false, false},
|
||||
{"RGBA32F", 16, 4, FormatType::FLOAT, true, false, false, false},
|
||||
{"RGBA32UI", 16, 4, FormatType::UINT, true, false, false, false},
|
||||
{"RGBA32I", 16, 4, FormatType::INT, true, false, false, false},
|
||||
|
||||
{"R5G6B5", 2, 3, FormatType::UNORM, false, false, false, false},
|
||||
{"R11G11B10F", 4, 3, FormatType::FLOAT, false, false, false, false},
|
||||
{"RGB5A1", 2, 4, FormatType::UNORM, true, false, false, false},
|
||||
{"RGBA4", 2, 4, FormatType::UNORM, true, false, false, false},
|
||||
{"RGB10A2", 2, 4, FormatType::UNORM, true, false, false, false},
|
||||
{"RGB10A2UI", 2, 4, FormatType::UINT, true, false, false, false},
|
||||
{"RGB9E5", 2, 4, FormatType::FLOAT, true, false, false, false},
|
||||
|
||||
{"DEPTH", 4, 1, FormatType::FLOAT, false, true, false, false},
|
||||
{"DEPTH_STENCIL", 5, 2, FormatType::FLOAT, false, true, true, false},
|
||||
|
||||
{"BC1", 1, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"BC1_ALPHA", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC1_SRGB", 1, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"BC1_SRGB_ALPHA", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC2", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC2_SRGB", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC3", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC3_SRGB", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC4", 1, 1, FormatType::UNORM, false, false, false, true},
|
||||
{"BC4_SNORM", 1, 1, FormatType::SNORM, false, false, false, true},
|
||||
{"BC5", 1, 2, FormatType::UNORM, false, false, false, true},
|
||||
{"BC5_SNORM", 1, 2, FormatType::SNORM, false, false, false, true},
|
||||
{"BC6H_UF16", 1, 3, FormatType::UFLOAT, false, false, false, true},
|
||||
{"BC6H_SF16", 1, 3, FormatType::FLOAT, false, false, false, true},
|
||||
{"BC7", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"BC7_SRGB", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
|
||||
{"ETC_RGB8", 1, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"ETC2_RGB8", 1, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"ETC2_SRGB8", 1, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"ETC2_RGB8_A1", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ETC2_SRGB8_A1", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"EAC_R11", 1, 1, FormatType::UNORM, false, false, false, true},
|
||||
{"EAC_R11SN", 1, 1, FormatType::SNORM, false, false, false, true},
|
||||
{"EAC_RG11", 2, 2, FormatType::UNORM, false, false, false, true},
|
||||
{"EAC_RG11SN", 2, 2, FormatType::SNORM, false, false, false, true},
|
||||
|
||||
{"PVRTC_RGB2", 2, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"PVRTC_RGBA2", 2, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"PVRTC_RGB4", 2, 3, FormatType::UNORM, false, false, false, true},
|
||||
{"PVRTC_RGBA4", 2, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"PVRTC2_2BPP", 2, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"PVRTC2_4BPP", 2, 4, FormatType::UNORM, true, false, false, true},
|
||||
|
||||
{"ASTC_RGBA_4X4", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_5X4", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_5X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_6X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_6X6", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_8X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_8X6", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_8X8", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_10X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_10X6", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_10X8", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_10X10", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_12X10", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_RGBA_12X12", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
|
||||
{"ASTC_SRGBA_4X4", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_5X4", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_5X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_6X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_6X6", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_8X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_8X6", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_8X8", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_10X5", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_10X6", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_10X8", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_10X10", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_12X10", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
{"ASTC_SRGBA_12X12", 1, 4, FormatType::UNORM, true, false, false, true},
|
||||
};
|
||||
|
||||
bool isCombinedImageSampler(Type type) { return type >= Type::SAMPLER1D && type <= Type::SAMPLER_CUBE; }
|
||||
bool isSampledImage(Type type) { return type >= Type::TEXTURE1D && type <= Type::TEXTURE_CUBE; }
|
||||
bool isStorageImage(Type type) { return type >= Type::IMAGE1D && type <= Type::IMAGE_CUBE; }
|
||||
|
||||
uint32_t ceilDiv(uint32_t x, uint32_t y) { return (x - 1) / y + 1; }
|
||||
|
||||
uint32_t formatSize(Format format, uint32_t width, uint32_t height, uint32_t depth) {
|
||||
if (!GFX_FORMAT_INFOS[static_cast<uint32_t>(format)].isCompressed) {
|
||||
return (width * height * depth * GFX_FORMAT_INFOS[static_cast<uint32_t>(format)].size);
|
||||
}
|
||||
switch (format) {
|
||||
case Format::BC1:
|
||||
case Format::BC1_ALPHA:
|
||||
case Format::BC1_SRGB:
|
||||
case Format::BC1_SRGB_ALPHA:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 8 * depth;
|
||||
case Format::BC2:
|
||||
case Format::BC2_SRGB:
|
||||
case Format::BC3:
|
||||
case Format::BC3_SRGB:
|
||||
case Format::BC4:
|
||||
case Format::BC4_SNORM:
|
||||
case Format::BC6H_SF16:
|
||||
case Format::BC6H_UF16:
|
||||
case Format::BC7:
|
||||
case Format::BC7_SRGB:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 16 * depth;
|
||||
case Format::BC5:
|
||||
case Format::BC5_SNORM:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 32 * depth;
|
||||
|
||||
case Format::ETC_RGB8:
|
||||
case Format::ETC2_RGB8:
|
||||
case Format::ETC2_SRGB8:
|
||||
case Format::ETC2_RGB8_A1:
|
||||
case Format::EAC_R11:
|
||||
case Format::EAC_R11SN:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 8 * depth;
|
||||
case Format::ETC2_RGBA8:
|
||||
case Format::ETC2_SRGB8_A1:
|
||||
case Format::EAC_RG11:
|
||||
case Format::EAC_RG11SN:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 16 * depth;
|
||||
|
||||
case Format::PVRTC_RGB2:
|
||||
case Format::PVRTC_RGBA2:
|
||||
case Format::PVRTC2_2BPP:
|
||||
return ceilDiv(width, 8) * ceilDiv(height, 4) * 8 * depth;
|
||||
case Format::PVRTC_RGB4:
|
||||
case Format::PVRTC_RGBA4:
|
||||
case Format::PVRTC2_4BPP:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 8 * depth;
|
||||
|
||||
case Format::ASTC_RGBA_4X4:
|
||||
case Format::ASTC_SRGBA_4X4:
|
||||
return ceilDiv(width, 4) * ceilDiv(height, 4) * 16 * depth;
|
||||
case Format::ASTC_RGBA_5X4:
|
||||
case Format::ASTC_SRGBA_5X4:
|
||||
return ceilDiv(width, 5) * ceilDiv(height, 4) * 16 * depth;
|
||||
case Format::ASTC_RGBA_5X5:
|
||||
case Format::ASTC_SRGBA_5X5:
|
||||
return ceilDiv(width, 5) * ceilDiv(height, 5) * 16 * depth;
|
||||
case Format::ASTC_RGBA_6X5:
|
||||
case Format::ASTC_SRGBA_6X5:
|
||||
return ceilDiv(width, 6) * ceilDiv(height, 5) * 16 * depth;
|
||||
case Format::ASTC_RGBA_6X6:
|
||||
case Format::ASTC_SRGBA_6X6:
|
||||
return ceilDiv(width, 6) * ceilDiv(height, 6) * 16 * depth;
|
||||
case Format::ASTC_RGBA_8X5:
|
||||
case Format::ASTC_SRGBA_8X5:
|
||||
return ceilDiv(width, 8) * ceilDiv(height, 5) * 16 * depth;
|
||||
case Format::ASTC_RGBA_8X6:
|
||||
case Format::ASTC_SRGBA_8X6:
|
||||
return ceilDiv(width, 8) * ceilDiv(height, 6) * 16 * depth;
|
||||
case Format::ASTC_RGBA_8X8:
|
||||
case Format::ASTC_SRGBA_8X8:
|
||||
return ceilDiv(width, 8) * ceilDiv(height, 8) * 16 * depth;
|
||||
case Format::ASTC_RGBA_10X5:
|
||||
case Format::ASTC_SRGBA_10X5:
|
||||
return ceilDiv(width, 10) * ceilDiv(height, 5) * 16 * depth;
|
||||
case Format::ASTC_RGBA_10X6:
|
||||
case Format::ASTC_SRGBA_10X6:
|
||||
return ceilDiv(width, 10) * ceilDiv(height, 6) * 16 * depth;
|
||||
case Format::ASTC_RGBA_10X8:
|
||||
case Format::ASTC_SRGBA_10X8:
|
||||
return ceilDiv(width, 10) * ceilDiv(height, 8) * 16 * depth;
|
||||
case Format::ASTC_RGBA_10X10:
|
||||
case Format::ASTC_SRGBA_10X10:
|
||||
return ceilDiv(width, 10) * ceilDiv(height, 10) * 16 * depth;
|
||||
case Format::ASTC_RGBA_12X10:
|
||||
case Format::ASTC_SRGBA_12X10:
|
||||
return ceilDiv(width, 12) * ceilDiv(height, 10) * 16 * depth;
|
||||
case Format::ASTC_RGBA_12X12:
|
||||
case Format::ASTC_SRGBA_12X12:
|
||||
return ceilDiv(width, 12) * ceilDiv(height, 12) * 16 * depth;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
std::pair<uint32_t, uint32_t> formatAlignment(Format format) {
|
||||
switch (format) {
|
||||
case Format::BC1:
|
||||
case Format::BC1_ALPHA:
|
||||
case Format::BC1_SRGB:
|
||||
case Format::BC1_SRGB_ALPHA:
|
||||
case Format::BC2:
|
||||
case Format::BC2_SRGB:
|
||||
case Format::BC3:
|
||||
case Format::BC3_SRGB:
|
||||
case Format::BC4:
|
||||
case Format::BC4_SNORM:
|
||||
case Format::BC6H_SF16:
|
||||
case Format::BC6H_UF16:
|
||||
case Format::BC7:
|
||||
case Format::BC7_SRGB:
|
||||
case Format::BC5:
|
||||
case Format::BC5_SNORM:
|
||||
case Format::ETC_RGB8:
|
||||
case Format::ETC2_RGB8:
|
||||
case Format::ETC2_SRGB8:
|
||||
case Format::ETC2_RGB8_A1:
|
||||
case Format::EAC_R11:
|
||||
case Format::EAC_R11SN:
|
||||
case Format::ETC2_RGBA8:
|
||||
case Format::ETC2_SRGB8_A1:
|
||||
case Format::EAC_RG11:
|
||||
case Format::EAC_RG11SN:
|
||||
return std::make_pair(4, 4);
|
||||
|
||||
case Format::PVRTC_RGB2:
|
||||
case Format::PVRTC_RGBA2:
|
||||
case Format::PVRTC2_2BPP:
|
||||
return std::make_pair(8, 4);
|
||||
|
||||
case Format::PVRTC_RGB4:
|
||||
case Format::PVRTC_RGBA4:
|
||||
case Format::PVRTC2_4BPP:
|
||||
return std::make_pair(4, 4);
|
||||
|
||||
case Format::ASTC_RGBA_4X4:
|
||||
case Format::ASTC_SRGBA_4X4:
|
||||
return std::make_pair(4, 4);
|
||||
case Format::ASTC_RGBA_5X4:
|
||||
case Format::ASTC_SRGBA_5X4:
|
||||
return std::make_pair(5, 4);
|
||||
case Format::ASTC_RGBA_5X5:
|
||||
case Format::ASTC_SRGBA_5X5:
|
||||
return std::make_pair(5, 5);
|
||||
case Format::ASTC_RGBA_6X5:
|
||||
case Format::ASTC_SRGBA_6X5:
|
||||
return std::make_pair(6, 5);
|
||||
case Format::ASTC_RGBA_6X6:
|
||||
case Format::ASTC_SRGBA_6X6:
|
||||
return std::make_pair(6, 6);
|
||||
case Format::ASTC_RGBA_8X5:
|
||||
case Format::ASTC_SRGBA_8X5:
|
||||
return std::make_pair(8, 5);
|
||||
case Format::ASTC_RGBA_8X6:
|
||||
case Format::ASTC_SRGBA_8X6:
|
||||
return std::make_pair(8, 6);
|
||||
case Format::ASTC_RGBA_8X8:
|
||||
case Format::ASTC_SRGBA_8X8:
|
||||
return std::make_pair(8, 8);
|
||||
case Format::ASTC_RGBA_10X5:
|
||||
case Format::ASTC_SRGBA_10X5:
|
||||
return std::make_pair(10, 5);
|
||||
case Format::ASTC_RGBA_10X6:
|
||||
case Format::ASTC_SRGBA_10X6:
|
||||
return std::make_pair(10, 6);
|
||||
case Format::ASTC_RGBA_10X8:
|
||||
case Format::ASTC_SRGBA_10X8:
|
||||
return std::make_pair(10, 8);
|
||||
case Format::ASTC_RGBA_10X10:
|
||||
case Format::ASTC_SRGBA_10X10:
|
||||
return std::make_pair(10, 10);
|
||||
case Format::ASTC_RGBA_12X10:
|
||||
case Format::ASTC_SRGBA_12X10:
|
||||
return std::make_pair(12, 10);
|
||||
case Format::ASTC_RGBA_12X12:
|
||||
case Format::ASTC_SRGBA_12X12:
|
||||
return std::make_pair(12, 12);
|
||||
default:
|
||||
return std::make_pair(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr ccstd::array<uint32_t, static_cast<size_t>(Type::COUNT)> GFX_TYPE_SIZES = {
|
||||
0, // UNKNOWN
|
||||
4, // BOOL
|
||||
8, // BOOL2
|
||||
12, // BOOL3
|
||||
16, // BOOL4
|
||||
4, // INT
|
||||
8, // INT2
|
||||
12, // INT3
|
||||
16, // INT4
|
||||
4, // UINT
|
||||
8, // UINT2
|
||||
12, // UINT3
|
||||
16, // UINT4
|
||||
4, // FLOAT
|
||||
8, // FLOAT2
|
||||
12, // FLOAT3
|
||||
16, // FLOAT4
|
||||
16, // MAT2
|
||||
24, // MAT2X3
|
||||
32, // MAT2X4
|
||||
24, // MAT3X2
|
||||
36, // MAT3
|
||||
48, // MAT3X4
|
||||
32, // MAT4X2
|
||||
48, // MAT4X3
|
||||
64, // MAT4
|
||||
4, // SAMPLER1D
|
||||
4, // SAMPLER1D_ARRAY
|
||||
4, // SAMPLER2D
|
||||
4, // SAMPLER2D_ARRAY
|
||||
4, // SAMPLER3D
|
||||
4, // SAMPLER_CUBE
|
||||
};
|
||||
|
||||
/**
|
||||
* @en Get the memory size of the specified type.
|
||||
* @zh 得到 GFX 数据类型的大小。
|
||||
* @param type The target type.
|
||||
*/
|
||||
uint32_t getTypeSize(Type type) {
|
||||
if (type < Type::COUNT) {
|
||||
return GFX_TYPE_SIZES[toNumber(type)];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t formatSurfaceSize(Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t mips) {
|
||||
uint32_t size = 0;
|
||||
|
||||
for (uint32_t i = 0; i < mips; ++i) {
|
||||
size += formatSize(format, width, height, depth);
|
||||
width = std::max(width >> 1, 1U);
|
||||
height = std::max(height >> 1, 1U);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t gcd(uint32_t a, uint32_t b) {
|
||||
while (b) {
|
||||
uint32_t t = a % b;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
uint32_t lcm(uint32_t a, uint32_t b) {
|
||||
return a * b / gcd(a, b);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
150
cocos/renderer/gfx-base/GFXDef.h
Normal file
150
cocos/renderer/gfx-base/GFXDef.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "GFXDef-common.h"
|
||||
#include "base/std/hash/hash.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
template <typename T, typename Enable = std::enable_if_t<std::is_class<T>::value>>
|
||||
struct Hasher final {
|
||||
// NOTE: ccstd::hash_t is a typedef of uint32_t now, sizeof(ccstd::hash_t) == sizeof(size_t) on 32 bits architecture device,
|
||||
// sizeof(ccstd::hash_t) < sizeof(size_t) on 64 bits architecture device.
|
||||
// STL containers like ccstd::unordered_map<K, V, Hasher> expects the custom Hasher function to return size_t.
|
||||
// So it's safe to return ccstd::hash_t for operator() function now.
|
||||
// If we need to define ccstd::hash_t to uint64_t someday, we must take care of the return value of operator(),
|
||||
// it should be size_t and we need to convert hash value from uint64_t to uint32_t for 32 bit architecture device.
|
||||
ccstd::hash_t operator()(const T &info) const;
|
||||
};
|
||||
|
||||
// make this ccstd::hash compatible
|
||||
template <typename T, typename Enable = std::enable_if_t<std::is_class<T>::value>>
|
||||
ccstd::hash_t hash_value(const T &info) { return Hasher<T>()(info); } // NOLINT(readability-identifier-naming)
|
||||
|
||||
#define DEFINE_CMP_OP(type) \
|
||||
bool operator==(const type &lhs, const type &rhs); \
|
||||
inline bool operator!=(const type &lhs, const type &rhs) { return !(lhs == rhs); }
|
||||
|
||||
DEFINE_CMP_OP(DepthStencilAttachment)
|
||||
DEFINE_CMP_OP(SubpassInfo)
|
||||
DEFINE_CMP_OP(SubpassDependency)
|
||||
DEFINE_CMP_OP(RenderPassInfo)
|
||||
DEFINE_CMP_OP(FramebufferInfo)
|
||||
DEFINE_CMP_OP(Viewport)
|
||||
DEFINE_CMP_OP(Rect)
|
||||
DEFINE_CMP_OP(Color)
|
||||
DEFINE_CMP_OP(Offset)
|
||||
DEFINE_CMP_OP(Extent)
|
||||
DEFINE_CMP_OP(Size)
|
||||
DEFINE_CMP_OP(TextureInfo)
|
||||
DEFINE_CMP_OP(TextureViewInfo)
|
||||
DEFINE_CMP_OP(BufferInfo)
|
||||
DEFINE_CMP_OP(SamplerInfo)
|
||||
DEFINE_CMP_OP(GeneralBarrierInfo)
|
||||
DEFINE_CMP_OP(TextureBarrierInfo)
|
||||
DEFINE_CMP_OP(BufferBarrierInfo)
|
||||
|
||||
#undef DEFINE_CMP_OP
|
||||
|
||||
class Executable {
|
||||
public:
|
||||
virtual ~Executable() = default;
|
||||
virtual void execute() = 0;
|
||||
};
|
||||
|
||||
template <typename ExecuteMethodType>
|
||||
class CallbackExecutable final : public Executable {
|
||||
public:
|
||||
using ExecuteMethod = std::remove_reference_t<ExecuteMethodType>;
|
||||
|
||||
explicit CallbackExecutable(ExecuteMethod &execute) : Executable(), _execute(execute) {}
|
||||
explicit CallbackExecutable(ExecuteMethod &&execute) : Executable(), _execute(execute) {}
|
||||
|
||||
void execute() override { _execute(); }
|
||||
|
||||
private:
|
||||
ExecuteMethod _execute;
|
||||
};
|
||||
|
||||
struct SwapchainTextureInfo final {
|
||||
Swapchain *swapchain{nullptr};
|
||||
Format format{Format::UNKNOWN};
|
||||
uint32_t width{0};
|
||||
uint32_t height{0};
|
||||
};
|
||||
|
||||
constexpr TextureUsage TEXTURE_USAGE_TRANSIENT = static_cast<TextureUsage>(
|
||||
static_cast<uint32_t>(TextureUsageBit::COLOR_ATTACHMENT) |
|
||||
static_cast<uint32_t>(TextureUsageBit::DEPTH_STENCIL_ATTACHMENT) |
|
||||
static_cast<uint32_t>(TextureUsageBit::INPUT_ATTACHMENT));
|
||||
|
||||
constexpr DescriptorType DESCRIPTOR_BUFFER_TYPE = static_cast<DescriptorType>(
|
||||
static_cast<uint32_t>(DescriptorType::STORAGE_BUFFER) |
|
||||
static_cast<uint32_t>(DescriptorType::DYNAMIC_STORAGE_BUFFER) |
|
||||
static_cast<uint32_t>(DescriptorType::UNIFORM_BUFFER) |
|
||||
static_cast<uint32_t>(DescriptorType::DYNAMIC_UNIFORM_BUFFER));
|
||||
|
||||
constexpr DescriptorType DESCRIPTOR_TEXTURE_TYPE = static_cast<DescriptorType>(
|
||||
static_cast<uint32_t>(DescriptorType::SAMPLER_TEXTURE) |
|
||||
static_cast<uint32_t>(DescriptorType::SAMPLER) |
|
||||
static_cast<uint32_t>(DescriptorType::TEXTURE) |
|
||||
static_cast<uint32_t>(DescriptorType::STORAGE_IMAGE) |
|
||||
static_cast<uint32_t>(DescriptorType::INPUT_ATTACHMENT));
|
||||
|
||||
constexpr DescriptorType DESCRIPTOR_SAMPLER_TYPE = static_cast<DescriptorType>(
|
||||
static_cast<uint32_t>(DescriptorType::SAMPLER_TEXTURE) |
|
||||
static_cast<uint32_t>(DescriptorType::SAMPLER) |
|
||||
static_cast<uint32_t>(DescriptorType::TEXTURE) |
|
||||
static_cast<uint32_t>(DescriptorType::STORAGE_IMAGE) |
|
||||
static_cast<uint32_t>(DescriptorType::INPUT_ATTACHMENT));
|
||||
|
||||
constexpr DescriptorType DESCRIPTOR_DYNAMIC_TYPE = static_cast<DescriptorType>(
|
||||
static_cast<uint32_t>(DescriptorType::DYNAMIC_STORAGE_BUFFER) |
|
||||
static_cast<uint32_t>(DescriptorType::DYNAMIC_UNIFORM_BUFFER));
|
||||
|
||||
extern const FormatInfo GFX_FORMAT_INFOS[];
|
||||
|
||||
std::pair<uint32_t, uint32_t> formatAlignment(Format format);
|
||||
|
||||
uint32_t formatSize(Format format, uint32_t width, uint32_t height, uint32_t depth);
|
||||
|
||||
uint32_t formatSurfaceSize(Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t mips);
|
||||
|
||||
/**
|
||||
* @en Get the memory size of the specified type.
|
||||
* @zh 得到 GFX 数据类型的大小。
|
||||
* @param type The target type.
|
||||
*/
|
||||
uint32_t getTypeSize(gfx::Type type);
|
||||
|
||||
uint32_t gcd(uint32_t a, uint32_t b);
|
||||
|
||||
uint32_t lcm(uint32_t a, uint32_t b);
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
143
cocos/renderer/gfx-base/GFXDescriptorSet.cpp
Normal file
143
cocos/renderer/gfx-base/GFXDescriptorSet.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXDescriptorSet.h"
|
||||
#include "GFXBuffer.h"
|
||||
#include "GFXDescriptorSetLayout.h"
|
||||
#include "GFXObject.h"
|
||||
#include "GFXTexture.h"
|
||||
#include "states/GFXSampler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DescriptorSet::DescriptorSet()
|
||||
: GFXObject(ObjectType::DESCRIPTOR_SET) {
|
||||
}
|
||||
|
||||
DescriptorSet::~DescriptorSet() = default;
|
||||
|
||||
void DescriptorSet::initialize(const DescriptorSetInfo &info) {
|
||||
CC_ASSERT(info.layout);
|
||||
|
||||
_layout = info.layout;
|
||||
uint32_t descriptorCount = _layout->getDescriptorCount();
|
||||
_buffers.resize(descriptorCount);
|
||||
_textures.resize(descriptorCount);
|
||||
_samplers.resize(descriptorCount);
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void DescriptorSet::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_layout = nullptr;
|
||||
// have to clear these or else it might not be properly updated when reused
|
||||
_buffers.clear();
|
||||
_textures.clear();
|
||||
_samplers.clear();
|
||||
}
|
||||
|
||||
void DescriptorSet::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index) {
|
||||
bindBuffer(binding, buffer, index, AccessFlagBit::NONE);
|
||||
}
|
||||
|
||||
void DescriptorSet::bindTexture(uint32_t binding, Texture *texture, uint32_t index) {
|
||||
bindTexture(binding, texture, index, AccessFlagBit::NONE);
|
||||
}
|
||||
|
||||
void DescriptorSet::bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) {
|
||||
const uint32_t descriptorIndex = _layout->getDescriptorIndices()[binding] + index;
|
||||
const uint32_t newId = getObjectID(texture);
|
||||
if (_textures[descriptorIndex].id != newId) {
|
||||
_textures[descriptorIndex].ptr = texture;
|
||||
_textures[descriptorIndex].id = newId;
|
||||
_textures[descriptorIndex].flags = flags;
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorSet::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) {
|
||||
const uint32_t descriptorIndex = _layout->getDescriptorIndices()[binding] + index;
|
||||
const uint32_t newId = getObjectID(buffer);
|
||||
if (_buffers[descriptorIndex].id != newId) {
|
||||
_buffers[descriptorIndex].ptr = buffer;
|
||||
_buffers[descriptorIndex].id = newId;
|
||||
_buffers[descriptorIndex].flags = flags;
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorSet::bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) {
|
||||
const uint32_t descriptorIndex = _layout->getDescriptorIndices()[binding] + index;
|
||||
const uint32_t newId = getObjectID(sampler);
|
||||
if (_samplers[descriptorIndex].id != newId) {
|
||||
_samplers[descriptorIndex].ptr = sampler;
|
||||
_samplers[descriptorIndex].id = newId;
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool DescriptorSet::bindBufferJSB(uint32_t binding, Buffer *buffer, uint32_t index) {
|
||||
bindBuffer(binding, buffer, index);
|
||||
return _isDirty;
|
||||
}
|
||||
|
||||
bool DescriptorSet::bindTextureJSB(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) {
|
||||
bindTexture(binding, texture, index, flags);
|
||||
return _isDirty;
|
||||
}
|
||||
|
||||
bool DescriptorSet::bindSamplerJSB(uint32_t binding, Sampler *sampler, uint32_t index) {
|
||||
bindSampler(binding, sampler, index);
|
||||
return _isDirty;
|
||||
}
|
||||
|
||||
Buffer *DescriptorSet::getBuffer(uint32_t binding, uint32_t index) const {
|
||||
const ccstd::vector<uint32_t> &descriptorIndices = _layout->getDescriptorIndices();
|
||||
if (binding >= descriptorIndices.size()) return nullptr;
|
||||
const uint32_t descriptorIndex = descriptorIndices[binding] + index;
|
||||
if (descriptorIndex >= _buffers.size()) return nullptr;
|
||||
return _buffers[descriptorIndex].ptr;
|
||||
}
|
||||
|
||||
Texture *DescriptorSet::getTexture(uint32_t binding, uint32_t index) const {
|
||||
const ccstd::vector<uint32_t> &descriptorIndices = _layout->getDescriptorIndices();
|
||||
if (binding >= descriptorIndices.size()) return nullptr;
|
||||
const uint32_t descriptorIndex = descriptorIndices[binding] + index;
|
||||
if (descriptorIndex >= _textures.size()) return nullptr;
|
||||
return _textures[descriptorIndex].ptr;
|
||||
}
|
||||
|
||||
Sampler *DescriptorSet::getSampler(uint32_t binding, uint32_t index) const {
|
||||
const ccstd::vector<uint32_t> &descriptorIndices = _layout->getDescriptorIndices();
|
||||
if (binding >= descriptorIndices.size()) return nullptr;
|
||||
const uint32_t descriptorIndex = descriptorIndices[binding] + index;
|
||||
if (descriptorIndex >= _samplers.size()) return nullptr;
|
||||
return _samplers[descriptorIndex].ptr;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
89
cocos/renderer/gfx-base/GFXDescriptorSet.h
Normal file
89
cocos/renderer/gfx-base/GFXDescriptorSet.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL DescriptorSet : public GFXObject, public RefCounted {
|
||||
public:
|
||||
DescriptorSet();
|
||||
~DescriptorSet() override;
|
||||
|
||||
void initialize(const DescriptorSetInfo &info);
|
||||
void destroy();
|
||||
|
||||
virtual void update() = 0;
|
||||
virtual void forceUpdate() = 0;
|
||||
|
||||
virtual void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags);
|
||||
virtual void bindSampler(uint32_t binding, Sampler *sampler, uint32_t index);
|
||||
virtual void bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags);
|
||||
|
||||
void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index);
|
||||
void bindTexture(uint32_t binding, Texture *texture, uint32_t index);
|
||||
|
||||
// Functions invoked by JSB adapter
|
||||
bool bindBufferJSB(uint32_t binding, Buffer *buffer, uint32_t index);
|
||||
bool bindTextureJSB(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags);
|
||||
bool bindSamplerJSB(uint32_t binding, Sampler *sampler, uint32_t index);
|
||||
|
||||
Buffer *getBuffer(uint32_t binding, uint32_t index) const;
|
||||
Texture *getTexture(uint32_t binding, uint32_t index) const;
|
||||
Sampler *getSampler(uint32_t binding, uint32_t index) const;
|
||||
|
||||
inline const DescriptorSetLayout *getLayout() const { return _layout; }
|
||||
|
||||
inline void bindBuffer(uint32_t binding, Buffer *buffer) { bindBuffer(binding, buffer, 0U); }
|
||||
inline void bindTexture(uint32_t binding, Texture *texture) { bindTexture(binding, texture, 0U); }
|
||||
inline void bindSampler(uint32_t binding, Sampler *sampler) { bindSampler(binding, sampler, 0U); }
|
||||
inline Buffer *getBuffer(uint32_t binding) const { return getBuffer(binding, 0U); }
|
||||
inline Texture *getTexture(uint32_t binding) const { return getTexture(binding, 0U); }
|
||||
inline Sampler *getSampler(uint32_t binding) const { return getSampler(binding, 0U); }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const DescriptorSetInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
template <typename T>
|
||||
struct ObjectWithId {
|
||||
T *ptr = nullptr;
|
||||
uint32_t id = INVALID_OBJECT_ID;
|
||||
AccessFlags flags = AccessFlagBit::NONE;
|
||||
};
|
||||
|
||||
const DescriptorSetLayout *_layout = nullptr;
|
||||
ccstd::vector<ObjectWithId<Buffer>> _buffers;
|
||||
ccstd::vector<ObjectWithId<Texture>> _textures;
|
||||
ccstd::vector<ObjectWithId<Sampler>> _samplers;
|
||||
|
||||
bool _isDirty = false;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
81
cocos/renderer/gfx-base/GFXDescriptorSetLayout.cpp
Normal file
81
cocos/renderer/gfx-base/GFXDescriptorSetLayout.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/Utils.h"
|
||||
|
||||
#include "GFXDescriptorSetLayout.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DescriptorSetLayout::DescriptorSetLayout()
|
||||
: GFXObject(ObjectType::DESCRIPTOR_SET_LAYOUT) {
|
||||
}
|
||||
|
||||
DescriptorSetLayout::~DescriptorSetLayout() = default;
|
||||
|
||||
void DescriptorSetLayout::initialize(const DescriptorSetLayoutInfo &info) {
|
||||
_bindings = info.bindings;
|
||||
auto bindingCount = utils::toUint(_bindings.size());
|
||||
_descriptorCount = 0U;
|
||||
|
||||
if (bindingCount) {
|
||||
uint32_t maxBinding = 0U;
|
||||
ccstd::vector<uint32_t> flattenedIndices(bindingCount);
|
||||
for (uint32_t i = 0U; i < bindingCount; i++) {
|
||||
const DescriptorSetLayoutBinding &binding = _bindings[i];
|
||||
if (binding.binding > maxBinding) maxBinding = binding.binding;
|
||||
flattenedIndices[i] = _descriptorCount;
|
||||
_descriptorCount += binding.count;
|
||||
}
|
||||
|
||||
_bindingIndices.resize(maxBinding + 1, INVALID_BINDING);
|
||||
_descriptorIndices.resize(maxBinding + 1, INVALID_BINDING);
|
||||
for (uint32_t i = 0U; i < bindingCount; i++) {
|
||||
const DescriptorSetLayoutBinding &binding = _bindings[i];
|
||||
_bindingIndices[binding.binding] = i;
|
||||
_descriptorIndices[binding.binding] = flattenedIndices[i];
|
||||
if (hasFlag(DESCRIPTOR_DYNAMIC_TYPE, binding.descriptorType)) {
|
||||
for (uint32_t j = 0U; j < binding.count; ++j) {
|
||||
_dynamicBindings.push_back(binding.binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void DescriptorSetLayout::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_bindings.clear();
|
||||
_descriptorCount = 0U;
|
||||
_bindingIndices.clear();
|
||||
_descriptorIndices.clear();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
59
cocos/renderer/gfx-base/GFXDescriptorSetLayout.h
Normal file
59
cocos/renderer/gfx-base/GFXDescriptorSetLayout.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL DescriptorSetLayout : public GFXObject, public RefCounted {
|
||||
public:
|
||||
DescriptorSetLayout();
|
||||
~DescriptorSetLayout() override;
|
||||
|
||||
void initialize(const DescriptorSetLayoutInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline const DescriptorSetLayoutBindingList &getBindings() const { return _bindings; }
|
||||
inline const ccstd::vector<uint32_t> &getDynamicBindings() const { return _dynamicBindings; }
|
||||
inline const ccstd::vector<uint32_t> &getBindingIndices() const { return _bindingIndices; }
|
||||
inline const ccstd::vector<uint32_t> &getDescriptorIndices() const { return _descriptorIndices; }
|
||||
inline uint32_t getDescriptorCount() const { return _descriptorCount; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const DescriptorSetLayoutInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
DescriptorSetLayoutBindingList _bindings;
|
||||
uint32_t _descriptorCount = 0U;
|
||||
ccstd::vector<uint32_t> _bindingIndices;
|
||||
ccstd::vector<uint32_t> _descriptorIndices;
|
||||
ccstd::vector<uint32_t> _dynamicBindings;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
200
cocos/renderer/gfx-base/GFXDevice.cpp
Normal file
200
cocos/renderer/gfx-base/GFXDevice.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXDevice.h"
|
||||
#include "GFXObject.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "platform/BasePlatform.h"
|
||||
#include "platform/interfaces/modules/ISystemWindow.h"
|
||||
#include "platform/interfaces/modules/ISystemWindowManager.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
Device *Device::instance = nullptr;
|
||||
bool Device::isSupportDetachDeviceThread = true;
|
||||
|
||||
Device *Device::getInstance() {
|
||||
return Device::instance;
|
||||
}
|
||||
|
||||
Device::Device() {
|
||||
Device::instance = this;
|
||||
// Device instance is created and hold by TS. Native should hold it too
|
||||
// to make sure it exists after JavaScript virtual machine is destroyed.
|
||||
// Then will destroy the Device instance in native.
|
||||
addRef();
|
||||
_features.fill(false);
|
||||
_formatFeatures.fill(FormatFeature::NONE);
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
Device::instance = nullptr;
|
||||
CC_SAFE_RELEASE(_cmdBuff);
|
||||
CC_SAFE_RELEASE(_queue);
|
||||
}
|
||||
|
||||
bool Device::initialize(const DeviceInfo &info) {
|
||||
_bindingMappingInfo = info.bindingMappingInfo;
|
||||
|
||||
#if CC_CPU_ARCH == CC_CPU_ARCH_32
|
||||
static_assert(sizeof(void *) == 4, "pointer size assumption broken");
|
||||
#else
|
||||
static_assert(sizeof(void *) == 8, "pointer size assumption broken");
|
||||
#endif
|
||||
|
||||
bool result = doInit(info);
|
||||
|
||||
CC_SAFE_ADD_REF(_cmdBuff);
|
||||
CC_SAFE_ADD_REF(_queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Device::destroy() {
|
||||
for (auto pair : _samplers) {
|
||||
CC_SAFE_DELETE(pair.second);
|
||||
}
|
||||
_samplers.clear();
|
||||
|
||||
for (auto pair : _generalBarriers) {
|
||||
CC_SAFE_DELETE(pair.second);
|
||||
}
|
||||
_generalBarriers.clear();
|
||||
|
||||
for (auto pair : _textureBarriers) {
|
||||
CC_SAFE_DELETE(pair.second);
|
||||
}
|
||||
_textureBarriers.clear();
|
||||
|
||||
for (auto pair : _bufferBarriers) {
|
||||
CC_SAFE_DELETE(pair.second);
|
||||
}
|
||||
_bufferBarriers.clear();
|
||||
|
||||
doDestroy();
|
||||
|
||||
CC_SAFE_DELETE(_onAcquire);
|
||||
}
|
||||
|
||||
Sampler *Device::getSampler(const SamplerInfo &info) {
|
||||
if (!_samplers.count(info)) {
|
||||
_samplers[info] = createSampler(info);
|
||||
}
|
||||
return _samplers[info];
|
||||
}
|
||||
|
||||
GeneralBarrier *Device::getGeneralBarrier(const GeneralBarrierInfo &info) {
|
||||
if (!_generalBarriers.count(info)) {
|
||||
_generalBarriers[info] = createGeneralBarrier(info);
|
||||
}
|
||||
return _generalBarriers[info];
|
||||
}
|
||||
|
||||
TextureBarrier *Device::getTextureBarrier(const TextureBarrierInfo &info) {
|
||||
if (!_textureBarriers.count(info)) {
|
||||
_textureBarriers[info] = createTextureBarrier(info);
|
||||
}
|
||||
return _textureBarriers[info];
|
||||
}
|
||||
|
||||
BufferBarrier *Device::getBufferBarrier(const BufferBarrierInfo &info) {
|
||||
if (!_bufferBarriers.count(info)) {
|
||||
_bufferBarriers[info] = createBufferBarrier(info);
|
||||
}
|
||||
return _bufferBarriers[info];
|
||||
}
|
||||
|
||||
DefaultResource::DefaultResource(Device *device) {
|
||||
uint32_t bufferSize = 64;
|
||||
ccstd::vector<uint8_t> buffer(bufferSize, 255);
|
||||
const uint8_t *bufferData = buffer.data();
|
||||
if (device->getCapabilities().maxTextureSize >= 2) {
|
||||
_texture2D = device->createTexture({TextureType::TEX2D, TextureUsageBit::STORAGE | TextureUsageBit::SAMPLED | TextureUsageBit::TRANSFER_DST,
|
||||
Format::RGBA8, 2, 2, TextureFlagBit::NONE});
|
||||
BufferTextureCopy region = {0, 0, 0, {0, 0, 0}, {2, 2, 1}, {0, 0, 1}};
|
||||
device->copyBuffersToTexture(&bufferData, _texture2D, ®ion, 1);
|
||||
}
|
||||
if (device->getCapabilities().maxTextureSize >= 2) {
|
||||
_textureCube = device->createTexture({TextureType::CUBE, TextureUsageBit::STORAGE | TextureUsageBit::SAMPLED | TextureUsageBit::TRANSFER_DST,
|
||||
Format::RGBA8, 2, 2, TextureFlagBit::NONE, 6});
|
||||
BufferTextureCopy region = {0, 0, 0, {0, 0, 0}, {2, 2, 1}, {0, 0, 1}};
|
||||
device->copyBuffersToTexture(&bufferData, _textureCube, ®ion, 1);
|
||||
region.texSubres.baseArrayLayer = 1;
|
||||
device->copyBuffersToTexture(&bufferData, _textureCube, ®ion, 1);
|
||||
region.texSubres.baseArrayLayer = 2;
|
||||
device->copyBuffersToTexture(&bufferData, _textureCube, ®ion, 1);
|
||||
region.texSubres.baseArrayLayer = 3;
|
||||
device->copyBuffersToTexture(&bufferData, _textureCube, ®ion, 1);
|
||||
region.texSubres.baseArrayLayer = 4;
|
||||
device->copyBuffersToTexture(&bufferData, _textureCube, ®ion, 1);
|
||||
region.texSubres.baseArrayLayer = 5;
|
||||
device->copyBuffersToTexture(&bufferData, _textureCube, ®ion, 1);
|
||||
}
|
||||
|
||||
if (device->getCapabilities().max3DTextureSize >= 2) {
|
||||
_texture3D = device->createTexture({TextureType::TEX3D, TextureUsageBit::STORAGE | TextureUsageBit::SAMPLED | TextureUsageBit::TRANSFER_DST,
|
||||
Format::RGBA8, 2, 2, TextureFlagBit::NONE, 1, 1, SampleCount::X1, 2});
|
||||
BufferTextureCopy region = {0, 0, 0, {0, 0, 0}, {2, 2, 2}, {0, 0, 1}};
|
||||
device->copyBuffersToTexture(&bufferData, _texture3D, ®ion, 1);
|
||||
}
|
||||
if (device->getCapabilities().maxArrayTextureLayers >= 2) {
|
||||
_texture2DArray = device->createTexture({TextureType::TEX2D_ARRAY, TextureUsageBit::STORAGE | TextureUsageBit::SAMPLED | TextureUsageBit::TRANSFER_DST,
|
||||
Format::RGBA8, 2, 2, TextureFlagBit::NONE, 2});
|
||||
BufferTextureCopy region = {0, 0, 0, {0, 0, 0}, {2, 2, 1}, {0, 0, 1}};
|
||||
device->copyBuffersToTexture(&bufferData, _texture2DArray, ®ion, 1);
|
||||
region.texSubres.baseArrayLayer = 1;
|
||||
device->copyBuffersToTexture(&bufferData, _texture2DArray, ®ion, 1);
|
||||
}
|
||||
{
|
||||
BufferInfo bufferInfo = {};
|
||||
bufferInfo.usage = BufferUsageBit::STORAGE | BufferUsageBit::TRANSFER_DST | BufferUsageBit::TRANSFER_SRC | BufferUsageBit::VERTEX | BufferUsageBit::INDEX | BufferUsageBit::INDIRECT;
|
||||
bufferInfo.memUsage = MemoryUsageBit::DEVICE | MemoryUsageBit::HOST;
|
||||
bufferInfo.size = 5 * sizeof(uint32_t); // for indirect command buffer
|
||||
bufferInfo.stride = bufferInfo.size;
|
||||
_buffer = device->createBuffer(bufferInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Texture *DefaultResource::getTexture(TextureType type) const {
|
||||
switch (type) {
|
||||
case TextureType::TEX2D:
|
||||
return _texture2D;
|
||||
case TextureType::CUBE:
|
||||
return _textureCube;
|
||||
case TextureType::TEX3D:
|
||||
return _texture3D;
|
||||
case TextureType::TEX2D_ARRAY:
|
||||
return _texture2DArray;
|
||||
default:
|
||||
CC_ABORT();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer *DefaultResource::getBuffer() const {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
339
cocos/renderer/gfx-base/GFXDevice.h
Normal file
339
cocos/renderer/gfx-base/GFXDevice.h
Normal file
@@ -0,0 +1,339 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXBuffer.h"
|
||||
#include "GFXCommandBuffer.h"
|
||||
#include "GFXDescriptorSet.h"
|
||||
#include "GFXDescriptorSetLayout.h"
|
||||
#include "GFXFramebuffer.h"
|
||||
#include "GFXInputAssembler.h"
|
||||
#include "GFXObject.h"
|
||||
#include "GFXPipelineLayout.h"
|
||||
#include "GFXPipelineState.h"
|
||||
#include "GFXQueryPool.h"
|
||||
#include "GFXQueue.h"
|
||||
#include "GFXRenderPass.h"
|
||||
#include "GFXShader.h"
|
||||
#include "GFXSwapchain.h"
|
||||
#include "GFXTexture.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/std/container/array.h"
|
||||
#include "states/GFXBufferBarrier.h"
|
||||
#include "states/GFXGeneralBarrier.h"
|
||||
#include "states/GFXSampler.h"
|
||||
#include "states/GFXTextureBarrier.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL Device : public RefCounted {
|
||||
public:
|
||||
static Device *getInstance();
|
||||
|
||||
~Device() override;
|
||||
|
||||
bool initialize(const DeviceInfo &info);
|
||||
void destroy();
|
||||
|
||||
// aim to ensure waiting for work on gpu done when cpu encodes ahead of gpu certain frame(s).
|
||||
virtual void frameSync() = 0;
|
||||
|
||||
virtual void acquire(Swapchain *const *swapchains, uint32_t count) = 0;
|
||||
virtual void present() = 0;
|
||||
|
||||
virtual void flushCommands(CommandBuffer *const *cmdBuffs, uint32_t count) {}
|
||||
|
||||
virtual MemoryStatus &getMemoryStatus() { return _memoryStatus; }
|
||||
virtual uint32_t getNumDrawCalls() const { return _numDrawCalls; }
|
||||
virtual uint32_t getNumInstances() const { return _numInstances; }
|
||||
virtual uint32_t getNumTris() const { return _numTriangles; }
|
||||
|
||||
inline CommandBuffer *createCommandBuffer(const CommandBufferInfo &info);
|
||||
inline Queue *createQueue(const QueueInfo &info);
|
||||
inline QueryPool *createQueryPool(const QueryPoolInfo &info);
|
||||
inline Swapchain *createSwapchain(const SwapchainInfo &info);
|
||||
inline const ccstd::vector<Swapchain *> &getSwapchains() const { return _swapchains; }
|
||||
inline Buffer *createBuffer(const BufferInfo &info);
|
||||
inline Buffer *createBuffer(const BufferViewInfo &info);
|
||||
inline Texture *createTexture(const TextureInfo &info);
|
||||
inline Texture *createTexture(const TextureViewInfo &info);
|
||||
inline Shader *createShader(const ShaderInfo &info);
|
||||
inline InputAssembler *createInputAssembler(const InputAssemblerInfo &info);
|
||||
inline RenderPass *createRenderPass(const RenderPassInfo &info);
|
||||
inline Framebuffer *createFramebuffer(const FramebufferInfo &info);
|
||||
inline DescriptorSet *createDescriptorSet(const DescriptorSetInfo &info);
|
||||
inline DescriptorSetLayout *createDescriptorSetLayout(const DescriptorSetLayoutInfo &info);
|
||||
inline PipelineLayout *createPipelineLayout(const PipelineLayoutInfo &info);
|
||||
inline PipelineState *createPipelineState(const PipelineStateInfo &info);
|
||||
|
||||
virtual Sampler *getSampler(const SamplerInfo &info);
|
||||
virtual GeneralBarrier *getGeneralBarrier(const GeneralBarrierInfo &info);
|
||||
virtual TextureBarrier *getTextureBarrier(const TextureBarrierInfo &info);
|
||||
virtual BufferBarrier *getBufferBarrier(const BufferBarrierInfo &info);
|
||||
|
||||
virtual void copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) = 0;
|
||||
virtual void copyTextureToBuffers(Texture *src, uint8_t *const *buffers, const BufferTextureCopy *region, uint32_t count) = 0;
|
||||
virtual void getQueryPoolResults(QueryPool *queryPool) = 0;
|
||||
|
||||
inline void copyTextureToBuffers(Texture *src, BufferSrcList &buffers, const BufferTextureCopyList ®ions);
|
||||
inline void copyBuffersToTexture(const BufferDataList &buffers, Texture *dst, const BufferTextureCopyList ®ions);
|
||||
inline void flushCommands(const ccstd::vector<CommandBuffer *> &cmdBuffs);
|
||||
inline void acquire(const ccstd::vector<Swapchain *> &swapchains);
|
||||
|
||||
inline Queue *getQueue() const { return _queue; }
|
||||
inline QueryPool *getQueryPool() const { return _queryPool; }
|
||||
inline CommandBuffer *getCommandBuffer() const { return _cmdBuff; }
|
||||
inline const DeviceCaps &getCapabilities() const { return _caps; }
|
||||
inline API getGfxAPI() const { return _api; }
|
||||
inline const ccstd::string &getDeviceName() const { return _deviceName; }
|
||||
inline const ccstd::string &getRenderer() const { return _renderer; }
|
||||
inline const ccstd::string &getVendor() const { return _vendor; }
|
||||
inline bool hasFeature(Feature feature) const { return _features[toNumber(feature)]; }
|
||||
inline FormatFeature getFormatFeatures(Format format) const { return _formatFeatures[toNumber(format)]; }
|
||||
|
||||
inline const BindingMappingInfo &bindingMappingInfo() const { return _bindingMappingInfo; }
|
||||
|
||||
// for external update operations which has to be performed on the device thread.
|
||||
// AR camera texture update, etc.
|
||||
template <typename ExecuteMethod>
|
||||
void registerOnAcquireCallback(ExecuteMethod &&execute);
|
||||
|
||||
virtual void enableAutoBarrier(bool en) { _options.enableBarrierDeduce = en; }
|
||||
virtual SampleCount getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const {
|
||||
std::ignore = format;
|
||||
std::ignore = usage;
|
||||
std::ignore = flags;
|
||||
return SampleCount::X1;
|
||||
};
|
||||
|
||||
protected:
|
||||
static Device *instance;
|
||||
static bool isSupportDetachDeviceThread;
|
||||
|
||||
friend class DeviceAgent;
|
||||
friend class DeviceValidator;
|
||||
friend class DeviceManager;
|
||||
|
||||
Device();
|
||||
|
||||
virtual bool doInit(const DeviceInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
virtual CommandBuffer *createCommandBuffer(const CommandBufferInfo &info, bool hasAgent) = 0;
|
||||
virtual Queue *createQueue() = 0;
|
||||
virtual QueryPool *createQueryPool() = 0;
|
||||
virtual Swapchain *createSwapchain() = 0;
|
||||
virtual Buffer *createBuffer() = 0;
|
||||
virtual Texture *createTexture() = 0;
|
||||
virtual Shader *createShader() = 0;
|
||||
virtual InputAssembler *createInputAssembler() = 0;
|
||||
virtual RenderPass *createRenderPass() = 0;
|
||||
virtual Framebuffer *createFramebuffer() = 0;
|
||||
virtual DescriptorSet *createDescriptorSet() = 0;
|
||||
virtual DescriptorSetLayout *createDescriptorSetLayout() = 0;
|
||||
virtual PipelineLayout *createPipelineLayout() = 0;
|
||||
virtual PipelineState *createPipelineState() = 0;
|
||||
|
||||
virtual Sampler *createSampler(const SamplerInfo &info) { return ccnew Sampler(info); }
|
||||
virtual GeneralBarrier *createGeneralBarrier(const GeneralBarrierInfo &info) { return ccnew GeneralBarrier(info); }
|
||||
virtual TextureBarrier *createTextureBarrier(const TextureBarrierInfo &info) { return ccnew TextureBarrier(info); }
|
||||
virtual BufferBarrier *createBufferBarrier(const BufferBarrierInfo &info) { return ccnew BufferBarrier(info); }
|
||||
|
||||
// For context switching between threads
|
||||
virtual void bindContext(bool bound) {}
|
||||
|
||||
ccstd::string _deviceName;
|
||||
ccstd::string _renderer;
|
||||
ccstd::string _vendor;
|
||||
ccstd::string _version;
|
||||
API _api{API::UNKNOWN};
|
||||
DeviceCaps _caps;
|
||||
BindingMappingInfo _bindingMappingInfo;
|
||||
DeviceOptions _options;
|
||||
|
||||
bool _multithreadedCommandRecording{true};
|
||||
|
||||
ccstd::array<bool, static_cast<size_t>(Feature::COUNT)> _features;
|
||||
ccstd::array<FormatFeature, static_cast<size_t>(Format::COUNT)> _formatFeatures;
|
||||
|
||||
Queue *_queue{nullptr};
|
||||
QueryPool *_queryPool{nullptr};
|
||||
CommandBuffer *_cmdBuff{nullptr};
|
||||
Executable *_onAcquire{nullptr};
|
||||
|
||||
uint32_t _numDrawCalls{0U};
|
||||
uint32_t _numInstances{0U};
|
||||
uint32_t _numTriangles{0U};
|
||||
MemoryStatus _memoryStatus;
|
||||
|
||||
ccstd::unordered_map<SamplerInfo, Sampler *, Hasher<SamplerInfo>> _samplers;
|
||||
ccstd::unordered_map<GeneralBarrierInfo, GeneralBarrier *, Hasher<GeneralBarrierInfo>> _generalBarriers;
|
||||
ccstd::unordered_map<TextureBarrierInfo, TextureBarrier *, Hasher<TextureBarrierInfo>> _textureBarriers;
|
||||
ccstd::unordered_map<BufferBarrierInfo, BufferBarrier *, Hasher<BufferBarrierInfo>> _bufferBarriers;
|
||||
|
||||
private:
|
||||
ccstd::vector<Swapchain *> _swapchains; // weak reference
|
||||
};
|
||||
|
||||
class DefaultResource {
|
||||
public:
|
||||
explicit DefaultResource(Device *device);
|
||||
|
||||
~DefaultResource() = default;
|
||||
|
||||
Texture *getTexture(TextureType type) const;
|
||||
Buffer *getBuffer() const;
|
||||
|
||||
private:
|
||||
IntrusivePtr<Texture> _texture2D;
|
||||
IntrusivePtr<Texture> _texture2DArray;
|
||||
IntrusivePtr<Texture> _textureCube;
|
||||
IntrusivePtr<Texture> _texture3D;
|
||||
IntrusivePtr<Buffer> _buffer;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommandBuffer *Device::createCommandBuffer(const CommandBufferInfo &info) {
|
||||
CommandBuffer *res = createCommandBuffer(info, false);
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Queue *Device::createQueue(const QueueInfo &info) {
|
||||
Queue *res = createQueue();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
QueryPool *Device::createQueryPool(const QueryPoolInfo &info) {
|
||||
QueryPool *res = createQueryPool();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Swapchain *Device::createSwapchain(const SwapchainInfo &info) {
|
||||
Swapchain *res = createSwapchain();
|
||||
res->initialize(info);
|
||||
_swapchains.push_back(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
Buffer *Device::createBuffer(const BufferInfo &info) {
|
||||
Buffer *res = createBuffer();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Buffer *Device::createBuffer(const BufferViewInfo &info) {
|
||||
Buffer *res = createBuffer();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Texture *Device::createTexture(const TextureInfo &info) {
|
||||
Texture *res = createTexture();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Texture *Device::createTexture(const TextureViewInfo &info) {
|
||||
Texture *res = createTexture();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Shader *Device::createShader(const ShaderInfo &info) {
|
||||
Shader *res = createShader();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
InputAssembler *Device::createInputAssembler(const InputAssemblerInfo &info) {
|
||||
InputAssembler *res = createInputAssembler();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
RenderPass *Device::createRenderPass(const RenderPassInfo &info) {
|
||||
RenderPass *res = createRenderPass();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
Framebuffer *Device::createFramebuffer(const FramebufferInfo &info) {
|
||||
Framebuffer *res = createFramebuffer();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
DescriptorSet *Device::createDescriptorSet(const DescriptorSetInfo &info) {
|
||||
DescriptorSet *res = createDescriptorSet();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
DescriptorSetLayout *Device::createDescriptorSetLayout(const DescriptorSetLayoutInfo &info) {
|
||||
DescriptorSetLayout *res = createDescriptorSetLayout();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
PipelineLayout *Device::createPipelineLayout(const PipelineLayoutInfo &info) {
|
||||
PipelineLayout *res = createPipelineLayout();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
PipelineState *Device::createPipelineState(const PipelineStateInfo &info) {
|
||||
PipelineState *res = createPipelineState();
|
||||
res->initialize(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
void Device::copyBuffersToTexture(const BufferDataList &buffers, Texture *dst, const BufferTextureCopyList ®ions) {
|
||||
copyBuffersToTexture(buffers.data(), dst, regions.data(), utils::toUint(regions.size()));
|
||||
}
|
||||
|
||||
void Device::copyTextureToBuffers(Texture *src, BufferSrcList &buffers, const BufferTextureCopyList ®ions) {
|
||||
copyTextureToBuffers(src, buffers.data(), regions.data(), utils::toUint(regions.size()));
|
||||
}
|
||||
|
||||
void Device::flushCommands(const ccstd::vector<CommandBuffer *> &cmdBuffs) {
|
||||
flushCommands(cmdBuffs.data(), utils::toUint(cmdBuffs.size()));
|
||||
}
|
||||
|
||||
void Device::acquire(const ccstd::vector<Swapchain *> &swapchains) {
|
||||
acquire(swapchains.data(), utils::toUint(swapchains.size()));
|
||||
}
|
||||
|
||||
template <typename ExecuteMethod>
|
||||
void Device::registerOnAcquireCallback(ExecuteMethod &&execute) {
|
||||
_onAcquire = ccnew CallbackExecutable<ExecuteMethod>(std::forward<ExecuteMethod>(execute));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
71
cocos/renderer/gfx-base/GFXDeviceObject.h
Normal file
71
cocos/renderer/gfx-base/GFXDeviceObject.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
|
||||
http://www.cocos.com
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include "base/Macros.h"
|
||||
#include "base/Ptr.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
struct DefaultDeleter {
|
||||
template <typename T>
|
||||
void operator()(T *ptr) const {
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Deleter = DefaultDeleter>
|
||||
class GFXDeviceObject {
|
||||
public:
|
||||
virtual ~GFXDeviceObject() noexcept = default;
|
||||
|
||||
void addRef() const noexcept {
|
||||
++_referenceCount;
|
||||
}
|
||||
|
||||
void release() const noexcept {
|
||||
// atomic::operator _Ty uses load(memory_order_seq_cst), all threads observe all modifications in the same order.
|
||||
auto count = static_cast<int32_t>(--_referenceCount);
|
||||
CC_ASSERT_GE(count, 0);
|
||||
if (count == 0) {
|
||||
Deleter()(this);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getRefCount() const noexcept {
|
||||
return static_cast<uint32_t>(_referenceCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
GFXDeviceObject() noexcept = default;
|
||||
|
||||
mutable std::atomic_uint32_t _referenceCount{0};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using ConstPtr = IntrusivePtr<const T>;
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
62
cocos/renderer/gfx-base/GFXFramebuffer.cpp
Normal file
62
cocos/renderer/gfx-base/GFXFramebuffer.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXFramebuffer.h"
|
||||
#include "GFXRenderPass.h"
|
||||
#include "GFXTexture.h"
|
||||
#include "base/Utils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
Framebuffer::Framebuffer()
|
||||
: GFXObject(ObjectType::FRAMEBUFFER) {
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer() = default;
|
||||
|
||||
ccstd::hash_t Framebuffer::computeHash(const FramebufferInfo &info) {
|
||||
return Hasher<FramebufferInfo>()(info);
|
||||
}
|
||||
|
||||
void Framebuffer::initialize(const FramebufferInfo &info) {
|
||||
_renderPass = info.renderPass;
|
||||
_colorTextures = info.colorTextures;
|
||||
_depthStencilTexture = info.depthStencilTexture;
|
||||
_depthStencilResolveTexture = info.depthStencilResolveTexture;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void Framebuffer::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_renderPass = nullptr;
|
||||
_colorTextures.clear();
|
||||
_depthStencilTexture = nullptr;
|
||||
_depthStencilResolveTexture = nullptr;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
64
cocos/renderer/gfx-base/GFXFramebuffer.h
Normal file
64
cocos/renderer/gfx-base/GFXFramebuffer.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/Ptr.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/RefVector.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL Framebuffer : public GFXObject, public RefCounted {
|
||||
public:
|
||||
Framebuffer();
|
||||
~Framebuffer() override;
|
||||
|
||||
static ccstd::hash_t computeHash(const FramebufferInfo &info);
|
||||
|
||||
void initialize(const FramebufferInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline RenderPass *getRenderPass() const { return _renderPass; }
|
||||
inline const TextureList &getColorTextures() const { return _colorTextures; }
|
||||
inline Texture *getDepthStencilTexture() const { return _depthStencilTexture; }
|
||||
inline Texture *getDepthStencilResolveTexture() const { return _depthStencilResolveTexture; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const FramebufferInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
// weak reference
|
||||
RenderPass *_renderPass{nullptr};
|
||||
// weak reference
|
||||
TextureList _colorTextures;
|
||||
// weak reference
|
||||
Texture *_depthStencilTexture{nullptr};
|
||||
Texture *_depthStencilResolveTexture{nullptr};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
86
cocos/renderer/gfx-base/GFXInputAssembler.cpp
Normal file
86
cocos/renderer/gfx-base/GFXInputAssembler.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/std/hash/hash.h"
|
||||
|
||||
#include "GFXBuffer.h"
|
||||
#include "GFXInputAssembler.h"
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
InputAssembler::InputAssembler()
|
||||
: GFXObject(ObjectType::INPUT_ASSEMBLER) {
|
||||
}
|
||||
|
||||
InputAssembler::~InputAssembler() = default;
|
||||
|
||||
ccstd::hash_t InputAssembler::computeAttributesHash() const {
|
||||
ccstd::hash_t seed = static_cast<uint32_t>(_attributes.size()) * 6;
|
||||
for (const auto &attribute : _attributes) {
|
||||
ccstd::hash_combine(seed, attribute.name);
|
||||
ccstd::hash_combine(seed, attribute.format);
|
||||
ccstd::hash_combine(seed, attribute.isNormalized);
|
||||
ccstd::hash_combine(seed, attribute.stream);
|
||||
ccstd::hash_combine(seed, attribute.isInstanced);
|
||||
ccstd::hash_combine(seed, attribute.location);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
void InputAssembler::initialize(const InputAssemblerInfo &info) {
|
||||
_attributes = info.attributes;
|
||||
_vertexBuffers = info.vertexBuffers;
|
||||
_indexBuffer = info.indexBuffer;
|
||||
_indirectBuffer = info.indirectBuffer;
|
||||
_attributesHash = computeAttributesHash();
|
||||
|
||||
if (_indexBuffer) {
|
||||
_drawInfo.indexCount = _indexBuffer->getCount();
|
||||
_drawInfo.firstIndex = 0;
|
||||
} else if (!_vertexBuffers.empty()) {
|
||||
_drawInfo.vertexCount = _vertexBuffers[0]->getCount();
|
||||
_drawInfo.firstVertex = 0;
|
||||
_drawInfo.vertexOffset = 0;
|
||||
}
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void InputAssembler::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_attributes.clear();
|
||||
_attributesHash = 0U;
|
||||
|
||||
_vertexBuffers.clear();
|
||||
_indexBuffer = nullptr;
|
||||
_indirectBuffer = nullptr;
|
||||
|
||||
_drawInfo = DrawInfo();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
83
cocos/renderer/gfx-base/GFXInputAssembler.h
Normal file
83
cocos/renderer/gfx-base/GFXInputAssembler.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL InputAssembler : public GFXObject, public RefCounted {
|
||||
public:
|
||||
InputAssembler();
|
||||
~InputAssembler() override;
|
||||
|
||||
void initialize(const InputAssemblerInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline const AttributeList &getAttributes() const { return _attributes; }
|
||||
inline const BufferList &getVertexBuffers() const { return _vertexBuffers; }
|
||||
inline Buffer *getIndexBuffer() const { return _indexBuffer; }
|
||||
inline Buffer *getIndirectBuffer() const { return _indirectBuffer; }
|
||||
inline ccstd::hash_t getAttributesHash() const { return _attributesHash; }
|
||||
|
||||
inline const DrawInfo &getDrawInfo() const { return _drawInfo; }
|
||||
inline void setDrawInfo(const DrawInfo &info) { _drawInfo = info; }
|
||||
|
||||
inline void setVertexCount(uint32_t count) { _drawInfo.vertexCount = count; }
|
||||
inline void setFirstVertex(uint32_t first) { _drawInfo.firstVertex = first; }
|
||||
inline void setIndexCount(uint32_t count) { _drawInfo.indexCount = count; }
|
||||
inline void setFirstIndex(uint32_t first) { _drawInfo.firstIndex = first; }
|
||||
inline void setVertexOffset(int32_t offset) { _drawInfo.vertexOffset = offset; }
|
||||
inline void setInstanceCount(uint32_t count) { _drawInfo.instanceCount = count; }
|
||||
inline void setFirstInstance(uint32_t first) { _drawInfo.firstInstance = first; }
|
||||
|
||||
inline uint32_t getVertexCount() const { return _drawInfo.vertexCount; }
|
||||
inline uint32_t getFirstVertex() const { return _drawInfo.firstVertex; }
|
||||
inline uint32_t getIndexCount() const { return _drawInfo.indexCount; }
|
||||
inline uint32_t getFirstIndex() const { return _drawInfo.firstIndex; }
|
||||
inline uint32_t getVertexOffset() const { return _drawInfo.vertexOffset; }
|
||||
inline uint32_t getInstanceCount() const { return _drawInfo.instanceCount; }
|
||||
inline uint32_t getFirstInstance() const { return _drawInfo.firstInstance; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const InputAssemblerInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
ccstd::hash_t computeAttributesHash() const;
|
||||
|
||||
AttributeList _attributes;
|
||||
ccstd::hash_t _attributesHash = 0;
|
||||
|
||||
BufferList _vertexBuffers;
|
||||
Buffer *_indexBuffer{nullptr};
|
||||
Buffer *_indirectBuffer{nullptr};
|
||||
|
||||
DrawInfo _drawInfo;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
35
cocos/renderer/gfx-base/GFXObject.cpp
Normal file
35
cocos/renderer/gfx-base/GFXObject.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
GFXObject::GFXObject(ObjectType type)
|
||||
: _objectType(type),
|
||||
_objectID(generateObjectID<GFXObject>()) {}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
59
cocos/renderer/gfx-base/GFXObject.h
Normal file
59
cocos/renderer/gfx-base/GFXObject.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class GFXObject {
|
||||
public:
|
||||
explicit GFXObject(ObjectType type);
|
||||
virtual ~GFXObject() = default;
|
||||
|
||||
inline ObjectType getObjectType() const { return _objectType; }
|
||||
inline uint32_t getObjectID() const { return _objectID; }
|
||||
inline uint32_t getTypedID() const { return _typedID; }
|
||||
|
||||
inline static uint32_t getObjectID(const GFXObject *obj) {
|
||||
return obj == nullptr ? INVALID_OBJECT_ID : obj->getObjectID();
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
static uint32_t generateObjectID() noexcept {
|
||||
static uint32_t generator = 1 << 16;
|
||||
return ++generator;
|
||||
}
|
||||
|
||||
static constexpr uint32_t INVALID_OBJECT_ID = 0;
|
||||
ObjectType _objectType = ObjectType::UNKNOWN;
|
||||
uint32_t _objectID = 0U;
|
||||
|
||||
uint32_t _typedID = 0U; // inited by sub-classes
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-base/GFXPipelineLayout.cpp
Normal file
50
cocos/renderer/gfx-base/GFXPipelineLayout.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXPipelineLayout.h"
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
PipelineLayout::PipelineLayout()
|
||||
: GFXObject(ObjectType::PIPELINE_LAYOUT) {
|
||||
}
|
||||
|
||||
PipelineLayout::~PipelineLayout() = default;
|
||||
|
||||
void PipelineLayout::initialize(const PipelineLayoutInfo &info) {
|
||||
_setLayouts = info.setLayouts;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void PipelineLayout::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_setLayouts.clear();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
51
cocos/renderer/gfx-base/GFXPipelineLayout.h
Normal file
51
cocos/renderer/gfx-base/GFXPipelineLayout.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL PipelineLayout : public GFXObject, public RefCounted {
|
||||
public:
|
||||
PipelineLayout();
|
||||
~PipelineLayout() override;
|
||||
|
||||
void initialize(const PipelineLayoutInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline const DescriptorSetLayoutList &getSetLayouts() const { return _setLayouts; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const PipelineLayoutInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
DescriptorSetLayoutList _setLayouts;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
62
cocos/renderer/gfx-base/GFXPipelineState.cpp
Normal file
62
cocos/renderer/gfx-base/GFXPipelineState.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXPipelineState.h"
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
PipelineState::PipelineState()
|
||||
: GFXObject(ObjectType::PIPELINE_STATE) {
|
||||
}
|
||||
|
||||
PipelineState::~PipelineState() = default;
|
||||
|
||||
void PipelineState::initialize(const PipelineStateInfo &info) {
|
||||
_primitive = info.primitive;
|
||||
_shader = info.shader;
|
||||
_inputState = info.inputState;
|
||||
_rasterizerState = info.rasterizerState;
|
||||
_depthStencilState = info.depthStencilState;
|
||||
_bindPoint = info.bindPoint;
|
||||
_blendState = info.blendState;
|
||||
_dynamicStates = info.dynamicStates;
|
||||
_renderPass = info.renderPass;
|
||||
_subpass = info.subpass;
|
||||
_pipelineLayout = info.pipelineLayout;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void PipelineState::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_shader = nullptr;
|
||||
_renderPass = nullptr;
|
||||
_pipelineLayout = nullptr;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
70
cocos/renderer/gfx-base/GFXPipelineState.h
Normal file
70
cocos/renderer/gfx-base/GFXPipelineState.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL PipelineState : public GFXObject, public RefCounted {
|
||||
public:
|
||||
PipelineState();
|
||||
~PipelineState() override;
|
||||
|
||||
void initialize(const PipelineStateInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline Shader *getShader() const { return _shader; }
|
||||
inline PipelineBindPoint getBindPoint() const { return _bindPoint; }
|
||||
inline PrimitiveMode getPrimitive() const { return _primitive; }
|
||||
inline DynamicStateFlags getDynamicStates() const { return _dynamicStates; }
|
||||
inline const InputState &getInputState() const { return _inputState; }
|
||||
inline const RasterizerState &getRasterizerState() const { return _rasterizerState; }
|
||||
inline const DepthStencilState &getDepthStencilState() const { return _depthStencilState; }
|
||||
inline const BlendState &getBlendState() const { return _blendState; }
|
||||
inline const RenderPass *getRenderPass() const { return _renderPass; }
|
||||
inline const PipelineLayout *getPipelineLayout() const { return _pipelineLayout; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const PipelineStateInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
Shader *_shader = nullptr;
|
||||
PipelineBindPoint _bindPoint = PipelineBindPoint::GRAPHICS;
|
||||
PrimitiveMode _primitive = PrimitiveMode::TRIANGLE_LIST;
|
||||
DynamicStateFlags _dynamicStates = DynamicStateFlags::NONE;
|
||||
InputState _inputState;
|
||||
RasterizerState _rasterizerState;
|
||||
DepthStencilState _depthStencilState;
|
||||
BlendState _blendState;
|
||||
RenderPass *_renderPass = nullptr;
|
||||
uint32_t _subpass = 0U;
|
||||
PipelineLayout *_pipelineLayout = nullptr;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
52
cocos/renderer/gfx-base/GFXQueryPool.cpp
Normal file
52
cocos/renderer/gfx-base/GFXQueryPool.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXQueryPool.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
QueryPool::QueryPool()
|
||||
: GFXObject(ObjectType::QUERY_POOL) {
|
||||
}
|
||||
|
||||
QueryPool::~QueryPool() = default;
|
||||
|
||||
void QueryPool::initialize(const QueryPoolInfo &info) {
|
||||
_type = info.type;
|
||||
_maxQueryObjects = info.maxQueryObjects;
|
||||
_forceWait = info.forceWait;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void QueryPool::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_type = QueryType::OCCLUSION;
|
||||
_maxQueryObjects = 0;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
74
cocos/renderer/gfx-base/GFXQueryPool.h
Normal file
74
cocos/renderer/gfx-base/GFXQueryPool.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include "GFXObject.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
/**
|
||||
* QueryPool usage:
|
||||
* Update
|
||||
* Render
|
||||
* getQueryPoolResults
|
||||
* resetQueryPool
|
||||
* for each renderObject
|
||||
* beginQuery
|
||||
* drawObject
|
||||
* endQuery
|
||||
* completeQueryPool
|
||||
*/
|
||||
|
||||
class CC_DLL QueryPool : public GFXObject {
|
||||
public:
|
||||
QueryPool();
|
||||
~QueryPool() override;
|
||||
|
||||
void initialize(const QueryPoolInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline bool hasResult(uint32_t id) { return _results.count(id) != 0; }
|
||||
inline uint64_t getResult(uint32_t id) { return _results[id]; }
|
||||
inline QueryType getType() const { return _type; }
|
||||
inline uint32_t getMaxQueryObjects() const { return _maxQueryObjects; }
|
||||
inline bool getForceWait() const { return _forceWait; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const QueryPoolInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
QueryType _type{QueryType::OCCLUSION};
|
||||
uint32_t _maxQueryObjects{0};
|
||||
bool _forceWait{true};
|
||||
std::mutex _mutex;
|
||||
ccstd::unordered_map<uint32_t, uint64_t> _results;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-base/GFXQueue.cpp
Normal file
50
cocos/renderer/gfx-base/GFXQueue.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXQueue.h"
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
Queue::Queue()
|
||||
: GFXObject(ObjectType::QUEUE) {
|
||||
}
|
||||
|
||||
Queue::~Queue() = default;
|
||||
|
||||
void Queue::initialize(const QueueInfo &info) {
|
||||
_type = info.type;
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void Queue::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_type = QueueType::GRAPHICS;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
56
cocos/renderer/gfx-base/GFXQueue.h
Normal file
56
cocos/renderer/gfx-base/GFXQueue.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/Utils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL Queue : public GFXObject, public RefCounted {
|
||||
public:
|
||||
Queue();
|
||||
~Queue() override;
|
||||
|
||||
void initialize(const QueueInfo &info);
|
||||
void destroy();
|
||||
|
||||
virtual void submit(CommandBuffer *const *cmdBuffs, uint32_t count) = 0;
|
||||
|
||||
inline void submit(const CommandBufferList &cmdBuffs) { submit(cmdBuffs.data(), utils::toUint(cmdBuffs.size())); }
|
||||
|
||||
inline QueueType getType() const { return _type; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const QueueInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
QueueType _type = QueueType::GRAPHICS;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
78
cocos/renderer/gfx-base/GFXRenderPass.cpp
Normal file
78
cocos/renderer/gfx-base/GFXRenderPass.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "base/std/hash/hash.h"
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "GFXRenderPass.h"
|
||||
#include "base/Utils.h"
|
||||
#include "gfx-base/GFXDef-common.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
RenderPass::RenderPass()
|
||||
: GFXObject(ObjectType::RENDER_PASS) {
|
||||
}
|
||||
|
||||
RenderPass::~RenderPass() = default;
|
||||
|
||||
// Based on render pass compatibility
|
||||
ccstd::hash_t RenderPass::computeHash() {
|
||||
ccstd::hash_t seed = static_cast<uint32_t>(_colorAttachments.size()) * 2 + 3;
|
||||
for (const ColorAttachment &ca : _colorAttachments) {
|
||||
ccstd::hash_combine(seed, ca);
|
||||
}
|
||||
ccstd::hash_combine(seed, _depthStencilAttachment);
|
||||
ccstd::hash_combine(seed, _depthStencilResolveAttachment);
|
||||
|
||||
ccstd::hash_combine(seed, _subpasses);
|
||||
return seed;
|
||||
}
|
||||
|
||||
ccstd::hash_t RenderPass::computeHash(const RenderPassInfo &info) {
|
||||
return Hasher<RenderPassInfo>()(info);
|
||||
}
|
||||
|
||||
void RenderPass::initialize(const RenderPassInfo &info) {
|
||||
_colorAttachments = info.colorAttachments;
|
||||
_depthStencilAttachment = info.depthStencilAttachment;
|
||||
_depthStencilResolveAttachment = info.depthStencilResolveAttachment;
|
||||
_subpasses = info.subpasses;
|
||||
_dependencies = info.dependencies;
|
||||
_hash = computeHash();
|
||||
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void RenderPass::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_colorAttachments.clear();
|
||||
_subpasses.clear();
|
||||
_hash = 0U;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
65
cocos/renderer/gfx-base/GFXRenderPass.h
Normal file
65
cocos/renderer/gfx-base/GFXRenderPass.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GFXObject.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL RenderPass : public GFXObject, public RefCounted {
|
||||
public:
|
||||
RenderPass();
|
||||
~RenderPass() override;
|
||||
|
||||
static ccstd::hash_t computeHash(const RenderPassInfo &info);
|
||||
|
||||
void initialize(const RenderPassInfo &info);
|
||||
void destroy();
|
||||
|
||||
inline const ColorAttachmentList &getColorAttachments() const { return _colorAttachments; }
|
||||
inline const DepthStencilAttachment &getDepthStencilAttachment() const { return _depthStencilAttachment; }
|
||||
inline const DepthStencilAttachment &getDepthStencilResolveAttachment() const { return _depthStencilResolveAttachment; }
|
||||
inline const SubpassInfoList &getSubpasses() const { return _subpasses; }
|
||||
inline const SubpassDependencyList &getDependencies() const { return _dependencies; }
|
||||
inline ccstd::hash_t getHash() const { return _hash; }
|
||||
|
||||
protected:
|
||||
ccstd::hash_t computeHash();
|
||||
|
||||
virtual void doInit(const RenderPassInfo &info) = 0;
|
||||
virtual void doDestroy() = 0;
|
||||
|
||||
ColorAttachmentList _colorAttachments;
|
||||
DepthStencilAttachment _depthStencilAttachment;
|
||||
DepthStencilAttachment _depthStencilResolveAttachment;
|
||||
SubpassInfoList _subpasses;
|
||||
SubpassDependencyList _dependencies;
|
||||
ccstd::hash_t _hash = 0;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
68
cocos/renderer/gfx-base/GFXShader.cpp
Normal file
68
cocos/renderer/gfx-base/GFXShader.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2019-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "GFXShader.h"
|
||||
#include "GFXDevice.h"
|
||||
#include "GFXObject.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
Shader::Shader()
|
||||
: GFXObject(ObjectType::SHADER) {
|
||||
}
|
||||
|
||||
Shader::~Shader() = default;
|
||||
|
||||
void Shader::initialize(const ShaderInfo &info) {
|
||||
_name = info.name;
|
||||
_stages = info.stages;
|
||||
_attributes = info.attributes;
|
||||
_blocks = info.blocks;
|
||||
_buffers = info.buffers;
|
||||
_samplerTextures = info.samplerTextures;
|
||||
_samplers = info.samplers;
|
||||
_textures = info.textures;
|
||||
_images = info.images;
|
||||
_subpassInputs = info.subpassInputs;
|
||||
_hash = info.hash;
|
||||
doInit(info);
|
||||
}
|
||||
|
||||
void Shader::destroy() {
|
||||
doDestroy();
|
||||
|
||||
_stages.clear();
|
||||
_attributes.clear();
|
||||
_blocks.clear();
|
||||
_buffers.clear();
|
||||
_samplerTextures.clear();
|
||||
_samplers.clear();
|
||||
_textures.clear();
|
||||
_images.clear();
|
||||
_subpassInputs.clear();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user