Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace AgcDriver::Graphics {

class Recorder;

void BindResourceDescriptorSets_nid_no_patch(const Context& context, VkCommandBuffer commands, VkPipelineBindPoint bindPoint, VkPipelineLayout layout, VkDescriptorSet main, VkDescriptorSet fragment);

void FlushCachedTextures(VkDevice device);
void ClearCachedTextures(VkDevice device);
std::uint64_t TextureCacheBudget(const VkPhysicalDeviceMemoryProperties& memory);
Expand Down
5 changes: 1 addition & 4 deletions core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1765,10 +1765,7 @@ void recordDraw(const Context& context, const State& state, const Pm4::DrawParam
}
APS5_LOG_CHARS_OUT_DEBUG("Pipeline Begin OK");
if (drawBindings != nullptr) {
const auto set = drawBindings->allocation.set;
const auto fragmentSet = drawBindings->fragmentAllocation.set;
if (set != VK_NULL_HANDLE) context.Resolved(&DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, VK_PIPELINE_BIND_POINT_GRAPHICS, record.pipeline->Layout(), 0, 1, &set, 0, nullptr);
if (fragmentSet != VK_NULL_HANDLE) context.Resolved(&DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, VK_PIPELINE_BIND_POINT_GRAPHICS, record.pipeline->Layout(), ShaderRecompiler::RuntimeAbi::FragmentDescriptorSet, 1, &fragmentSet, 0, nullptr);
BindResourceDescriptorSets_nid_no_patch(context, commands, VK_PIPELINE_BIND_POINT_GRAPHICS, record.pipeline->Layout(), drawBindings->allocation.set, drawBindings->fragmentAllocation.set);
} else {
resources.Bind(commands, VK_PIPELINE_BIND_POINT_GRAPHICS, record.pipeline->Layout());
}
Expand Down
12 changes: 10 additions & 2 deletions core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4475,9 +4475,17 @@ std::shared_ptr<ShaderResources::DrawBindings> ShaderResources::PrepareDrawBindi
return result;
}

void BindResourceDescriptorSets_nid_no_patch(const Context& context, VkCommandBuffer commands, VkPipelineBindPoint bindPoint, VkPipelineLayout layout, VkDescriptorSet main, VkDescriptorSet fragment) {
static_assert(ShaderRecompiler::RuntimeAbi::FragmentDescriptorSet == 1);
if (main == VK_NULL_HANDLE && fragment == VK_NULL_HANDLE) return;
const std::array sets{main, fragment};
const std::uint32_t first = main == VK_NULL_HANDLE ? 1u : 0u;
const std::uint32_t count = main != VK_NULL_HANDLE && fragment != VK_NULL_HANDLE ? 2u : 1u;
context.Resolved(&DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, bindPoint, layout, first, count, sets.data() + first, 0, nullptr);
}

void ShaderResources::Bind(VkCommandBuffer commands, VkPipelineBindPoint bindPoint, VkPipelineLayout layout) const {
if (_set != VK_NULL_HANDLE) context.Resolved(&DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, bindPoint, layout, 0, 1, &_set, 0, nullptr);
if (fragment.set != VK_NULL_HANDLE) context.Resolved(&DeviceFunctions::cmdBindDescriptorSets, "vkCmdBindDescriptorSets")(commands, bindPoint, layout, ShaderRecompiler::RuntimeAbi::FragmentDescriptorSet, 1, &fragment.set, 0, nullptr);
BindResourceDescriptorSets_nid_no_patch(context, commands, bindPoint, layout, _set, fragment.set);
}

namespace {
Expand Down
28 changes: 27 additions & 1 deletion core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2887,6 +2887,9 @@ struct MockVulkan {
std::vector<VkCopyDescriptorSet> copies;
bool allowCopies = false;
std::uint32_t boundSets = 0;
std::uint32_t bindCalls = 0;
std::vector<VkDescriptorSet> boundHandles;
std::map<std::uint32_t, VkDescriptorSet> writtenSets;
std::uint32_t boundFirst = 0;
VkPipelineBindPoint boundPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM;
std::map<VkPipelineLayout, VkDeviceSize> pipelineLayoutPushConstantSize;
Expand Down Expand Up @@ -3049,14 +3052,17 @@ VKAPI_ATTR void VKAPI_CALL mockUpdateDescriptorSets(VkDevice, std::uint32_t coun
Require(copyCount == 0 || mock.allowCopies, "descriptor copies are not expected");
if (copyCount != 0) mock.copies.insert(mock.copies.end(), copies, copies + copyCount);
for (std::uint32_t i = 0; i < count; ++i) {
mock.writtenSets[writes[i].dstBinding] = writes[i].dstSet;
MockDescriptorWrite write{writes[i].dstBinding, writes[i].dstArrayElement, writes[i].descriptorCount, writes[i].descriptorType, {}, {}};
if (writes[i].pBufferInfo != nullptr) write.buffers.assign(writes[i].pBufferInfo, writes[i].pBufferInfo + writes[i].descriptorCount);
if (writes[i].pImageInfo != nullptr) write.images.assign(writes[i].pImageInfo, writes[i].pImageInfo + writes[i].descriptorCount);
mock.writes.push_back(write);
}
}

VKAPI_ATTR void VKAPI_CALL mockCmdBindDescriptorSets(VkCommandBuffer, VkPipelineBindPoint point, VkPipelineLayout, std::uint32_t first, std::uint32_t count, const VkDescriptorSet*, std::uint32_t, const std::uint32_t*) {
VKAPI_ATTR void VKAPI_CALL mockCmdBindDescriptorSets(VkCommandBuffer, VkPipelineBindPoint point, VkPipelineLayout, std::uint32_t first, std::uint32_t count, const VkDescriptorSet* sets, std::uint32_t, const std::uint32_t*) {
++mock.bindCalls;
mock.boundHandles.assign(sets, sets + count);
mock.boundPoint = point;
mock.boundFirst = first;
mock.boundSets = count;
Expand Down Expand Up @@ -3561,6 +3567,25 @@ void descriptorSnapshotTests() {
}
}

void splitResourceBindTests() {
mock = MockVulkan{};
const auto context = mockContext();
const auto state = AgcDriver::Graphics::DecodeState(makeState());
{
ShaderRecompiler::RecompileResult vertex, fragment;
vertex.bindings.push_back(makeBinding(Role::GuestBuffers, 0, 1, vsharp(guestFirst.data(), 16)));
const auto fragmentBinding = ShaderRecompiler::RuntimeAbi::BindingNumber(ShaderRecompiler::RuntimeAbi::Stage::Fragment, ShaderRecompiler::RuntimeAbi::Binding::Buffers);
fragment.bindings.push_back(makeBinding(Role::GuestBuffers, fragmentBinding, 1, vsharp(guestThird.data(), 8)));
fragment.bindings.back().descriptorSet = ShaderRecompiler::RuntimeAbi::FragmentDescriptorSet;
const std::array<AgcDriver::Graphics::CompiledShader, 2> shaders{{{ShaderRecompiler::ShaderStage::Vertex, &vertex, 0}, {ShaderRecompiler::ShaderStage::Fragment, &fragment, 0}}};
AgcDriver::Graphics::ShaderResources resources(context, shaders, state.color, 1, 0, 0);
resources.Bind(reinterpret_cast<VkCommandBuffer>(std::uintptr_t{1}), VK_PIPELINE_BIND_POINT_GRAPHICS, VK_NULL_HANDLE);
Require(mock.bindCalls == 1 && mock.boundFirst == 0 && mock.boundSets == 2, "split resources require one bind of consecutive sets");
Require(mock.boundHandles == std::vector<VkDescriptorSet>{mock.writtenSets.at(0), mock.writtenSets.at(fragmentBinding)}, "split resources lost descriptor set order or identity");
}
Require(mock.live == 0, "split resources leaked Vulkan objects");
}

void resourceTests() {
mock = MockVulkan{};
const auto context = mockContext();
Expand Down Expand Up @@ -6499,6 +6524,7 @@ int main(int argc, char** argv) {
descriptorPoolTests();
pushConstantTests();
resourceTests();
splitResourceBindTests();
descriptorSnapshotTests();
descriptorCacheTests();
bufferBudgetPlacementTests();
Expand Down
Loading