mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-07 23:31:13 +00:00
Vulkan: Add ImgRefs to track usage of image subresorces
Change-Id: I7f111fb8aa4e1296315a8c852830205cf51f05e5
This commit is contained in:
committed by
Baldur Karlsson
parent
217506869f
commit
be2a6549dd
@@ -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
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
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<FrameRefType> 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<FrameRefType> 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<FrameRefType> 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<FrameRefType> 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<FrameRefType> 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<FrameRefType> 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)
|
||||
@@ -99,6 +99,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="imgrefs_tests.cpp" />
|
||||
<ClCompile Include="precompiled.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
||||
@@ -139,6 +139,9 @@
|
||||
<ClCompile Include="vk_bindless_feedback.cpp">
|
||||
<Filter>Replay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="imgrefs_tests.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="vk_replay.h">
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<VkImageAspectFlagBits, VkImageAspectFlags, int32_t> ImageAspectFlagIter;
|
||||
|
||||
struct ImgRefs
|
||||
{
|
||||
std::vector<FrameRefType> 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 <typename Compose>
|
||||
FrameRefType Update(ImageRange range, FrameRefType refType, Compose comp);
|
||||
inline FrameRefType Update(const ImageRange &range, FrameRefType refType)
|
||||
{
|
||||
return Update(range, refType, ComposeFrameRefs);
|
||||
}
|
||||
template <typename Compose>
|
||||
FrameRefType Merge(const ImgRefs &other, Compose comp);
|
||||
inline FrameRefType Merge(const ImgRefs &other) { return Merge(other, ComposeFrameRefs); }
|
||||
};
|
||||
|
||||
template <typename Compose>
|
||||
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<VkImageAspectFlags> 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 <typename Compose>
|
||||
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<FrameRefType> rangeRefs;
|
||||
@@ -1054,6 +1270,20 @@ FrameRefType MemRefs::Merge(MemRefs &other, Compose comp)
|
||||
return maxRefType;
|
||||
}
|
||||
|
||||
struct ImageLayouts;
|
||||
|
||||
template <typename Compose>
|
||||
FrameRefType MarkImageReferenced(std::map<ResourceId, ImgRefs> &imgRefs, ResourceId img,
|
||||
const ImageLayouts &layout, const ImageRange &range,
|
||||
FrameRefType refType, Compose comp);
|
||||
|
||||
inline FrameRefType MarkImageReferenced(std::map<ResourceId, ImgRefs> &imgRefs, ResourceId img,
|
||||
const ImageLayouts &layout, const ImageRange &range,
|
||||
FrameRefType refType)
|
||||
{
|
||||
return MarkImageReferenced(imgRefs, img, layout, range, refType, ComposeFrameRefs);
|
||||
}
|
||||
|
||||
template <typename Compose>
|
||||
FrameRefType MarkMemoryReferenced(std::map<ResourceId, MemRefs> &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 <typename Compose>
|
||||
FrameRefType MarkImageReferenced(std::map<ResourceId, ImgRefs> &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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user