Skip to content
Draft
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
21 changes: 21 additions & 0 deletions core/libs/prx/libSceAgcDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,31 @@ add_custom_command(
VERBATIM
)

foreach(agcSampleAspect IN ITEMS Depth Stencil)
set(agcSampleArrayDefines)
if(agcSampleAspect STREQUAL "Stencil")
set(agcSampleArrayDefines -DSTENCIL=1)
endif()
set(agcSampleArraySource ${CMAKE_CURRENT_SOURCE_DIR}/tests/shaders/SampleArray.comp)
set(agcSampleArraySpv ${agcTestShaderGeneratedRoot}/Sample${agcSampleAspect}Array.spv)
set(agcSampleArrayHeader ${agcTestShaderGeneratedRoot}/Sample${agcSampleAspect}Array_spv.h)
add_custom_command(
OUTPUT "${agcSampleArrayHeader}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${agcTestShaderGeneratedRoot}"
COMMAND "$<TARGET_FILE:glslang-standalone>" -V --target-env vulkan1.1 ${agcSampleArrayDefines} -o "${agcSampleArraySpv}" "${agcSampleArraySource}"
COMMAND ${CMAKE_COMMAND} -DINPUT=${agcSampleArraySpv} -DOUTPUT=${agcSampleArrayHeader}
-DSYMBOL=SAMPLE_${agcSampleAspect}_ARRAY_SPV -P "${CMAKE_CURRENT_SOURCE_DIR}/embed_spirv.cmake"
DEPENDS "${agcSampleArraySource}" glslang-standalone
VERBATIM
)
list(APPEND agcSampleArrayHeaders "${agcSampleArrayHeader}")
endforeach()

add_test_executable(agc_driver_recorder_tests EXCLUDE_FROM_ALL
tests/Recorder.cpp
tests/ResidentPresent.cpp
${agcSampleLodShaderHeader}
${agcSampleArrayHeaders}
)

target_include_directories(agc_driver_recorder_tests PRIVATE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ inline Registers InitialContextRegisters() {
{0x318, 0}, {0x31b, 0}, {0x31c, 0}, {0x31d, 0},
{0x390, 0}, {0x3b0, 0}, {0x3b8, 0}
};
for (std::uint32_t i = 0; i < 8; ++i) result.emplace(0x1e0 + i, 0x20010001);
for (std::uint32_t i = 0; i < 8; ++i) {
result.emplace(0x1e0 + i, 0x20010001);
result.emplace(0x31c + 0xfu * i, 0);
}
for (std::uint32_t i = 0; i < 16; ++i) {
result.emplace(0x94 + 2 * i, 0x80000000);
result.emplace(0x95 + 2 * i, 0x40004000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ class VulkanDevice {
// built for its draw-cache entry (design_cpu_final M8); null otherwise.
void Draw(const Graphics::State& graphics, const Pm4::DrawParameters& draw, std::span<const Graphics::CompiledShader> shaders, std::span<const Graphics::GuestMemorySnapshot> snapshots = {}, std::shared_ptr<const DrawRecipe>* recipe = nullptr);
std::optional<std::string> KnownDrawRejection(const Graphics::State& graphics, std::span<const Graphics::CompiledShader> shaders) const;
void DepthClearPass(const Graphics::DepthClearPass& pass);
void DepthCopyPass(const Graphics::DepthCopyPass& pass);
void ColorMetadataPass(const Graphics::ColorMetadataPass& pass);
// A draw-cache hit recorded from its recipe (Graphics::DrawWithRecipe), under the mutex after
// the packet's labels; Rebuild when the recipe's device is not this one or DrawWithRecipe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,35 @@ std::optional<DrawVerdict> Driver::precheckDraw(const QueueState& queue, const S
localDevice->ColorMetadataPass(*pass);
return DrawVerdict::Drawn;
}
rejected = Graphics::DepthMaintenanceRejection(queue);
if (!rejected.empty()) return DrawVerdict::Rejected;
if (const auto pass = Graphics::DecodeDepthCopyPass(queue)) {
require(!drawParameters.indirect, "indirect depth copies are unsupported");
GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Draw);
std::lock_guard gpuLock(GuestMemory::GpuMutex());
if (device == nullptr) device = std::make_shared<VulkanDevice>();
const std::shared_ptr<VulkanDevice> localDevice = device;
recordLabelsForPacket(localDevice.get(), submission.queue);
localDevice->DepthCopyPass(*pass);
return DrawVerdict::Drawn;
}
if (const auto pass = Graphics::DecodeDepthClearPass(queue)) {
require(!drawParameters.indirect, "indirect depth clears are unsupported");
GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Draw);
std::lock_guard gpuLock(GuestMemory::GpuMutex());
if (device == nullptr) device = std::make_shared<VulkanDevice>();
const std::shared_ptr<VulkanDevice> localDevice = device;
recordLabelsForPacket(localDevice.get(), submission.queue);
localDevice->DepthClearPass(*pass);
return DrawVerdict::Drawn;
}
static const bool traceIndirectEnabled = std::getenv("APS5_TRACE_INDIRECT_DRAWS") != nullptr;
traceIndirect = traceIndirectEnabled;
if (traceIndirect && drawParameters.indirect) std::fprintf(stderr, "[draw] indirect packet %s args 0x%llx count %u reached\n", Pm4::Name(packet[0]).c_str(), static_cast<unsigned long long>(drawParameters.indirect->arguments), drawParameters.indirect->count);
{
const auto targetMask = queue.context.find(0x8e);
const auto shaderMask = queue.context.find(0x8f);
const bool colorWrites = targetMask != queue.context.end() && shaderMask != queue.context.end() && (targetMask->second & shaderMask->second) != 0;
const bool colorWrites = targetMask != queue.context.end() && shaderMask != queue.context.end() && Graphics::ColorWriteMask(queue.context) != 0;
if (!colorWrites && !queue.shader.contains(0x8)) {
const auto word = [&](std::uint32_t offset) { const auto it = queue.context.find(offset); return it == queue.context.end() ? 0u : it->second; };
if ((word(0x200) & 3u) == 0 || ((word(0x010) & 3u) == 0 && (word(0x011) & 1u) == 0)) return DrawVerdict::Nothing;
Expand Down
8 changes: 8 additions & 0 deletions core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2488,6 +2488,14 @@ std::optional<std::string> VulkanDevice::KnownDrawRejection(const Graphics::Stat
return Graphics::KnownValidationFailure(graphicsContext(), shaders, graphics);
}

void VulkanDevice::DepthClearPass(const Graphics::DepthClearPass& pass) {
Graphics::RunDepthClearPass(graphicsContext(), pass);
}

void VulkanDevice::DepthCopyPass(const Graphics::DepthCopyPass& pass) {
Graphics::RunDepthCopyPass(graphicsContext(), pass);
}

void VulkanDevice::ColorMetadataPass(const Graphics::ColorMetadataPass& pass) {
Graphics::RunColorMetadataPass(graphicsContext(), pass);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ namespace AgcDriver::Graphics {
class Texture;

VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target);
void NoteDepthSurfaceWrite(const Context& context, const DepthTarget& target, VkImageAspectFlags aspects);
void NoteDepthSurfaceWrite(const Context& context, const State& state);
void RunDepthClearPass(const Context& context, const DepthClearPass& pass);
void RunDepthCopyPass(const Context& context, const DepthCopyPass& pass);
std::uint64_t DepthSliceBytes(VkExtent2D extent, std::uint32_t bytesPerTexel);
void ClearDepthSurfaces(VkDevice device);
bool DepthSurfaceAt(std::uint64_t address);
Expand Down
13 changes: 13 additions & 0 deletions core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,26 @@ State DecodeState(const QueueState& queue);
std::array<std::uint8_t, 8> ExportMappings(const State& state);
ColorTarget DecodeColorBuffer(const Registers& context, std::uint32_t slot);
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 };
Mode mode;
std::vector<ColorTarget> targets;
};
std::optional<ColorMetadataPass> DecodeColorMetadataPass(const QueueState& queue);
struct DepthClearPass {
DepthTarget target;
VkImageAspectFlags aspects;
};
std::optional<DepthClearPass> DecodeDepthClearPass(const QueueState& queue);
struct DepthCopyPass {
DepthTarget source;
DepthTarget destination;
VkImageAspectFlags aspects;
};
std::optional<DepthCopyPass> DecodeDepthCopyPass(const QueueState& queue);
std::string DepthMaintenanceRejection(const QueueState& queue);
// The message DecodeState (or the pixel stage decode after it) would throw for the register rules
// this precheck covers, evaluated without exceptions before the draw is decoded; empty when they
// pass (DecodeState still checks everything). A register a rule needs that is absent is no verdict.
Expand Down
2 changes: 1 addition & 1 deletion core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Texture {
// 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);
Texture(const Context& context, VkImage depthImage, VkFormat depthFormat, VkImageAspectFlags aspect, VkComponentMapping components, VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D, std::uint32_t layers = 1);
static bool CanCopyFrom(const StorageTexture& source, const GuestTextureResource& descriptor);
~Texture();
Texture(const Texture&) = delete;
Expand Down
Loading
Loading