Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,14 @@ class DepthPlaneCopy {
std::shared_ptr<Texture> Refresh(std::span<const DepthPlaneSlice> slices, const GuestTextureResource& resource, VkComponentMapping components, VkImageViewType viewType) {
Require(slices.size() == layers, "depth plane copy slices do not match its layers");
const auto geometry = DescribeSurface(resource);
Require(geometry.layers == layers && geometry.sliceLinearBytes == sliceBytes() && !geometry.mips.empty(), "depth plane copy geometry does not match its layers");
Require(geometry.layers == layers && !geometry.mips.empty(), "depth plane copy geometry does not match its layers");
const auto& plane = geometry.mips.front();
Require(plane.pitchBytes % texelBytes() == 0 && plane.pitchBytes >= extent.width * texelBytes() && plane.height >= extent.height, "depth plane copy geometry does not match its layers");
const auto stagingBytes = static_cast<std::size_t>(geometry.LinearLayerOffset(layers - 1) + plane.linearOffset + static_cast<std::uint64_t>(plane.pitchBytes) * plane.height);
if (staging->Size() < stagingBytes) {
Require(!filled, "depth plane copy geometry does not match its layers");
staging = std::make_unique<DeviceBuffer>(context, stagingBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
}
std::vector<std::shared_ptr<Buffer>> uploads;
std::vector<std::uint32_t> uploadLayers;
std::vector<std::uint32_t> copiedLayers;
Expand Down Expand Up @@ -370,9 +377,12 @@ class DepthPlaneCopy {
const auto barrier = context.Resolved(&DeviceFunctions::cmdPipelineBarrier, "vkCmdPipelineBarrier");
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT);
std::vector<VkBufferImageCopy> regions;
const auto& plane = geometry.mips.front();
const auto region = [&](std::uint32_t layer, VkImageAspectFlags aspectMask, std::uint32_t imageLayer) {
VkBufferImageCopy copy{};
copy.bufferOffset = sliceBytes() * layer;
copy.bufferOffset = geometry.LinearLayerOffset(layer) + plane.linearOffset;
copy.bufferRowLength = plane.pitchBytes / texelBytes();
copy.bufferImageHeight = plane.height;
copy.imageSubresource = {aspectMask, 0, imageLayer, 1};
copy.imageExtent = {extent.width, extent.height, 1};
return copy;
Expand All @@ -386,7 +396,7 @@ class DepthPlaneCopy {
RecordMemoryBarrier(context, commands, VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
for (std::size_t upload = 0; upload < uploads.size(); ++upload) {
const auto layer = uploadLayers[upload];
context.detiler->Dispatch(commands, resource.tileMode, format == VK_FORMAT_D32_SFLOAT ? 4u : 2u, uploads[upload]->Handle(), 0, staging->Handle(), geometry.LinearLayerOffset(layer), geometry.mips.front(), false, layer, geometry.thick);
context.detiler->Dispatch(commands, resource.tileMode, texelBytes(), uploads[upload]->Handle(), 0, staging->Handle(), geometry.LinearLayerOffset(layer), plane, false, layer, geometry.thick);
regions.push_back(region(layer, aspect(), layer));
}
if (recorder != nullptr) {
Expand Down Expand Up @@ -416,8 +426,12 @@ class DepthPlaneCopy {
else Recorder::CountBarriers(Recorder::CommandClass::Draw, 3);
}

std::uint32_t texelBytes() const {
return format == VK_FORMAT_D32_SFLOAT ? 4u : 2u;
}

VkDeviceSize sliceBytes() const {
return static_cast<VkDeviceSize>(extent.width) * extent.height * (format == VK_FORMAT_D32_SFLOAT ? 4u : 2u);
return static_cast<VkDeviceSize>(extent.width) * extent.height * texelBytes();
}

VkImageAspectFlags aspect() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ constexpr std::size_t IntegerOffset = 0xa0000;
constexpr std::size_t DepthBitsOffset = 0xb0000;
constexpr std::size_t OneSliceOffset = 0xd0000;
constexpr std::size_t FirstSliceOffset = 0xe0000;
constexpr std::size_t PaddedCubeOffset = 0x120000;
constexpr float DrawnDepth = 0.25f;
constexpr float DrawnD16Depth = 0.2f;
constexpr std::uint32_t DrawnD16Bits = 13107;
Expand Down Expand Up @@ -316,6 +317,17 @@ void FirstSliceCase(AgcDriver::VulkanDevice& device, GuestBlock& block, std::spa
Expect(output, Bits(DrawnDepth), "3-slice D32 2D array through a 2D shader image");
}

void PaddedCubeCase(AgcDriver::VulkanDevice& device, GuestBlock& block, std::span<std::uint32_t> output) {
auto* base = block.At(PaddedCubeOffset);
DrawDepth(device, reinterpret_cast<std::uintptr_t>(base), {128, 128}, VK_FORMAT_D16_UNORM, DrawnD16Depth);
for (std::uint32_t face = 1; face < 6u; ++face) FillSlice(base + face * SliceBytes, SliceBytes, 0x1000u + face, 2u);
const Shape shape{Format16Uint, 128, 128, TypeCube, 0, Swizzle64KbZX};
for (std::uint32_t face = 0; face < 6u; ++face) {
Load(device, base, shape, face, output);
Expect(output, face == 0 ? DrawnD16Bits : 0x1000u + face, "D16 cube with padded rows, face " + std::to_string(face));
}
}

// A plane array from a later base slice is still refused (its slice offsets are not modeled here).
void RefusalCase(AgcDriver::VulkanDevice& device, GuestBlock& block, std::span<std::uint32_t> output) {
bool refused = false;
Expand Down Expand Up @@ -343,6 +355,7 @@ int main() {
IntegerCase(*device, block, output);
DepthBitsArrayCase(*device, block, output);
FirstSliceCase(*device, block, output);
PaddedCubeCase(*device, block, output);
RefusalCase(*device, block, output);
std::puts("depth plane sampling tests passed");
return 0;
Expand Down
Loading