Skip to content

Commit

Permalink
V3.8.1 gpudriven (cocos#15)
Browse files Browse the repository at this point in the history
* fg move
  • Loading branch information
hana-alice authored Aug 24, 2023
1 parent a5e7fa7 commit 66d1880
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 45 deletions.
19 changes: 19 additions & 0 deletions native/cocos/renderer/gfx-base/GFXDef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,25 @@ bool operator==(const GeneralBarrierInfo &lhs, const GeneralBarrierInfo &rhs) {
return !memcmp(&lhs, &rhs, sizeof(GeneralBarrierInfo));
}

template <>
ccstd::hash_t Hasher<ResourceRange>::operator()(const ResourceRange &info) const {
ccstd::hash_t seed = sizeof(info);
ccstd::hash_combine(seed, info.width);
ccstd::hash_combine(seed, info.height);
ccstd::hash_combine(seed, info.depthOrArraySize);
ccstd::hash_combine(seed, info.firstSlice);
ccstd::hash_combine(seed, info.numSlices);
ccstd::hash_combine(seed, info.mipLevel);
ccstd::hash_combine(seed, info.levelCount);
ccstd::hash_combine(seed, info.basePlane);
ccstd::hash_combine(seed, info.planeCount);
return seed;
}

bool operator==(const ResourceRange &lhs, const ResourceRange &rhs) {
return !memcmp(&lhs, &rhs, sizeof(ResourceRange));
}

template <>
ccstd::hash_t Hasher<TextureBarrierInfo>::operator()(const TextureBarrierInfo &info) const {
return quickHashTrivialStruct(&info);
Expand Down
1 change: 1 addition & 0 deletions native/cocos/renderer/gfx-base/GFXDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ DEFINE_CMP_OP(SamplerInfo)
DEFINE_CMP_OP(GeneralBarrierInfo)
DEFINE_CMP_OP(TextureBarrierInfo)
DEFINE_CMP_OP(BufferBarrierInfo)
DEFINE_CMP_OP(ResourceRange)

#undef DEFINE_CMP_OP

Expand Down
15 changes: 9 additions & 6 deletions native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ void CCVKCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const Buf
_barrierEvents.insert({obj, event});
};

static constexpr bool ENABLE_SPLIT_BARRIER{false};
if (textureBarrierCount > 0) {
for (uint32_t i = 0U; i < textureBarrierCount; ++i) {
const auto *ccBarrier = static_cast<const CCVKTextureBarrier *const>(textureBarriers[i]);
Expand All @@ -828,11 +829,13 @@ void CCVKCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const Buf
auto *gpuTexture = ccTexture->gpuTexture();

if (ccBarrier->getInfo().type == BarrierType::SPLIT_BEGIN) {
signalEvent(ccTexture, gpuBarrier->srcStageMask);
if (ENABLE_SPLIT_BARRIER) {
signalEvent(ccTexture, gpuBarrier->srcStageMask);
}
} else {
bool fullBarrier = ccBarrier->getInfo().type == BarrierType::FULL;
bool missed = _barrierEvents.find(ccTexture) == _barrierEvents.end();
if (!fullBarrier && !missed) {
if (!fullBarrier && !missed && ENABLE_SPLIT_BARRIER) {
//CC_ASSERT(_barrierEvents.find(ccTexture) != _barrierEvents.end());
VkEvent event = _barrierEvents.at(ccTexture);
scheduledEvents.push_back(event);
Expand All @@ -851,7 +854,6 @@ void CCVKCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const Buf
} else {
gpuTexture->currentAccessTypes.assign(gpuBarrier->barrier.pNextAccesses, gpuBarrier->barrier.pNextAccesses + gpuBarrier->barrier.nextAccessCount);
fullImageBarriers.push_back(gpuBarrier->vkBarrier);
fullImageBarriers.back().srcAccessMask = missed ? VK_IMAGE_LAYOUT_UNDEFINED : fullImageBarriers.back().srcAccessMask;
fullImageBarriers.back().subresourceRange.aspectMask = gpuTexture->aspectMask;
if (gpuTexture->swapchain) {
fullImageBarriers.back().image = gpuTexture->swapchainVkImages[gpuTexture->swapchain->curImageIndex];
Expand All @@ -873,11 +875,13 @@ void CCVKCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const Buf
auto *gpuBuffer = ccBuffer->gpuBuffer();

if (ccBarrier->getInfo().type == BarrierType::SPLIT_BEGIN) {
signalEvent(ccBuffer, gpuBarrier->srcStageMask);
if (ENABLE_SPLIT_BARRIER) {
signalEvent(ccBuffer, gpuBarrier->srcStageMask);
}
} else {
bool fullBarrier = ccBarrier->getInfo().type == BarrierType::FULL;
bool missed = _barrierEvents.find(ccBuffer) != _barrierEvents.end();
if (!fullBarrier && !missed) {
if (!fullBarrier && !missed && ENABLE_SPLIT_BARRIER) {
CC_ASSERT(_barrierEvents.find(ccBuffer) != _barrierEvents.end());
VkEvent event = _barrierEvents.at(ccBuffer);
scheduledEvents.push_back(event);
Expand All @@ -890,7 +894,6 @@ void CCVKCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const Buf
} else {
gpuBuffer->currentAccessTypes.assign(gpuBarrier->barrier.pNextAccesses, gpuBarrier->barrier.pNextAccesses + gpuBarrier->barrier.nextAccessCount);
fullBufferBarriers.push_back(gpuBarrier->vkBarrier);
fullBufferBarriers.back().srcAccessMask = missed ? VK_IMAGE_LAYOUT_UNDEFINED : fullBufferBarriers.back().srcAccessMask;
fullBufferBarriers.back().buffer = gpuBuffer->vkBuffer;
fullSrcStageMask |= gpuBarrier->srcStageMask;
fullDstStageMask |= gpuBarrier->dstStageMask;
Expand Down
4 changes: 3 additions & 1 deletion native/cocos/renderer/gfx-vulkan/VKGPUObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -1061,8 +1061,10 @@ class CCVKGPUDescriptorHub final {
descriptor->imageLayout = VK_IMAGE_LAYOUT_GENERAL;
} else if (hasFlag(texture->gpuTexture->usage, TextureUsage::DEPTH_STENCIL_ATTACHMENT)) {
descriptor->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
} else {
} else if (flags == AccessFlags::NONE) {
descriptor->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
} else {
descriptor->imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
}
}
Expand Down
117 changes: 100 additions & 17 deletions native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,9 +542,13 @@ auto dependencyCheck(ResourceAccessGraph &rag, ResourceAccessGraph::vertex_descr
const auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resourceID);
const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resourceID);

auto range = originRange;
if (rag.movedSourceStatus.find(name) != rag.movedSourceStatus.end()) {
range = rag.movedSourceStatus.at(name).range;
const auto& range = originRange;
if (rag.movedTargetStatus.find(name) != rag.movedTargetStatus.end()) {
CC_ASSERT(rag.movedTargetStatus.at(name).full);
for (const auto &[src, ignored] : rag.movedTarget.at(name)) {
const auto &srcRange = rag.movedSourceStatus.at(src).range;
rag.resourceAccess.at(src).emplace(curVertID, AccessStatus{accessFlag, srcRange});
}
}

bool isExternalPass = get(get(ResourceGraph::TraitsTag{}, resourceGraph), resourceID).hasSideEffects();
Expand Down Expand Up @@ -1556,12 +1560,19 @@ void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass)

auto lastStatusIter = resourceAccessGraph.resourceAccess.at(pair.source).rbegin();
resourceAccessGraph.movedSourceStatus.emplace(pair.source, AccessStatus{lastStatusIter->second.accessFlag, srcResourceRange});
resourceAccessGraph.movedTarget[pair.target].emplace(getSubresourceNameByRange(srcResourceRange, resourceAccessGraph.resource()), pair.source);
resourceAccessGraph.movedTarget[pair.target].emplace(pair.source, getSubresourceNameByRange(srcResourceRange, resourceAccessGraph.resource()));

const auto &srcAccess = resourceAccessGraph.resourceAccess.at(pair.source);
auto &srcAccess = resourceAccessGraph.resourceAccess.at(pair.source);
auto &targetAccess = resourceAccessGraph.resourceAccess[pair.target];
targetAccess.clear();
targetAccess.emplace(*srcAccess.rbegin());

if (!targetAccess.empty()) {
// second move
srcAccess.emplace(targetAccess.rbegin()->first, AccessStatus{targetAccess.rbegin()->second.accessFlag, srcResourceRange});
}

if (resourceAccessGraph.movedTarget.find(pair.target) != resourceAccessGraph.movedTarget.end()) {
srcAccess.erase(0);
}

auto targetResID = findVertex(pair.target, resourceGraph);
resourceAccessGraph.resourceIndex[pair.target] = targetResID;
Expand All @@ -1573,7 +1584,7 @@ void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass)
rag.resourceIndex[source] = v;

if (rag.movedTarget.find(source) != rag.movedTarget.end()) {
for (const auto &[rangeStr, prt] : rag.movedTarget[source]) {
for (const auto &[prt, rangeStr] : rag.movedTarget[source]) {
feedBack(prt, v);
}
}
Expand Down Expand Up @@ -1644,20 +1655,20 @@ void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) {
using RecursiveFuncType = std::function<void(const PmrFlatMap<ccstd::pmr::string, ccstd::pmr::string> &, const ccstd::pmr::string &)>;
RecursiveFuncType addSubres = [&](const PmrFlatMap<ccstd::pmr::string, ccstd::pmr::string> &subreses, const ccstd::pmr::string &resName) {
if (subreses.size() == 1) {
const auto &src = subreses.begin()->second;
const auto &src = subreses.begin()->first;
rag.resourceIndex[src] = rag.resourceIndex.at(resName);

if (rag.movedTarget.find(src) != rag.movedTarget.end()) {
addSubres(rag.movedTarget.at(src), src);
}
} else {
for (const auto &[rangeStr, subres] : subreses) {
for (const auto &[subres, rangeStr] : subreses) {
auto targetResID = rag.resourceIndex.at(resName);
const auto &targetName = get(ResourceGraph::NameTag{}, resg, targetResID);
const auto &targetDesc = get(ResourceGraph::DescTag{}, resg, targetResID);
const auto &srcResourceRange = rag.movedSourceStatus.at(subres).range;
const auto &targetTraits = get(ResourceGraph::TraitsTag{}, resg, targetResID);
const auto &indexName = concatResName(targetName, subres, rag.resource());
const auto &indexName = concatResName(targetName, rangeStr, rag.resource());
auto subresID = findVertex(indexName, resg);
if (subresID == ResourceGraph::null_vertex()) {
const auto &subView = makeSubresourceView(targetDesc, srcResourceRange);
Expand All @@ -1674,6 +1685,7 @@ void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) {
targetResID);
}
rag.resourceIndex[subres] = subresID;
rag.resourceIndex[indexName] = subresID;

if (rag.movedTarget.find(subres) != rag.movedTarget.end()) {
addSubres(rag.movedTarget.at(subres), subres);
Expand Down Expand Up @@ -1868,6 +1880,13 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
return gfxBarrier;
};

struct AccessWeight{
ccstd::pmr::string name;
gfx::AccessFlags access{gfx::AccessFlags::NONE};
ResourceAccessGraph::vertex_descriptor vertID{0};
};
ccstd::unordered_map<ResourceGraph::vertex_descriptor, ccstd::unordered_map<gfx::ResourceRange, AccessWeight, gfx::Hasher<gfx::ResourceRange>>> rangeLastAccess;

// found pass id in this map ? barriers you should commit when run into this pass
// : or no extra barrier needed.
for (auto &accessPair : rag.resourceAccess) {
Expand All @@ -1888,6 +1907,27 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
auto srcPassID = get(ResourceAccessGraph::PassIDTag{}, rag, srcRagVertID);
auto dstPassID = get(ResourceAccessGraph::PassIDTag{}, rag, dstRagVertID);

std::function<bool(ccstd::pmr::string, ResourceAccessGraph::vertex_descriptor, ResourceAccessGraph::vertex_descriptor)> interAccessCheck =
[&](const ccstd::pmr::string &sName, ResourceAccessGraph::vertex_descriptor startVert, ResourceAccessGraph::vertex_descriptor endVert) {
bool interAccessed = false;
if (rag.movedTarget.find(sName) != rag.movedTarget.end()) {
for (const auto &[src, ignored] : rag.movedTarget.at(sName)) {
const auto srcStart = rag.resourceAccess.at(src).begin()->first;
const auto srcEnd = rag.resourceAccess.at(src).rbegin()->first;
interAccessed |= !((srcStart > endVert) || (srcEnd < startVert));
interAccessed |= interAccessCheck(src, startVert, endVert);
if (interAccessed) {
return true;
}
}
}
return interAccessed;
};

if (interAccessCheck(resName, srcRagVertID, dstRagVertID)) {
continue;
}

if (holds<RasterPassTag>(dstPassID, renderGraph) || holds<RasterSubpassTag>(dstPassID, renderGraph)) {
const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, dstRagVertID);
if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end() ||
Expand Down Expand Up @@ -1931,8 +1971,14 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
continue;
}

auto sRange = iter->second.range;
if (rag.movedSourceStatus.find(resName) != rag.movedSourceStatus.end()) {
// resource id
realResourceID = rag.resourceIndex.at(resName);
const auto &tName = get(ResourceGraph::NameTag{}, resourceGraph, realResourceID);
// parent id
realResourceID = realID(tName, resourceGraph);
sRange = rag.movedSourceStatus.at(resName).range;
}

// undefined access
Expand All @@ -1943,17 +1989,17 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
firstMeetBarrier.type = gfx::BarrierType::FULL;
firstMeetBarrier.beginVert = dstPassID;
firstMeetBarrier.endVert = dstPassID;
firstMeetBarrier.beginStatus = iter->second;
firstMeetBarrier.endStatus = nextIter->second;
firstMeetBarrier.beginStatus = {iter->second.accessFlag, sRange};
firstMeetBarrier.endStatus = {nextIter->second.accessFlag, sRange};
firstMeetBarrier.barrier = getGFXBarrier(firstMeetBarrier);
} else if (accessDependent(iter->second.accessFlag, nextIter->second.accessFlag, isBuffer)) {
auto &srcBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, srcRagVertID);
auto &beginBarrier = srcBarrierNode.rearBarriers.emplace_back();
beginBarrier.resourceID = realResourceID;
beginBarrier.beginVert = srcPassID;
beginBarrier.endVert = dstPassID;
beginBarrier.beginStatus = iter->second;
beginBarrier.endStatus = nextIter->second;
beginBarrier.beginStatus = {iter->second.accessFlag, sRange};
beginBarrier.endStatus = {nextIter->second.accessFlag, sRange};
if (isPassExecAdjecent(iter->first, nextIter->first)) {
beginBarrier.type = gfx::BarrierType::FULL;
} else {
Expand All @@ -1965,8 +2011,8 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
endBarrier.type = gfx::BarrierType::SPLIT_END;
endBarrier.beginVert = srcPassID;
endBarrier.endVert = dstPassID;
endBarrier.beginStatus = iter->second;
endBarrier.endStatus = nextIter->second;
endBarrier.beginStatus = {iter->second.accessFlag, sRange};
endBarrier.endStatus = {nextIter->second.accessFlag, sRange};
endBarrier.barrier = getGFXBarrier(endBarrier);
}
beginBarrier.barrier = getGFXBarrier(beginBarrier);
Expand All @@ -1975,6 +2021,15 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, realResourceID);
auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, realResourceID);
if (traits.hasSideEffects()) {
if (out_degree(realResourceID, resourceGraph) > 1) {
auto sRange = iter->second.range;
if (rag.movedSourceStatus.find(resName) != rag.movedSourceStatus.end()) {
sRange = rag.movedSourceStatus.at(resName).range;
}
if (rangeLastAccess[realResourceID][sRange].vertID < (accessRecord.rbegin()->first)) {
rangeLastAccess[realResourceID][sRange] = AccessWeight{resName, iter->second.accessFlag, accessRecord.rbegin()->first};
}
}
states.states = iter->second.accessFlag;
if (traits.residency == ResourceResidency::BACKBUFFER) {
auto lastAccessPassID = get(ResourceAccessGraph::PassIDTag{}, rag, iter->first);
Expand All @@ -1993,6 +2048,34 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) {
}
}

for (const auto &[resID, rangeWeight] : rangeLastAccess) {
ccstd::unordered_map<gfx::AccessFlags, uint32_t> rangeMap;
for (const auto& [range, weight] : rangeWeight) {
rangeMap[weight.access] += 1;
}
auto iter = std::max_element(rangeMap.begin(), rangeMap.end(), [](const auto &lhs, const auto &rhs) {
return lhs.second < rhs.second;
});
auto mostCommonAccesss = iter->first;

for (const auto &[range, weight] : rangeWeight) {
if (weight.access != mostCommonAccesss) {
auto &barrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, weight.vertID);
auto& barrier = barrierNode.rearBarriers.emplace_back();
barrier.resourceID = resID;
barrier.beginVert = weight.vertID;
barrier.endVert = weight.vertID;
barrier.type = gfx::BarrierType::FULL;
barrier.beginStatus = {weight.access, range};
barrier.endStatus = {mostCommonAccesss, range};
barrier.barrier = getGFXBarrier(barrier);
}
}
auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resID);
states.states = mostCommonAccesss;
}


{
for (auto &fgRenderpassInfo : rag.rpInfo) {
auto &colorAttachments = fgRenderpassInfo.rpInfo.colorAttachments;
Expand Down
Loading

0 comments on commit 66d1880

Please sign in to comment.