mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
Rewrite descriptor bindings and unify graphics push constants
This commit is contained in:
@@ -4,48 +4,18 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::IR {
|
||||
namespace {
|
||||
|
||||
constexpr uint32_t MaxPushConstantBytes = 128;
|
||||
|
||||
constexpr std::array ImageBindingKinds = {
|
||||
DescriptorBindingKind::Sampled1D,
|
||||
DescriptorBindingKind::Sampled1DArray,
|
||||
DescriptorBindingKind::Sampled2D,
|
||||
DescriptorBindingKind::Sampled2DArray,
|
||||
DescriptorBindingKind::Sampled2DMsaa,
|
||||
DescriptorBindingKind::Sampled2DMsaaArray,
|
||||
DescriptorBindingKind::Sampled3D,
|
||||
DescriptorBindingKind::SampledUint1D,
|
||||
DescriptorBindingKind::SampledUint1DArray,
|
||||
DescriptorBindingKind::SampledUint2D,
|
||||
DescriptorBindingKind::SampledUint2DArray,
|
||||
DescriptorBindingKind::SampledUint2DMsaa,
|
||||
DescriptorBindingKind::SampledUint2DMsaaArray,
|
||||
DescriptorBindingKind::SampledUint3D,
|
||||
DescriptorBindingKind::Storage1D,
|
||||
DescriptorBindingKind::Storage1DArray,
|
||||
DescriptorBindingKind::Storage2D,
|
||||
DescriptorBindingKind::Storage2DArray,
|
||||
DescriptorBindingKind::Storage3D,
|
||||
DescriptorBindingKind::StorageUint1D,
|
||||
DescriptorBindingKind::StorageUint1DArray,
|
||||
DescriptorBindingKind::StorageUint2D,
|
||||
DescriptorBindingKind::StorageUint2DArray,
|
||||
DescriptorBindingKind::StorageUint3D,
|
||||
DescriptorBindingKind::StorageAtomic1D,
|
||||
DescriptorBindingKind::StorageAtomic1DArray,
|
||||
DescriptorBindingKind::StorageAtomic2D,
|
||||
DescriptorBindingKind::StorageAtomic2DArray,
|
||||
DescriptorBindingKind::StorageAtomic3D,
|
||||
};
|
||||
constexpr auto FirstImageBinding = DescriptorBindingKind::Sampled1D;
|
||||
constexpr uint32_t ImageBindingCount =
|
||||
static_cast<uint32_t>(DescriptorBindingKind::StorageAtomic3D) -
|
||||
static_cast<uint32_t>(FirstImageBinding) + 1u;
|
||||
|
||||
bool CollectUserData(const Program& program, std::vector<uint32_t>& result) {
|
||||
std::set<uint32_t> registers;
|
||||
std::array<bool, NumScalarRegs> registers {};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() != ValueOpcode::GetUserData || !inst.HasUses()) {
|
||||
@@ -58,17 +28,21 @@ bool CollectUserData(const Program& program, std::vector<uint32_t>& result) {
|
||||
if (index >= NumScalarRegs) {
|
||||
return false;
|
||||
}
|
||||
registers.insert(index);
|
||||
registers[index] = true;
|
||||
}
|
||||
}
|
||||
result.clear();
|
||||
for (uint32_t index = 0; index < registers.size(); index++) {
|
||||
if (registers[index]) {
|
||||
result.push_back(index);
|
||||
}
|
||||
}
|
||||
result.assign(registers.begin(), registers.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddBinding(BindingLayout& layout, DescriptorBindingKind kind,
|
||||
std::vector<uint32_t> resources = {}) {
|
||||
layout.descriptors.push_back(
|
||||
{kind, static_cast<uint32_t>(layout.descriptors.size()), std::move(resources)});
|
||||
layout.descriptors.push_back({kind, std::move(resources)});
|
||||
}
|
||||
|
||||
bool UsesGds(const Program& program, bool& uses_gds) {
|
||||
@@ -94,7 +68,7 @@ bool UsesGds(const Program& program, bool& uses_gds) {
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std::string* error) {
|
||||
bool AllocateBindings(Program& program, uint32_t push_constant_offset, std::string* error) {
|
||||
if (!program.shader_info_complete || program.binding_layout_complete) {
|
||||
if (error != nullptr) {
|
||||
*error = !program.shader_info_complete ? "shader info is not ready"
|
||||
@@ -102,28 +76,22 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (options.push_constant_offset > MaxPushConstantBytes) {
|
||||
if (error != nullptr) {
|
||||
*error = "push-constant offset exceeds the Vulkan minimum guarantee";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (options.push_constant_offset % 4u != 0) {
|
||||
if (error != nullptr) {
|
||||
*error = "push-constant offset is not dword aligned";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (program.values == nullptr) {
|
||||
if (error != nullptr) {
|
||||
*error = "typed value program is not available";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (push_constant_offset > NativePushConstantSize ||
|
||||
push_constant_offset % sizeof(uint32_t) != 0) {
|
||||
if (error != nullptr) {
|
||||
*error = "push-constant offset exceeds the Vulkan minimum guarantee or is unaligned";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BindingLayout next;
|
||||
next.descriptor_set = options.descriptor_set;
|
||||
next.push_constant_offset = options.push_constant_offset;
|
||||
next.push_constant_offset = push_constant_offset;
|
||||
if (!CollectUserData(program, next.user_data_registers)) {
|
||||
if (error != nullptr) {
|
||||
*error = "typed shader contains an invalid user-data register";
|
||||
@@ -142,7 +110,7 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
AddBinding(next, DescriptorBindingKind::Buffers, std::move(resources));
|
||||
}
|
||||
|
||||
std::array<std::vector<uint32_t>, ImageBindingKinds.size()> image_groups;
|
||||
std::array<std::vector<uint32_t>, ImageBindingCount> image_groups;
|
||||
for (uint32_t i = 0; i < program.info.images.size(); i++) {
|
||||
const auto kind = DescriptorBindingForImage(program.info.images[i]);
|
||||
if (!kind.has_value()) {
|
||||
@@ -151,14 +119,14 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const auto group = std::find(ImageBindingKinds.begin(), ImageBindingKinds.end(), *kind);
|
||||
if (group == ImageBindingKinds.end()) {
|
||||
const auto group = static_cast<uint32_t>(*kind) - static_cast<uint32_t>(FirstImageBinding);
|
||||
if (group >= image_groups.size()) {
|
||||
if (error != nullptr) {
|
||||
*error = "shader info contains an unmapped image binding class";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto& resources = image_groups[static_cast<size_t>(group - ImageBindingKinds.begin())];
|
||||
auto& resources = image_groups[group];
|
||||
const auto dynamic = program.info.images[i].mip_mode == ImageMipMode::DynamicStorage;
|
||||
const auto count = dynamic ? program.info.images[i].mip_count : 1u;
|
||||
if (count == 0u || (!dynamic && program.info.images[i].mip_count != 1u)) {
|
||||
@@ -171,7 +139,10 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
}
|
||||
for (uint32_t i = 0; i < image_groups.size(); i++) {
|
||||
if (!image_groups[i].empty()) {
|
||||
AddBinding(next, ImageBindingKinds[i], std::move(image_groups[i]));
|
||||
AddBinding(
|
||||
next,
|
||||
static_cast<DescriptorBindingKind>(static_cast<uint32_t>(FirstImageBinding) + i),
|
||||
std::move(image_groups[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,9 +179,8 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
AddBinding(next, DescriptorBindingKind::FlattenedSrt);
|
||||
}
|
||||
|
||||
const auto available_push_dwords = (MaxPushConstantBytes - options.push_constant_offset) / 4u;
|
||||
const auto push_limit = std::min(options.max_push_dwords, available_push_dwords);
|
||||
if (next.ShaderDataDwords() <= push_limit) {
|
||||
const auto push_dwords = (NativePushConstantSize - push_constant_offset) / sizeof(uint32_t);
|
||||
if (next.ShaderDataDwords() <= push_dwords) {
|
||||
next.push_constant_size = next.ShaderDataDwords() * sizeof(uint32_t);
|
||||
} else {
|
||||
AddBinding(next, DescriptorBindingKind::UserData);
|
||||
|
||||
Reference in New Issue
Block a user