no message
This commit is contained in:
208
cocos/renderer/gfx-validator/BufferValidator.cpp
Normal file
208
cocos/renderer/gfx-validator/BufferValidator.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/****************************************************************************
|
||||
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 "BufferValidator.h"
|
||||
#include <cstring>
|
||||
#include "DeviceValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
#include "base/Log.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
BufferValidator::BufferValidator(Buffer *actor)
|
||||
: Agent<Buffer>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
BufferValidator::~BufferValidator() {
|
||||
DeviceResourceTracker<Buffer>::erase(this);
|
||||
|
||||
if (_source != nullptr) {
|
||||
CC_ASSERT(_isBufferView);
|
||||
_source->removeView(this);
|
||||
}
|
||||
for (auto *view : _views) {
|
||||
CC_ASSERT(view->isBufferView());
|
||||
view->onExpire();
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(_actor);
|
||||
|
||||
uint64_t lifeTime = DeviceValidator::getInstance()->currentFrame() - _creationFrame;
|
||||
// skip those that have never been updated
|
||||
if (!_isBufferView && hasFlag(_memUsage, MemoryUsageBit::HOST) && _totalUpdateTimes && _totalUpdateTimes < lifeTime / 3) {
|
||||
CC_LOG_WARNING("Triple buffer enabled for infrequently-updated buffer, consider using MemoryUsageBit::DEVICE instead");
|
||||
CC_LOG_DEBUG("Init Stacktrace: %s", _initStack.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void BufferValidator::doInit(const BufferInfo &info) {
|
||||
// Initialize twice?
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
CC_ASSERT_NE(info.usage, BufferUsageBit::NONE);
|
||||
CC_ASSERT_NE(info.memUsage, MemoryUsageBit::NONE);
|
||||
CC_ASSERT(info.size);
|
||||
CC_ASSERT(info.size / info.stride * info.stride == info.size);
|
||||
|
||||
_initStack = utils::getStacktraceJS();
|
||||
_creationFrame = DeviceValidator::getInstance()->currentFrame();
|
||||
_totalUpdateTimes = 0U;
|
||||
|
||||
if (hasFlag(info.usage, BufferUsageBit::VERTEX) && !info.stride) {
|
||||
// Invalid stride for vertex buffer.
|
||||
CC_ABORT();
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void BufferValidator::doInit(const BufferViewInfo &info) {
|
||||
// Initialize twice?
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
auto *vBuffer = static_cast<BufferValidator *>(info.buffer);
|
||||
// Already been destroyed?
|
||||
CC_ASSERT(vBuffer != nullptr && vBuffer->isInited());
|
||||
CC_ASSERT(info.offset + info.range <= info.buffer->getSize());
|
||||
// zero-sized buffer?
|
||||
CC_ASSERT(info.range);
|
||||
|
||||
uint32_t stride = info.buffer->getStride();
|
||||
// Offset is not multiple of stride?
|
||||
CC_ASSERT(info.offset / stride * stride == info.offset);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
BufferViewInfo actorInfo = info;
|
||||
actorInfo.buffer = vBuffer->getActor();
|
||||
|
||||
_source = vBuffer;
|
||||
_source->addView(this);
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void BufferValidator::doResize(uint32_t size, uint32_t /*count*/) {
|
||||
// Already been destroyed?
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Cannot resize through buffer views.
|
||||
CC_ASSERT(!_isBufferView);
|
||||
CC_ASSERT(size);
|
||||
|
||||
for (auto *view : _views) {
|
||||
view->onExpire();
|
||||
}
|
||||
_views.clear();
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->resize(size);
|
||||
}
|
||||
|
||||
void BufferValidator::doDestroy() {
|
||||
// Be destroyed twice?"
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void BufferValidator::update(const void *buffer, uint32_t size) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Cannot update through buffer views.
|
||||
CC_ASSERT(!_isBufferView);
|
||||
CC_ASSERT(size && size <= _size);
|
||||
CC_ASSERT(buffer);
|
||||
|
||||
if (hasFlag(_usage, BufferUsageBit::INDIRECT)) {
|
||||
const auto *drawInfo = static_cast<const DrawInfo *>(buffer);
|
||||
const size_t drawInfoCount = size / sizeof(DrawInfo);
|
||||
const bool isIndexed = drawInfoCount > 0 && drawInfo->indexCount > 0;
|
||||
for (size_t i = 1U; i < drawInfoCount; ++i) {
|
||||
if ((++drawInfo)->indexCount > 0 != isIndexed) {
|
||||
// Inconsistent indirect draw infos on using index buffer.
|
||||
CC_ABORT();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sanityCheck(buffer, size);
|
||||
++_totalUpdateTimes; // only count direct updates
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->update(buffer, size);
|
||||
}
|
||||
|
||||
void BufferValidator::sanityCheck(const void *buffer, uint32_t size) {
|
||||
uint64_t cur = DeviceValidator::getInstance()->currentFrame();
|
||||
|
||||
if (cur == _lastUpdateFrame) {
|
||||
// FIXME: minggo: as current implementation need to update some buffers more than once, so disable it.
|
||||
// Should enable it when it is fixed.
|
||||
// CC_LOG_WARNING(utils::getStacktraceJS().c_str());
|
||||
// CC_LOG_WARNING("performance warning: buffer updated more than once per frame");
|
||||
}
|
||||
|
||||
if (DeviceValidator::getInstance()->isRecording()) {
|
||||
_buffer.resize(_size);
|
||||
memcpy(_buffer.data(), buffer, size);
|
||||
}
|
||||
|
||||
_lastUpdateFrame = cur;
|
||||
}
|
||||
|
||||
void BufferValidator::addView(BufferValidator *view) {
|
||||
_views.emplace_back(view);
|
||||
}
|
||||
|
||||
void BufferValidator::removeView(BufferValidator *view) {
|
||||
_views.erase(std::remove(_views.begin(), _views.end(), view), _views.end());
|
||||
}
|
||||
|
||||
void BufferValidator::onExpire() {
|
||||
_source = nullptr;
|
||||
_expired = true;
|
||||
}
|
||||
|
||||
void BufferValidator::flush(const uint8_t *buffer) {
|
||||
Buffer::flushBuffer(_actor, buffer);
|
||||
}
|
||||
|
||||
uint8_t *BufferValidator::getStagingAddress() const {
|
||||
return Buffer::getBufferStagingAddress(_actor);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
75
cocos/renderer/gfx-validator/BufferValidator.h
Normal file
75
cocos/renderer/gfx-validator/BufferValidator.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
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/GFXBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL BufferValidator final : public Agent<Buffer> {
|
||||
public:
|
||||
explicit BufferValidator(Buffer *actor);
|
||||
~BufferValidator() override;
|
||||
|
||||
void update(const void *buffer, uint32_t size) override;
|
||||
|
||||
void sanityCheck(const void *buffer, uint32_t size);
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
inline bool isValid() const { return !_expired; }
|
||||
|
||||
protected:
|
||||
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;
|
||||
|
||||
void addView(BufferValidator *view);
|
||||
void removeView(BufferValidator *view);
|
||||
void onExpire();
|
||||
|
||||
ccstd::vector<uint8_t> _buffer;
|
||||
|
||||
BufferValidator *_source{nullptr};
|
||||
ccstd::vector<BufferValidator *> _views; // weak reference
|
||||
|
||||
uint64_t _lastUpdateFrame{0U};
|
||||
uint64_t _totalUpdateTimes{0U};
|
||||
uint64_t _creationFrame{0U};
|
||||
|
||||
bool _inited{false};
|
||||
bool _expired{false};
|
||||
|
||||
ccstd::string _initStack;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
619
cocos/renderer/gfx-validator/CommandBufferValidator.cpp
Normal file
619
cocos/renderer/gfx-validator/CommandBufferValidator.cpp
Normal file
@@ -0,0 +1,619 @@
|
||||
/****************************************************************************
|
||||
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/Macros.h"
|
||||
#include "base/job-system/JobSystem.h"
|
||||
|
||||
#include "BufferValidator.h"
|
||||
#include "CommandBufferValidator.h"
|
||||
#include "DescriptorSetValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "FramebufferValidator.h"
|
||||
#include "InputAssemblerValidator.h"
|
||||
#include "PipelineStateValidator.h"
|
||||
#include "QueryPoolValidator.h"
|
||||
#include "QueueValidator.h"
|
||||
#include "RenderPassValidator.h"
|
||||
#include "TextureValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
#include "gfx-base/GFXCommandBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
CommandBufferValidator::CommandBufferValidator(CommandBuffer *actor)
|
||||
: Agent<CommandBuffer>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
CommandBufferValidator::~CommandBufferValidator() {
|
||||
DeviceResourceTracker<CommandBuffer>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::initValidator() {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
size_t descriptorSetCount = DeviceValidator::getInstance()->bindingMappingInfo().setIndices.size();
|
||||
_curStates.descriptorSets.resize(descriptorSetCount);
|
||||
_curStates.dynamicOffsets.resize(descriptorSetCount);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::destroyValidator() {
|
||||
}
|
||||
|
||||
void CommandBufferValidator::doInit(const CommandBufferInfo &info) {
|
||||
initValidator();
|
||||
|
||||
// Already been destroyed?
|
||||
CC_ASSERT(info.queue && static_cast<QueueValidator *>(info.queue)->isInited());
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
CommandBufferInfo actorInfo = info;
|
||||
actorInfo.queue = static_cast<QueueValidator *>(info.queue)->getActor();
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::doDestroy() {
|
||||
// Destroy twice?
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void CommandBufferValidator::begin(RenderPass *renderPass, uint32_t subpass, Framebuffer *framebuffer) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(!renderPass || static_cast<RenderPassValidator *>(renderPass)->isInited());
|
||||
CC_ASSERT(!framebuffer || static_cast<FramebufferValidator *>(framebuffer)->isInited());
|
||||
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
// Primary command buffer cannot inherit render passes.
|
||||
CC_ASSERT(_type != CommandBufferType::PRIMARY || !renderPass);
|
||||
|
||||
// secondary command buffers enter the render pass right here
|
||||
_insideRenderPass = !!renderPass;
|
||||
_commandsFlushed = false;
|
||||
|
||||
_recorder.clear();
|
||||
_curStates.descriptorSets.assign(_curStates.descriptorSets.size(), nullptr);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
RenderPass *renderPassActor = renderPass ? static_cast<RenderPassValidator *>(renderPass)->getActor() : nullptr;
|
||||
Framebuffer *framebufferActor = framebuffer ? static_cast<FramebufferValidator *>(framebuffer)->getActor() : nullptr;
|
||||
|
||||
_actor->begin(renderPassActor, subpass, framebufferActor);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::end() {
|
||||
// Alread been destroyed?
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Still inside a render pass?
|
||||
CC_ASSERT(_type != CommandBufferType::PRIMARY || !_insideRenderPass);
|
||||
_insideRenderPass = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->end();
|
||||
}
|
||||
|
||||
void CommandBufferValidator::beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(renderPass && static_cast<RenderPassValidator *>(renderPass)->isInited());
|
||||
CC_ASSERT(fbo && static_cast<FramebufferValidator *>(fbo)->isInited());
|
||||
|
||||
// Command 'endRenderPass' must be recorded in primary command buffers.
|
||||
CC_ASSERT_EQ(_type, CommandBufferType::PRIMARY);
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
for (size_t i = 0; i < renderPass->getColorAttachments().size(); ++i) {
|
||||
const auto &desc = renderPass->getColorAttachments()[i];
|
||||
const auto *tex = fbo->getColorTextures()[i];
|
||||
CC_ASSERT(tex->getFormat() == desc.format);
|
||||
}
|
||||
if (fbo->getDepthStencilTexture()) {
|
||||
CC_ASSERT(fbo->getDepthStencilTexture()->getFormat() == renderPass->getDepthStencilAttachment().format);
|
||||
}
|
||||
|
||||
_insideRenderPass = true;
|
||||
_curSubpass = 0U;
|
||||
|
||||
_curStates.renderPass = renderPass;
|
||||
_curStates.framebuffer = fbo;
|
||||
_curStates.renderArea = renderArea;
|
||||
_curStates.clearDepth = depth;
|
||||
_curStates.clearStencil = stencil;
|
||||
size_t clearColorCount = renderPass->getColorAttachments().size();
|
||||
if (clearColorCount) {
|
||||
_curStates.clearColors.assign(colors, colors + clearColorCount);
|
||||
}
|
||||
|
||||
if (DeviceValidator::getInstance()->isRecording()) {
|
||||
_recorder.recordBeginRenderPass(_curStates);
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
static ccstd::vector<CommandBuffer *> secondaryCBActors;
|
||||
secondaryCBActors.resize(secondaryCBCount);
|
||||
|
||||
CommandBuffer **actorSecondaryCBs = nullptr;
|
||||
if (secondaryCBCount) {
|
||||
actorSecondaryCBs = secondaryCBActors.data();
|
||||
for (uint32_t i = 0; i < secondaryCBCount; ++i) {
|
||||
actorSecondaryCBs[i] = static_cast<CommandBufferValidator *>(secondaryCBs[i])->getActor();
|
||||
}
|
||||
}
|
||||
|
||||
RenderPass *renderPassActor = static_cast<RenderPassValidator *>(renderPass)->getActor();
|
||||
Framebuffer *framebufferActor = static_cast<FramebufferValidator *>(fbo)->getActor();
|
||||
|
||||
_actor->beginRenderPass(renderPassActor, framebufferActor, renderArea, colors, depth, stencil, actorSecondaryCBs, secondaryCBCount);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::nextSubpass() {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
++_curSubpass;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->nextSubpass();
|
||||
}
|
||||
|
||||
void CommandBufferValidator::endRenderPass() {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Command 'endRenderPass' must be recorded in primary command buffers.
|
||||
CC_ASSERT_EQ(_type, CommandBufferType::PRIMARY);
|
||||
CC_ASSERT(_insideRenderPass);
|
||||
_insideRenderPass = false;
|
||||
|
||||
if (DeviceValidator::getInstance()->isRecording()) {
|
||||
_recorder.recordEndRenderPass();
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->endRenderPass();
|
||||
}
|
||||
|
||||
void CommandBufferValidator::insertMarker(const MarkerInfo &marker) {
|
||||
_actor->insertMarker(marker);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::beginMarker(const MarkerInfo &marker) {
|
||||
_actor->beginMarker(marker);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::endMarker() {
|
||||
_actor->endMarker();
|
||||
}
|
||||
|
||||
void CommandBufferValidator::execute(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
if (!count) return; // be more lenient on this for now
|
||||
// Command 'execute' must be recorded in primary command buffers.
|
||||
CC_ASSERT_EQ(_type, CommandBufferType::PRIMARY);
|
||||
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
CC_ASSERT(cmdBuffs[i] && static_cast<CommandBufferValidator *>(cmdBuffs[i])->isInited());
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
static ccstd::vector<CommandBuffer *> cmdBuffActors;
|
||||
cmdBuffActors.resize(count);
|
||||
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
cmdBuffActors[i] = static_cast<CommandBufferValidator *>(cmdBuffs[i])->getActor();
|
||||
}
|
||||
|
||||
_actor->execute(cmdBuffActors.data(), count);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::bindPipelineState(PipelineState *pso) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(pso && static_cast<PipelineStateValidator *>(pso)->isInited());
|
||||
|
||||
_curStates.pipelineState = pso;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->bindPipelineState(static_cast<PipelineStateValidator *>(pso)->getActor());
|
||||
}
|
||||
|
||||
void CommandBufferValidator::bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(descriptorSet && static_cast<DescriptorSetValidator *>(descriptorSet)->isInited());
|
||||
|
||||
CC_ASSERT(set < DeviceValidator::getInstance()->bindingMappingInfo().setIndices.size());
|
||||
// CC_ASSERT(descriptorSet->getLayout()->getDynamicBindings().size() == dynamicOffsetCount); // be more lenient on this
|
||||
|
||||
_curStates.descriptorSets[set] = descriptorSet;
|
||||
_curStates.dynamicOffsets[set].assign(dynamicOffsets, dynamicOffsets + dynamicOffsetCount);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->bindDescriptorSet(set, static_cast<DescriptorSetValidator *>(descriptorSet)->getActor(), dynamicOffsetCount, dynamicOffsets);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::bindInputAssembler(InputAssembler *ia) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(ia && static_cast<InputAssemblerValidator *>(ia)->isInited());
|
||||
|
||||
_curStates.inputAssembler = ia;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->bindInputAssembler(static_cast<InputAssemblerValidator *>(ia)->getActor());
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setViewport(const Viewport &vp) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_curStates.viewport = vp;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setViewport(vp);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setScissor(const Rect &rect) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_curStates.scissor = rect;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setScissor(rect);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setLineWidth(float width) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_curStates.lineWidth = width;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setLineWidth(width);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setDepthBias(float constant, float clamp, float slope) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_curStates.depthBiasConstant = constant;
|
||||
_curStates.depthBiasClamp = clamp;
|
||||
_curStates.depthBiasSlope = slope;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setDepthBias(constant, clamp, slope);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setBlendConstants(const Color &constants) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_curStates.blendConstant = constants;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setBlendConstants(constants);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setDepthBound(float minBounds, float maxBounds) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_curStates.depthMinBounds = minBounds;
|
||||
_curStates.depthMaxBounds = maxBounds;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setDepthBound(minBounds, maxBounds);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setStencilWriteMask(StencilFace face, uint32_t mask) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
if (hasFlag(face, StencilFace::FRONT)) {
|
||||
_curStates.stencilStatesFront.writeMask = mask;
|
||||
}
|
||||
if (hasFlag(face, StencilFace::BACK)) {
|
||||
_curStates.stencilStatesBack.writeMask = mask;
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setStencilWriteMask(face, mask);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::setStencilCompareMask(StencilFace face, uint32_t ref, uint32_t mask) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
if (hasFlag(face, StencilFace::FRONT)) {
|
||||
_curStates.stencilStatesFront.reference = ref;
|
||||
_curStates.stencilStatesFront.compareMask = mask;
|
||||
}
|
||||
if (hasFlag(face, StencilFace::BACK)) {
|
||||
_curStates.stencilStatesBack.reference = ref;
|
||||
_curStates.stencilStatesBack.compareMask = mask;
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->setStencilCompareMask(face, ref, mask);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::draw(const DrawInfo &info) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Command 'draw' must be recorded inside render passes.
|
||||
CC_ASSERT(_insideRenderPass);
|
||||
|
||||
if (DeviceValidator::getInstance()->isRecording()) {
|
||||
_recorder.recordDrawcall(_curStates);
|
||||
}
|
||||
|
||||
const auto &psoLayouts = _curStates.pipelineState->getPipelineLayout()->getSetLayouts();
|
||||
for (size_t i = 0; i < psoLayouts.size(); ++i) {
|
||||
if (!_curStates.descriptorSets[i]) continue; // there may be inactive sets
|
||||
const auto &dsBindings = _curStates.descriptorSets[i]->getLayout()->getBindings();
|
||||
const auto &psoBindings = psoLayouts[i]->getBindings();
|
||||
CC_ASSERT(psoBindings.size() == dsBindings.size());
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->draw(info);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::updateBuffer(Buffer *buff, const void *data, uint32_t size) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(buff && static_cast<BufferValidator *>(buff)->isInited());
|
||||
|
||||
// Command 'updateBuffer' must be recorded in primary command buffers.
|
||||
CC_ASSERT_EQ(_type, CommandBufferType::PRIMARY);
|
||||
// Command 'updateBuffer' must be recorded outside render passes.
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
auto *bufferValidator = static_cast<BufferValidator *>(buff);
|
||||
bufferValidator->sanityCheck(data, size);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->updateBuffer(bufferValidator->getActor(), data, size);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::copyBuffersToTexture(const uint8_t *const *buffers, Texture *texture, const BufferTextureCopy *regions, uint32_t count) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(texture && static_cast<TextureValidator *>(texture)->isInited());
|
||||
|
||||
// Command 'copyBuffersToTexture' must be recorded in primary command buffers.
|
||||
CC_ASSERT_EQ(_type, CommandBufferType::PRIMARY);
|
||||
// Command 'copyBuffersToTexture' must be recorded outside render passes.
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
auto *textureValidator = static_cast<TextureValidator *>(texture);
|
||||
textureValidator->sanityCheck();
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->copyBuffersToTexture(buffers, textureValidator->getActor(), regions, count);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(srcTexture && static_cast<TextureValidator *>(srcTexture)->isInited());
|
||||
CC_ASSERT(dstTexture && static_cast<TextureValidator *>(dstTexture)->isInited());
|
||||
const auto &srcInfo = srcTexture->getInfo();
|
||||
const auto &dstInfo = dstTexture->getInfo();
|
||||
|
||||
CC_ASSERT(srcInfo.format == dstInfo.format);
|
||||
CC_ASSERT(srcInfo.format != Format::DEPTH_STENCIL &&
|
||||
srcInfo.format != Format::DEPTH);
|
||||
|
||||
CC_ASSERT(srcInfo.samples > SampleCount::X1 &&
|
||||
dstInfo.samples == SampleCount::X1);
|
||||
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const auto ®ion = regions[i];
|
||||
CC_ASSERT(region.srcOffset.x + region.extent.width <= srcInfo.width);
|
||||
CC_ASSERT(region.srcOffset.y + region.extent.height <= srcInfo.height);
|
||||
CC_ASSERT(region.srcOffset.z + region.extent.depth <= srcInfo.depth);
|
||||
|
||||
CC_ASSERT(region.dstOffset.x + region.extent.width <= dstInfo.width);
|
||||
CC_ASSERT(region.dstOffset.y + region.extent.height <= dstInfo.height);
|
||||
CC_ASSERT(region.dstOffset.z + region.extent.depth <= dstInfo.depth);
|
||||
}
|
||||
|
||||
Texture *actorSrcTexture = nullptr;
|
||||
Texture *actorDstTexture = nullptr;
|
||||
if (srcTexture) actorSrcTexture = static_cast<TextureValidator *>(srcTexture)->getActor();
|
||||
if (dstTexture) actorDstTexture = static_cast<TextureValidator *>(dstTexture)->getActor();
|
||||
|
||||
_actor->resolveTexture(actorSrcTexture, actorDstTexture, regions, count);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(srcTexture && static_cast<TextureValidator *>(srcTexture)->isInited());
|
||||
CC_ASSERT(dstTexture && static_cast<TextureValidator *>(dstTexture)->isInited());
|
||||
const auto &srcInfo = srcTexture->getInfo();
|
||||
const auto &dstInfo = dstTexture->getInfo();
|
||||
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const auto ®ion = regions[i];
|
||||
CC_ASSERT(region.srcOffset.x + region.extent.width <= srcInfo.width);
|
||||
CC_ASSERT(region.srcOffset.y + region.extent.height <= srcInfo.height);
|
||||
CC_ASSERT(region.srcOffset.z + region.extent.depth <= srcInfo.depth);
|
||||
|
||||
CC_ASSERT(region.dstOffset.x + region.extent.width <= dstInfo.width);
|
||||
CC_ASSERT(region.dstOffset.y + region.extent.height <= dstInfo.height);
|
||||
CC_ASSERT(region.dstOffset.z + region.extent.depth <= dstInfo.depth);
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
Texture *actorSrcTexture = nullptr;
|
||||
Texture *actorDstTexture = nullptr;
|
||||
if (srcTexture) actorSrcTexture = static_cast<TextureValidator *>(srcTexture)->getActor();
|
||||
if (dstTexture) actorDstTexture = static_cast<TextureValidator *>(dstTexture)->getActor();
|
||||
|
||||
_actor->copyTexture(actorSrcTexture, actorDstTexture, regions, count);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(srcTexture && static_cast<TextureValidator *>(srcTexture)->isInited());
|
||||
CC_ASSERT(dstTexture && static_cast<TextureValidator *>(dstTexture)->isInited());
|
||||
// Blit on multisampled texture is not allowed.
|
||||
CC_ASSERT(srcTexture->getInfo().samples == SampleCount::X1);
|
||||
// blit on multisampled texture is not allowed.
|
||||
CC_ASSERT(dstTexture->getInfo().samples == SampleCount::X1);
|
||||
|
||||
// Command 'blitTexture' must be recorded outside render passes.
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const auto ®ion = regions[i];
|
||||
CC_ASSERT(region.srcOffset.x + region.srcExtent.width <= srcTexture->getInfo().width);
|
||||
CC_ASSERT(region.srcOffset.y + region.srcExtent.height <= srcTexture->getInfo().height);
|
||||
CC_ASSERT(region.srcOffset.z + region.srcExtent.depth <= srcTexture->getInfo().depth);
|
||||
|
||||
CC_ASSERT(region.dstOffset.x + region.dstExtent.width <= dstTexture->getInfo().width);
|
||||
CC_ASSERT(region.dstOffset.y + region.dstExtent.height <= dstTexture->getInfo().height);
|
||||
CC_ASSERT(region.dstOffset.z + region.dstExtent.depth <= dstTexture->getInfo().depth);
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
Texture *actorSrcTexture = nullptr;
|
||||
Texture *actorDstTexture = nullptr;
|
||||
if (srcTexture) actorSrcTexture = static_cast<TextureValidator *>(srcTexture)->getActor();
|
||||
if (dstTexture) actorDstTexture = static_cast<TextureValidator *>(dstTexture)->getActor();
|
||||
|
||||
_actor->blitTexture(actorSrcTexture, actorDstTexture, regions, count, filter);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::dispatch(const DispatchInfo &info) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Command 'dispatch' must be recorded outside render passes.
|
||||
CC_ASSERT(!_insideRenderPass);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
DispatchInfo actorInfo = info;
|
||||
if (info.indirectBuffer) actorInfo.indirectBuffer = static_cast<BufferValidator *>(info.indirectBuffer)->getActor();
|
||||
|
||||
_actor->dispatch(info);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::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) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
for (uint32_t i = 0U; i < textureBarrierCount; ++i) {
|
||||
CC_ASSERT(textures[i] && static_cast<const TextureValidator *>(textures[i])->isInited());
|
||||
}
|
||||
|
||||
for (uint32_t i = 0U; i < bufferBarrierCount; ++i) {
|
||||
CC_ASSERT(buffers[i] && static_cast<const BufferValidator *>(buffers[i])->isInited());
|
||||
}
|
||||
/////////// execute ///////////
|
||||
|
||||
static ccstd::vector<Texture *> textureActors;
|
||||
textureActors.resize(textureBarrierCount);
|
||||
|
||||
Texture **actorTextures = nullptr;
|
||||
if (textureBarrierCount) {
|
||||
actorTextures = textureActors.data();
|
||||
for (uint32_t i = 0U; i < textureBarrierCount; ++i) {
|
||||
actorTextures[i] = textures[i] ? static_cast<const TextureValidator *>(textures[i])->getActor() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static ccstd::vector<Buffer *> bufferActors;
|
||||
bufferActors.resize(bufferBarrierCount);
|
||||
|
||||
Buffer **actorBuffers = nullptr;
|
||||
if (bufferBarrierCount) {
|
||||
actorBuffers = bufferActors.data();
|
||||
for (uint32_t i = 0U; i < bufferBarrierCount; ++i) {
|
||||
actorBuffers[i] = buffers[i] ? static_cast<const BufferValidator *>(buffers[i])->getActor() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
_actor->pipelineBarrier(barrier, bufferBarriers, actorBuffers, bufferBarrierCount, textureBarriers, actorTextures, textureBarrierCount);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::beginQuery(QueryPool *queryPool, uint32_t id) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(static_cast<QueryPoolValidator *>(queryPool)->isInited());
|
||||
|
||||
QueryPool *actorQueryPool = static_cast<QueryPoolValidator *>(queryPool)->getActor();
|
||||
_actor->beginQuery(actorQueryPool, id);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::endQuery(QueryPool *queryPool, uint32_t id) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(static_cast<QueryPoolValidator *>(queryPool)->isInited());
|
||||
|
||||
QueryPool *actorQueryPool = static_cast<QueryPoolValidator *>(queryPool)->getActor();
|
||||
_actor->endQuery(actorQueryPool, id);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::resetQueryPool(QueryPool *queryPool) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(static_cast<QueryPoolValidator *>(queryPool)->isInited());
|
||||
|
||||
QueryPool *actorQueryPool = static_cast<QueryPoolValidator *>(queryPool)->getActor();
|
||||
_actor->resetQueryPool(actorQueryPool);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::completeQueryPool(QueryPool *queryPool) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(static_cast<QueryPoolValidator *>(queryPool)->isInited());
|
||||
|
||||
QueryPool *actorQueryPool = static_cast<QueryPoolValidator *>(queryPool)->getActor();
|
||||
_actor->completeQueryPool(actorQueryPool);
|
||||
}
|
||||
|
||||
void CommandBufferValidator::customCommand(CustomCommand &&cmd) {
|
||||
_actor->customCommand(std::move(cmd));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
101
cocos/renderer/gfx-validator/CommandBufferValidator.h
Normal file
101
cocos/renderer/gfx-validator/CommandBufferValidator.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/****************************************************************************
|
||||
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"
|
||||
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL CommandBufferValidator final : public Agent<CommandBuffer> {
|
||||
public:
|
||||
explicit CommandBufferValidator(CommandBuffer *actor);
|
||||
~CommandBufferValidator() override;
|
||||
|
||||
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 bool isInited() const { return _inited; }
|
||||
inline bool isCommandsFlushed() const { return _commandsFlushed; }
|
||||
|
||||
protected:
|
||||
friend class DeviceValidator;
|
||||
|
||||
void initValidator();
|
||||
void destroyValidator();
|
||||
|
||||
void doInit(const CommandBufferInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
CommandBufferStorage _curStates;
|
||||
CommandRecorder _recorder;
|
||||
|
||||
bool _insideRenderPass{false};
|
||||
bool _commandsFlushed{false};
|
||||
uint32_t _curSubpass{0U};
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
112
cocos/renderer/gfx-validator/DescriptorSetLayoutValidator.cpp
Normal file
112
cocos/renderer/gfx-validator/DescriptorSetLayoutValidator.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/****************************************************************************
|
||||
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 "gfx-base/GFXDef-common.h"
|
||||
#include "math/Math.h"
|
||||
|
||||
#include "DescriptorSetLayoutValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DescriptorSetLayoutValidator::DescriptorSetLayoutValidator(DescriptorSetLayout *actor)
|
||||
: Agent<DescriptorSetLayout>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
DescriptorSetLayoutValidator::~DescriptorSetLayoutValidator() {
|
||||
DeviceResourceTracker<DescriptorSetLayout>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void DescriptorSetLayoutValidator::doInit(const DescriptorSetLayoutInfo &info) {
|
||||
// Initialize twice?
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
DescriptorSetLayoutBindingList bindings{info.bindings};
|
||||
std::sort(bindings.begin(), bindings.end(), [&](const auto &a, const auto &b) {
|
||||
return a.binding < b.binding;
|
||||
});
|
||||
|
||||
static constexpr uint32_t DESCRIPTOR_TYPE_ORDERS[]{
|
||||
INVALID_BINDING, // UNKNOWN
|
||||
0, // UNIFORM_BUFFER
|
||||
0, // DYNAMIC_UNIFORM_BUFFER
|
||||
4, // STORAGE_BUFFER
|
||||
4, // DYNAMIC_STORAGE_BUFFER
|
||||
1, // SAMPLER_TEXTURE
|
||||
2, // SAMPLER
|
||||
3, // TEXTURE
|
||||
5, // STORAGE_IMAGE
|
||||
6, // INPUT_ATTACHMENT
|
||||
};
|
||||
_typeCounts.resize(DESCRIPTOR_TYPE_ORDERS[utils::getBitPosition(toNumber(DescriptorType::INPUT_ATTACHMENT))] + 1);
|
||||
uint32_t lastType{0};
|
||||
for (const auto &binding : bindings) {
|
||||
CC_ASSERT(binding.binding != INVALID_BINDING);
|
||||
CC_ASSERT_NE(binding.descriptorType, DescriptorType::UNKNOWN);
|
||||
CC_ASSERT(math::isPowerOfTwo(toNumber(binding.descriptorType)));
|
||||
CC_ASSERT(binding.count);
|
||||
CC_ASSERT_NE(binding.stageFlags, ShaderStageFlagBit::NONE);
|
||||
for (const Sampler *sampler : binding.immutableSamplers) {
|
||||
CC_ASSERT(sampler);
|
||||
}
|
||||
/**
|
||||
* Descriptors should be defined strictly in the following order,
|
||||
* with consecutive bindings within each type:
|
||||
* * Block
|
||||
* * SamplerTexture
|
||||
* * Sampler
|
||||
* * Texture
|
||||
* * Buffer
|
||||
* * Image
|
||||
* * SubpassInput
|
||||
*/
|
||||
uint32_t type{DESCRIPTOR_TYPE_ORDERS[utils::getBitPosition(toNumber(binding.descriptorType))]};
|
||||
// deffered pipeline issue: https://github.com/cocos/cocos-engine/pull/10701
|
||||
// CC_ASSERT_LE(lastType, type);
|
||||
lastType = type;
|
||||
++_typeCounts[type];
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void DescriptorSetLayoutValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
52
cocos/renderer/gfx-validator/DescriptorSetLayoutValidator.h
Normal file
52
cocos/renderer/gfx-validator/DescriptorSetLayoutValidator.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
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 DescriptorSetLayoutValidator final : public Agent<DescriptorSetLayout> {
|
||||
public:
|
||||
explicit DescriptorSetLayoutValidator(DescriptorSetLayout *actor);
|
||||
~DescriptorSetLayoutValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
friend class PipelineLayoutValidator;
|
||||
|
||||
void doInit(const DescriptorSetLayoutInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
ccstd::vector<uint32_t> _typeCounts;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
191
cocos/renderer/gfx-validator/DescriptorSetValidator.cpp
Normal file
191
cocos/renderer/gfx-validator/DescriptorSetValidator.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/****************************************************************************
|
||||
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/Log.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "BufferValidator.h"
|
||||
#include "DescriptorSetLayoutValidator.h"
|
||||
#include "DescriptorSetValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "TextureValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DescriptorSetValidator::DescriptorSetValidator(DescriptorSet *actor)
|
||||
: Agent<DescriptorSet>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
DescriptorSetValidator::~DescriptorSetValidator() {
|
||||
DeviceResourceTracker<DescriptorSet>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::doInit(const DescriptorSetInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
CC_ASSERT(info.layout && static_cast<const DescriptorSetLayoutValidator *>(info.layout)->isInited());
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
DescriptorSetInfo actorInfo;
|
||||
actorInfo.layout = static_cast<const DescriptorSetLayoutValidator *>(info.layout)->getActor();
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::doDestroy() {
|
||||
// Destroy twice.
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::update() {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
const auto descriptorCount = _textures.size();
|
||||
|
||||
Texture *texture = nullptr;
|
||||
Sampler *sampler = nullptr;
|
||||
Format format = {};
|
||||
|
||||
for (size_t i = 0; i < descriptorCount; ++i) {
|
||||
texture = _textures[i].ptr;
|
||||
sampler = _samplers[i].ptr;
|
||||
if (texture == nullptr || sampler == nullptr) continue;
|
||||
format = texture->getInfo().format;
|
||||
|
||||
if (sampler->getInfo().magFilter == Filter::LINEAR ||
|
||||
sampler->getInfo().mipFilter == Filter::LINEAR ||
|
||||
sampler->getInfo().minFilter == Filter::LINEAR) {
|
||||
if (!hasFlag(DeviceValidator::getInstance()->getFormatFeatures(format), FormatFeature::LINEAR_FILTER)) {
|
||||
CC_LOG_WARNING("[WARNING]: Format doesn't support linear filter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DescriptorSet can not be updated after bound to CommandBuffer.
|
||||
CC_ASSERT(_referenceStamp < DeviceValidator::getInstance()->currentFrame());
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
if (!_isDirty) return;
|
||||
|
||||
_actor->update();
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::forceUpdate() {
|
||||
_isDirty = true;
|
||||
_actor->forceUpdate();
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::updateReferenceStamp() {
|
||||
_referenceStamp = DeviceValidator::getInstance()->currentFrame();
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) {
|
||||
CC_ASSERT(isInited());
|
||||
auto *vBuffer = static_cast<BufferValidator *>(buffer);
|
||||
CC_ASSERT(buffer && vBuffer->isInited());
|
||||
CC_ASSERT(vBuffer->isValid() && "Buffer View Expired");
|
||||
|
||||
const ccstd::vector<uint32_t> &bindingIndices = _layout->getBindingIndices();
|
||||
const DescriptorSetLayoutBindingList &bindings = _layout->getBindings();
|
||||
CC_ASSERT(binding < bindingIndices.size() && bindingIndices[binding] < bindings.size());
|
||||
|
||||
const DescriptorSetLayoutBinding &info = bindings[bindingIndices[binding]];
|
||||
CC_ASSERT(hasAnyFlags(info.descriptorType, DESCRIPTOR_BUFFER_TYPE));
|
||||
|
||||
if (hasAnyFlags(info.descriptorType, DESCRIPTOR_DYNAMIC_TYPE)) {
|
||||
// Should bind buffer views for dynamic descriptors.
|
||||
CC_ASSERT(buffer->isBufferView());
|
||||
}
|
||||
|
||||
if (hasAnyFlags(info.descriptorType, DescriptorType::UNIFORM_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER)) {
|
||||
CC_ASSERT(hasFlag(buffer->getUsage(), BufferUsageBit::UNIFORM));
|
||||
} else if (hasAnyFlags(info.descriptorType, DescriptorType::STORAGE_BUFFER | DescriptorType::DYNAMIC_STORAGE_BUFFER)) {
|
||||
CC_ASSERT(hasFlag(buffer->getUsage(), BufferUsageBit::STORAGE));
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
DescriptorSet::bindBuffer(binding, buffer, index, flags);
|
||||
|
||||
_actor->bindBuffer(binding, vBuffer->getActor(), index, flags);
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) {
|
||||
CC_ASSERT(isInited());
|
||||
CC_ASSERT(texture && static_cast<TextureValidator *>(texture)->isInited());
|
||||
|
||||
const ccstd::vector<uint32_t> &bindingIndices = _layout->getBindingIndices();
|
||||
const DescriptorSetLayoutBindingList &bindings = _layout->getBindings();
|
||||
CC_ASSERT(binding < bindingIndices.size() && bindingIndices[binding] < bindings.size());
|
||||
|
||||
const DescriptorSetLayoutBinding &info = bindings[bindingIndices[binding]];
|
||||
CC_ASSERT(hasAnyFlags(info.descriptorType, DESCRIPTOR_TEXTURE_TYPE));
|
||||
|
||||
if (hasFlag(info.descriptorType, DescriptorType::INPUT_ATTACHMENT)) {
|
||||
CC_ASSERT(hasFlag(texture->getInfo().usage, TextureUsageBit::INPUT_ATTACHMENT));
|
||||
} else if (hasFlag(info.descriptorType, DescriptorType::STORAGE_IMAGE)) {
|
||||
CC_ASSERT(hasFlag(texture->getInfo().usage, TextureUsageBit::STORAGE));
|
||||
} else {
|
||||
CC_ASSERT(hasFlag(texture->getInfo().usage, TextureUsageBit::SAMPLED));
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
DescriptorSet::bindTexture(binding, texture, index, flags);
|
||||
|
||||
_actor->bindTexture(binding, static_cast<TextureValidator *>(texture)->getActor(), index, flags);
|
||||
}
|
||||
|
||||
void DescriptorSetValidator::bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
const ccstd::vector<uint32_t> &bindingIndices = _layout->getBindingIndices();
|
||||
const DescriptorSetLayoutBindingList &bindings = _layout->getBindings();
|
||||
CC_ASSERT(binding < bindingIndices.size() && bindingIndices[binding] < bindings.size());
|
||||
|
||||
const DescriptorSetLayoutBinding &info = bindings[bindingIndices[binding]];
|
||||
CC_ASSERT(hasAnyFlags(info.descriptorType, DESCRIPTOR_TEXTURE_TYPE));
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
DescriptorSet::bindSampler(binding, sampler, index);
|
||||
|
||||
_actor->bindSampler(binding, sampler, index);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
59
cocos/renderer/gfx-validator/DescriptorSetValidator.h
Normal file
59
cocos/renderer/gfx-validator/DescriptorSetValidator.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
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 DescriptorSetValidator final : public Agent<DescriptorSet> {
|
||||
public:
|
||||
explicit DescriptorSetValidator(DescriptorSet *actor);
|
||||
~DescriptorSetValidator() 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;
|
||||
|
||||
void updateReferenceStamp();
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const DescriptorSetInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
uint64_t _referenceStamp{0U};
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
360
cocos/renderer/gfx-validator/DeviceValidator.cpp
Normal file
360
cocos/renderer/gfx-validator/DeviceValidator.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
/****************************************************************************
|
||||
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/Log.h"
|
||||
|
||||
#include "BufferValidator.h"
|
||||
#include "CommandBufferValidator.h"
|
||||
#include "DescriptorSetLayoutValidator.h"
|
||||
#include "DescriptorSetValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "FramebufferValidator.h"
|
||||
#include "InputAssemblerValidator.h"
|
||||
#include "PipelineLayoutValidator.h"
|
||||
#include "PipelineStateValidator.h"
|
||||
#include "QueryPoolValidator.h"
|
||||
#include "QueueValidator.h"
|
||||
#include "RenderPassValidator.h"
|
||||
#include "ShaderValidator.h"
|
||||
#include "SwapchainValidator.h"
|
||||
#include "TextureValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
DeviceValidator *DeviceValidator::instance = nullptr;
|
||||
bool DeviceValidator::allowStacktraceJS{true};
|
||||
|
||||
DeviceValidator *DeviceValidator::getInstance() {
|
||||
return DeviceValidator::instance;
|
||||
}
|
||||
|
||||
DeviceValidator::DeviceValidator(Device *device) : Agent(device) {
|
||||
DeviceValidator::instance = this;
|
||||
}
|
||||
|
||||
DeviceValidator::~DeviceValidator() {
|
||||
CC_SAFE_DELETE(_actor);
|
||||
DeviceValidator::instance = nullptr;
|
||||
}
|
||||
|
||||
bool DeviceValidator::doInit(const DeviceInfo &info) {
|
||||
uint32_t flexibleSet{info.bindingMappingInfo.setIndices.back()};
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxBlockCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxSamplerTextureCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxSamplerCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxTextureCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxBufferCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxImageCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
CC_ASSERT(!info.bindingMappingInfo.maxSubpassInputCounts[flexibleSet]); // Flexible set limits should be zero.
|
||||
|
||||
if (!_actor->initialize(info)) {
|
||||
return false;
|
||||
}
|
||||
_api = _actor->getGfxAPI();
|
||||
_deviceName = _actor->getDeviceName();
|
||||
_queue = ccnew QueueValidator(_actor->getQueue());
|
||||
_queryPool = ccnew QueryPoolValidator(_actor->getQueryPool());
|
||||
_cmdBuff = ccnew CommandBufferValidator(_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));
|
||||
|
||||
static_cast<QueueValidator *>(_queue)->_inited = true;
|
||||
static_cast<QueryPoolValidator *>(_queryPool)->_inited = true;
|
||||
static_cast<CommandBufferValidator *>(_cmdBuff)->_queue = _queue;
|
||||
static_cast<CommandBufferValidator *>(_cmdBuff)->initValidator();
|
||||
|
||||
DeviceResourceTracker<CommandBuffer>::push(_cmdBuff);
|
||||
DeviceResourceTracker<QueryPool>::push(_queryPool);
|
||||
DeviceResourceTracker<Queue>::push(_queue);
|
||||
|
||||
CC_LOG_INFO("Device validator enabled.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeviceValidator::doDestroy() {
|
||||
if (_cmdBuff) {
|
||||
static_cast<CommandBufferValidator *>(_cmdBuff)->destroyValidator();
|
||||
static_cast<CommandBufferValidator *>(_cmdBuff)->_actor = nullptr;
|
||||
delete _cmdBuff;
|
||||
_cmdBuff = nullptr;
|
||||
}
|
||||
if (_queryPool) {
|
||||
static_cast<QueryPoolValidator *>(_queryPool)->_actor = nullptr;
|
||||
delete _queryPool;
|
||||
_queryPool = nullptr;
|
||||
}
|
||||
if (_queue) {
|
||||
static_cast<QueueValidator *>(_queue)->_actor = nullptr;
|
||||
delete _queue;
|
||||
_queue = nullptr;
|
||||
}
|
||||
|
||||
DeviceResourceTracker<CommandBuffer>::checkEmpty();
|
||||
DeviceResourceTracker<QueryPool>::checkEmpty();
|
||||
DeviceResourceTracker<Queue>::checkEmpty();
|
||||
DeviceResourceTracker<Swapchain>::checkEmpty();
|
||||
DeviceResourceTracker<Buffer>::checkEmpty();
|
||||
DeviceResourceTracker<Texture>::checkEmpty();
|
||||
DeviceResourceTracker<Sampler>::checkEmpty();
|
||||
DeviceResourceTracker<Shader>::checkEmpty();
|
||||
DeviceResourceTracker<InputAssembler>::checkEmpty();
|
||||
DeviceResourceTracker<RenderPass>::checkEmpty();
|
||||
DeviceResourceTracker<Framebuffer>::checkEmpty();
|
||||
DeviceResourceTracker<DescriptorSet>::checkEmpty();
|
||||
DeviceResourceTracker<DescriptorSetLayout>::checkEmpty();
|
||||
DeviceResourceTracker<PipelineLayout>::checkEmpty();
|
||||
DeviceResourceTracker<PipelineState>::checkEmpty();
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void DeviceValidator::acquire(Swapchain *const *swapchains, uint32_t count) {
|
||||
static ccstd::vector<Swapchain *> swapchainActors;
|
||||
swapchainActors.resize(count);
|
||||
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
auto *swapchain = static_cast<SwapchainValidator *>(swapchains[i]);
|
||||
swapchainActors[i] = swapchain->getActor();
|
||||
}
|
||||
|
||||
if (_onAcquire) _onAcquire->execute();
|
||||
_actor->acquire(swapchainActors.data(), count);
|
||||
}
|
||||
|
||||
void DeviceValidator::present() {
|
||||
_actor->present();
|
||||
|
||||
++_currentFrame;
|
||||
}
|
||||
|
||||
CommandBuffer *DeviceValidator::createCommandBuffer(const CommandBufferInfo &info, bool hasAgent) {
|
||||
CommandBuffer *actor = _actor->createCommandBuffer(info, hasAgent);
|
||||
CommandBuffer *result = ccnew CommandBufferValidator(actor);
|
||||
DeviceResourceTracker<CommandBuffer>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Queue *DeviceValidator::createQueue() {
|
||||
Queue *actor = _actor->createQueue();
|
||||
Queue *result = ccnew QueueValidator(actor);
|
||||
DeviceResourceTracker<Queue>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QueryPool *DeviceValidator::createQueryPool() {
|
||||
QueryPool *actor = _actor->createQueryPool();
|
||||
QueryPool *result = ccnew QueryPoolValidator(actor);
|
||||
DeviceResourceTracker<QueryPool>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Swapchain *DeviceValidator::createSwapchain() {
|
||||
Swapchain *actor = _actor->createSwapchain();
|
||||
Swapchain *result = ccnew SwapchainValidator(actor);
|
||||
DeviceResourceTracker<Swapchain>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Buffer *DeviceValidator::createBuffer() {
|
||||
Buffer *actor = _actor->createBuffer();
|
||||
Buffer *result = ccnew BufferValidator(actor);
|
||||
DeviceResourceTracker<Buffer>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Texture *DeviceValidator::createTexture() {
|
||||
Texture *actor = _actor->createTexture();
|
||||
Texture *result = ccnew TextureValidator(actor);
|
||||
DeviceResourceTracker<Texture>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Shader *DeviceValidator::createShader() {
|
||||
Shader *actor = _actor->createShader();
|
||||
Shader *result = ccnew ShaderValidator(actor);
|
||||
DeviceResourceTracker<Shader>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
InputAssembler *DeviceValidator::createInputAssembler() {
|
||||
InputAssembler *actor = _actor->createInputAssembler();
|
||||
InputAssembler *result = ccnew InputAssemblerValidator(actor);
|
||||
DeviceResourceTracker<InputAssembler>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
RenderPass *DeviceValidator::createRenderPass() {
|
||||
RenderPass *actor = _actor->createRenderPass();
|
||||
RenderPass *result = ccnew RenderPassValidator(actor);
|
||||
DeviceResourceTracker<RenderPass>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Framebuffer *DeviceValidator::createFramebuffer() {
|
||||
Framebuffer *actor = _actor->createFramebuffer();
|
||||
Framebuffer *result = ccnew FramebufferValidator(actor);
|
||||
DeviceResourceTracker<Framebuffer>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
DescriptorSet *DeviceValidator::createDescriptorSet() {
|
||||
DescriptorSet *actor = _actor->createDescriptorSet();
|
||||
DescriptorSet *result = ccnew DescriptorSetValidator(actor);
|
||||
DeviceResourceTracker<DescriptorSet>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
DescriptorSetLayout *DeviceValidator::createDescriptorSetLayout() {
|
||||
DescriptorSetLayout *actor = _actor->createDescriptorSetLayout();
|
||||
DescriptorSetLayout *result = ccnew DescriptorSetLayoutValidator(actor);
|
||||
DeviceResourceTracker<DescriptorSetLayout>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
PipelineLayout *DeviceValidator::createPipelineLayout() {
|
||||
PipelineLayout *actor = _actor->createPipelineLayout();
|
||||
PipelineLayout *result = ccnew PipelineLayoutValidator(actor);
|
||||
DeviceResourceTracker<PipelineLayout>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
PipelineState *DeviceValidator::createPipelineState() {
|
||||
PipelineState *actor = _actor->createPipelineState();
|
||||
PipelineState *result = ccnew PipelineStateValidator(actor);
|
||||
DeviceResourceTracker<PipelineState>::push(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Sampler *DeviceValidator::getSampler(const SamplerInfo &info) {
|
||||
if (info.addressU != info.addressV || info.addressV != info.addressW) {
|
||||
CC_LOG_WARNING("Samplers with different wrapping modes may case reduced performance");
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
return _actor->getSampler(info);
|
||||
}
|
||||
|
||||
GeneralBarrier *DeviceValidator::getGeneralBarrier(const GeneralBarrierInfo &info) {
|
||||
/////////// execute ///////////
|
||||
return _actor->getGeneralBarrier(info);
|
||||
}
|
||||
|
||||
TextureBarrier *DeviceValidator::getTextureBarrier(const TextureBarrierInfo &info) {
|
||||
/////////// execute ///////////
|
||||
return _actor->getTextureBarrier(info);
|
||||
}
|
||||
|
||||
BufferBarrier *DeviceValidator::getBufferBarrier(const BufferBarrierInfo &info) {
|
||||
return _actor->getBufferBarrier(info);
|
||||
}
|
||||
|
||||
void DeviceValidator::copyBuffersToTexture(const uint8_t *const *buffers, Texture *dst, const BufferTextureCopy *regions, uint32_t count) {
|
||||
auto *textureValidator = static_cast<TextureValidator *>(dst);
|
||||
textureValidator->sanityCheck();
|
||||
|
||||
uint32_t blockWidth = formatAlignment(dst->getFormat()).first;
|
||||
uint32_t blockHeight = formatAlignment(dst->getFormat()).second;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const auto region = regions[i];
|
||||
uint32_t level = region.texSubres.mipLevel;
|
||||
|
||||
uint32_t offsetX = region.texOffset.x;
|
||||
uint32_t offsetY = region.texOffset.y;
|
||||
uint32_t extentX = region.texExtent.width;
|
||||
uint32_t extentY = region.texExtent.height;
|
||||
uint32_t imgWidth = dst->getWidth() >> level;
|
||||
uint32_t imgHeight = dst->getHeight() >> level;
|
||||
|
||||
CC_ASSERT(offsetX % blockWidth == 0);
|
||||
CC_ASSERT(offsetY % blockHeight == 0);
|
||||
|
||||
CC_ASSERT((extentX % blockWidth == 0) || (extentX % blockWidth != 0 && offsetX + extentX == imgWidth));
|
||||
CC_ASSERT((extentY % blockHeight == 0) || (extentY % blockHeight != 0 && offsetY + extentY == imgHeight));
|
||||
}
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->copyBuffersToTexture(buffers, textureValidator->getActor(), regions, count);
|
||||
}
|
||||
|
||||
void DeviceValidator::copyTextureToBuffers(Texture *src, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count) {
|
||||
auto *textureValidator = static_cast<TextureValidator *>(src);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->copyTextureToBuffers(textureValidator->getActor(), buffers, regions, count);
|
||||
}
|
||||
|
||||
void DeviceValidator::flushCommands(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
if (!count) return;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
static ccstd::vector<CommandBuffer *> cmdBuffActors;
|
||||
cmdBuffActors.resize(count);
|
||||
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
auto *cmdBuff = static_cast<CommandBufferValidator *>(cmdBuffs[i]);
|
||||
cmdBuff->_commandsFlushed = true;
|
||||
cmdBuffActors[i] = cmdBuff->getActor();
|
||||
}
|
||||
|
||||
_actor->flushCommands(cmdBuffActors.data(), count);
|
||||
}
|
||||
|
||||
void DeviceValidator::getQueryPoolResults(QueryPool *queryPool) {
|
||||
auto *actorQueryPool = static_cast<QueryPoolValidator *>(queryPool)->getActor();
|
||||
|
||||
_actor->getQueryPoolResults(actorQueryPool);
|
||||
|
||||
auto *actorQueryPoolValidator = static_cast<QueryPoolValidator *>(actorQueryPool);
|
||||
auto *queryPoolValidator = static_cast<QueryPoolValidator *>(queryPool);
|
||||
std::lock_guard<std::mutex> lock(actorQueryPoolValidator->_mutex);
|
||||
queryPoolValidator->_results = actorQueryPoolValidator->_results;
|
||||
}
|
||||
|
||||
void DeviceValidator::enableAutoBarrier(bool en) {
|
||||
_actor->enableAutoBarrier(en);
|
||||
}
|
||||
|
||||
void DeviceValidator::frameSync() {
|
||||
_actor->frameSync();
|
||||
}
|
||||
|
||||
SampleCount DeviceValidator::getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const {
|
||||
return _actor->getMaxSampleCount(format, usage, flags);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
116
cocos/renderer/gfx-validator/DeviceValidator.h
Normal file
116
cocos/renderer/gfx-validator/DeviceValidator.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
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/GFXDevice.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL DeviceValidator final : public Agent<Device> {
|
||||
public:
|
||||
static DeviceValidator *getInstance();
|
||||
static bool allowStacktraceJS;
|
||||
|
||||
~DeviceValidator() override;
|
||||
|
||||
using Device::copyBuffersToTexture;
|
||||
using Device::createBuffer;
|
||||
using Device::createBufferBarrier;
|
||||
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 getQueryPoolResults(QueryPool *queryPool) override;
|
||||
|
||||
void flushCommands(CommandBuffer *const *cmdBuffs, uint32_t count) 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(); }
|
||||
|
||||
inline void enableRecording(bool recording) { _recording = recording; }
|
||||
inline bool isRecording() const { return _recording; }
|
||||
inline uint64_t currentFrame() const { return _currentFrame; }
|
||||
|
||||
void enableAutoBarrier(bool enable) override;
|
||||
SampleCount getMaxSampleCount(Format format, TextureUsage usage, TextureFlags flags) const override;
|
||||
protected:
|
||||
static DeviceValidator *instance;
|
||||
|
||||
friend class DeviceManager;
|
||||
|
||||
explicit DeviceValidator(Device *device);
|
||||
|
||||
bool doInit(const DeviceInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
void bindContext(bool bound) override { _actor->bindContext(bound); }
|
||||
|
||||
bool _recording{false};
|
||||
uint64_t _currentFrame{1U};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
109
cocos/renderer/gfx-validator/FramebufferValidator.cpp
Normal file
109
cocos/renderer/gfx-validator/FramebufferValidator.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
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/Macros.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceValidator.h"
|
||||
#include "FramebufferValidator.h"
|
||||
#include "RenderPassValidator.h"
|
||||
#include "TextureValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
FramebufferValidator::FramebufferValidator(Framebuffer *actor)
|
||||
: Agent<Framebuffer>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
FramebufferValidator::~FramebufferValidator() {
|
||||
DeviceResourceTracker<Framebuffer>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void FramebufferValidator::doInit(const FramebufferInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
CC_ASSERT(info.renderPass && static_cast<RenderPassValidator *>(info.renderPass)->isInited());
|
||||
CC_ASSERT(!info.colorTextures.empty() || info.depthStencilTexture);
|
||||
CC_ASSERT(info.colorTextures.size() == info.renderPass->getColorAttachments().size());
|
||||
if (info.renderPass->getDepthStencilAttachment().format != Format::UNKNOWN) {
|
||||
CC_ASSERT(info.depthStencilTexture);
|
||||
}
|
||||
if (info.renderPass->getDepthStencilResolveAttachment().format != Format::UNKNOWN) {
|
||||
CC_ASSERT(info.depthStencilResolveTexture);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0U; i < info.colorTextures.size(); ++i) {
|
||||
const auto &desc = info.renderPass->getColorAttachments()[i];
|
||||
const auto *tex = info.colorTextures[i];
|
||||
CC_ASSERT(tex && static_cast<const TextureValidator *>(tex)->isInited());
|
||||
CC_ASSERT(hasAnyFlags(tex->getInfo().usage, TextureUsageBit::COLOR_ATTACHMENT | TextureUsageBit::DEPTH_STENCIL_ATTACHMENT | TextureUsageBit::SHADING_RATE));
|
||||
CC_ASSERT(tex->getFormat() == desc.format);
|
||||
}
|
||||
if (info.depthStencilTexture) {
|
||||
CC_ASSERT(static_cast<TextureValidator *>(info.depthStencilTexture)->isInited());
|
||||
CC_ASSERT(hasFlag(info.depthStencilTexture->getInfo().usage, TextureUsageBit::DEPTH_STENCIL_ATTACHMENT));
|
||||
CC_ASSERT(info.depthStencilTexture->getFormat() == info.renderPass->getDepthStencilAttachment().format);
|
||||
}
|
||||
if (info.depthStencilResolveTexture) {
|
||||
CC_ASSERT(static_cast<TextureValidator *>(info.depthStencilResolveTexture)->isInited());
|
||||
CC_ASSERT(hasFlag(info.depthStencilResolveTexture->getInfo().usage, TextureUsageBit::DEPTH_STENCIL_ATTACHMENT));
|
||||
CC_ASSERT(info.depthStencilResolveTexture->getFormat() == info.renderPass->getDepthStencilResolveAttachment().format);
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
FramebufferInfo actorInfo = info;
|
||||
for (uint32_t i = 0U; i < info.colorTextures.size(); ++i) {
|
||||
if (info.colorTextures[i]) {
|
||||
actorInfo.colorTextures[i] = static_cast<TextureValidator *>(info.colorTextures[i])->getActor();
|
||||
}
|
||||
}
|
||||
if (info.depthStencilTexture) {
|
||||
actorInfo.depthStencilTexture = static_cast<TextureValidator *>(info.depthStencilTexture)->getActor();
|
||||
}
|
||||
if (info.depthStencilResolveTexture) {
|
||||
actorInfo.depthStencilResolveTexture = static_cast<TextureValidator *>(info.depthStencilResolveTexture)->getActor();
|
||||
}
|
||||
actorInfo.renderPass = static_cast<RenderPassValidator *>(info.renderPass)->getActor();
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void FramebufferValidator::doDestroy() {
|
||||
// Destroy twice?
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-validator/FramebufferValidator.h
Normal file
48
cocos/renderer/gfx-validator/FramebufferValidator.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/GFXFramebuffer.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL FramebufferValidator final : public Agent<Framebuffer> {
|
||||
public:
|
||||
explicit FramebufferValidator(Framebuffer *actor);
|
||||
~FramebufferValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const FramebufferInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
94
cocos/renderer/gfx-validator/InputAssemblerValidator.cpp
Normal file
94
cocos/renderer/gfx-validator/InputAssemblerValidator.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
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 "BufferValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "InputAssemblerValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
InputAssemblerValidator::InputAssemblerValidator(InputAssembler *actor)
|
||||
: Agent<InputAssembler>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
InputAssemblerValidator::~InputAssemblerValidator() {
|
||||
DeviceResourceTracker<InputAssembler>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void InputAssemblerValidator::doInit(const InputAssemblerInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
// vertex attributes validations
|
||||
for (auto const &attribute : info.attributes) {
|
||||
// Format not supported for the specified features.
|
||||
CC_ASSERT(hasFlag(DeviceValidator::getInstance()->getFormatFeatures(attribute.format), FormatFeature::VERTEX_ATTRIBUTE));
|
||||
}
|
||||
|
||||
for (auto *vertexBuffer : info.vertexBuffers) {
|
||||
CC_ASSERT(vertexBuffer && static_cast<BufferValidator *>(vertexBuffer)->isInited());
|
||||
CC_ASSERT(hasFlag(vertexBuffer->getUsage(), BufferUsageBit::VERTEX));
|
||||
}
|
||||
if (info.indexBuffer) {
|
||||
CC_ASSERT(static_cast<BufferValidator *>(info.indexBuffer)->isInited());
|
||||
CC_ASSERT(hasFlag(info.indexBuffer->getUsage(), BufferUsageBit::INDEX));
|
||||
}
|
||||
if (info.indirectBuffer) {
|
||||
CC_ASSERT(static_cast<BufferValidator *>(info.indirectBuffer)->isInited());
|
||||
CC_ASSERT(hasFlag(info.indirectBuffer->getUsage(), BufferUsageBit::INDIRECT));
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
InputAssemblerInfo actorInfo = info;
|
||||
for (auto &vertexBuffer : actorInfo.vertexBuffers) {
|
||||
vertexBuffer = static_cast<BufferValidator *>(vertexBuffer)->getActor();
|
||||
}
|
||||
if (actorInfo.indexBuffer) {
|
||||
actorInfo.indexBuffer = static_cast<BufferValidator *>(actorInfo.indexBuffer)->getActor();
|
||||
}
|
||||
if (actorInfo.indirectBuffer) {
|
||||
actorInfo.indirectBuffer = static_cast<BufferValidator *>(actorInfo.indirectBuffer)->getActor();
|
||||
}
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void InputAssemblerValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-validator/InputAssemblerValidator.h
Normal file
48
cocos/renderer/gfx-validator/InputAssemblerValidator.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/GFXInputAssembler.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL InputAssemblerValidator final : public Agent<InputAssembler> {
|
||||
public:
|
||||
explicit InputAssemblerValidator(InputAssembler *actor);
|
||||
~InputAssemblerValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const InputAssemblerInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
87
cocos/renderer/gfx-validator/PipelineLayoutValidator.cpp
Normal file
87
cocos/renderer/gfx-validator/PipelineLayoutValidator.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
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/Macros.h"
|
||||
#include "base/threading/MessageQueue.h"
|
||||
|
||||
#include "DescriptorSetLayoutValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "PipelineLayoutValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
PipelineLayoutValidator::PipelineLayoutValidator(PipelineLayout *actor)
|
||||
: Agent<PipelineLayout>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
PipelineLayoutValidator::~PipelineLayoutValidator() {
|
||||
DeviceResourceTracker<PipelineLayout>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void PipelineLayoutValidator::doInit(const PipelineLayoutInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
const auto &bindingMappings{DeviceValidator::getInstance()->bindingMappingInfo()};
|
||||
// deffered pipeline issue: https://github.com/cocos/cocos-engine/pull/10701
|
||||
// for (uint32_t i = 0; i < info.setLayouts.size(); ++i) {
|
||||
// auto *layout{static_cast<DescriptorSetLayoutValidator *>(info.setLayouts[i])};
|
||||
// CC_ASSERT(layout && layout->isInited());
|
||||
// // check against limits specified in BindingMappingInfo
|
||||
// if (bindingMappings.setIndices.back() == i) continue; // flexible set
|
||||
// CC_ASSERT(layout->_typeCounts[0] <= bindingMappings.maxBlockCounts[i]);
|
||||
// CC_ASSERT(layout->_typeCounts[1] <= bindingMappings.maxSamplerTextureCounts[i]);
|
||||
// CC_ASSERT(layout->_typeCounts[2] <= bindingMappings.maxSamplerCounts[i]);
|
||||
// CC_ASSERT(layout->_typeCounts[3] <= bindingMappings.maxTextureCounts[i]);
|
||||
// CC_ASSERT(layout->_typeCounts[4] <= bindingMappings.maxBufferCounts[i]);
|
||||
// CC_ASSERT(layout->_typeCounts[5] <= bindingMappings.maxImageCounts[i]);
|
||||
// CC_ASSERT(layout->_typeCounts[6] <= bindingMappings.maxSubpassInputCounts[i]);
|
||||
// }
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
PipelineLayoutInfo actorInfo;
|
||||
actorInfo.setLayouts.resize(info.setLayouts.size());
|
||||
for (uint32_t i = 0U; i < info.setLayouts.size(); i++) {
|
||||
actorInfo.setLayouts[i] = static_cast<DescriptorSetLayoutValidator *>(info.setLayouts[i])->getActor();
|
||||
}
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void PipelineLayoutValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-validator/PipelineLayoutValidator.h
Normal file
48
cocos/renderer/gfx-validator/PipelineLayoutValidator.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/GFXPipelineLayout.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL PipelineLayoutValidator final : public Agent<PipelineLayout> {
|
||||
public:
|
||||
explicit PipelineLayoutValidator(PipelineLayout *actor);
|
||||
~PipelineLayoutValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const PipelineLayoutInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
74
cocos/renderer/gfx-validator/PipelineStateValidator.cpp
Normal file
74
cocos/renderer/gfx-validator/PipelineStateValidator.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/threading/MessageQueue.h"
|
||||
|
||||
#include "DeviceValidator.h"
|
||||
#include "PipelineLayoutValidator.h"
|
||||
#include "PipelineStateValidator.h"
|
||||
#include "RenderPassValidator.h"
|
||||
#include "ShaderValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
PipelineStateValidator::PipelineStateValidator(PipelineState *actor)
|
||||
: Agent<PipelineState>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
PipelineStateValidator::~PipelineStateValidator() {
|
||||
DeviceResourceTracker<PipelineState>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void PipelineStateValidator::doInit(const PipelineStateInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
CC_ASSERT(info.shader && static_cast<ShaderValidator *>(info.shader)->isInited());
|
||||
CC_ASSERT(info.pipelineLayout && static_cast<PipelineLayoutValidator *>(info.pipelineLayout)->isInited());
|
||||
CC_ASSERT(!info.renderPass || static_cast<RenderPassValidator *>(info.renderPass)->isInited());
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
PipelineStateInfo actorInfo = info;
|
||||
actorInfo.shader = static_cast<ShaderValidator *>(info.shader)->getActor();
|
||||
actorInfo.pipelineLayout = static_cast<PipelineLayoutValidator *>(info.pipelineLayout)->getActor();
|
||||
if (info.renderPass) actorInfo.renderPass = static_cast<RenderPassValidator *>(info.renderPass)->getActor();
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void PipelineStateValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-validator/PipelineStateValidator.h
Normal file
48
cocos/renderer/gfx-validator/PipelineStateValidator.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/GFXPipelineState.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL PipelineStateValidator final : public Agent<PipelineState> {
|
||||
public:
|
||||
explicit PipelineStateValidator(PipelineState *actor);
|
||||
~PipelineStateValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const PipelineStateInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
64
cocos/renderer/gfx-validator/QueryPoolValidator.cpp
Normal file
64
cocos/renderer/gfx-validator/QueryPoolValidator.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
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 "QueryPoolValidator.h"
|
||||
#include "CommandBufferValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
QueryPoolValidator::QueryPoolValidator(QueryPool *actor)
|
||||
: Agent<QueryPool>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
_type = actor->getType();
|
||||
_maxQueryObjects = actor->getMaxQueryObjects();
|
||||
}
|
||||
|
||||
QueryPoolValidator::~QueryPoolValidator() {
|
||||
DeviceResourceTracker<QueryPool>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void QueryPoolValidator::doInit(const QueryPoolInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void QueryPoolValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
50
cocos/renderer/gfx-validator/QueryPoolValidator.h
Normal file
50
cocos/renderer/gfx-validator/QueryPoolValidator.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/GFXQueryPool.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL QueryPoolValidator final : public Agent<QueryPool> {
|
||||
public:
|
||||
explicit QueryPoolValidator(QueryPool *actor);
|
||||
~QueryPoolValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
friend class DeviceValidator;
|
||||
|
||||
void doInit(const QueryPoolInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
85
cocos/renderer/gfx-validator/QueueValidator.cpp
Normal file
85
cocos/renderer/gfx-validator/QueueValidator.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
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 "QueueValidator.h"
|
||||
#include "CommandBufferValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
QueueValidator::QueueValidator(Queue *actor)
|
||||
: Agent<Queue>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
QueueValidator::~QueueValidator() {
|
||||
DeviceResourceTracker<Queue>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void QueueValidator::doInit(const QueueInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void QueueValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void QueueValidator::submit(CommandBuffer *const *cmdBuffs, uint32_t count) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
if (!count) return;
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
auto *cmdBuff = static_cast<CommandBufferValidator *>(cmdBuffs[i]);
|
||||
CC_ASSERT(cmdBuff && cmdBuff->isInited());
|
||||
// Command buffers must be flushed before submit.
|
||||
CC_ASSERT(cmdBuff->isCommandsFlushed());
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
static ccstd::vector<CommandBuffer *> cmdBuffActors;
|
||||
cmdBuffActors.resize(count);
|
||||
|
||||
for (uint32_t i = 0U; i < count; ++i) {
|
||||
cmdBuffActors[i] = static_cast<CommandBufferValidator *>(cmdBuffs[i])->getActor();
|
||||
}
|
||||
|
||||
_actor->submit(cmdBuffActors.data(), count);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
54
cocos/renderer/gfx-validator/QueueValidator.h
Normal file
54
cocos/renderer/gfx-validator/QueueValidator.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
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 QueueValidator final : public Agent<Queue> {
|
||||
public:
|
||||
using Queue::submit;
|
||||
|
||||
explicit QueueValidator(Queue *actor);
|
||||
~QueueValidator() override;
|
||||
|
||||
void submit(CommandBuffer *const *cmdBuffs, uint32_t count) override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
friend class DeviceValidator;
|
||||
|
||||
void doInit(const QueueInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
70
cocos/renderer/gfx-validator/RenderPassValidator.cpp
Normal file
70
cocos/renderer/gfx-validator/RenderPassValidator.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 "DeviceValidator.h"
|
||||
#include "RenderPassValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
RenderPassValidator::RenderPassValidator(RenderPass *actor)
|
||||
: Agent<RenderPass>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
RenderPassValidator::~RenderPassValidator() {
|
||||
DeviceResourceTracker<RenderPass>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void RenderPassValidator::doInit(const RenderPassInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
bool hasDepth = info.depthStencilAttachment.format != Format::UNKNOWN;
|
||||
if (!hasDepth) {
|
||||
for (const auto &subpass : info.subpasses) {
|
||||
CC_ASSERT(subpass.depthStencil == INVALID_BINDING || subpass.depthStencil < info.colorAttachments.size());
|
||||
}
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void RenderPassValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-validator/RenderPassValidator.h
Normal file
48
cocos/renderer/gfx-validator/RenderPassValidator.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/GFXRenderPass.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL RenderPassValidator final : public Agent<RenderPass> {
|
||||
public:
|
||||
explicit RenderPassValidator(RenderPass *actor);
|
||||
~RenderPassValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const RenderPassInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
63
cocos/renderer/gfx-validator/ShaderValidator.cpp
Normal file
63
cocos/renderer/gfx-validator/ShaderValidator.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
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 "DeviceValidator.h"
|
||||
#include "ShaderValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
ShaderValidator::ShaderValidator(Shader *actor)
|
||||
: Agent<Shader>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
ShaderValidator::~ShaderValidator() {
|
||||
DeviceResourceTracker<Shader>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void ShaderValidator::doInit(const ShaderInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void ShaderValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
48
cocos/renderer/gfx-validator/ShaderValidator.h
Normal file
48
cocos/renderer/gfx-validator/ShaderValidator.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/GFXShader.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL ShaderValidator final : public Agent<Shader> {
|
||||
public:
|
||||
explicit ShaderValidator(Shader *actor);
|
||||
~ShaderValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
protected:
|
||||
void doInit(const ShaderInfo &info) override;
|
||||
void doDestroy() override;
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
125
cocos/renderer/gfx-validator/SwapchainValidator.cpp
Normal file
125
cocos/renderer/gfx-validator/SwapchainValidator.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/****************************************************************************
|
||||
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 "SwapchainValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
#include "gfx-validator/DeviceValidator.h"
|
||||
#include "gfx-validator/TextureValidator.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
SwapchainValidator::SwapchainValidator(Swapchain *actor)
|
||||
: Agent<Swapchain>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
_preRotationEnabled = static_cast<SwapchainValidator *>(actor)->_preRotationEnabled;
|
||||
}
|
||||
|
||||
SwapchainValidator::~SwapchainValidator() {
|
||||
DeviceResourceTracker<Swapchain>::erase(this);
|
||||
CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void SwapchainValidator::doInit(const SwapchainInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
|
||||
auto *colorTexture = ccnew TextureValidator(_actor->getColorTexture());
|
||||
colorTexture->renounceOwnership();
|
||||
_colorTexture = colorTexture;
|
||||
DeviceResourceTracker<Texture>::push(_colorTexture.get());
|
||||
|
||||
auto *depthStencilTexture = ccnew TextureValidator(_actor->getDepthStencilTexture());
|
||||
depthStencilTexture->renounceOwnership();
|
||||
_depthStencilTexture = depthStencilTexture;
|
||||
DeviceResourceTracker<Texture>::push(_depthStencilTexture.get());
|
||||
|
||||
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 SwapchainValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
_depthStencilTexture = nullptr;
|
||||
_colorTexture = nullptr;
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void SwapchainValidator::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 SwapchainValidator::doResize(uint32_t width, uint32_t height, SurfaceTransform transform) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_actor->resize(width, height, transform);
|
||||
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
void SwapchainValidator::doDestroySurface() {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_actor->destroySurface();
|
||||
}
|
||||
|
||||
void SwapchainValidator::doCreateSurface(void *windowHandle) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
_actor->createSurface(windowHandle);
|
||||
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
53
cocos/renderer/gfx-validator/SwapchainValidator.h
Normal file
53
cocos/renderer/gfx-validator/SwapchainValidator.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
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/GFXDef-common.h"
|
||||
#include "gfx-base/GFXSwapchain.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
class CC_DLL SwapchainValidator final : public Agent<Swapchain> {
|
||||
public:
|
||||
explicit SwapchainValidator(Swapchain *actor);
|
||||
~SwapchainValidator() override;
|
||||
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
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();
|
||||
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
177
cocos/renderer/gfx-validator/TextureValidator.cpp
Normal file
177
cocos/renderer/gfx-validator/TextureValidator.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/****************************************************************************
|
||||
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 "TextureValidator.h"
|
||||
#include "DeviceValidator.h"
|
||||
#include "SwapchainValidator.h"
|
||||
#include "ValidationUtils.h"
|
||||
#include "gfx-base/GFXDef-common.h"
|
||||
|
||||
namespace cc {
|
||||
namespace gfx {
|
||||
|
||||
namespace {
|
||||
struct EnumHasher final {
|
||||
template <typename T, typename Enable = std::enable_if_t<std::is_enum<T>::value>>
|
||||
size_t operator()(const T &v) const {
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
};
|
||||
|
||||
ccstd::unordered_map<Format, Feature, EnumHasher> featureCheckMap{};
|
||||
} // namespace
|
||||
|
||||
TextureValidator::TextureValidator(Texture *actor)
|
||||
: Agent<Texture>(actor) {
|
||||
_typedID = actor->getTypedID();
|
||||
}
|
||||
|
||||
TextureValidator::~TextureValidator() {
|
||||
DeviceResourceTracker<Texture>::erase(this);
|
||||
if (_ownTheActor) CC_SAFE_DELETE(_actor);
|
||||
}
|
||||
|
||||
void TextureValidator::doInit(const TextureInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
|
||||
CC_ASSERT(info.width && info.height && info.depth);
|
||||
|
||||
FormatFeature ff = FormatFeature::NONE;
|
||||
if (hasAnyFlags(info.usage, TextureUsageBit::COLOR_ATTACHMENT | TextureUsageBit::DEPTH_STENCIL_ATTACHMENT)) ff |= FormatFeature::RENDER_TARGET;
|
||||
if (hasAnyFlags(info.usage, TextureUsageBit::SAMPLED)) ff |= FormatFeature::SAMPLED_TEXTURE;
|
||||
if (hasAnyFlags(info.usage, TextureUsageBit::STORAGE)) ff |= FormatFeature::STORAGE_TEXTURE;
|
||||
if (ff != FormatFeature::NONE) {
|
||||
CC_ASSERT(hasAllFlags(DeviceValidator::getInstance()->getFormatFeatures(info.format), ff));
|
||||
}
|
||||
|
||||
switch (info.type) {
|
||||
case TextureType::TEX2D: {
|
||||
if (std::max(info.width, info.height) > DeviceValidator::getInstance()->getCapabilities().maxTextureSize) {
|
||||
CC_ABORT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextureType::TEX1D_ARRAY: {
|
||||
if (std::min(info.width, info.height) > 1 || std::max(info.width, info.height) > DeviceValidator::getInstance()->getCapabilities().maxTextureSize || info.layerCount > DeviceValidator::getInstance()->getCapabilities().maxArrayTextureLayers) {
|
||||
CC_ABORT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextureType::TEX2D_ARRAY: {
|
||||
if (std::max(info.width, info.height) > DeviceValidator::getInstance()->getCapabilities().maxTextureSize || info.layerCount > DeviceValidator::getInstance()->getCapabilities().maxArrayTextureLayers) {
|
||||
CC_ABORT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextureType::CUBE: {
|
||||
if (std::max(info.width, info.height) > DeviceValidator::getInstance()->getCapabilities().maxCubeMapTextureSize || info.layerCount != 6) {
|
||||
CC_ABORT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextureType::TEX3D: {
|
||||
if (std::max(std::max(info.width, info.height), info.depth) > DeviceValidator::getInstance()->getCapabilities().maxCubeMapTextureSize) {
|
||||
CC_ABORT();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
CC_ABORT();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFlag(info.flags, TextureFlagBit::GEN_MIPMAP)) {
|
||||
CC_ASSERT(info.levelCount > 1);
|
||||
|
||||
bool isCompressed = GFX_FORMAT_INFOS[static_cast<int>(info.format)].isCompressed;
|
||||
CC_ASSERT(!isCompressed);
|
||||
}
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->initialize(info);
|
||||
}
|
||||
|
||||
void TextureValidator::doInit(const TextureViewInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
_isTextureView = true;
|
||||
CC_ASSERT(info.texture && static_cast<TextureValidator *>(info.texture)->isInited());
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
TextureViewInfo actorInfo = info;
|
||||
actorInfo.texture = static_cast<TextureValidator *>(info.texture)->getActor();
|
||||
|
||||
_actor->initialize(actorInfo);
|
||||
}
|
||||
|
||||
void TextureValidator::doInit(const SwapchainTextureInfo &info) {
|
||||
CC_ASSERT(!isInited());
|
||||
_inited = true;
|
||||
CC_UNUSED_PARAM(info); // workaround tidy issue
|
||||
CC_ASSERT(info.swapchain && static_cast<SwapchainValidator *>(info.swapchain)->isInited());
|
||||
|
||||
// the actor is already initialized
|
||||
}
|
||||
|
||||
void TextureValidator::doDestroy() {
|
||||
CC_ASSERT(isInited());
|
||||
_inited = false;
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->destroy();
|
||||
}
|
||||
|
||||
void TextureValidator::doResize(uint32_t width, uint32_t height, uint32_t /*size*/) {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
// Cannot resize texture views.
|
||||
CC_ASSERT(!_isTextureView);
|
||||
|
||||
/////////// execute ///////////
|
||||
|
||||
_actor->resize(width, height);
|
||||
}
|
||||
|
||||
void TextureValidator::sanityCheck() {
|
||||
CC_ASSERT(isInited());
|
||||
|
||||
uint64_t cur = DeviceValidator::getInstance()->currentFrame();
|
||||
|
||||
// FIXME: minggo: as current implementation need to update some textures more than once, so disable it.
|
||||
// Should enable it when it is fixed.
|
||||
// if (cur == _lastUpdateFrame) {
|
||||
// CC_LOG_WARNING(utils::getStacktraceJS().c_str());
|
||||
// CC_LOG_WARNING("performance warning: texture updated more than once per frame");
|
||||
// }
|
||||
|
||||
_lastUpdateFrame = cur;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
62
cocos/renderer/gfx-validator/TextureValidator.h
Normal file
62
cocos/renderer/gfx-validator/TextureValidator.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
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 TextureValidator final : public Agent<Texture> {
|
||||
public:
|
||||
explicit TextureValidator(Texture *actor);
|
||||
~TextureValidator() override;
|
||||
|
||||
void sanityCheck();
|
||||
|
||||
inline void renounceOwnership() { _ownTheActor = false; }
|
||||
inline bool isInited() const { return _inited; }
|
||||
|
||||
const Texture *getRaw() const override { return _actor->getRaw(); }
|
||||
|
||||
uint32_t getGLTextureHandle() const noexcept override { return _actor->getGLTextureHandle(); }
|
||||
|
||||
protected:
|
||||
friend class SwapchainValidator;
|
||||
|
||||
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;
|
||||
|
||||
uint64_t _lastUpdateFrame{0U};
|
||||
bool _ownTheActor{true};
|
||||
bool _inited{false};
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
112
cocos/renderer/gfx-validator/ValidationUtils.cpp
Normal file
112
cocos/renderer/gfx-validator/ValidationUtils.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/****************************************************************************
|
||||
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 "ValidationUtils.h"
|
||||
|
||||
#include "DeviceValidator.h"
|
||||
#ifndef CC_WGPU_WASM
|
||||
#include "bindings/jswrapper/SeApi.h"
|
||||
#endif
|
||||
|
||||
#include "gfx-base/GFXInputAssembler.h"
|
||||
#include "gfx-base/GFXPipelineState.h"
|
||||
#include "gfx-base/GFXRenderPass.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace utils {
|
||||
|
||||
ccstd::string getStacktraceJS() {
|
||||
#ifndef CC_WGPU_WASM
|
||||
if (!gfx::DeviceValidator::allowStacktraceJS) return "";
|
||||
return se::ScriptEngine::getInstance()->getCurrentStackTrace();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
namespace gfx {
|
||||
|
||||
void CommandRecorder::recordBeginRenderPass(const RenderPassSnapshot &renderPass) {
|
||||
_renderPassCommands.emplace_back();
|
||||
RenderPassCommand &command = _renderPassCommands.back();
|
||||
command.renderArea = renderPass.renderArea;
|
||||
command.clearColors = renderPass.clearColors;
|
||||
command.clearDepth = renderPass.clearDepth;
|
||||
command.clearStencil = renderPass.clearStencil;
|
||||
|
||||
command.colorAttachments = renderPass.renderPass->getColorAttachments();
|
||||
command.depthStencilAttachment = renderPass.renderPass->getDepthStencilAttachment();
|
||||
|
||||
_commands.push_back(CommandType::BEGIN_RENDER_PASS);
|
||||
}
|
||||
|
||||
void CommandRecorder::recordDrawcall(const DrawcallSnapshot &drawcall) {
|
||||
_drawcallCommands.emplace_back();
|
||||
DrawcallCommand &command = _drawcallCommands.back();
|
||||
command.inputState = drawcall.pipelineState->getInputState();
|
||||
command.rasterizerState = drawcall.pipelineState->getRasterizerState();
|
||||
command.depthStencilState = drawcall.pipelineState->getDepthStencilState();
|
||||
command.blendState = drawcall.pipelineState->getBlendState();
|
||||
command.primitive = drawcall.pipelineState->getPrimitive();
|
||||
command.dynamicStates = drawcall.pipelineState->getDynamicStates();
|
||||
command.bindPoint = drawcall.pipelineState->getBindPoint();
|
||||
command.drawInfo = drawcall.inputAssembler->getDrawInfo();
|
||||
|
||||
command.descriptorSets = drawcall.descriptorSets;
|
||||
for (const auto &offsets : drawcall.dynamicOffsets) command.dynamicOffsets.insert(command.dynamicOffsets.end(), offsets.begin(), offsets.end());
|
||||
|
||||
_commands.push_back(CommandType::DRAW);
|
||||
}
|
||||
|
||||
void CommandRecorder::recordEndRenderPass() {
|
||||
_commands.push_back(CommandType::END_RENDER_PASS);
|
||||
}
|
||||
|
||||
void CommandRecorder::clear() {
|
||||
_commands.clear();
|
||||
_renderPassCommands.clear();
|
||||
_drawcallCommands.clear();
|
||||
}
|
||||
|
||||
ccstd::vector<uint32_t> CommandRecorder::serialize(const CommandRecorder &recorder) {
|
||||
ccstd::vector<uint32_t> bytes;
|
||||
bytes.push_back(static_cast<uint32_t>(recorder._commands.size()));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
CommandRecorder CommandRecorder::deserialize(const ccstd::vector<uint32_t> &bytes) {
|
||||
CommandRecorder recorder;
|
||||
recorder._commands.resize(bytes[0]);
|
||||
return recorder;
|
||||
}
|
||||
|
||||
bool CommandRecorder::compare(const CommandRecorder &test, const CommandRecorder &baseline) {
|
||||
return test._commands.empty() && baseline._commands.empty();
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
190
cocos/renderer/gfx-validator/ValidationUtils.h
Normal file
190
cocos/renderer/gfx-validator/ValidationUtils.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/****************************************************************************
|
||||
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 <algorithm>
|
||||
#include "base/Utils.h"
|
||||
#include "base/std/container/array.h"
|
||||
#include "gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace utils {
|
||||
|
||||
ccstd::string getStacktraceJS();
|
||||
|
||||
} // namespace utils
|
||||
|
||||
namespace gfx {
|
||||
|
||||
struct RenderPassSnapshot {
|
||||
RenderPass *renderPass = nullptr;
|
||||
Framebuffer *framebuffer = nullptr;
|
||||
Rect renderArea;
|
||||
ccstd::vector<Color> clearColors;
|
||||
float clearDepth = 1.F;
|
||||
uint32_t clearStencil = 0U;
|
||||
};
|
||||
|
||||
struct DrawcallSnapshot {
|
||||
PipelineState *pipelineState;
|
||||
InputAssembler *inputAssembler;
|
||||
ccstd::vector<DescriptorSet *> descriptorSets;
|
||||
ccstd::vector<ccstd::vector<uint32_t>> dynamicOffsets;
|
||||
};
|
||||
|
||||
struct CommandBufferStorage : public DynamicStates, RenderPassSnapshot, DrawcallSnapshot {};
|
||||
|
||||
class CommandRecorder {
|
||||
public:
|
||||
void recordBeginRenderPass(const RenderPassSnapshot &renderPass);
|
||||
void recordDrawcall(const DrawcallSnapshot &drawcall);
|
||||
void recordEndRenderPass();
|
||||
void clear();
|
||||
|
||||
static ccstd::vector<uint32_t> serialize(const CommandRecorder &recorder);
|
||||
static CommandRecorder deserialize(const ccstd::vector<uint32_t> &bytes);
|
||||
static bool compare(const CommandRecorder &test, const CommandRecorder &baseline);
|
||||
|
||||
private:
|
||||
enum class CommandType {
|
||||
BEGIN_RENDER_PASS,
|
||||
END_RENDER_PASS,
|
||||
DRAW
|
||||
};
|
||||
|
||||
struct RenderPassCommand {
|
||||
ColorAttachmentList colorAttachments;
|
||||
DepthStencilAttachment depthStencilAttachment;
|
||||
|
||||
Rect renderArea;
|
||||
ccstd::vector<Color> clearColors;
|
||||
float clearDepth = 1.F;
|
||||
uint32_t clearStencil = 0U;
|
||||
};
|
||||
|
||||
struct DrawcallCommand {
|
||||
InputState inputState;
|
||||
RasterizerState rasterizerState;
|
||||
DepthStencilState depthStencilState;
|
||||
BlendState blendState;
|
||||
PrimitiveMode primitive = PrimitiveMode::TRIANGLE_LIST;
|
||||
DynamicStateFlags dynamicStates = DynamicStateFlagBit::NONE;
|
||||
PipelineBindPoint bindPoint = PipelineBindPoint::GRAPHICS;
|
||||
|
||||
DrawInfo drawInfo;
|
||||
|
||||
ccstd::vector<DescriptorSet *> descriptorSets;
|
||||
ccstd::vector<uint32_t> dynamicOffsets;
|
||||
};
|
||||
|
||||
ccstd::vector<CommandType> _commands;
|
||||
ccstd::vector<RenderPassCommand> _renderPassCommands;
|
||||
ccstd::vector<DrawcallCommand> _drawcallCommands;
|
||||
|
||||
struct BufferData {
|
||||
BufferInfo info;
|
||||
ccstd::vector<uint8_t> data;
|
||||
};
|
||||
ccstd::unordered_map<uint32_t, BufferData> _bufferMap;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
struct RecordStacktrace : std::false_type {};
|
||||
|
||||
template <typename Resource, typename Enable = std::enable_if_t<std::is_base_of<GFXObject, Resource>::value>>
|
||||
class DeviceResourceTracker {
|
||||
public:
|
||||
template <typename T, typename = std::enable_if_t<std::is_same<Resource, T>::value>>
|
||||
static std::enable_if_t<RecordStacktrace<T>::value, void> push(T *resource);
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_same<Resource, T>::value>>
|
||||
static std::enable_if_t<!RecordStacktrace<T>::value, void> push(T *resource);
|
||||
|
||||
static void erase(Resource *resource);
|
||||
static void checkEmpty();
|
||||
|
||||
private:
|
||||
struct ResourceRecord {
|
||||
Resource *resource = nullptr;
|
||||
ccstd::string initStack;
|
||||
};
|
||||
|
||||
static ccstd::vector<ResourceRecord> resources;
|
||||
};
|
||||
|
||||
template <typename Resource, typename Enable>
|
||||
ccstd::vector<typename DeviceResourceTracker<Resource, Enable>::ResourceRecord> DeviceResourceTracker<Resource, Enable>::resources;
|
||||
|
||||
template <typename Resource, typename Enable>
|
||||
template <typename T, typename EnableFn>
|
||||
std::enable_if_t<RecordStacktrace<T>::value, void>
|
||||
DeviceResourceTracker<Resource, Enable>::push(T *resource) {
|
||||
resources.emplace_back(ResourceRecord{resource, utils::getStacktrace(6, 10)});
|
||||
}
|
||||
|
||||
template <typename Resource, typename Enable>
|
||||
template <typename T, typename EnableFn>
|
||||
std::enable_if_t<!RecordStacktrace<T>::value, void>
|
||||
DeviceResourceTracker<Resource, Enable>::push(T *resource) {
|
||||
resources.emplace_back(ResourceRecord{resource, {}});
|
||||
}
|
||||
|
||||
template <typename Resource, typename Enable>
|
||||
void DeviceResourceTracker<Resource, Enable>::erase(Resource *resource) {
|
||||
CC_ASSERT(!resources.empty());
|
||||
|
||||
resources.erase(std::remove_if(resources.begin(), resources.end(),
|
||||
[resource](const auto &record) { return record.resource == resource; }));
|
||||
}
|
||||
|
||||
template <typename Resource, typename Enable>
|
||||
void DeviceResourceTracker<Resource, Enable>::checkEmpty() {
|
||||
// If this assertion is hit, it means you have leaked gfx resources.
|
||||
// You can debug this by uncomment the `record_stacktrace` template specialization for the relevant type
|
||||
// and look up the resource initialization stacktrace in `resources[i].initStack`.
|
||||
// Note: capturing stacktrace is a painfully time-consuming process,
|
||||
// so better to uncomment the exact type of resource that is leaking rather than toggle them all at once.
|
||||
CC_ASSERT(resources.empty()); // Resource leaked.
|
||||
}
|
||||
|
||||
//template <> struct RecordStacktrace<CommandBuffer> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<Queue> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<Buffer> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<Texture> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<Sampler> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<Shader> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<InputAssembler> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<RenderPass> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<Framebuffer> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<DescriptorSet> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<DescriptorSetLayout> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<PipelineLayout> : std::true_type {};
|
||||
//template <> struct RecordStacktrace<PipelineState> : std::true_type {};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace cc
|
||||
Reference in New Issue
Block a user