mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
shader: lower FMASK loads before binding images
This commit is contained in:
@@ -687,6 +687,8 @@ CompileResult CompileProgram(TranslateResult translated, const CompileOptions& o
|
||||
const auto emit_begin = std::chrono::steady_clock::now();
|
||||
auto& ir = translated.program;
|
||||
IR::ApplyResourceSpecialization(ir, specialization);
|
||||
IR::RemoveIdentities(ir.blocks);
|
||||
IR::EliminateDeadCode(ir.blocks);
|
||||
|
||||
const ShaderVertexInputInfo* vertex = nullptr;
|
||||
const ShaderPixelInputInfo* pixel = nullptr;
|
||||
|
||||
@@ -362,6 +362,28 @@ struct SamplerPlan {
|
||||
uint32_t sampler_count = 0;
|
||||
};
|
||||
|
||||
struct ImageRemap {
|
||||
explicit ImageRemap(const ResourceSpecialization& specialization) {
|
||||
for (const auto& image: specialization.images) {
|
||||
indices.push_back(image.fmask ? UINT32_MAX : count++);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Apply(std::vector<T>& images) const {
|
||||
EXIT_IF(images.size() != indices.size());
|
||||
for (uint32_t index = 0; index < indices.size(); index++) {
|
||||
if (indices[index] != UINT32_MAX && indices[index] != index) {
|
||||
images[indices[index]] = std::move(images[index]);
|
||||
}
|
||||
}
|
||||
images.resize(count);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> indices;
|
||||
uint32_t count = 0;
|
||||
};
|
||||
|
||||
template <typename Images>
|
||||
bool BuildSamplerPlan(const ShaderInfo& base, const Images& images, SamplerPlan& plan);
|
||||
|
||||
@@ -495,6 +517,15 @@ static bool BuildResourceSpecialization(const ResourcePlan& program, Materialize
|
||||
static_cast<uint32_t>(format)));
|
||||
}
|
||||
const bool storage = base.resource_class == ImageResourceClass::Storage;
|
||||
image.fmask = Prospero::IsFmaskTextureFormat(format);
|
||||
if (image.fmask) {
|
||||
if (storage || base.depth_compare ||
|
||||
image.indirect_root != ImageResource::NoIndirectImage ||
|
||||
std::ranges::any_of(program.info.sampled_pairs,
|
||||
[&](const auto& pair) { return pair.image == i; })) {
|
||||
return SpecializationFail("FMASK requires a direct image load");
|
||||
}
|
||||
}
|
||||
image.conversion_format = ImageConversionFormat(format);
|
||||
if (storage || image.conversion_format != Prospero::BufferFormat::kInvalid) {
|
||||
image.shader_swizzle = DescriptorImageSwizzle(descriptor);
|
||||
@@ -585,6 +616,7 @@ static bool BuildResourceSpecialization(const ResourcePlan& program, Materialize
|
||||
next_snapshot.samplers.push_back(next_snapshot.samplers[index]);
|
||||
}
|
||||
}
|
||||
ImageRemap(next_specialization).Apply(next_snapshot.images);
|
||||
specialization = std::move(next_specialization);
|
||||
specialized_snapshot = std::move(next_snapshot);
|
||||
return true;
|
||||
@@ -1012,8 +1044,10 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization&
|
||||
}
|
||||
|
||||
auto memory_info = program.memory_info;
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
const ImageRemap image_remap(specialization);
|
||||
for (auto* block: program.blocks) {
|
||||
for (auto it = block->begin(); it != block->end(); ++it) {
|
||||
auto& inst = *it;
|
||||
const auto image_opcode = ImageOpcodeInfoOf(inst.GetOpcode());
|
||||
if (image_opcode.access == ImageAccess::None) {
|
||||
continue;
|
||||
@@ -1023,6 +1057,23 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization&
|
||||
auto& memory = memory_info[index];
|
||||
EXIT_IF(memory.resource >= images.size());
|
||||
const auto& image = images[memory.resource];
|
||||
if (specialization.images[memory.resource].fmask) {
|
||||
EXIT_IF(inst.GetOpcode() != ValueOpcode::ImageRead || memory.data_bits != 32u);
|
||||
// Vulkan MSAA stores each sample directly; FMASK's four-bit fragment indices
|
||||
// therefore map each coverage sample to the same host sample.
|
||||
constexpr uint32_t indices[] = {0x76543210u, 0xfedcba98u};
|
||||
std::array<Value, 2> fragments;
|
||||
for (uint32_t component = 0; component < fragments.size(); component++) {
|
||||
const auto selected = block->PrependNewInst(
|
||||
it, ValueOpcode::SelectU32, {inst.Arg(2), Value(indices[component]), Value(0u)});
|
||||
fragments[component] = Value(&*selected);
|
||||
}
|
||||
const auto result = block->PrependNewInst(
|
||||
it, ValueOpcode::CompositeConstructU32x4,
|
||||
{fragments[0], fragments[1], Value(0u), Value(0u)});
|
||||
inst.ReplaceUsesWith(Value(&*result));
|
||||
continue;
|
||||
}
|
||||
if (image_opcode.needs_sampler && RequiresPointSampler(image) &&
|
||||
memory.sampler < program.info.samplers.size()) {
|
||||
EXIT_IF(sampler_plan.point_sampler[memory.sampler] == UINT32_MAX);
|
||||
@@ -1032,6 +1083,35 @@ void ApplyResourceSpecialization(Program& program, const ResourceSpecialization&
|
||||
inst.GetOpcode() != ValueOpcode::ImageSampleRaw);
|
||||
}
|
||||
}
|
||||
for (auto* block: program.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
if (inst.GetOpcode() == ValueOpcode::GetImageResource) {
|
||||
inst.SetFlags(image_remap.indices.at(inst.Flags<uint32_t>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& memory: memory_info) {
|
||||
if (memory.kind == ResourceKind::Image && !memory.planning_only) {
|
||||
memory.resource = image_remap.indices.at(memory.resource);
|
||||
}
|
||||
}
|
||||
for (auto& buffer: buffers) {
|
||||
if (buffer.image_alias != BufferResource::NoImageAlias) {
|
||||
buffer.image_alias = image_remap.indices.at(buffer.image_alias);
|
||||
}
|
||||
}
|
||||
for (auto& pair: sampled_pairs) {
|
||||
pair.image = image_remap.indices.at(pair.image);
|
||||
}
|
||||
for (auto& image: images) {
|
||||
if (image.indirect_root != ImageResource::NoIndirectImage) {
|
||||
image.indirect_root = image_remap.indices.at(image.indirect_root);
|
||||
}
|
||||
for (auto& resource: image.indirect_resources) {
|
||||
resource = image_remap.indices.at(resource);
|
||||
}
|
||||
}
|
||||
image_remap.Apply(images);
|
||||
program.info.buffers = std::move(buffers);
|
||||
program.info.images = std::move(images);
|
||||
program.info.samplers = std::move(samplers);
|
||||
|
||||
@@ -25,6 +25,7 @@ struct ResourceSpecialization {
|
||||
uint32_t indirect_mapping_offset = 0;
|
||||
uint32_t indirect_search_iterations = 0;
|
||||
bool cube = false;
|
||||
bool fmask = false;
|
||||
bool operator==(const Image&) const = default;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user