diff --git a/renderdoc/driver/vulkan/CMakeLists.txt b/renderdoc/driver/vulkan/CMakeLists.txt index aae0f2f76..ef5f9870d 100644 --- a/renderdoc/driver/vulkan/CMakeLists.txt +++ b/renderdoc/driver/vulkan/CMakeLists.txt @@ -37,6 +37,7 @@ set(sources vk_serialise.cpp vk_stringise.cpp vk_layer.cpp + imgrefs_tests.cpp official/vk_layer.h official/vk_layer_dispatch_table.h official/vk_platform.h diff --git a/renderdoc/driver/vulkan/imgrefs_tests.cpp b/renderdoc/driver/vulkan/imgrefs_tests.cpp new file mode 100644 index 000000000..8f115ecb4 --- /dev/null +++ b/renderdoc/driver/vulkan/imgrefs_tests.cpp @@ -0,0 +1,214 @@ +/****************************************************************************** +* The MIT License (MIT) +* +* Copyright (c) 2019 Baldur Karlsson +* +* 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 "common/globalconfig.h" + +#if ENABLED(ENABLE_UNIT_TESTS) + +#include "3rdparty/catch/catch.hpp" + +#include "vk_resources.h" + +#include +#include + +TEST_CASE("Test ImgRefs type", "[imgrefs]") +{ + SECTION("unsplit") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 0); + }; + SECTION("split aspect") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(true, false, false); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 1); + }; + SECTION("split levels") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(false, true, false); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 2); + }; + SECTION("split layers") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(false, false, true); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 5); + }; + SECTION("split aspect and levels") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(true, true, false); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 11 + 2); + }; + SECTION("split aspect and layers") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(true, false, true); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 17 + 5); + }; + SECTION("split levels and layers") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(false, true, true); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 2 * 17 + 5); + }; + SECTION("split aspect and levels and layers") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + imgRefs.Split(true, true, true); + CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 11 * 17 + 2 * 17 + 5); + }; + SECTION("update unsplit") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + ImageRange range; + imgRefs.Update(range, eFrameRef_Read); + std::vector expected = {eFrameRef_Read}; + CHECK(imgRefs.rangeRefs == expected); + }; + SECTION("update split aspect") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + ImageRange range; + range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + imgRefs.Update(range, eFrameRef_Read); + std::vector expected = {eFrameRef_None, eFrameRef_Read}; + CHECK(imgRefs.rangeRefs == expected); + }; + SECTION("update split levels") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + ImageRange range; + range.baseMipLevel = 1; + range.levelCount = 3; + imgRefs.Update(range, eFrameRef_Read); + std::vector expected = {eFrameRef_None, eFrameRef_Read, eFrameRef_Read, + eFrameRef_Read, eFrameRef_None, eFrameRef_None, + eFrameRef_None, eFrameRef_None, eFrameRef_None, + eFrameRef_None, eFrameRef_None}; + CHECK(imgRefs.rangeRefs == expected); + }; + SECTION("update split layers") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + ImageRange range; + range.baseArrayLayer = 7; + imgRefs.Update(range, eFrameRef_Read); + std::vector expected = { + eFrameRef_None, eFrameRef_None, eFrameRef_None, eFrameRef_None, eFrameRef_None, + eFrameRef_None, eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, + eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, + eFrameRef_Read, eFrameRef_Read}; + CHECK(imgRefs.rangeRefs == expected); + }; + SECTION("update split aspect then levels") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 11, + 17, {100, 100, 1}); + ImageRange range0; + range0.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + imgRefs.Update(range0, eFrameRef_Read); + ImageRange range1; + range1.baseMipLevel = 5; + range1.levelCount = 2; + imgRefs.Update(range1, eFrameRef_PartialWrite); + std::vector expected = { + // VK_IMAGE_ASPECT_DEPTH_BIT + eFrameRef_None, eFrameRef_None, eFrameRef_None, eFrameRef_None, eFrameRef_None, + eFrameRef_PartialWrite, eFrameRef_PartialWrite, eFrameRef_None, eFrameRef_None, + eFrameRef_None, eFrameRef_None, + // VK_IMAGE_ASPECT_STENCIL_BIT + eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, eFrameRef_Read, + eFrameRef_ReadBeforeWrite, eFrameRef_ReadBeforeWrite, eFrameRef_Read, eFrameRef_Read, + eFrameRef_Read, eFrameRef_Read, + }; + CHECK(imgRefs.rangeRefs == expected); + } + SECTION("update split layers then aspects and levels") + { + ImgRefs imgRefs(VK_IMAGE_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 7, 5, + {100, 100, 1}); + ImageRange range0; + range0.baseArrayLayer = 1; + range0.layerCount = 2; + imgRefs.Update(range0, eFrameRef_Read); + ImageRange range1; + range1.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + range1.baseMipLevel = 2; + range1.levelCount = 3; + imgRefs.Update(range1, eFrameRef_PartialWrite); + std::vector expected = { + // (Depth, level 0) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Depth, level 1) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Depth, level 2) + eFrameRef_PartialWrite, eFrameRef_ReadBeforeWrite, eFrameRef_ReadBeforeWrite, + eFrameRef_PartialWrite, eFrameRef_PartialWrite, + // (Depth, level 3) + eFrameRef_PartialWrite, eFrameRef_ReadBeforeWrite, eFrameRef_ReadBeforeWrite, + eFrameRef_PartialWrite, eFrameRef_PartialWrite, + // (Depth, level 4) + eFrameRef_PartialWrite, eFrameRef_ReadBeforeWrite, eFrameRef_ReadBeforeWrite, + eFrameRef_PartialWrite, eFrameRef_PartialWrite, + // (Depth, level 5) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Depth, level 6) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 0) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 1) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 2) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 3) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 4) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 5) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + // (Stencil, level 6) + eFrameRef_None, eFrameRef_Read, eFrameRef_Read, eFrameRef_None, eFrameRef_None, + + }; + CHECK(imgRefs.rangeRefs == expected); + } +}; + +#endif // ENABLED(ENABLE_UNIT_TESTS) diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj index 82c5fd0ab..cd7337f06 100644 --- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj +++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj @@ -99,6 +99,7 @@ + Create diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters index 8ef091dc6..9981802af 100644 --- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters +++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters @@ -139,6 +139,9 @@ Replay + + Util + diff --git a/renderdoc/driver/vulkan/vk_resources.cpp b/renderdoc/driver/vulkan/vk_resources.cpp index 0ef9594cf..519133a5d 100644 --- a/renderdoc/driver/vulkan/vk_resources.cpp +++ b/renderdoc/driver/vulkan/vk_resources.cpp @@ -2919,6 +2919,91 @@ VkImageAspectFlags FormatImageAspects(VkFormat fmt) return VK_IMAGE_ASPECT_COLOR_BIT; } +int ImgRefs::GetAspectCount() const +{ + int aspectCount = 0; + for(auto aspectIt = ImageAspectFlagIter::begin(aspectMask); + aspectIt != ImageAspectFlagIter::end(); ++aspectIt) + { + ++aspectCount; + } + return aspectCount; +} + +int ImgRefs::SubresourceIndex(VkImageAspectFlagBits aspect, int level, int layer) const +{ + int aspectIndex = 0; + if(areAspectsSplit) + { + for(auto aspectIt = ImageAspectFlagIter::begin(aspectMask); + aspectIt != ImageAspectFlagIter::end(); ++aspectIt) + { + if(*aspectIt == aspect) + break; + ++aspectIndex; + } + } + return SubresourceIndex(aspectIndex, level, layer); +} + +int ImgRefs::SubresourceIndex(int aspectIndex, int level, int layer) const +{ + if(!areAspectsSplit) + aspectIndex = 0; + int splitLevelCount = 1; + if(areLevelsSplit) + splitLevelCount = levelCount; + else + level = 0; + int splitLayerCount = 1; + if(areLayersSplit) + splitLayerCount = layerCount; + else + layer = 0; + return (aspectIndex * splitLevelCount + level) * splitLayerCount + layer; +} + +void ImgRefs::Split(bool splitAspects, bool splitLevels, bool splitLayers) +{ + int newSplitAspectCount = 1; + if(splitAspects || areAspectsSplit) + { + newSplitAspectCount = GetAspectCount(); + } + + int oldSplitLevelCount = areLevelsSplit ? levelCount : 1; + int newSplitLevelCount = splitLevels ? levelCount : oldSplitLevelCount; + + int oldSplitLayerCount = areLayersSplit ? layerCount : 1; + int newSplitLayerCount = splitLayers ? layerCount : oldSplitLayerCount; + + int newSize = newSplitAspectCount * newSplitLevelCount * newSplitLayerCount; + if(newSize == (int)rangeRefs.size()) + return; + rangeRefs.resize(newSize); + + for(int newAspectIndex = newSplitAspectCount - 1; newAspectIndex >= 0; --newAspectIndex) + { + int oldAspectIndex = areAspectsSplit ? newAspectIndex : 0; + for(int newLevel = newSplitLevelCount - 1; newLevel >= 0; --newLevel) + { + int oldLevel = areLevelsSplit ? newLevel : 0; + for(int newLayer = newSplitLayerCount - 1; newLayer >= 0; --newLayer) + { + int oldLayer = areLayersSplit ? newLayer : 0; + int oldIndex = + (oldAspectIndex * oldSplitLevelCount + oldLevel) * oldSplitLayerCount + oldLayer; + int newIndex = + (newAspectIndex * newSplitLevelCount + newLevel) * newSplitLayerCount + newLayer; + rangeRefs[newIndex] = rangeRefs[oldIndex]; + } + } + } + areAspectsSplit = newSplitAspectCount > 1; + areLevelsSplit = newSplitLevelCount > 1; + areLayersSplit = newSplitLayerCount > 1; +} + VkResourceRecord::~VkResourceRecord() { VkResourceType resType = Resource != NULL ? IdentifyTypeByPtr(Resource) : eResUnknown; diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index ae56a8527..2642cd1d5 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -25,6 +25,7 @@ #pragma once #include "common/wrapped_pool.h" +#include "core/bit_flag_iterator.h" #include "core/intervals.h" #include "core/resource_manager.h" #include "vk_common.h" @@ -1006,6 +1007,221 @@ struct AttachmentInfo VkImageMemoryBarrier barrier; }; +struct ImageRange +{ + ImageRange() {} + ImageRange(const VkImageSubresourceRange &range) + : aspectMask(range.aspectMask), + baseMipLevel(range.baseMipLevel), + levelCount(range.levelCount), + baseArrayLayer(range.baseArrayLayer), + layerCount(range.layerCount) + { + } + ImageRange(const VkImageSubresourceLayers &range) + : aspectMask(range.aspectMask), + baseMipLevel(range.mipLevel), + levelCount(1), + baseArrayLayer(range.baseArrayLayer), + layerCount(range.layerCount) + { + } + VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM; + uint32_t baseMipLevel = 0; + uint32_t levelCount = VK_REMAINING_MIP_LEVELS; + uint32_t baseArrayLayer = 0; + uint32_t layerCount = VK_REMAINING_ARRAY_LAYERS; + VkOffset3D offset = {0, 0, 0}; + VkExtent3D extent = {~0u, ~0u, ~0u}; + VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; +}; + +typedef BitFlagIterator ImageAspectFlagIter; + +struct ImgRefs +{ + std::vector rangeRefs; + WrappedVkRes *initializedLiveRes; + VkImageType type; + VkImageAspectFlags aspectMask; + int levelCount; + int layerCount; + VkExtent3D extent; + + bool areAspectsSplit = false; + bool areLevelsSplit = false; + bool areLayersSplit = false; + + int GetAspectCount() const; + + ImgRefs() : initializedLiveRes(NULL) {} + inline ImgRefs(VkImageType type, VkImageAspectFlags aspectMask, int levelCount, int layerCount, + VkExtent3D extent) + : rangeRefs(1, eFrameRef_None), + initializedLiveRes(NULL), + type(type), + aspectMask(aspectMask), + levelCount(levelCount), + layerCount(layerCount), + extent(extent) + { + if(type == VK_IMAGE_TYPE_3D) + // Depth slices of 3D views are treated as array layers + layerCount = extent.depth; + } + int SubresourceIndex(VkImageAspectFlagBits aspect, int level, int layer) const; + int SubresourceIndex(int aspectIndex, int level, int layer) const; + inline FrameRefType SubresourceRef(VkImageAspectFlagBits aspect, int level, int layer) const + { + return rangeRefs[SubresourceIndex(aspect, level, layer)]; + } + inline FrameRefType SubresourceRef(int aspectIndex, int level, int layer) const + { + return rangeRefs[SubresourceIndex(aspectIndex, level, layer)]; + } + void Split(bool splitAspects, bool splitLevels, bool splitLayers); + template + FrameRefType Update(ImageRange range, FrameRefType refType, Compose comp); + inline FrameRefType Update(const ImageRange &range, FrameRefType refType) + { + return Update(range, refType, ComposeFrameRefs); + } + template + FrameRefType Merge(const ImgRefs &other, Compose comp); + inline FrameRefType Merge(const ImgRefs &other) { return Merge(other, ComposeFrameRefs); } +}; + +template +FrameRefType ImgRefs::Update(ImageRange range, FrameRefType refType, Compose comp) +{ + range.extent.width = RDCMIN(range.extent.width, extent.width - range.offset.x); + range.extent.height = RDCMIN(range.extent.height, extent.height - range.offset.y); + + if(type == VK_IMAGE_TYPE_3D && range.viewType != VK_IMAGE_VIEW_TYPE_2D && + range.viewType != VK_IMAGE_VIEW_TYPE_2D_ARRAY) + { + // The Vulkan spec allows 2D `VkImageView`s of 3D `VkImage`s--the depth slices of the images are + // interpreted as array layers in the 2D view. Note that the spec does not allow 3D images to + // have array layers, so 3D images always have exactly 1 array layer when not accessed using a + // 2D view. + // + // `ImgRefs` treats the depth slices of 3D images as array layers (as if accessed through a 2D + // view). When a 3D image is accessed without a 2D view, we need to translate the Z axis into + // array layer indices. + + range.extent.depth = RDCMIN(range.extent.depth, extent.depth - range.offset.z); + range.baseArrayLayer = range.offset.z; + range.layerCount = range.extent.depth; + } + else if(range.layerCount == VK_REMAINING_ARRAY_LAYERS) + { + range.layerCount = layerCount - range.baseArrayLayer; + } + + if(range.levelCount == VK_REMAINING_MIP_LEVELS) + range.levelCount = levelCount - range.baseMipLevel; + + if(refType == eFrameRef_CompleteWrite && + (range.offset.x != 0 || range.offset.y != 0 || range.extent.width != extent.width || + range.extent.height != extent.height)) + // Complete write, but only to part of the image. + // We don't track writes at the pixel level, so turn this into a partial write + refType = eFrameRef_PartialWrite; + + if(range.aspectMask != aspectMask) + { + if(range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) + { + // For multi-planar images, the color aspect can be an alias for the plane aspects + range.aspectMask |= + (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT) & + aspectMask; + } + range.aspectMask &= aspectMask; + } + + Split(range.aspectMask != aspectMask, + range.baseMipLevel != 0 || (int)range.levelCount != levelCount, + range.baseArrayLayer != 0 || (int)range.layerCount != layerCount); + + std::vector splitAspects; + if(areAspectsSplit) + { + for(auto aspectIt = ImageAspectFlagIter::begin(aspectMask); + aspectIt != ImageAspectFlagIter::end(); ++aspectIt) + { + splitAspects.push_back(*aspectIt); + } + } + else + { + splitAspects.push_back(aspectMask); + } + + int splitLevelCount = 1; + int levelEnd = 1; + if(areLevelsSplit) + { + splitLevelCount = levelCount; + levelEnd = (int)(range.baseMipLevel + range.levelCount); + } + + int splitLayerCount = 1; + int layerEnd = 1; + if(areLayersSplit) + { + splitLayerCount = layerCount; + layerEnd = (int)(range.baseArrayLayer + range.layerCount); + } + + FrameRefType maxRefType = eFrameRef_None; + for(int aspectIndex = 0; aspectIndex < (int)splitAspects.size(); ++aspectIndex) + { + VkImageAspectFlags aspect = splitAspects[aspectIndex]; + if((aspect & range.aspectMask) == 0) + continue; + for(int level = (int)range.baseMipLevel; level < levelEnd; ++level) + { + for(int layer = (int)range.baseArrayLayer; layer < layerEnd; ++layer) + { + int index = (aspectIndex * splitLevelCount + level) * splitLayerCount + layer; + rangeRefs[index] = comp(rangeRefs[index], refType); + maxRefType = RDCMAX(maxRefType, rangeRefs[index]); + } + } + } + return maxRefType; +} + +template +FrameRefType ImgRefs::Merge(const ImgRefs &other, Compose comp) +{ + Split(other.areAspectsSplit, other.areLevelsSplit, other.areLayersSplit); + + int splitAspectCount = 1; + if(areAspectsSplit) + splitAspectCount = GetAspectCount(); + + int splitLevelCount = areLevelsSplit ? levelCount : 1; + + int splitLayerCount = areLayersSplit ? layerCount : 1; + + FrameRefType maxRefType = eFrameRef_None; + for(int aspectIndex = 0; aspectIndex < splitAspectCount; ++aspectIndex) + { + for(int level = 0; level < splitLevelCount; ++level) + { + for(int layer = 0; layer < splitLayerCount; ++layer) + { + int index = SubresourceIndex(aspectIndex, level, layer); + rangeRefs[index] = comp(rangeRefs[index], other.SubresourceRef(aspectIndex, level, layer)); + maxRefType = RDCMAX(maxRefType, rangeRefs[index]); + } + } + } + return maxRefType; +} + struct MemRefs { Intervals rangeRefs; @@ -1054,6 +1270,20 @@ FrameRefType MemRefs::Merge(MemRefs &other, Compose comp) return maxRefType; } +struct ImageLayouts; + +template +FrameRefType MarkImageReferenced(std::map &imgRefs, ResourceId img, + const ImageLayouts &layout, const ImageRange &range, + FrameRefType refType, Compose comp); + +inline FrameRefType MarkImageReferenced(std::map &imgRefs, ResourceId img, + const ImageLayouts &layout, const ImageRange &range, + FrameRefType refType) +{ + return MarkImageReferenced(imgRefs, img, layout, range, refType, ComposeFrameRefs); +} + template FrameRefType MarkMemoryReferenced(std::map &memRefs, ResourceId mem, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType, @@ -1319,7 +1549,12 @@ public: struct ImageLayouts { - ImageLayouts() : layerCount(1), levelCount(1), sampleCount(1), format(VK_FORMAT_UNDEFINED) + ImageLayouts() + : layerCount(1), + levelCount(1), + sampleCount(1), + format(VK_FORMAT_UNDEFINED), + imageType(VK_IMAGE_TYPE_MAX_ENUM) { extent.width = extent.height = extent.depth = 1; } @@ -1360,3 +1595,22 @@ void GetYUVShaderParameters(VkFormat f, Vec4u &YUVDownsampleRate, Vec4u &YUVACha uint32_t GetByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip); uint32_t GetPlaneByteSize(uint32_t Width, uint32_t Height, uint32_t Depth, VkFormat Format, uint32_t mip, uint32_t plane); + +template +FrameRefType MarkImageReferenced(std::map &imgRefs, ResourceId img, + const ImageLayouts &layout, const ImageRange &range, + FrameRefType refType, Compose comp) +{ + if(refType == eFrameRef_None) + return refType; + auto refs = imgRefs.find(img); + if(refs == imgRefs.end()) + { + refs = + imgRefs + .insert(std::make_pair(img, ImgRefs(layout.imageType, FormatImageAspects(layout.format), + layout.levelCount, layout.layerCount, layout.extent))) + .first; + } + return refs->second.Update(range, refType, comp); +}