mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
Merge pull request #10837 from Raghav314/perf/agc-depth-plane-copies
perf(agc): keep depth plane copies resident instead of remaking them on each use
This commit is contained in:
4 files changed
+119
-18
No files matched your search
@@ -65,7 +65,7 @@ public:
|
||||
// compute pass writing it and the next pass sampling it share one image and copy nothing.
|
||||
// CanCopyFrom says whether the two descriptors address the same surface compatibly.
|
||||
Texture(const Context& context, const std::shared_ptr<StorageTexture>& source, const GuestTextureResource& descriptor, VkComponentMapping components);
|
||||
Texture(const Context& context, VkImage depthImage, VkFormat depthFormat, VkImageAspectFlags aspect, VkComponentMapping components, VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D, std::uint32_t baseLayer = 0, std::shared_ptr<OwnedImage> owner = {}, VkImageUsageFlags usage = 0);
|
||||
Texture(const Context& context, VkImage depthImage, VkFormat depthFormat, VkImageAspectFlags aspect, VkComponentMapping components, VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D, std::uint32_t baseLayer = 0, std::shared_ptr<OwnedImage> owner = {}, VkImageUsageFlags usage = 0, std::uint32_t layerCount = VK_REMAINING_ARRAY_LAYERS);
|
||||
struct DepthCopyTag {};
|
||||
Texture(const Context& context, const std::shared_ptr<StorageTexture>& source, const GuestTextureResource& descriptor, VkComponentMapping components, DepthCopyTag);
|
||||
struct SrgbExpandTag {};
|
||||
|
||||
@@ -1190,7 +1190,6 @@ struct DepthPlaneSlice {
|
||||
class DepthPlaneCopy {
|
||||
public:
|
||||
DepthPlaneCopy(const Context& context, VkExtent2D extent, VkFormat format, std::uint32_t layers) : context(context), extent(extent), format(format), layers(layers), guestLayers(layers), surfaceLayers(layers) {
|
||||
this->context.bufferPool.reset();
|
||||
VkImageCreateInfo info{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
info.flags = layers % 6u == 0 && extent.width == extent.height ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u;
|
||||
info.imageType = VK_IMAGE_TYPE_2D;
|
||||
@@ -1205,15 +1204,16 @@ public:
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
try {
|
||||
Check(context.Function<PFN_vkCreateImage>("vkCreateImage")(context.device, &info, nullptr, &image), "vkCreateImage depth plane copy");
|
||||
owned = std::make_shared<OwnedImage>(context, image, VK_NULL_HANDLE);
|
||||
VkMemoryRequirements requirements{};
|
||||
context.Function<PFN_vkGetImageMemoryRequirements>("vkGetImageMemoryRequirements")(context.device, image, &requirements);
|
||||
VkMemoryAllocateInfo allocation{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
allocation.allocationSize = requirements.size;
|
||||
allocation.memoryTypeIndex = context.MemoryType(requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
memory = AllocateImageMemory(context, allocation, requirements.memoryTypeBits, "vkAllocateMemory depth plane copy");
|
||||
owned->Allocate(context, allocation, requirements.memoryTypeBits, "vkAllocateMemory depth plane copy");
|
||||
memory = owned->memory;
|
||||
Check(context.Function<PFN_vkBindImageMemory>("vkBindImageMemory")(context.device, image, memory, 0), "vkBindImageMemory depth plane copy");
|
||||
imageBytes = requirements.size;
|
||||
owned = std::make_shared<OwnedImage>(context, image, memory);
|
||||
} catch (...) {
|
||||
release();
|
||||
throw;
|
||||
@@ -1224,19 +1224,21 @@ public:
|
||||
DepthPlaneCopy& operator=(const DepthPlaneCopy&) = delete;
|
||||
|
||||
std::shared_ptr<Texture> Refresh(std::span<const DepthPlaneSlice> slices, const GuestTextureResource& resource, VkComponentMapping components, VkImageViewType viewType, std::uint32_t baseLayer) {
|
||||
Require(slices.size() == layers, "depth plane copy slices do not match its layers");
|
||||
const auto requested = static_cast<std::uint32_t>(slices.size());
|
||||
Require(requested != 0 && requested <= layers, "depth plane copy slices exceed its layers");
|
||||
Require(baseLayer < requested, "a depth plane copy view starts past the slices it was given");
|
||||
const auto geometry = DescribeSurface(resource);
|
||||
const bool guestFill = std::any_of(slices.begin(), slices.end(), [](const auto& slice) { return slice.image == VK_NULL_HANDLE; });
|
||||
if (guestFill && (geometry.layers != layers || geometry.sliceLinearBytes < sliceBytes() || geometry.mips.empty())) {
|
||||
if (guestFill && (geometry.layers != requested || geometry.sliceLinearBytes < sliceBytes() || geometry.mips.empty())) {
|
||||
char text[320];
|
||||
std::snprintf(text, sizeof(text), "AGC graphics: depth plane copy geometry does not match its layers (copy %ux%u, %u layers, %llu bytes a slice; texture %ux%u guest format %u, dimension %d, tile mode %u, %u layers, %llu bytes a slice, %zu mips)", extent.width, extent.height, layers, static_cast<unsigned long long>(sliceBytes()), resource.width, resource.height, resource.format, static_cast<int>(resource.dimension), resource.tileMode, geometry.layers, static_cast<unsigned long long>(geometry.sliceLinearBytes), geometry.mips.size());
|
||||
throw std::runtime_error(text);
|
||||
}
|
||||
const auto stagingBytes = std::max<std::size_t>(static_cast<std::size_t>(geometry.sliceLinearBytes), static_cast<std::size_t>(sliceBytes())) * layers;
|
||||
const auto stagingBytes = std::max<std::size_t>(static_cast<std::size_t>(geometry.sliceLinearBytes), static_cast<std::size_t>(sliceBytes())) * requested;
|
||||
std::vector<std::shared_ptr<Buffer>> uploads;
|
||||
std::vector<std::uint32_t> uploadLayers;
|
||||
std::vector<std::uint32_t> copiedLayers;
|
||||
for (std::uint32_t layer = 0; layer < layers; ++layer) {
|
||||
for (std::uint32_t layer = 0; layer < requested; ++layer) {
|
||||
auto& held = guestLayers[layer];
|
||||
auto& surface = surfaceLayers[layer];
|
||||
if (slices[layer].image != VK_NULL_HANDLE) {
|
||||
@@ -1264,10 +1266,11 @@ public:
|
||||
if (staging == nullptr || stagingBytes > staging->Size()) staging = std::make_shared<DeviceBuffer>(context, stagingBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
record(slices, resource, geometry, copiedLayers, uploads, uploadLayers, staging);
|
||||
}
|
||||
const std::array<std::uint32_t, 6> key{static_cast<std::uint32_t>(components.r), static_cast<std::uint32_t>(components.g), static_cast<std::uint32_t>(components.b), static_cast<std::uint32_t>(components.a), static_cast<std::uint32_t>(viewType), baseLayer};
|
||||
const auto viewLayers = viewType == VK_IMAGE_VIEW_TYPE_2D ? 1u : requested - baseLayer;
|
||||
const std::array<std::uint32_t, 7> key{static_cast<std::uint32_t>(components.r), static_cast<std::uint32_t>(components.g), static_cast<std::uint32_t>(components.b), static_cast<std::uint32_t>(components.a), static_cast<std::uint32_t>(viewType), baseLayer, viewLayers};
|
||||
auto& texture = textures[key];
|
||||
if (texture == nullptr) {
|
||||
texture = std::make_shared<Texture>(context, image, format, aspect(), components, viewType, baseLayer, owned);
|
||||
texture = std::make_shared<Texture>(context, image, format, aspect(), components, viewType, baseLayer, owned, 0, viewLayers);
|
||||
texture->MarkRefreshedPerUse();
|
||||
}
|
||||
return texture;
|
||||
@@ -1295,7 +1298,7 @@ private:
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
std::shared_ptr<OwnedImage> owned;
|
||||
std::shared_ptr<DeviceBuffer> staging;
|
||||
std::map<std::array<std::uint32_t, 6>, std::shared_ptr<Texture>> textures;
|
||||
std::map<std::array<std::uint32_t, 7>, std::shared_ptr<Texture>> textures;
|
||||
std::vector<GuestLayer> guestLayers;
|
||||
std::vector<DepthPlaneSlice> surfaceLayers;
|
||||
bool filled = false;
|
||||
@@ -1385,8 +1388,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
std::map<std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat, std::uint32_t>, std::unique_ptr<DepthPlaneCopy>>& planeCopies() {
|
||||
static auto* copies = new std::map<std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat, std::uint32_t>, std::unique_ptr<DepthPlaneCopy>>();
|
||||
std::map<std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat>, std::unique_ptr<DepthPlaneCopy>>& planeCopies() {
|
||||
static auto* copies = new std::map<std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat>, std::unique_ptr<DepthPlaneCopy>>();
|
||||
return *copies;
|
||||
}
|
||||
|
||||
@@ -1395,7 +1398,7 @@ std::uint64_t& planeCopyClock() {
|
||||
return clock;
|
||||
}
|
||||
|
||||
void evictPlaneCopies(const std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat, std::uint32_t>& keep) {
|
||||
void evictPlaneCopies(const std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat>& keep) {
|
||||
static const VkDeviceSize budget = [] {
|
||||
const char* text = std::getenv("APS5_DEPTH_PLANE_COPY_MIB");
|
||||
return static_cast<VkDeviceSize>(text != nullptr ? std::strtoull(text, nullptr, 10) : 256ull) << 20u;
|
||||
@@ -2419,9 +2422,9 @@ std::shared_ptr<Texture> DepthSurfaceTexture(const Context& context, std::span<c
|
||||
}
|
||||
const auto imageFormat = integer ? VK_FORMAT_R16_UINT : d16 ? VK_FORMAT_D16_UNORM : VK_FORMAT_D32_SFLOAT;
|
||||
auto& copies = planeCopies();
|
||||
const std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat, std::uint32_t> copyKey{context.device, base.address, base.extent.width, base.extent.height, imageFormat, layers};
|
||||
const std::tuple<VkDevice, std::uint64_t, std::uint32_t, std::uint32_t, VkFormat> copyKey{context.device, base.address, base.extent.width, base.extent.height, imageFormat};
|
||||
auto& copy = copies[copyKey];
|
||||
if (copy == nullptr) copy = std::make_unique<DepthPlaneCopy>(context, base.extent, imageFormat, layers);
|
||||
if (copy == nullptr || copy->layers < layers) copy = std::make_unique<DepthPlaneCopy>(context, base.extent, imageFormat, layers);
|
||||
copy->lastUse = ++planeCopyClock();
|
||||
auto texture = copy->Refresh(slices, resource, components, cube || resource.dimension == TextureDimension::k2DArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, layered && !cube ? resource.baseArray : 0u);
|
||||
evictPlaneCopies(copyKey);
|
||||
|
||||
@@ -1087,7 +1087,7 @@ Texture::Texture(const Context& context, const std::shared_ptr<StorageTexture>&
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Texture(const Context& context, VkImage depthImage, VkFormat depthFormat, VkImageAspectFlags aspect, VkComponentMapping components, VkImageViewType viewType, std::uint32_t baseLayer, std::shared_ptr<OwnedImage> owner, VkImageUsageFlags usage) : context(context), owned(std::move(owner)) {
|
||||
Texture::Texture(const Context& context, VkImage depthImage, VkFormat depthFormat, VkImageAspectFlags aspect, VkComponentMapping components, VkImageViewType viewType, std::uint32_t baseLayer, std::shared_ptr<OwnedImage> owner, VkImageUsageFlags usage, std::uint32_t layerCount) : context(context), owned(std::move(owner)) {
|
||||
Require(owned == nullptr || (owned->image == depthImage && owned->context.device == context.device), "a depth sampled view must retain its own device and image");
|
||||
layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
VkImageViewCreateInfo viewInfo{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
@@ -1099,7 +1099,7 @@ Texture::Texture(const Context& context, VkImage depthImage, VkFormat depthForma
|
||||
viewInfo.format = depthFormat;
|
||||
viewFormat = depthFormat;
|
||||
viewInfo.components = components;
|
||||
viewInfo.subresourceRange = {aspect, 0, 1, baseLayer, viewType == VK_IMAGE_VIEW_TYPE_2D ? 1u : VK_REMAINING_ARRAY_LAYERS};
|
||||
viewInfo.subresourceRange = {aspect, 0, 1, baseLayer, viewType == VK_IMAGE_VIEW_TYPE_2D ? 1u : layerCount};
|
||||
Check(context.Function<PFN_vkCreateImageView>("vkCreateImageView")(context.device, &viewInfo, nullptr, &view), "vkCreateImageView depth plane");
|
||||
viewRange = {viewInfo.viewType, viewInfo.subresourceRange.levelCount, viewInfo.subresourceRange.layerCount};
|
||||
if (viewType != VK_IMAGE_VIEW_TYPE_2D_ARRAY) return;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "prx/libSceAgcDriver/Execution/include/BdaFeatures.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/BufferPool.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Recorder.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Texture.hpp"
|
||||
@@ -46,6 +47,18 @@ PFN_vkCmdCopyImageToBuffer realCopyImageToBuffer = nullptr;
|
||||
PFN_vkCmdCopyBufferToImage realCopyBufferToImage = nullptr;
|
||||
std::atomic<std::uint32_t> imageToBufferCopies{0};
|
||||
std::atomic<std::uint32_t> bufferToImageCopies{0};
|
||||
std::atomic<VkImage> lastFilledImage{VK_NULL_HANDLE};
|
||||
PFN_vkAllocateMemory realAllocateMemory = nullptr;
|
||||
std::atomic<std::uint32_t> memoryAllocations{0};
|
||||
std::atomic<VkDeviceSize> lastAllocationBytes{0};
|
||||
std::atomic<std::uint32_t> lastAllocationType{0};
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL CountAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* info, const VkAllocationCallbacks* allocator, VkDeviceMemory* memory) {
|
||||
memoryAllocations.fetch_add(1);
|
||||
lastAllocationBytes = info->allocationSize;
|
||||
lastAllocationType = info->memoryTypeIndex;
|
||||
return realAllocateMemory(device, info, allocator, memory);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL CountImageToBuffer(VkCommandBuffer commands, VkImage image, VkImageLayout layout, VkBuffer buffer, std::uint32_t count, const VkBufferImageCopy* regions) {
|
||||
imageToBufferCopies.fetch_add(1);
|
||||
@@ -54,6 +67,7 @@ VKAPI_ATTR void VKAPI_CALL CountImageToBuffer(VkCommandBuffer commands, VkImage
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL CountBufferToImage(VkCommandBuffer commands, VkBuffer buffer, VkImage image, VkImageLayout layout, std::uint32_t count, const VkBufferImageCopy* regions) {
|
||||
bufferToImageCopies.fetch_add(1);
|
||||
lastFilledImage = image;
|
||||
realCopyBufferToImage(commands, buffer, image, layout, count, regions);
|
||||
}
|
||||
|
||||
@@ -64,6 +78,10 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL CountingDeviceProc(VkDevice device, con
|
||||
realCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(function);
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&CountImageToBuffer);
|
||||
}
|
||||
if (std::strcmp(name, "vkAllocateMemory") == 0) {
|
||||
realAllocateMemory = reinterpret_cast<PFN_vkAllocateMemory>(function);
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&CountAllocateMemory);
|
||||
}
|
||||
if (std::strcmp(name, "vkCmdCopyBufferToImage") == 0) {
|
||||
realCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(function);
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&CountBufferToImage);
|
||||
@@ -434,6 +452,76 @@ void RecordedUploads(const Context& context, const WatchedBlock& block) {
|
||||
recorder.Sync();
|
||||
}
|
||||
|
||||
void PooledPlaneCopies(const Context& context, const WatchedBlock& first, const WatchedBlock& second) {
|
||||
ClearDepthSurfaces(context.device);
|
||||
FillLayer(first.Data() + LayerBytes, 0.25f);
|
||||
FillLayer(second.Data() + LayerBytes, 0.75f);
|
||||
DepthSurfaceView(context, DepthTarget{first.Address(), 0, {Side, Side}, VK_FORMAT_D32_SFLOAT, 1.0f, 0, 0});
|
||||
DepthSurfaceView(context, DepthTarget{second.Address(), 0, {Side, Side}, VK_FORMAT_D32_SFLOAT, 1.0f, 0, 0});
|
||||
const auto sample = [&](const WatchedBlock& block, int round) {
|
||||
lastFilledImage = VK_NULL_HANDLE;
|
||||
bufferToImageCopies = 0;
|
||||
Require(DepthSurfaceTexture(context, words, ArrayOver(block.Address()), components) != nullptr, "the 2D array over a depth surface was not sampled through its depth planes in round " + std::to_string(round));
|
||||
Require(DepthPlaneCopyCount() == 1, "the depth plane copies outgrew a budget that holds one in round " + std::to_string(round) + ", " + std::to_string(DepthPlaneCopyCount()) + " copies");
|
||||
Require(lastFilledImage.load() != VK_NULL_HANDLE && bufferToImageCopies.load() == 1, "a plane copy made again over a full budget was not filled from its surface once in round " + std::to_string(round) + ", " + std::to_string(bufferToImageCopies.load()) + " fills");
|
||||
};
|
||||
sample(first, 0);
|
||||
sample(second, 0);
|
||||
const auto keepsCopies = [&] {
|
||||
if (context.bufferPool == nullptr) return false;
|
||||
const VkMemoryAllocateInfo probe{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, nullptr, lastAllocationBytes.load(), lastAllocationType.load()};
|
||||
const auto memory = context.bufferPool->TakeImageMemory(probe, "vkAllocateMemory pool probe");
|
||||
const auto before = context.bufferPool->RetainedImages();
|
||||
context.bufferPool->PutImageMemory(memory, probe.allocationSize, probe.memoryTypeIndex);
|
||||
const bool kept = context.bufferPool->RetainedImages() > before;
|
||||
return kept;
|
||||
}();
|
||||
memoryAllocations = 0;
|
||||
for (int round = 1; round <= 3; ++round) {
|
||||
sample(first, round);
|
||||
sample(second, round);
|
||||
}
|
||||
if (!keepsCopies) {
|
||||
std::printf("note: the device memory pool does not keep a block of a plane copy's size and memory type here (not device-tiered, or its heap over budget); the reuse of evicted copies' memory is not checked\n");
|
||||
} else {
|
||||
Require(memoryAllocations.load() == 0, "plane copies evicted and made again over a full budget allocated device memory " + std::to_string(memoryAllocations.load()) + " times instead of taking the evicted copies' memory back");
|
||||
}
|
||||
ClearDepthSurfaces(context.device);
|
||||
}
|
||||
|
||||
void SharedLayerRanges(const Context& context, const WatchedBlock& block) {
|
||||
ClearDepthSurfaces(context.device);
|
||||
auto resource = ArrayOver(block.Address());
|
||||
resource.depthOrLastArray = 3;
|
||||
const auto geometry = DescribeSurface(resource);
|
||||
for (std::uint32_t layer = 0; layer < 4; ++layer) {
|
||||
DepthSurfaceView(context, DepthTarget{block.Address() + geometry.GuestLayerOffset(layer), 0, {Side, Side}, VK_FORMAT_D32_SFLOAT, 1.0f, 0, 0});
|
||||
}
|
||||
DepthSurfaceView(context, DepthTarget{block.Address() + 16u * LayerBytes, 0, {Side, Side}, VK_FORMAT_D32_SFLOAT, 1.0f, 0, 0});
|
||||
const auto sample = [&](std::uint32_t lastArray, std::uint32_t baseArray, std::uint32_t fromSlices, std::uint32_t intoCopy) {
|
||||
auto range = resource;
|
||||
range.depthOrLastArray = lastArray;
|
||||
range.baseArray = baseArray;
|
||||
imageToBufferCopies = 0;
|
||||
bufferToImageCopies = 0;
|
||||
const auto texture = DepthSurfaceTexture(context, words, range, components);
|
||||
const auto when = "layers " + std::to_string(baseArray) + "-" + std::to_string(lastArray);
|
||||
Require(texture != nullptr, "the 2D array over depth surfaces was not sampled through its depth planes for " + when);
|
||||
if (imageToBufferCopies.load() != fromSlices || bufferToImageCopies.load() != intoCopy) {
|
||||
throw std::runtime_error("sampling " + when + " of the depth surfaces recorded " + std::to_string(imageToBufferCopies.load()) + " depth surface copies and " + std::to_string(bufferToImageCopies.load()) + " plane copy fills, expected " + std::to_string(fromSlices) + " and " + std::to_string(intoCopy));
|
||||
}
|
||||
const auto view = texture->SampledViewRange(false);
|
||||
Require(view.layers == lastArray + 1u - baseArray, "the view sampling " + when + " covers " + std::to_string(view.layers) + " layers, not the texture's own");
|
||||
return texture;
|
||||
};
|
||||
sample(3, 0, 4, 1);
|
||||
sample(2, 0, 0, 0);
|
||||
sample(1, 0, 0, 0);
|
||||
sample(2, 1, 0, 0);
|
||||
sample(3, 0, 0, 0);
|
||||
ClearDepthSurfaces(context.device);
|
||||
}
|
||||
|
||||
void RunCubeGather(const Context& base, const WatchedBlock& block) {
|
||||
TextureDetiler detiler(base);
|
||||
auto context = base;
|
||||
@@ -508,6 +596,11 @@ void RunCubeTiledSlice(const Context& base, const WatchedBlock& block) {
|
||||
|
||||
int main() {
|
||||
try {
|
||||
#ifdef _WIN32
|
||||
_putenv_s("APS5_DEPTH_PLANE_COPY_MIB", "1");
|
||||
#else
|
||||
setenv("APS5_DEPTH_PLANE_COPY_MIB", "1", 1);
|
||||
#endif
|
||||
if (!AgcDriver::GuestMemory::WriteWatched()) {
|
||||
std::puts("skipped, guest memory has no write watch");
|
||||
return Skipped;
|
||||
@@ -528,6 +621,11 @@ int main() {
|
||||
Require(AgcDriver::GuestMemory::Watched(block.Address(), BlockBytes), "depth plane guest layers: the guest block is not write-watched");
|
||||
Run(context, block);
|
||||
RecordedUploads(context, block);
|
||||
{
|
||||
WatchedBlock second;
|
||||
PooledPlaneCopies(context, block, second);
|
||||
}
|
||||
SharedLayerRanges(context, block);
|
||||
RunCubeGather(context, block);
|
||||
RunCubeTiledSlice(context, block);
|
||||
SparseGuestLayers(context);
|
||||
|
||||
Reference in new issue
Block a user