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
10 changes: 9 additions & 1 deletion core/libs/prx/libSceAgcDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ set(agcDriverSources
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/Resources.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/Recorder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/ShaderInputState.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/BindingPlan.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/ShaderResources.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/ShaderAddressResources.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/GuestBufferMemory.cpp
Expand Down Expand Up @@ -250,6 +251,11 @@ target_link_libraries(agc_shader_memory_tests PRIVATE shader_recompiler_agc_driv
set_target_properties(agc_shader_memory_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_shader_memory_tests)

add_test_executable(agc_binding_materialization_tests EXCLUDE_FROM_ALL tests/BindingMaterialization.cpp)
target_link_libraries(agc_binding_materialization_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_binding_materialization_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_binding_materialization_tests)

add_test_executable(agc_write_tracking_tests EXCLUDE_FROM_ALL
tests/WriteTracking.cpp
Execution/src/GuestMemory.cpp
Expand Down Expand Up @@ -441,6 +447,7 @@ add_test_executable(agc_driver_graphics_tests EXCLUDE_FROM_ALL
Graphics/src/ColorTargetLayout.cpp
Graphics/src/ColorTargetTransfer.cpp
Graphics/src/Resources.cpp
Graphics/src/BindingPlan.cpp
Graphics/src/ShaderResources.cpp
Graphics/src/ShaderAddressResources.cpp
Graphics/src/GuestBufferMemory.cpp
Expand Down Expand Up @@ -537,7 +544,7 @@ foreach(agcExecutionTestSource IN LISTS agcExecutionTestSources)
endforeach()

if(BUILD_TESTING)
foreach(agcTest IN ITEMS agc_driver_tests agc_shader_memory_tests agc_structurizer_tests agc_spirv_module_tests agc_dpp_write_tests agc_masked_select_tests agc_vop1_control_decode_tests agc_validate_program_tests agc_shader_disk_cache_tests agc_shader_control_flow_tests agc_driver_flip_tests agc_driver_pm4_tests agc_driver_graphics_tests agc_driver_bda_device_tests ${agcExecutionTests})
foreach(agcTest IN ITEMS agc_driver_tests agc_shader_memory_tests agc_structurizer_tests agc_spirv_module_tests agc_dpp_write_tests agc_masked_select_tests agc_vop1_control_decode_tests agc_validate_program_tests agc_shader_disk_cache_tests agc_shader_control_flow_tests agc_driver_flip_tests agc_driver_pm4_tests agc_driver_graphics_tests agc_driver_bda_device_tests ${agcExecutionTests} agc_binding_materialization_tests)
string(REGEX REPLACE "_tests$" "" agcTestName "${agcTest}")
set_target_properties(${agcTest} PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME ${agcTestName} COMMAND ${agcTest})
Expand Down Expand Up @@ -597,6 +604,7 @@ if(AGC_BUILD_VISUAL_TEST)
Graphics/src/Pipeline.cpp
Graphics/src/PipelineCache.cpp
Graphics/src/Resources.cpp
Graphics/src/BindingPlan.cpp
Graphics/src/ShaderResources.cpp
Graphics/src/ShaderAddressResources.cpp
Graphics/src/GuestBufferMemory.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ void Driver::forEachWrittenBuffer(const ShaderRecompiler::RecompileResult& compi
for (const auto& binding : compiled.bindings) {
if (binding.role != ShaderRecompiler::DescriptorRole::GuestBuffers) continue;
for (std::uint32_t element = 0; element < binding.count; ++element) {
const bool written = element >= binding.bufferWritten.size() || binding.bufferWritten[element];
const bool written = element >= binding.Usage().bufferWritten.size() || binding.Usage().bufferWritten[element];
if (!written || binding.guestDescriptor.size() < (static_cast<std::size_t>(element) + 1) * 4) continue;
const auto words = std::span<const std::uint32_t>(binding.guestDescriptor).subspan(static_cast<std::size_t>(element) * 4, 4);
const ShaderRecompiler::ShaderBufferResource descriptor{{words[0], words[1], words[2], words[3]}};
const auto base = descriptor.Base48();
const auto size = descriptor.GetSize();
if (base == 0 || size == 0) continue;
visit(element, base, base + size, element < binding.bufferAtomic.size() && binding.bufferAtomic[element]);
visit(element, base, base + size, element < binding.Usage().bufferAtomic.size() && binding.Usage().bufferAtomic[element]);
}
}
}
Expand Down
77 changes: 77 additions & 0 deletions core/libs/prx/libSceAgcDriver/Graphics/include/BindingPlan.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_GRAPHICS_INCLUDE_BINDINGPLAN_HPP
#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_GRAPHICS_INCLUDE_BINDINGPLAN_HPP

#include "prx/libSceAgcDriver/Graphics/include/Shaders.hpp"
#include <array>
#include <compare>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <ranges>
#include <vector>

namespace AgcDriver::Graphics {

class BindingPlan {
public:
BindingPlan(const Context& context, std::span<const CompiledShader> shaders);
BindingPlan(const BindingPlan&) = delete;
BindingPlan& operator=(const BindingPlan&) = delete;

struct Binding {
VkDescriptorSetLayoutBinding layout;
std::size_t shader;
std::size_t source;
ShaderRecompiler::DescriptorRole role;
std::ranges::iota_view<std::size_t, std::size_t> allocations;
std::ranges::iota_view<std::size_t, std::size_t> imageAllocations;
std::size_t firstSampler = 0;
std::size_t samplerCount = 0;
};
struct Buffer {
bool written = true;
bool atomic = false;
std::int32_t pushByte = -1;
std::int64_t dataAllocation = -1;
std::uint32_t dataByte = 0;
};

std::vector<Binding> bindings;
std::vector<Buffer> buffers;
std::vector<VkDescriptorSetLayoutBinding> layout;
std::vector<std::uint32_t> layoutKey;
std::vector<VkDescriptorPoolSize> descriptorSizes;
std::uint32_t sampledImages = 0;
std::uint32_t storageImages = 0;
std::uint32_t samplers = 0;
};

class BindingPlanCache {
public:
explicit BindingPlanCache(const Context& context, std::size_t capacity = 1024);
std::shared_ptr<const BindingPlan> Get(std::span<const CompiledShader> shaders);
std::size_t Size() const;

private:
struct StageKey {
std::uint64_t variant = 0;
ShaderRecompiler::ShaderStage stage{};
std::uint32_t pushOffset = 0;
auto operator<=>(const StageKey&) const = default;
};
using Key = std::array<StageKey, 6>;
struct Entry {
std::shared_ptr<const BindingPlan> plan;
std::list<Key>::iterator order;
};
Context context;
std::size_t capacity;
mutable std::mutex mutex;
std::list<Key> order;
std::map<Key, Entry> entries;
};

}

#endif
25 changes: 10 additions & 15 deletions core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_GRAPHICS_INCLUDE_SHADERRESOURCES_HPP

#include "prx/libSceAgcDriver/Graphics/include/Resources.hpp"
#include "prx/libSceAgcDriver/Graphics/include/BindingPlan.hpp"
#include "prx/libSceAgcDriver/Graphics/include/BdaResources.hpp"
#include "prx/libSceAgcDriver/Graphics/include/Texture.hpp"
#include "prx/libSceAgcDriver/Graphics/include/Sampler.hpp"
Expand Down Expand Up @@ -73,6 +74,7 @@ class DescriptorCache {
std::uint64_t pools = 0;
};
Stats Counters() const;
std::shared_ptr<const BindingPlan> Plan(std::span<const CompiledShader> shaders) { return plans.Get(shaders); }

private:
Context context;
Expand All @@ -83,6 +85,7 @@ class DescriptorCache {
std::map<std::vector<std::uint32_t>, VkDescriptorSetLayout> layouts;
std::vector<VkDescriptorPool> pools;
Stats stats;
BindingPlanCache plans;
};

class ShaderResources {
Expand Down Expand Up @@ -149,7 +152,8 @@ class ShaderResources {
// a draw for which neither holds (Draw.cpp).
bool WritesMemory() const;
bool ReadsImage(const StorageTexture* image) const;
const std::vector<std::uint32_t>& LayoutKey() const { return layoutKey; }
const std::vector<std::uint32_t>& LayoutKey() const { return bindingPlan->layoutKey; }
const BindingPlan& Plan() const { return *bindingPlan; }
// Debug aid: each bound guest resource with the fraction of sampled bytes that are nonzero.
std::string Describe() const;

Expand Down Expand Up @@ -261,11 +265,7 @@ class ShaderResources {
};
void writeDataWords(VkCommandBuffer commands, std::size_t allocation, std::span<const std::uint32_t> words) const;

struct Binding {
VkDescriptorSetLayoutBinding layout;
std::vector<std::size_t> allocations;
std::vector<std::size_t> imageAllocations;
};
using Binding = BindingPlan::Binding;

// A host-imported buffer region the set reads in place, with its import's identity at build time.
struct DirectRegion {
Expand All @@ -292,7 +292,7 @@ class ShaderResources {
std::size_t addDataBuffer(std::span<const std::uint32_t> words);
// Stage A: the layout entry of an image binding (samplers are taken at once, the sampler cache
// locks itself); stage B looks the sampled textures and storage images up (resolveImageBinding).
void addImageBinding(const ShaderRecompiler::DescriptorBinding& binding, VkShaderStageFlags flags);
void addImageBinding(const ShaderRecompiler::DescriptorBinding& binding, std::size_t index);
// Stage A: one record per planned image element (ImageRecord), in plan order: the decoded
// descriptor and its surface size (computed once for the build), the write watch walked so stage
// B's collects are memo hits (APS5_NO_PRECOLLECT=1 skips the pass entirely), and for a sampled
Expand Down Expand Up @@ -326,7 +326,7 @@ class ShaderResources {
// Stage B: the record's texture when the fastRevalidate predicate proves it current under the
// lock and the cache still holds it; null sends the element to cachedTexture.
std::shared_ptr<Texture> fastTexture(const ImageRecord& record);
void resolveImageBinding(const ShaderRecompiler::DescriptorBinding& binding, Binding& item, std::span<const std::shared_ptr<Sampler>> shaderSamplers);
void resolveImageBinding(const ShaderRecompiler::DescriptorBinding& binding, std::span<const std::shared_ptr<Sampler>> shaderSamplers);
void forgetDeferredInputs();
void release() noexcept;
void prepareAddressBindings(std::span<const CompiledShader> shaders, std::span<const GuestMemorySnapshot> snapshots);
Expand Down Expand Up @@ -387,7 +387,7 @@ class ShaderResources {
// Today's per-element walk (APS5_NO_EPOCH_REVALIDATE=1).
bool fastRevalidateEach();
Context context;
std::vector<std::uint32_t> layoutKey;
std::shared_ptr<const BindingPlan> bindingPlan;
GuestBufferMemory guestMemory;
std::unique_ptr<BdaResources> bda;
bool usesBda = false;
Expand Down Expand Up @@ -433,17 +433,12 @@ class ShaderResources {
// Build state carried from stage A to stage B: the bindings in plan order, the image bindings
// still to look up (index into `bindings`; the DescriptorBinding lives in the compiled shader),
// the descriptor counts the set was sized for, and the compute stage of a deferred build.
std::vector<Binding> bindings;
std::span<const Binding> bindings;
struct DeferredImages {
const ShaderRecompiler::DescriptorBinding* binding;
std::size_t index;
std::size_t firstSampler = 0;
std::size_t samplerCount = 0;
};
std::vector<DeferredImages> deferredImages;
std::uint64_t storageBuffers = 0;
std::uint32_t plannedSampledImages = 0;
std::uint32_t plannedStorageImages = 0;
// The compute constructor's shader and captured regions: the caller's objects, valid only until
// the build (Complete() for a deferred one) is done, and reset then (forgetDeferredInputs).
CompiledShader deferredCompute{};
Expand Down
Loading
Loading