mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 00:13:08 +00:00
renderer_vulkan: Add fallback path for pipelines with more than 32 bindings
This commit is contained in:
parent
fe5c38f77e
commit
449c99868a
@ -208,6 +208,9 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) {
|
|||||||
if (info.uses_group_quad) {
|
if (info.uses_group_quad) {
|
||||||
ctx.AddCapability(spv::Capability::GroupNonUniformQuad);
|
ctx.AddCapability(spv::Capability::GroupNonUniformQuad);
|
||||||
}
|
}
|
||||||
|
if (info.uses_group_ballot) {
|
||||||
|
ctx.AddCapability(spv::Capability::GroupNonUniformBallot);
|
||||||
|
}
|
||||||
switch (program.info.stage) {
|
switch (program.info.stage) {
|
||||||
case Stage::Compute: {
|
case Stage::Compute: {
|
||||||
const std::array<u32, 3> workgroup_size{ctx.runtime_info.cs_info.workgroup_size};
|
const std::array<u32, 3> workgroup_size{ctx.runtime_info.cs_info.workgroup_size};
|
||||||
|
@ -27,7 +27,8 @@ Id EmitReadFirstLane(EmitContext& ctx, Id value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Id EmitReadLane(EmitContext& ctx, Id value, u32 lane) {
|
Id EmitReadLane(EmitContext& ctx, Id value, u32 lane) {
|
||||||
return ctx.OpGroupNonUniformBroadcast(ctx.U32[1], SubgroupScope(ctx), value, ctx.ConstU32(lane));
|
return ctx.OpGroupNonUniformBroadcast(ctx.U32[1], SubgroupScope(ctx), value,
|
||||||
|
ctx.ConstU32(lane));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane) {
|
Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane) {
|
||||||
|
@ -324,16 +324,18 @@ void EmitContext::DefineOutputs() {
|
|||||||
|
|
||||||
void EmitContext::DefinePushDataBlock() {
|
void EmitContext::DefinePushDataBlock() {
|
||||||
// Create push constants block for instance steps rates
|
// Create push constants block for instance steps rates
|
||||||
const Id struct_type{Name(TypeStruct(U32[1], U32[1], U32[4], U32[4]), "AuxData")};
|
const Id struct_type{Name(TypeStruct(U32[1], U32[1], U32[4], U32[4], U32[4]), "AuxData")};
|
||||||
Decorate(struct_type, spv::Decoration::Block);
|
Decorate(struct_type, spv::Decoration::Block);
|
||||||
MemberName(struct_type, 0, "sr0");
|
MemberName(struct_type, 0, "sr0");
|
||||||
MemberName(struct_type, 1, "sr1");
|
MemberName(struct_type, 1, "sr1");
|
||||||
MemberName(struct_type, 2, "buf_offsets0");
|
MemberName(struct_type, 2, "buf_offsets0");
|
||||||
MemberName(struct_type, 3, "buf_offsets1");
|
MemberName(struct_type, 3, "buf_offsets1");
|
||||||
|
MemberName(struct_type, 4, "buf_offsets2");
|
||||||
MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U);
|
MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U);
|
||||||
MemberDecorate(struct_type, 1, spv::Decoration::Offset, 4U);
|
MemberDecorate(struct_type, 1, spv::Decoration::Offset, 4U);
|
||||||
MemberDecorate(struct_type, 2, spv::Decoration::Offset, 8U);
|
MemberDecorate(struct_type, 2, spv::Decoration::Offset, 8U);
|
||||||
MemberDecorate(struct_type, 3, spv::Decoration::Offset, 24U);
|
MemberDecorate(struct_type, 3, spv::Decoration::Offset, 24U);
|
||||||
|
MemberDecorate(struct_type, 4, spv::Decoration::Offset, 40U);
|
||||||
push_data_block = DefineVar(struct_type, spv::StorageClass::PushConstant);
|
push_data_block = DefineVar(struct_type, spv::StorageClass::PushConstant);
|
||||||
Name(push_data_block, "push_data");
|
Name(push_data_block, "push_data");
|
||||||
interfaces.push_back(push_data_block);
|
interfaces.push_back(push_data_block);
|
||||||
|
@ -89,7 +89,7 @@ struct PushData {
|
|||||||
|
|
||||||
u32 step0;
|
u32 step0;
|
||||||
u32 step1;
|
u32 step1;
|
||||||
std::array<u8, 32> buf_offsets;
|
std::array<u8, 48> buf_offsets;
|
||||||
|
|
||||||
void AddOffset(u32 binding, u32 offset) {
|
void AddOffset(u32 binding, u32 offset) {
|
||||||
ASSERT(offset < 256 && binding < buf_offsets.size());
|
ASSERT(offset < 256 && binding < buf_offsets.size());
|
||||||
@ -166,6 +166,7 @@ struct Info {
|
|||||||
bool has_image_query{};
|
bool has_image_query{};
|
||||||
bool uses_lane_id{};
|
bool uses_lane_id{};
|
||||||
bool uses_group_quad{};
|
bool uses_group_quad{};
|
||||||
|
bool uses_group_ballot{};
|
||||||
bool uses_shared{};
|
bool uses_shared{};
|
||||||
bool uses_fp16{};
|
bool uses_fp16{};
|
||||||
bool uses_step_rates{};
|
bool uses_step_rates{};
|
||||||
|
@ -223,12 +223,8 @@ public:
|
|||||||
|
|
||||||
u32 Add(const SamplerResource& desc) {
|
u32 Add(const SamplerResource& desc) {
|
||||||
const u32 index{Add(sampler_resources, desc, [this, &desc](const auto& existing) {
|
const u32 index{Add(sampler_resources, desc, [this, &desc](const auto& existing) {
|
||||||
if (desc.sgpr_base == existing.sgpr_base &&
|
return desc.sgpr_base == existing.sgpr_base &&
|
||||||
desc.dword_offset == existing.dword_offset) {
|
desc.dword_offset == existing.dword_offset;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Samplers with different bindings might still be the same.
|
|
||||||
return existing.GetSharp(info) == desc.GetSharp(info);
|
|
||||||
})};
|
})};
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,9 @@ void Visit(Info& info, IR::Inst& inst) {
|
|||||||
case IR::Opcode::QuadShuffle:
|
case IR::Opcode::QuadShuffle:
|
||||||
info.uses_group_quad = true;
|
info.uses_group_quad = true;
|
||||||
break;
|
break;
|
||||||
|
case IR::Opcode::ReadLane:
|
||||||
|
info.uses_group_ballot = true;
|
||||||
|
break;
|
||||||
case IR::Opcode::Discard:
|
case IR::Opcode::Discard:
|
||||||
case IR::Opcode::DiscardCond:
|
case IR::Opcode::DiscardCond:
|
||||||
info.has_discard = true;
|
info.has_discard = true;
|
||||||
|
@ -577,9 +577,6 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Image& image = texture_cache.GetImage(image_id);
|
Image& image = texture_cache.GetImage(image_id);
|
||||||
if (image.info.guest_size_bytes > size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
boost::container::small_vector<vk::BufferImageCopy, 8> copies;
|
boost::container::small_vector<vk::BufferImageCopy, 8> copies;
|
||||||
u32 offset = buffer.Offset(image.cpu_addr);
|
u32 offset = buffer.Offset(image.cpu_addr);
|
||||||
const u32 num_layers = image.info.resources.layers;
|
const u32 num_layers = image.info.resources.layers;
|
||||||
@ -589,6 +586,9 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||||||
const u32 depth =
|
const u32 depth =
|
||||||
image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u;
|
image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u;
|
||||||
const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m];
|
const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m];
|
||||||
|
if (offset + (mip_ofs * num_layers) > buffer.SizeBytes()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
copies.push_back({
|
copies.push_back({
|
||||||
.bufferOffset = offset,
|
.bufferOffset = offset,
|
||||||
.bufferRowLength = static_cast<u32>(mip_pitch),
|
.bufferRowLength = static_cast<u32>(mip_pitch),
|
||||||
@ -604,11 +604,13 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||||||
});
|
});
|
||||||
offset += mip_ofs * num_layers;
|
offset += mip_ofs * num_layers;
|
||||||
}
|
}
|
||||||
|
if (!copies.empty()) {
|
||||||
scheduler.EndRendering();
|
scheduler.EndRendering();
|
||||||
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead);
|
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead);
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.buffer,
|
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.buffer,
|
||||||
copies);
|
copies);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler_,
|
ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler_,
|
||||||
vk::PipelineCache pipeline_cache, u64 compute_key_,
|
DescriptorHeap& desc_heap_, vk::PipelineCache pipeline_cache,
|
||||||
const Shader::Info& info_, vk::ShaderModule module)
|
u64 compute_key_, const Shader::Info& info_,
|
||||||
: instance{instance_}, scheduler{scheduler_}, compute_key{compute_key_}, info{&info_} {
|
vk::ShaderModule module)
|
||||||
|
: instance{instance_}, scheduler{scheduler_}, desc_heap{desc_heap_}, compute_key{compute_key_},
|
||||||
|
info{&info_} {
|
||||||
const vk::PipelineShaderStageCreateInfo shader_ci = {
|
const vk::PipelineShaderStageCreateInfo shader_ci = {
|
||||||
.stage = vk::ShaderStageFlagBits::eCompute,
|
.stage = vk::ShaderStageFlagBits::eCompute,
|
||||||
.module = module,
|
.module = module,
|
||||||
@ -66,8 +68,12 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
|
|||||||
.size = sizeof(Shader::PushData),
|
.size = sizeof(Shader::PushData),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uses_push_descriptors = binding < instance.MaxPushDescriptors();
|
||||||
|
const auto flags = uses_push_descriptors
|
||||||
|
? vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR
|
||||||
|
: vk::DescriptorSetLayoutCreateFlagBits{};
|
||||||
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = {
|
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = {
|
||||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR,
|
.flags = flags,
|
||||||
.bindingCount = static_cast<u32>(bindings.size()),
|
.bindingCount = static_cast<u32>(bindings.size()),
|
||||||
.pBindings = bindings.data(),
|
.pBindings = bindings.data(),
|
||||||
};
|
};
|
||||||
@ -265,9 +271,21 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache,
|
|||||||
cmdbuf.pipelineBarrier2(dependencies);
|
cmdbuf.pipelineBarrier2(dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uses_push_descriptors) {
|
||||||
|
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0,
|
||||||
|
set_writes);
|
||||||
|
} else {
|
||||||
|
const auto desc_set = desc_heap.Commit(*desc_layout);
|
||||||
|
for (auto& set_write : set_writes) {
|
||||||
|
set_write.dstSet = desc_set;
|
||||||
|
}
|
||||||
|
instance.GetDevice().updateDescriptorSets(set_writes, {});
|
||||||
|
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, desc_set,
|
||||||
|
{});
|
||||||
|
}
|
||||||
|
|
||||||
cmdbuf.pushConstants(*pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0u, sizeof(push_data),
|
cmdbuf.pushConstants(*pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0u, sizeof(push_data),
|
||||||
&push_data);
|
&push_data);
|
||||||
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, set_writes);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,13 @@ namespace Vulkan {
|
|||||||
|
|
||||||
class Instance;
|
class Instance;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
|
class DescriptorHeap;
|
||||||
|
|
||||||
class ComputePipeline {
|
class ComputePipeline {
|
||||||
public:
|
public:
|
||||||
explicit ComputePipeline(const Instance& instance, Scheduler& scheduler,
|
explicit ComputePipeline(const Instance& instance, Scheduler& scheduler,
|
||||||
vk::PipelineCache pipeline_cache, u64 compute_key,
|
DescriptorHeap& desc_heap, vk::PipelineCache pipeline_cache,
|
||||||
const Shader::Info& info, vk::ShaderModule module);
|
u64 compute_key, const Shader::Info& info, vk::ShaderModule module);
|
||||||
~ComputePipeline();
|
~ComputePipeline();
|
||||||
|
|
||||||
[[nodiscard]] vk::Pipeline Handle() const noexcept {
|
[[nodiscard]] vk::Pipeline Handle() const noexcept {
|
||||||
@ -34,11 +35,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
|
DescriptorHeap& desc_heap;
|
||||||
vk::UniquePipeline pipeline;
|
vk::UniquePipeline pipeline;
|
||||||
vk::UniquePipelineLayout pipeline_layout;
|
vk::UniquePipelineLayout pipeline_layout;
|
||||||
vk::UniqueDescriptorSetLayout desc_layout;
|
vk::UniqueDescriptorSetLayout desc_layout;
|
||||||
u64 compute_key;
|
u64 compute_key;
|
||||||
const Shader::Info* info;
|
const Shader::Info* info;
|
||||||
|
bool uses_push_descriptors{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& scheduler_,
|
GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& scheduler_,
|
||||||
const GraphicsPipelineKey& key_,
|
DescriptorHeap& desc_heap_, const GraphicsPipelineKey& key_,
|
||||||
vk::PipelineCache pipeline_cache,
|
vk::PipelineCache pipeline_cache,
|
||||||
std::span<const Shader::Info*, MaxShaderStages> infos,
|
std::span<const Shader::Info*, MaxShaderStages> infos,
|
||||||
std::span<const vk::ShaderModule> modules)
|
std::span<const vk::ShaderModule> modules)
|
||||||
: instance{instance_}, scheduler{scheduler_}, key{key_} {
|
: instance{instance_}, scheduler{scheduler_}, desc_heap{desc_heap_}, key{key_} {
|
||||||
const vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
std::ranges::copy(infos, stages.begin());
|
std::ranges::copy(infos, stages.begin());
|
||||||
BuildDescSetLayout();
|
BuildDescSetLayout();
|
||||||
@ -343,8 +343,12 @@ void GraphicsPipeline::BuildDescSetLayout() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
uses_push_descriptors = binding < instance.MaxPushDescriptors();
|
||||||
|
const auto flags = uses_push_descriptors
|
||||||
|
? vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR
|
||||||
|
: vk::DescriptorSetLayoutCreateFlagBits{};
|
||||||
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = {
|
const vk::DescriptorSetLayoutCreateInfo desc_layout_ci = {
|
||||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR,
|
.flags = flags,
|
||||||
.bindingCount = static_cast<u32>(bindings.size()),
|
.bindingCount = static_cast<u32>(bindings.size()),
|
||||||
.pBindings = bindings.data(),
|
.pBindings = bindings.data(),
|
||||||
};
|
};
|
||||||
@ -510,8 +514,18 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!set_writes.empty()) {
|
if (!set_writes.empty()) {
|
||||||
|
if (uses_push_descriptors) {
|
||||||
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0,
|
cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0,
|
||||||
set_writes);
|
set_writes);
|
||||||
|
} else {
|
||||||
|
const auto desc_set = desc_heap.Commit(*desc_layout);
|
||||||
|
for (auto& set_write : set_writes) {
|
||||||
|
set_write.dstSet = desc_set;
|
||||||
|
}
|
||||||
|
instance.GetDevice().updateDescriptorSets(set_writes, {});
|
||||||
|
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *pipeline_layout, 0,
|
||||||
|
desc_set, {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cmdbuf.pushConstants(*pipeline_layout,
|
cmdbuf.pushConstants(*pipeline_layout,
|
||||||
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, 0U,
|
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, 0U,
|
||||||
|
@ -19,6 +19,7 @@ static constexpr u32 MaxShaderStages = 5;
|
|||||||
|
|
||||||
class Instance;
|
class Instance;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
|
class DescriptorHeap;
|
||||||
|
|
||||||
using Liverpool = AmdGpu::Liverpool;
|
using Liverpool = AmdGpu::Liverpool;
|
||||||
|
|
||||||
@ -59,7 +60,8 @@ struct GraphicsPipelineKey {
|
|||||||
class GraphicsPipeline {
|
class GraphicsPipeline {
|
||||||
public:
|
public:
|
||||||
explicit GraphicsPipeline(const Instance& instance, Scheduler& scheduler,
|
explicit GraphicsPipeline(const Instance& instance, Scheduler& scheduler,
|
||||||
const GraphicsPipelineKey& key, vk::PipelineCache pipeline_cache,
|
DescriptorHeap& desc_heap, const GraphicsPipelineKey& key,
|
||||||
|
vk::PipelineCache pipeline_cache,
|
||||||
std::span<const Shader::Info*, MaxShaderStages> stages,
|
std::span<const Shader::Info*, MaxShaderStages> stages,
|
||||||
std::span<const vk::ShaderModule> modules);
|
std::span<const vk::ShaderModule> modules);
|
||||||
~GraphicsPipeline();
|
~GraphicsPipeline();
|
||||||
@ -98,11 +100,13 @@ private:
|
|||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
|
DescriptorHeap& desc_heap;
|
||||||
vk::UniquePipeline pipeline;
|
vk::UniquePipeline pipeline;
|
||||||
vk::UniquePipelineLayout pipeline_layout;
|
vk::UniquePipelineLayout pipeline_layout;
|
||||||
vk::UniqueDescriptorSetLayout desc_layout;
|
vk::UniqueDescriptorSetLayout desc_layout;
|
||||||
std::array<const Shader::Info*, MaxShaderStages> stages{};
|
std::array<const Shader::Info*, MaxShaderStages> stages{};
|
||||||
GraphicsPipelineKey key;
|
GraphicsPipelineKey key;
|
||||||
|
bool uses_push_descriptors{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -176,8 +176,10 @@ bool Instance::CreateDevice() {
|
|||||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
|
||||||
const vk::StructureChain properties_chain = physical_device.getProperties2<
|
const vk::StructureChain properties_chain = physical_device.getProperties2<
|
||||||
vk::PhysicalDeviceProperties2, vk::PhysicalDevicePortabilitySubsetPropertiesKHR,
|
vk::PhysicalDeviceProperties2, vk::PhysicalDevicePortabilitySubsetPropertiesKHR,
|
||||||
vk::PhysicalDeviceExternalMemoryHostPropertiesEXT, vk::PhysicalDeviceVulkan11Properties>();
|
vk::PhysicalDeviceExternalMemoryHostPropertiesEXT, vk::PhysicalDeviceVulkan11Properties,
|
||||||
|
vk::PhysicalDevicePushDescriptorPropertiesKHR>();
|
||||||
subgroup_size = properties_chain.get<vk::PhysicalDeviceVulkan11Properties>().subgroupSize;
|
subgroup_size = properties_chain.get<vk::PhysicalDeviceVulkan11Properties>().subgroupSize;
|
||||||
|
push_descriptor_props = properties_chain.get<vk::PhysicalDevicePushDescriptorPropertiesKHR>();
|
||||||
LOG_INFO(Render_Vulkan, "Physical device subgroup size {}", subgroup_size);
|
LOG_INFO(Render_Vulkan, "Physical device subgroup size {}", subgroup_size);
|
||||||
|
|
||||||
features = feature_chain.get().features;
|
features = feature_chain.get().features;
|
||||||
|
@ -207,6 +207,11 @@ public:
|
|||||||
return properties.limits.maxTexelBufferElements;
|
return properties.limits.maxTexelBufferElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum number of push descriptors.
|
||||||
|
u32 MaxPushDescriptors() const {
|
||||||
|
return push_descriptor_props.maxPushDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if shaders can declare the ClipDistance attribute
|
/// Returns true if shaders can declare the ClipDistance attribute
|
||||||
bool IsShaderClipDistanceSupported() const {
|
bool IsShaderClipDistanceSupported() const {
|
||||||
return features.shaderClipDistance;
|
return features.shaderClipDistance;
|
||||||
@ -242,6 +247,7 @@ private:
|
|||||||
vk::PhysicalDevice physical_device;
|
vk::PhysicalDevice physical_device;
|
||||||
vk::UniqueDevice device;
|
vk::UniqueDevice device;
|
||||||
vk::PhysicalDeviceProperties properties;
|
vk::PhysicalDeviceProperties properties;
|
||||||
|
vk::PhysicalDevicePushDescriptorPropertiesKHR push_descriptor_props;
|
||||||
vk::PhysicalDeviceFeatures features;
|
vk::PhysicalDeviceFeatures features;
|
||||||
vk::DriverIdKHR driver_id;
|
vk::DriverIdKHR driver_id;
|
||||||
vk::UniqueDebugUtilsMessengerEXT debug_callback{};
|
vk::UniqueDebugUtilsMessengerEXT debug_callback{};
|
||||||
|
@ -20,6 +20,15 @@ namespace Vulkan {
|
|||||||
|
|
||||||
using Shader::VsOutput;
|
using Shader::VsOutput;
|
||||||
|
|
||||||
|
constexpr static std::array DescriptorHeapSizes = {
|
||||||
|
vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 8192},
|
||||||
|
vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer, 1024},
|
||||||
|
vk::DescriptorPoolSize{vk::DescriptorType::eUniformTexelBuffer, 128},
|
||||||
|
vk::DescriptorPoolSize{vk::DescriptorType::eStorageTexelBuffer, 128},
|
||||||
|
vk::DescriptorPoolSize{vk::DescriptorType::eSampledImage, 8192},
|
||||||
|
vk::DescriptorPoolSize{vk::DescriptorType::eSampler, 1024},
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
|
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
|
||||||
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
||||||
}
|
}
|
||||||
@ -120,7 +129,8 @@ Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) {
|
|||||||
|
|
||||||
PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
||||||
AmdGpu::Liverpool* liverpool_)
|
AmdGpu::Liverpool* liverpool_)
|
||||||
: instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_} {
|
: instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_},
|
||||||
|
desc_heap{instance, scheduler.GetMasterSemaphore(), DescriptorHeapSizes} {
|
||||||
profile = Shader::Profile{
|
profile = Shader::Profile{
|
||||||
.supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U,
|
.supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U,
|
||||||
.subgroup_size = instance.SubgroupSize(),
|
.subgroup_size = instance.SubgroupSize(),
|
||||||
@ -153,8 +163,8 @@ const GraphicsPipeline* PipelineCache::GetGraphicsPipeline() {
|
|||||||
}
|
}
|
||||||
const auto [it, is_new] = graphics_pipelines.try_emplace(graphics_key);
|
const auto [it, is_new] = graphics_pipelines.try_emplace(graphics_key);
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
it.value() = std::make_unique<GraphicsPipeline>(instance, scheduler, graphics_key,
|
it.value() = std::make_unique<GraphicsPipeline>(
|
||||||
*pipeline_cache, infos, modules);
|
instance, scheduler, desc_heap, graphics_key, *pipeline_cache, infos, modules);
|
||||||
}
|
}
|
||||||
const GraphicsPipeline* pipeline = it->second.get();
|
const GraphicsPipeline* pipeline = it->second.get();
|
||||||
return pipeline;
|
return pipeline;
|
||||||
@ -166,8 +176,8 @@ const ComputePipeline* PipelineCache::GetComputePipeline() {
|
|||||||
}
|
}
|
||||||
const auto [it, is_new] = compute_pipelines.try_emplace(compute_key);
|
const auto [it, is_new] = compute_pipelines.try_emplace(compute_key);
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
it.value() = std::make_unique<ComputePipeline>(instance, scheduler, *pipeline_cache,
|
it.value() = std::make_unique<ComputePipeline>(
|
||||||
compute_key, *infos[0], modules[0]);
|
instance, scheduler, desc_heap, *pipeline_cache, compute_key, *infos[0], modules[0]);
|
||||||
}
|
}
|
||||||
const ComputePipeline* pipeline = it->second.get();
|
const ComputePipeline* pipeline = it->second.get();
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "shader_recompiler/specialization.h"
|
#include "shader_recompiler/specialization.h"
|
||||||
#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
|
#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
|
||||||
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_resource_pool.h"
|
||||||
|
|
||||||
namespace Shader {
|
namespace Shader {
|
||||||
struct Info;
|
struct Info;
|
||||||
@ -66,6 +67,7 @@ private:
|
|||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
AmdGpu::Liverpool* liverpool;
|
AmdGpu::Liverpool* liverpool;
|
||||||
|
DescriptorHeap desc_heap;
|
||||||
vk::UniquePipelineCache pipeline_cache;
|
vk::UniquePipelineCache pipeline_cache;
|
||||||
vk::UniquePipelineLayout pipeline_layout;
|
vk::UniquePipelineLayout pipeline_layout;
|
||||||
Shader::Profile profile{};
|
Shader::Profile profile{};
|
||||||
|
@ -43,6 +43,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(
|
|||||||
case 0x609a13b: // Vertex attribute at location not consumed by shader
|
case 0x609a13b: // Vertex attribute at location not consumed by shader
|
||||||
case 0xc81ad50e:
|
case 0xc81ad50e:
|
||||||
case 0xb7c39078:
|
case 0xb7c39078:
|
||||||
|
case 0x30b6e267: // TODO remove this
|
||||||
case 0x32868fde: // vkCreateBufferView(): pCreateInfo->range does not equal VK_WHOLE_SIZE
|
case 0x32868fde: // vkCreateBufferView(): pCreateInfo->range does not equal VK_WHOLE_SIZE
|
||||||
case 0x92d66fc1: // `pMultisampleState is NULL` for depth only passes (confirmed VL error)
|
case 0x92d66fc1: // `pMultisampleState is NULL` for depth only passes (confirmed VL error)
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
|
@ -106,31 +106,10 @@ vk::CommandBuffer CommandPool::Commit() {
|
|||||||
constexpr u32 DESCRIPTOR_SET_BATCH = 32;
|
constexpr u32 DESCRIPTOR_SET_BATCH = 32;
|
||||||
|
|
||||||
DescriptorHeap::DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore,
|
DescriptorHeap::DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore,
|
||||||
std::span<const vk::DescriptorSetLayoutBinding> bindings,
|
std::span<const vk::DescriptorPoolSize> pool_sizes_,
|
||||||
u32 descriptor_heap_count_)
|
u32 descriptor_heap_count_)
|
||||||
: ResourcePool{master_semaphore, DESCRIPTOR_SET_BATCH}, device{instance.GetDevice()},
|
: ResourcePool{master_semaphore, DESCRIPTOR_SET_BATCH}, device{instance.GetDevice()},
|
||||||
descriptor_heap_count{descriptor_heap_count_} {
|
descriptor_heap_count{descriptor_heap_count_}, pool_sizes{pool_sizes_} {
|
||||||
// Create descriptor set layout.
|
|
||||||
const vk::DescriptorSetLayoutCreateInfo layout_ci = {
|
|
||||||
.bindingCount = static_cast<u32>(bindings.size()),
|
|
||||||
.pBindings = bindings.data(),
|
|
||||||
};
|
|
||||||
descriptor_set_layout = device.createDescriptorSetLayoutUnique(layout_ci);
|
|
||||||
if (instance.HasDebuggingToolAttached()) {
|
|
||||||
SetObjectName(device, *descriptor_set_layout, "DescriptorSetLayout");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build descriptor set pool counts.
|
|
||||||
std::unordered_map<vk::DescriptorType, u16> descriptor_type_counts;
|
|
||||||
for (const auto& binding : bindings) {
|
|
||||||
descriptor_type_counts[binding.descriptorType] += binding.descriptorCount;
|
|
||||||
}
|
|
||||||
for (const auto& [type, count] : descriptor_type_counts) {
|
|
||||||
auto& pool_size = pool_sizes.emplace_back();
|
|
||||||
pool_size.descriptorCount = count * descriptor_heap_count;
|
|
||||||
pool_size.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create descriptor pool
|
// Create descriptor pool
|
||||||
AppendDescriptorPool();
|
AppendDescriptorPool();
|
||||||
}
|
}
|
||||||
@ -143,7 +122,7 @@ void DescriptorHeap::Allocate(std::size_t begin, std::size_t end) {
|
|||||||
hashes.resize(end);
|
hashes.resize(end);
|
||||||
|
|
||||||
std::array<vk::DescriptorSetLayout, DESCRIPTOR_SET_BATCH> layouts;
|
std::array<vk::DescriptorSetLayout, DESCRIPTOR_SET_BATCH> layouts;
|
||||||
layouts.fill(*descriptor_set_layout);
|
layouts.fill(descriptor_set_layout);
|
||||||
|
|
||||||
u32 current_pool = 0;
|
u32 current_pool = 0;
|
||||||
vk::DescriptorSetAllocateInfo alloc_info = {
|
vk::DescriptorSetAllocateInfo alloc_info = {
|
||||||
@ -171,7 +150,8 @@ void DescriptorHeap::Allocate(std::size_t begin, std::size_t end) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DescriptorSet DescriptorHeap::Commit() {
|
vk::DescriptorSet DescriptorHeap::Commit(vk::DescriptorSetLayout set_layout) {
|
||||||
|
this->descriptor_set_layout = set_layout;
|
||||||
const std::size_t index = CommitResource();
|
const std::size_t index = CommitResource();
|
||||||
return descriptor_sets[index];
|
return descriptor_sets[index];
|
||||||
}
|
}
|
||||||
|
@ -65,26 +65,22 @@ private:
|
|||||||
class DescriptorHeap final : public ResourcePool {
|
class DescriptorHeap final : public ResourcePool {
|
||||||
public:
|
public:
|
||||||
explicit DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore,
|
explicit DescriptorHeap(const Instance& instance, MasterSemaphore* master_semaphore,
|
||||||
std::span<const vk::DescriptorSetLayoutBinding> bindings,
|
std::span<const vk::DescriptorPoolSize> pool_sizes,
|
||||||
u32 descriptor_heap_count = 1024);
|
u32 descriptor_heap_count = 1024);
|
||||||
~DescriptorHeap() override;
|
~DescriptorHeap() override;
|
||||||
|
|
||||||
const vk::DescriptorSetLayout& Layout() const {
|
|
||||||
return *descriptor_set_layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Allocate(std::size_t begin, std::size_t end) override;
|
void Allocate(std::size_t begin, std::size_t end) override;
|
||||||
|
|
||||||
vk::DescriptorSet Commit();
|
vk::DescriptorSet Commit(vk::DescriptorSetLayout set_layout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AppendDescriptorPool();
|
void AppendDescriptorPool();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
vk::UniqueDescriptorSetLayout descriptor_set_layout;
|
vk::DescriptorSetLayout descriptor_set_layout;
|
||||||
u32 descriptor_heap_count;
|
u32 descriptor_heap_count;
|
||||||
std::vector<vk::DescriptorPoolSize> pool_sizes;
|
std::span<const vk::DescriptorPoolSize> pool_sizes;
|
||||||
std::vector<vk::UniqueDescriptorPool> pools;
|
std::vector<vk::UniqueDescriptorPool> pools;
|
||||||
std::vector<vk::DescriptorSet> descriptor_sets;
|
std::vector<vk::DescriptorSet> descriptor_sets;
|
||||||
std::vector<std::size_t> hashes;
|
std::vector<std::size_t> hashes;
|
||||||
|
Loading…
Reference in New Issue
Block a user