Skip to content
Merged
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
6 changes: 5 additions & 1 deletion core/libs/prx/libSceAgcDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ set(agcDriverSources
${CMAKE_CURRENT_SOURCE_DIR}/Execution/src/PresentationScaler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/Draw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/DepthSurface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/MultisampleTarget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/ColorTargetLayout.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/ColorTargetTransfer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/Pipeline.cpp
Expand Down Expand Up @@ -790,8 +791,10 @@ if(BUILD_TESTING)
set_tests_properties(agc_descriptor_pool_recycling PROPERTIES SKIP_RETURN_CODE 77)
add_test(NAME agc_draw_snapshot_cap COMMAND agc_driver_recorder_tests --draw-snapshot-cap-only)
set_tests_properties(agc_draw_snapshot_cap PROPERTIES SKIP_RETURN_CODE 77)
add_test(NAME agc_multisample_guest_access COMMAND agc_driver_recorder_tests --multisample-only)
set_tests_properties(agc_multisample_guest_access PROPERTIES SKIP_RETURN_CODE 77)
if(WIN32)
set_tests_properties(agc_host_import_unmap agc_unit_shadow agc_descriptor_pool_recycling agc_draw_snapshot_cap PROPERTIES ENVIRONMENT_MODIFICATION
set_tests_properties(agc_host_import_unmap agc_unit_shadow agc_descriptor_pool_recycling agc_draw_snapshot_cap agc_multisample_guest_access PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
Expand Down Expand Up @@ -841,6 +844,7 @@ add_test_executable(agc_driver_graphics_tests EXCLUDE_FROM_ALL
tests/DepthSurfaceReuse.cpp
Graphics/src/Draw.cpp
Graphics/src/DepthSurface.cpp
Graphics/src/MultisampleTarget.cpp
Graphics/src/Pipeline.cpp
Graphics/src/PipelineLibrary.cpp
Graphics/src/State.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ unsigned long long CodeOffset(const void* address);
// every read and store through this interface calls first. Code that reads guest memory directly
// calls FlushGpuWrites itself.
void SetFlushHook(void (*hook)(std::uint64_t address, std::size_t bytes));
void SetReadGuard(void (*guard)(std::uint64_t address, std::size_t bytes));
void FlushGpuWrites(std::uint64_t address, std::size_t bytes);
// Moves with every ForgetPages call (the libc invalidator: memory unmapped or re-registered): odd
// while the call stores its page states, moved past it after, so a reader that loads an even
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
#include <algorithm>
#include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp"
#include "prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp"
#include <bit>
#include <cstdlib>
#include <optional>
Expand Down Expand Up @@ -265,7 +266,10 @@ bool Driver::fillBuffer(QueueState& queue, std::uint32_t queueId, std::span<cons
for (std::size_t done = 0; done < bytes; done += chunk) GuestMemory::Write(base + done, std::span<const std::byte>(block).first(std::min(chunk, bytes - done)), 16);
phase(FillCpu);
}
if (pattern[0] == pattern[1] && pattern[1] == pattern[2] && pattern[2] == pattern[3]) Graphics::NoteDepthMetadataFill(base, bytes, pattern[0]);
if (pattern[0] == pattern[1] && pattern[1] == pattern[2] && pattern[2] == pattern[3]) {
Graphics::NoteDepthMetadataFill(base, bytes, pattern[0]);
Graphics::NoteColorMetadataFill(base, bytes, pattern[0]);
}
if (profile) {
const auto now = std::chrono::steady_clock::now();
const auto cover = static_cast<std::size_t>(coverage.cover);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp"
#include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp"
#include "prx/libSceAgcDriver/Graphics/include/Recorder.hpp"
#include "prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp"
#include <cstdlib>
#include <cstring>
#include <limits>
Expand Down Expand Up @@ -60,7 +61,12 @@ bool Driver::preparePacketMemory(const Submission& submission, QueueState& queue
}
}
if (opcode == 0x50 && packet.size() >= 7) {
if (Pm4::DmaSource(packet) == 2 && Pm4::DmaDestination(packet) != 1) Graphics::NoteDepthMetadataFill(packet[4] | (static_cast<std::uint64_t>(packet[5]) << 32u), packet[6] & 0x3ffffffu, packet[2]);
if (Pm4::DmaSource(packet) == 0 || Pm4::DmaSource(packet) == 3) Graphics::RequireNoMultisampleTarget(packet[2] | (static_cast<std::uint64_t>(packet[3]) << 32u), packet[6] & 0x3ffffffu, "a DMA copy");
if (Pm4::DmaSource(packet) == 2 && Pm4::DmaDestination(packet) != 1) {
const auto address = packet[4] | (static_cast<std::uint64_t>(packet[5]) << 32u);
Graphics::NoteDepthMetadataFill(address, packet[6] & 0x3ffffffu, packet[2]);
Graphics::NoteColorMetadataFill(address, packet[6] & 0x3ffffffu, packet[2]);
}
}
if (!drainAll && !endOfPipeInterrupt && (opcode == 0x49 || opcode == 0x37)) {
if (const auto label = Pm4::DecodeLabelWrite(packet)) {
Expand Down
8 changes: 8 additions & 0 deletions core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1751,12 +1751,19 @@ void SetFlushHook(void (*hook)(std::uint64_t, std::size_t)) {
flushHook.store(hook, std::memory_order_release);
}

std::atomic<void (*)(std::uint64_t, std::size_t)> readGuard{nullptr};

void SetReadGuard(void (*guard)(std::uint64_t address, std::size_t bytes)) {
readGuard.store(guard, std::memory_order_release);
}

void FlushGpuWrites(std::uint64_t address, std::size_t bytes) {
if (const auto hook = flushHook.load(std::memory_order_acquire)) hook(address, bytes);
}

void Read(std::uint64_t address, std::span<std::byte> destination, std::size_t alignment) {
if (destination.empty()) return;
if (const auto guard = readGuard.load(std::memory_order_acquire)) guard(address, destination.size());
FlushGpuWrites(address, destination.size());
const TimedAccess timed(CounterRead, destination.size());
CountReadCaller(__builtin_return_address(0));
Expand All @@ -1773,6 +1780,7 @@ void Read(std::uint64_t address, std::span<std::byte> destination, std::size_t a

void ReadCommitted(std::uint64_t address, std::span<std::byte> destination) {
if (destination.empty()) return;
if (const auto guard = readGuard.load(std::memory_order_acquire)) guard(address, destination.size());
FlushGpuWrites(address, destination.size());
const TimedAccess timed(CounterRead, destination.size());
CountReadCaller(__builtin_return_address(0));
Expand Down
2 changes: 2 additions & 0 deletions core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "prx/libSceAgcDriver/Graphics/include/PlaceholderImages.hpp"
#include "prx/libSceAgcDriver/Graphics/include/DccMetadata.hpp"
#include "prx/libSceAgcDriver/Execution/include/DisplayFormat.hpp"
#include "prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp"
#include "prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp"
#include "prx/libSceAgcDriver/Graphics/include/GpuColorTransfer.hpp"
#include "prx/libSceAgcDriver/Graphics/include/BufferPool.hpp"
Expand Down Expand Up @@ -598,6 +599,7 @@ struct VulkanDevice::State {
// belong to this device and must be destroyed while it lives.
Graphics::ClearCachedPipelines(device);
Graphics::ClearDepthSurfaces(device);
Graphics::ClearMultisampleTargets(device);
{
std::lock_guard pipelines(computePipelinesMutex);
computePipelines.clear();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_GRAPHICS_INCLUDE_MULTISAMPLETARGET_HPP
#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_GRAPHICS_INCLUDE_MULTISAMPLETARGET_HPP

#include "prx/libSceAgcDriver/Graphics/include/Context.hpp"
#include "prx/libSceAgcDriver/Graphics/include/DccMetadata.hpp"
#include "prx/libSceAgcDriver/Graphics/include/State.hpp"
#include <cstddef>
#include <cstdint>
#include <string>

namespace AgcDriver::Graphics {

class StorageTexture;

class MultisampledCmask {
public:
MultisampledCmask() = default;
MultisampledCmask(std::uint64_t cmaskAddress, std::uint64_t cmaskBytes) : address(cmaskAddress), bytes(cmaskBytes) {}
void NoteFill(std::uint64_t fillAddress, std::size_t fillBytes, std::uint32_t pattern);
void SeedKeys(DccKeys seeded);
void CheckAddress(std::uint64_t cmaskAddress) const;
bool TakeClear();
DccKeys Keys() const { return keys; }
const std::string& Refusal() const { return refusal; }

private:
std::uint64_t address = 0;
std::uint64_t bytes = 0;
DccKeys keys = DccKeys::Uncompressed;
std::string refusal;
};

VkImageView MultisampleTargetView(const Context& context, const ColorTarget& target);
void ResolveMultisampleTarget(const Context& context, const ColorTarget& source, StorageTexture& destination, VkImageView destinationView);
void NoteColorMetadataFill(std::uint64_t address, std::size_t bytes, std::uint32_t pattern);
void ClearMultisampleTargets(VkDevice device);
void RequireNoMultisampleTarget(std::uint64_t address, std::size_t bytes, const char* access);

}

#endif
3 changes: 2 additions & 1 deletion core/libs/prx/libSceAgcDriver/Graphics/include/Pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Pipeline {
Pipeline(const Pipeline&) = delete;
Pipeline& operator=(const Pipeline&) = delete;
VkPipelineLayout Layout() const;
std::shared_ptr<Framebuffer> AcquireFramebuffer(std::span<const VkImageView> targets, std::span<const std::shared_ptr<StorageTexture>> owners, VkExtent2D extent);
std::shared_ptr<Framebuffer> AcquireFramebuffer(std::span<const VkImageView> targets, std::span<const std::shared_ptr<StorageTexture>> owners, VkExtent2D extent, std::span<const std::uint8_t> persistent = {});
// Begins the render pass on the framebuffer, binds the pipeline and sets its dynamic state.
void Begin(VkCommandBuffer commands, const Framebuffer& framebuffer, VkExtent2D extent, const State& state) const;
// The same inside a render pass another pipeline of the same attachments began (compatible by
Expand All @@ -64,6 +64,7 @@ class Pipeline {
struct CachedFramebuffer {
std::vector<VkImageView> views;
std::vector<std::weak_ptr<StorageTexture>> owners;
std::vector<bool> owned;
VkExtent2D extent;
std::shared_ptr<Framebuffer> framebuffer;
};
Expand Down
11 changes: 8 additions & 3 deletions core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct ColorTarget {
bool dccPipeAligned = false;
std::uint64_t cmaskAddress = 0;
std::size_t cmaskBytes = 0;
bool cmaskFastClear = false;
std::uint64_t surfaceAddress = 0;
VkExtent2D surfaceExtent{};
std::uint32_t mipCount = 1;
Expand All @@ -60,6 +61,7 @@ struct ColorTarget {
std::uint32_t exportIndex = 0;
bool uintExport = false;
std::uint32_t pipeBankXor = 0;
std::uint32_t samples = 1;
};

struct DepthTarget {
Expand All @@ -71,6 +73,7 @@ struct DepthTarget {
std::uint8_t clearStencil;
std::uint64_t htileAddress = 0;
bool htileStencil = false;
std::uint32_t samples = 1;
};

struct State {
Expand Down Expand Up @@ -112,6 +115,7 @@ struct State {
VkProvokingVertexModeEXT provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
VkPipelineColorBlendAttachmentState blend;
std::array<float, 4> blendConstants;
std::uint32_t samples = 1;
};

ShaderStages DecodeShaderStages(const QueueState& queue, bool vertexWorkgroup = false);
Expand All @@ -123,9 +127,10 @@ std::size_t CmaskBytes(std::uint32_t width, std::uint32_t height);
std::uint32_t ColorWriteMask(const Registers& context);

struct ColorMetadataPass {
enum class Mode { EliminateFastClear, DccDecompress };
enum class Mode { EliminateFastClear, DccDecompress, Resolve };
Mode mode;
std::vector<ColorTarget> targets;
std::optional<ColorTarget> source;
};
std::optional<ColorMetadataPass> DecodeColorMetadataPass(const QueueState& queue);
std::string DepthMaintenanceRejection(const QueueState& queue);
Expand Down Expand Up @@ -166,15 +171,15 @@ struct DrawKeyRange {
std::uint32_t first;
std::uint32_t count;
};
inline constexpr std::array<DrawKeyRange, 48> DrawKeyRegisters{{
inline constexpr std::array<DrawKeyRange, 49> DrawKeyRegisters{{
{RegisterBank::Context, 0x000, 1}, {RegisterBank::Context, 0x002, 1}, {RegisterBank::Context, 0x005, 1}, {RegisterBank::Context, 0x007, 7}, {RegisterBank::Context, 0x010, 6}, {RegisterBank::Context, 0x01a, 5},
{RegisterBank::Context, 0x080, 4}, {RegisterBank::Context, 0x08c, 4}, {RegisterBank::Context, 0x090, 2}, {RegisterBank::Context, 0x094, 2}, {RegisterBank::Context, 0x0b4, 2}, {RegisterBank::Context, 0x105, 4}, {RegisterBank::Context, 0x10b, 3}, {RegisterBank::Context, 0x10f, 6},
// SPI_PS_INPUT_CNTL_0..31, SPI_PS_INPUT_ENA/ADDR, SPI_PS_IN_CONTROL, SPI_SHADER_POS/Z/COL_FORMAT,
// CB_BLEND0..7_CONTROL, GE_MAX_OUTPUT_PER_SUBGROUP.
{RegisterBank::Context, 0x191, 32}, {RegisterBank::Context, 0x1b3, 2}, {RegisterBank::Context, 0x1b6, 1}, {RegisterBank::Context, 0x1c3, 3}, {RegisterBank::Context, 0x1e0, 8}, {RegisterBank::Context, 0x1ff, 1},
// DB_DEPTH_CONTROL .. PA_CL_VS_OUT_CNTL, PA_SC_MODE_CNTL_0/1, VGT_GS_MODE, VGT_GS_VERT_ITEMSIZE,
// PA_SU_VTX_CNTL, the sample masks, PA_SC_CONSERVATIVE_RASTERIZATION_CNTL.
{RegisterBank::Context, 0x200, 8}, {RegisterBank::Context, 0x286, 2}, {RegisterBank::Context, 0x292, 2}, {RegisterBank::Context, 0x29b, 1}, {RegisterBank::Context, 0x2ab, 1}, {RegisterBank::Context, 0x2ce, 1}, {RegisterBank::Context, 0x2d5, 2}, {RegisterBank::Context, 0x2db, 2}, {RegisterBank::Context, 0x2de, 6}, {RegisterBank::Context, 0x2f8, 2}, {RegisterBank::Context, 0x30e, 2}, {RegisterBank::Context, 0x313, 1},
{RegisterBank::Context, 0x200, 8}, {RegisterBank::Context, 0x286, 2}, {RegisterBank::Context, 0x292, 2}, {RegisterBank::Context, 0x29b, 1}, {RegisterBank::Context, 0x2ab, 1}, {RegisterBank::Context, 0x2ce, 1}, {RegisterBank::Context, 0x2d5, 2}, {RegisterBank::Context, 0x2db, 2}, {RegisterBank::Context, 0x2de, 6}, {RegisterBank::Context, 0x2f8, 2}, {RegisterBank::Context, 0x2fe, 16}, {RegisterBank::Context, 0x30e, 2}, {RegisterBank::Context, 0x313, 1},
// CB_COLOR0..7_BASE .. DCC_BASE (15 words a slot), CB_COLOR0..7_BASE_EXT, DCC_BASE_EXT, ATTRIB2, ATTRIB3.
{RegisterBank::Context, 0x318, 0x78}, {RegisterBank::Context, 0x390, 8}, {RegisterBank::Context, 0x398, 8}, {RegisterBank::Context, 0x3a8, 0x18},
// The pixel program address, RSRC2 and user words; the geometry-back user pointer and program
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ bool StorageFormatAvailable(const Context& context, std::uint32_t guestFormat);
bool StorageClearAvailable(const Context& context, std::uint32_t guestFormat, DccKeys keys);
std::uint64_t SampledTextureMemory();
bool ClearKeepsDenormals(const Context& context, VkFormat format);
bool ClearColorForTexel(VkFormat format, std::uint32_t elementBytes, std::span<const std::uint32_t, 4> pattern, VkClearColorValue& clear);

// A sampled texture's own VkImage with its memory, shared with the recorder while a recorded upload
// still writes it (see the snapshot constructor), so the texture may go before the batch completes.
Expand Down
7 changes: 4 additions & 3 deletions core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ class DepthSurface {
info.extent = {target.extent.width, target.extent.height, 1};
info.mipLevels = 1;
info.arrayLayers = 1;
info.samples = VK_SAMPLE_COUNT_1_BIT;
info.samples = static_cast<VkSampleCountFlagBits>(target.samples);
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | (target.samples == 1 ? VK_IMAGE_USAGE_SAMPLED_BIT : 0u);
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Check(context.Function<PFN_vkCreateImage>("vkCreateImage")(context.device, &info, nullptr, &image), "vkCreateImage depth");
Expand Down Expand Up @@ -113,6 +113,7 @@ class DepthSurface {
key[10] = components.b;
key[11] = components.a;
if (const auto found = textures.find(key); found != textures.end()) return found->second;
Require(target.samples == 1, "sampling a multisampled depth surface is not implemented");
const bool stencil = target.stencilAddress != 0 && resource.baseAddress == target.stencilAddress;
const bool d16 = target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT;
const auto expected = stencil ? VK_FORMAT_R8_UINT : d16 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R32_SFLOAT;
Expand Down Expand Up @@ -158,7 +159,7 @@ class DepthSurface {
};

bool sameSurface(const DepthTarget& a, const DepthTarget& b) {
return a.address == b.address && a.stencilAddress == b.stencilAddress && a.extent.width == b.extent.width && a.extent.height == b.extent.height && a.format == b.format;
return a.address == b.address && a.stencilAddress == b.stencilAddress && a.extent.width == b.extent.width && a.extent.height == b.extent.height && a.format == b.format && a.samples == b.samples;
}

std::mutex& surfacesMutex() {
Expand Down
Loading
Loading