mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
graphics: index live cache slots directly
This commit is contained in:
1 parent
170c107779
commit
269e411ef2
5 files changed
+67
-95
No files matched your search
+1
-4
@@ -95,10 +95,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend struct BufferCacheTestAccess;
|
friend struct BufferCacheTestAccess;
|
||||||
|
|
||||||
bool IsBufferInvalid(BufferId id) const {
|
bool IsBufferInvalid(BufferId id) const { return !id || m_slot_buffers[id].is_deleted; }
|
||||||
const auto* buffer = m_slot_buffers.try_get(id);
|
|
||||||
return buffer == nullptr || buffer->is_deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
using BufferMap = std::map<uint64_t, BufferId>;
|
using BufferMap = std::map<uint64_t, BufferId>;
|
||||||
struct OverlapResult {
|
struct OverlapResult {
|
||||||
|
|||||||
+45
-60
@@ -251,24 +251,24 @@ void TextureCache::UnregisterImage(ImageId id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::DeleteImage(ImageId id) {
|
void TextureCache::DeleteImage(ImageId id) {
|
||||||
auto* image = m_slot_images.try_get(id);
|
auto& image = m_slot_images[id];
|
||||||
if (image == nullptr || !image->registered) {
|
if (!image.registered) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (image->depth_id) {
|
if (image.depth_id) {
|
||||||
std::erase(m_slot_images[image->depth_id].stencil_ids, id);
|
std::erase(m_slot_images[image.depth_id].stencil_ids, id);
|
||||||
} else {
|
} else {
|
||||||
// Detach first: deleting each association also unlinks it from its depth owner.
|
// Detach first: deleting each association also unlinks it from its depth owner.
|
||||||
for (const auto association: std::exchange(image->stencil_ids, {})) {
|
for (const auto association: std::exchange(image.stencil_ids, {})) {
|
||||||
FreeImage(association);
|
FreeImage(association);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (image->IsGpuModified()) {
|
if (image.IsGpuModified()) {
|
||||||
EXIT("TextureCache: deleting a GPU-modified image without resolving its contents\n");
|
EXIT("TextureCache: deleting a GPU-modified image without resolving its contents\n");
|
||||||
}
|
}
|
||||||
m_download_images.erase(id);
|
m_download_images.erase(id);
|
||||||
if (image->info.metadata.kind == ImageMetadataKind::Htile) {
|
if (image.info.metadata.kind == ImageMetadataKind::Htile) {
|
||||||
m_surface_metas.erase(image->info.metadata.range.address);
|
m_surface_metas.erase(image.info.metadata.range.address);
|
||||||
}
|
}
|
||||||
UnregisterImage(id);
|
UnregisterImage(id);
|
||||||
if (m_scheduler.Active()) {
|
if (m_scheduler.Active()) {
|
||||||
@@ -779,15 +779,14 @@ void Resolve(TextureCache& cache, ImageId cached_id, ImageId merged_id) {
|
|||||||
TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& requested,
|
TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& requested,
|
||||||
BindingType binding, ImageId cached_id,
|
BindingType binding, ImageId cached_id,
|
||||||
ImageId merged_id) {
|
ImageId merged_id) {
|
||||||
auto owner = m_slot_images.try_get(cached_id);
|
auto& cached = m_slot_images[cached_id];
|
||||||
if (owner == nullptr || !owner->registered) {
|
if (!cached.registered) {
|
||||||
return {merged_id};
|
return {merged_id};
|
||||||
}
|
}
|
||||||
if (BcAlias::Matches(requested, owner->info) && !owner->IsCpuDirty()) {
|
if (BcAlias::Matches(requested, cached.info) && !cached.IsCpuDirty()) {
|
||||||
BcAlias::Resolve(*this, cached_id, merged_id);
|
BcAlias::Resolve(*this, cached_id, merged_id);
|
||||||
return {merged_id};
|
return {merged_id};
|
||||||
}
|
}
|
||||||
auto& cached = *owner;
|
|
||||||
const auto current_tick = m_scheduler.CurrentTick();
|
const auto current_tick = m_scheduler.CurrentTick();
|
||||||
const bool safe_to_delete =
|
const bool safe_to_delete =
|
||||||
current_tick - std::min(current_tick, cached.tick_accessed_last) > NumFramesBeforeRemoval &&
|
current_tick - std::min(current_tick, cached.tick_accessed_last) > NumFramesBeforeRemoval &&
|
||||||
@@ -861,9 +860,8 @@ TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& reques
|
|||||||
if (requested.pixel_format != cached.info.pixel_format ||
|
if (requested.pixel_format != cached.info.pixel_format ||
|
||||||
requested.data.size <= cached.info.data.size) {
|
requested.data.size <= cached.info.data.size) {
|
||||||
const auto result_id = merged_id ? merged_id : cached_id;
|
const auto result_id = merged_id ? merged_id : cached_id;
|
||||||
const auto result = m_slot_images.try_get(result_id);
|
return {ImageViewOps::FormatsCompatible(m_slot_images[result_id].info.pixel_format,
|
||||||
return {result != nullptr && ImageViewOps::FormatsCompatible(result->info.pixel_format,
|
requested.pixel_format)
|
||||||
requested.pixel_format)
|
|
||||||
? result_id
|
? result_id
|
||||||
: ImageId {}};
|
: ImageId {}};
|
||||||
}
|
}
|
||||||
@@ -1210,9 +1208,8 @@ ImageId TextureCache::AssociateStencil(ImageId depth_id, GuestRange stencil) {
|
|||||||
|
|
||||||
ImageId association {};
|
ImageId association {};
|
||||||
for (const auto id: FindImagesInRegion(stencil.address, stencil.size, false)) {
|
for (const auto id: FindImagesInRegion(stencil.address, stencil.size, false)) {
|
||||||
const auto owner = m_slot_images.try_get(id);
|
const auto& owner = m_slot_images[id];
|
||||||
if (owner != nullptr && owner->info.data == stencil &&
|
if (owner.info.data == stencil && owner.info.extent == depth.info.extent) {
|
||||||
owner->info.extent == depth.info.extent) {
|
|
||||||
association = id;
|
association = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1307,10 +1304,9 @@ ImageId TextureCache::FindImage(ImageDesc& desc, bool exact_format) {
|
|||||||
}
|
}
|
||||||
} else if (block_alias) {
|
} else if (block_alias) {
|
||||||
for (const auto candidate: candidates) {
|
for (const auto candidate: candidates) {
|
||||||
const auto* owner = m_slot_images.try_get(candidate);
|
const auto& owner = m_slot_images[candidate];
|
||||||
if (candidate != result && owner != nullptr && owner->registered &&
|
if (candidate != result && owner.registered && !owner.IsCpuDirty() &&
|
||||||
!owner->IsCpuDirty() &&
|
BcAlias::Matches(m_slot_images[result].info, owner.info)) {
|
||||||
BcAlias::Matches(m_slot_images[result].info, owner->info)) {
|
|
||||||
BcAlias::Resolve(*this, candidate, result);
|
BcAlias::Resolve(*this, candidate, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1373,14 +1369,14 @@ ImageId TextureCache::FindImageFromRange(uint64_t address, uint64_t size, bool e
|
|||||||
std::scoped_lock lock {m_lock};
|
std::scoped_lock lock {m_lock};
|
||||||
ImageIds matches;
|
ImageIds matches;
|
||||||
for (const auto id: FindImagesInRegion(address, size, false)) {
|
for (const auto id: FindImagesInRegion(address, size, false)) {
|
||||||
auto owner = m_slot_images.try_get(id);
|
const auto* owner = &m_slot_images[id];
|
||||||
if (owner == nullptr || owner->info.data.address != address) {
|
if (owner->info.data.address != address) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ensure_valid && owner->depth_id) {
|
if (ensure_valid && owner->depth_id) {
|
||||||
owner = m_slot_images.try_get(owner->depth_id);
|
owner = &m_slot_images[owner->depth_id];
|
||||||
}
|
}
|
||||||
if (owner == nullptr || (ensure_valid && !owner->SafeToDownload())) {
|
if (ensure_valid && !owner->SafeToDownload()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
matches.push_back(id);
|
matches.push_back(id);
|
||||||
@@ -1397,11 +1393,8 @@ ImageId TextureCache::FindImageFromRange(uint64_t address, uint64_t size, bool e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selected && ensure_valid) {
|
if (selected && ensure_valid && m_slot_images[selected].depth_id) {
|
||||||
const auto owner = m_slot_images.try_get(selected);
|
selected = m_slot_images[selected].depth_id;
|
||||||
if (owner != nullptr && owner->depth_id) {
|
|
||||||
selected = owner->depth_id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
@@ -1422,9 +1415,8 @@ vk::ImageView TextureCache::FindTexture(ImageId id, const ImageDesc& desc) {
|
|||||||
desc.info.data.End() <= image.info.stencil.End()) {
|
desc.info.data.End() <= image.info.stencil.End()) {
|
||||||
for (const auto stencil_id:
|
for (const auto stencil_id:
|
||||||
FindImagesInRegion(image.info.stencil.address, image.info.stencil.size, false)) {
|
FindImagesInRegion(image.info.stencil.address, image.info.stencil.size, false)) {
|
||||||
const auto* stencil = m_slot_images.try_get(stencil_id);
|
const auto& stencil = m_slot_images[stencil_id];
|
||||||
if (stencil != nullptr && stencil->depth_id == id &&
|
if (stencil.depth_id == id && stencil.info.data == image.info.stencil) {
|
||||||
stencil->info.data == image.info.stencil) {
|
|
||||||
RefreshImage(stencil_id);
|
RefreshImage(stencil_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1535,27 +1527,24 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer& command, uint64_t address
|
|||||||
vk::ImageAspectFlags aspect {};
|
vk::ImageAspectFlags aspect {};
|
||||||
ImageSubresourceRange subresources;
|
ImageSubresourceRange subresources;
|
||||||
for (const auto id: FindImagesInRegion(address, size, false)) {
|
for (const auto id: FindImagesInRegion(address, size, false)) {
|
||||||
auto owner = m_slot_images.try_get(id);
|
const auto& owner = m_slot_images[id];
|
||||||
if (owner == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vk::ImageAspectFlags candidate {};
|
vk::ImageAspectFlags candidate {};
|
||||||
ImageId candidate_id = id;
|
ImageId candidate_id = id;
|
||||||
ImageSubresourceRange candidate_subresources {
|
ImageSubresourceRange candidate_subresources {
|
||||||
0, owner->info.resources.levels, 0, owner->info.TransferLayers()};
|
0, owner.info.resources.levels, 0, owner.info.TransferLayers()};
|
||||||
if (owner->depth_id && owner->info.data.address == address &&
|
if (owner.depth_id && owner.info.data.address == address &&
|
||||||
owner->info.data.size == size) {
|
owner.info.data.size == size) {
|
||||||
candidate = vk::ImageAspectFlagBits::eStencil;
|
candidate = vk::ImageAspectFlagBits::eStencil;
|
||||||
candidate_id = owner->depth_id;
|
candidate_id = owner.depth_id;
|
||||||
candidate_subresources = owner->stencil_subresources;
|
candidate_subresources = owner.stencil_subresources;
|
||||||
owner = m_slot_images.try_get(candidate_id);
|
const auto& depth = m_slot_images[candidate_id];
|
||||||
if (owner == nullptr || owner->backing.image == nullptr || !owner->info.HasStencil()) {
|
if (depth.backing.image == nullptr || !depth.info.HasStencil()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (!owner->depth_id && owner->info.data.address == address &&
|
} else if (!owner.depth_id && owner.info.data.address == address &&
|
||||||
owner->info.data.size == size) {
|
owner.info.data.size == size) {
|
||||||
candidate = owner->info.IsDepth() ? vk::ImageAspectFlagBits::eDepth
|
candidate = owner.info.IsDepth() ? vk::ImageAspectFlagBits::eDepth
|
||||||
: vk::ImageAspectFlagBits::eColor;
|
: vk::ImageAspectFlagBits::eColor;
|
||||||
}
|
}
|
||||||
if (!candidate) {
|
if (!candidate) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1896,23 +1885,20 @@ void TextureCache::InvalidateCpuAliases(uint64_t address, uint64_t size) {
|
|||||||
const auto page_begin = Common::AlignDown(address, TRACKER_PAGE_SIZE);
|
const auto page_begin = Common::AlignDown(address, TRACKER_PAGE_SIZE);
|
||||||
const auto page_end = Common::AlignUp(address + size, TRACKER_PAGE_SIZE);
|
const auto page_end = Common::AlignUp(address + size, TRACKER_PAGE_SIZE);
|
||||||
for (const auto id: FindImagesInRegion(address, size, true)) {
|
for (const auto id: FindImagesInRegion(address, size, true)) {
|
||||||
auto owner = m_slot_images.try_get(id);
|
auto& owner = m_slot_images[id];
|
||||||
if (owner == nullptr) {
|
if (owner.Overlaps(address, size)) {
|
||||||
continue;
|
owner.MarkCpuDirty();
|
||||||
}
|
|
||||||
if (owner->Overlaps(address, size)) {
|
|
||||||
owner->MarkCpuDirty();
|
|
||||||
UntrackImage(id);
|
UntrackImage(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto image_begin = owner->info.data.address;
|
const auto image_begin = owner.info.data.address;
|
||||||
const auto image_end = owner->info.data.End();
|
const auto image_end = owner.info.data.End();
|
||||||
if (page_end < image_end) {
|
if (page_end < image_end) {
|
||||||
UntrackImageHead(id);
|
UntrackImageHead(id);
|
||||||
} else if (image_begin < page_begin) {
|
} else if (image_begin < page_begin) {
|
||||||
UntrackImageTail(id);
|
UntrackImageTail(id);
|
||||||
} else {
|
} else {
|
||||||
MarkAsMaybeDirty(id, *owner);
|
MarkAsMaybeDirty(id, owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2052,8 +2038,7 @@ void TextureCache::ProcessDownloadImages() {
|
|||||||
}
|
}
|
||||||
std::scoped_lock lock {m_lock};
|
std::scoped_lock lock {m_lock};
|
||||||
for (const auto id: m_download_images) {
|
for (const auto id: m_download_images) {
|
||||||
const auto owner = m_slot_images.try_get(id);
|
if (m_slot_images[id].IsGpuModified()) {
|
||||||
if (owner != nullptr && owner->registered && owner->IsGpuModified()) {
|
|
||||||
(void)DownloadImageMemory(id);
|
(void)DownloadImageMemory(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -672,9 +672,7 @@ void RenderExecutor::BindRenderTarget(ImageId id) {
|
|||||||
|
|
||||||
void RenderExecutor::ResetBindings() {
|
void RenderExecutor::ResetBindings() {
|
||||||
for (const auto id: m_bound_images) {
|
for (const auto id: m_bound_images) {
|
||||||
if (auto* image = m_context.GetTextureCache().m_slot_images.try_get(id); image != nullptr) {
|
m_context.GetTextureCache().m_slot_images[id].binding = {};
|
||||||
image->binding = {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_bound_images.clear();
|
m_bound_images.clear();
|
||||||
}
|
}
|
||||||
@@ -823,12 +821,9 @@ void RenderExecutor::RebindImages(PreparedBindings& prepared) {
|
|||||||
// Acquire each view before a later overlapping descriptor can replace its image.
|
// Acquire each view before a later overlapping descriptor can replace its image.
|
||||||
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
||||||
if (!images[i].image_id) continue;
|
if (!images[i].image_id) continue;
|
||||||
const auto old_image = texture_cache.m_slot_images.try_get(images[i].image_id);
|
auto& old_image = texture_cache.m_slot_images[images[i].image_id];
|
||||||
if (old_image == nullptr || !old_image->registered ||
|
if (!old_image.registered || old_image.binding.needs_rebind) {
|
||||||
old_image->binding.needs_rebind) {
|
old_image.binding = {};
|
||||||
if (old_image != nullptr) {
|
|
||||||
old_image->binding = {};
|
|
||||||
}
|
|
||||||
images[i] = ResolveTexture(program.info.images[i], snapshot.images[i]);
|
images[i] = ResolveTexture(program.info.images[i], snapshot.images[i]);
|
||||||
BindImage(images[i].image_id,
|
BindImage(images[i].image_id,
|
||||||
images[i].desc.type == TextureCache::BindingType::Storage);
|
images[i].desc.type == TextureCache::BindingType::Storage);
|
||||||
@@ -879,12 +874,9 @@ void RenderExecutor::PrepareGraphicsBindings(std::span<PreparedBindings* const>
|
|||||||
auto& cache = m_context.GetTextureCache();
|
auto& cache = m_context.GetTextureCache();
|
||||||
for (auto& target: colors) {
|
for (auto& target: colors) {
|
||||||
EXIT_IF(!target.image_id);
|
EXIT_IF(!target.image_id);
|
||||||
const auto old_image = cache.m_slot_images.try_get(target.image_id);
|
auto& old_image = cache.m_slot_images[target.image_id];
|
||||||
if (old_image == nullptr || !old_image->registered ||
|
if (!old_image.registered || old_image.binding.needs_rebind) {
|
||||||
old_image->binding.needs_rebind) {
|
old_image.binding = {};
|
||||||
if (old_image != nullptr) {
|
|
||||||
old_image->binding = {};
|
|
||||||
}
|
|
||||||
target.desc.view_info.base_level = target.guest_mip_level;
|
target.desc.view_info.base_level = target.guest_mip_level;
|
||||||
target.desc.view_info.base_layer = target.guest_array_layer;
|
target.desc.view_info.base_layer = target.guest_array_layer;
|
||||||
target.image_id = cache.FindImage(target.desc);
|
target.image_id = cache.FindImage(target.desc);
|
||||||
@@ -944,11 +936,10 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer,
|
|||||||
}
|
}
|
||||||
for (const auto [address, size]: reads) {
|
for (const auto [address, size]: reads) {
|
||||||
for (const auto id: m_bound_images) {
|
for (const auto id: m_bound_images) {
|
||||||
const auto* image = m_context.GetTextureCache().m_slot_images.try_get(id);
|
const auto& image = m_context.GetTextureCache().m_slot_images[id];
|
||||||
if (image == nullptr ||
|
if (!image.binding.shader_write && !image.binding.is_target) continue;
|
||||||
(!image->binding.shader_write && !image->binding.is_target)) continue;
|
for (const auto written: {image.info.data, image.info.stencil,
|
||||||
for (const auto written: {image->info.data, image->info.stencil,
|
image.info.metadata.range}) {
|
||||||
image->info.metadata.range}) {
|
|
||||||
if (written.size != 0 && ImageRangeOverlaps(address, size,
|
if (written.size != 0 && ImageRangeOverlaps(address, size,
|
||||||
written.address, written.size)) {
|
written.address, written.size)) {
|
||||||
EXIT("scalar resource reads overlap an image or attachment write\n");
|
EXIT("scalar resource reads overlap an image or attachment write\n");
|
||||||
|
|||||||
@@ -474,9 +474,8 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
|
|||||||
for (uint32_t i = 0; i < color_count; i++) {
|
for (uint32_t i = 0; i < color_count; i++) {
|
||||||
auto& target = colors[i];
|
auto& target = colors[i];
|
||||||
EXIT_IF(!target.image_id);
|
EXIT_IF(!target.image_id);
|
||||||
const auto owner = cache.m_slot_images.try_get(target.image_id);
|
const auto& owner = cache.m_slot_images[target.image_id];
|
||||||
if (owner == nullptr || (!owner->registered && !owner->info.data.Empty()) ||
|
if ((!owner.registered && !owner.info.data.Empty()) || owner.binding.needs_rebind) {
|
||||||
owner->binding.needs_rebind) {
|
|
||||||
EXIT("color target changed after render-state discovery\n");
|
EXIT("color target changed after render-state discovery\n");
|
||||||
}
|
}
|
||||||
const auto image_view = cache.FindRenderTarget(target.image_id, target.desc);
|
const auto image_view = cache.FindRenderTarget(target.image_id, target.desc);
|
||||||
@@ -502,8 +501,8 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
|
|||||||
attachment.image_layout = layout;
|
attachment.image_layout = layout;
|
||||||
}
|
}
|
||||||
if (depth.image_id) {
|
if (depth.image_id) {
|
||||||
const auto owner = cache.m_slot_images.try_get(depth.image_id);
|
const auto& owner = cache.m_slot_images[depth.image_id];
|
||||||
if (owner == nullptr || !owner->registered || owner->binding.needs_rebind) {
|
if (!owner.registered || owner.binding.needs_rebind) {
|
||||||
EXIT("depth target changed after render-state discovery\n");
|
EXIT("depth target changed after render-state discovery\n");
|
||||||
}
|
}
|
||||||
const auto image_view = cache.FindDepthTarget(depth.image_id, depth.desc);
|
const auto image_view = cache.FindDepthTarget(depth.image_id, depth.desc);
|
||||||
|
|||||||
@@ -4317,12 +4317,6 @@ public:
|
|||||||
BufferCacheTestAccess::PageOwner(
|
BufferCacheTestAccess::PageOwner(
|
||||||
cache, index_begin + 2 * index_page) == index_bridge,
|
cache, index_begin + 2 * index_page) == index_bridge,
|
||||||
"bridging acquisition did not publish its merged Buffer range");
|
"bridging acquisition did not publish its merged Buffer range");
|
||||||
scheduler.Finish();
|
|
||||||
constexpr uint64_t recycled_offset = index_offset + 4 * index_page;
|
|
||||||
const auto recycled = cache.FindBuffer(base + recycled_offset + 0x100,
|
|
||||||
sizeof(uint32_t));
|
|
||||||
Require(name, "slot reuse", recycled == index_left || recycled == index_right,
|
|
||||||
"retired Buffer slot was not reused");
|
|
||||||
const auto [resolved_left, resolved_left_offset] = cache.ObtainBuffer(
|
const auto [resolved_left, resolved_left_offset] = cache.ObtainBuffer(
|
||||||
index_begin + 0x100, sizeof(uint32_t), true, false, index_left);
|
index_begin + 0x100, sizeof(uint32_t), true, false, index_left);
|
||||||
const auto [resolved_right, resolved_right_offset] =
|
const auto [resolved_right, resolved_right_offset] =
|
||||||
@@ -4333,6 +4327,12 @@ public:
|
|||||||
resolved_right == resolved_left &&
|
resolved_right == resolved_left &&
|
||||||
resolved_left_offset != resolved_right_offset,
|
resolved_left_offset != resolved_right_offset,
|
||||||
"saved descriptor IDs did not resolve through the merged owner");
|
"saved descriptor IDs did not resolve through the merged owner");
|
||||||
|
scheduler.Finish();
|
||||||
|
constexpr uint64_t recycled_offset = index_offset + 4 * index_page;
|
||||||
|
const auto recycled = cache.FindBuffer(base + recycled_offset + 0x100,
|
||||||
|
sizeof(uint32_t));
|
||||||
|
Require(name, "slot reuse", recycled == index_left || recycled == index_right,
|
||||||
|
"retired Buffer slot was not reused");
|
||||||
|
|
||||||
constexpr uint64_t stream_page = BufferCache::CACHING_PAGESIZE;
|
constexpr uint64_t stream_page = BufferCache::CACHING_PAGESIZE;
|
||||||
constexpr uint64_t stream_leap = stream_page * 128;
|
constexpr uint64_t stream_leap = stream_page * 128;
|
||||||
|
|||||||
Reference in new issue
Block a user