mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 22:10:49 +00:00
Revert "God has forsaken me to BDA"
This commit is contained in:
@@ -41,17 +41,17 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std
|
|||||||
}
|
}
|
||||||
const u64 ssbo_align_mask{~(ctx.profile.min_ssbo_alignment - 1U)};
|
const u64 ssbo_align_mask{~(ctx.profile.min_ssbo_alignment - 1U)};
|
||||||
ctx.Add("LDC.U64 DC.x,c{}[{}];" // unaligned_ssbo_addr
|
ctx.Add("LDC.U64 DC.x,c{}[{}];" // unaligned_ssbo_addr
|
||||||
|
"AND.U64 DC.x,DC.x,{};" // ssbo_addr = unaligned_ssbo_addr & ssbo_align_mask
|
||||||
"LDC.U32 RC.x,c{}[{}];" // ssbo_size_u32
|
"LDC.U32 RC.x,c{}[{}];" // ssbo_size_u32
|
||||||
"CVT.U64.U32 DC.y,RC.x;" // ssbo_size = ssbo_size_u32
|
"CVT.U64.U32 DC.y,RC.x;" // ssbo_size = ssbo_size_u32
|
||||||
"ADD.U64 DC.y,DC.y,DC.x;" // ssbo_end = unaligned_ssbo_addr + ssbo_size
|
"ADD.U64 DC.y,DC.y,DC.x;" // ssbo_end = ssbo_addr + ssbo_size
|
||||||
"AND.U64 DC.x,DC.x,{};" // ssbo_addr = unaligned_ssbo_addr & ssbo_align_mask
|
|
||||||
"SGE.U64 RC.x,{}.x,DC.x;" // a = input_addr >= ssbo_addr ? -1 : 0
|
"SGE.U64 RC.x,{}.x,DC.x;" // a = input_addr >= ssbo_addr ? -1 : 0
|
||||||
"SLT.U64 RC.y,{}.x,DC.y;" // b = input_addr < ssbo_end ? -1 : 0
|
"SLT.U64 RC.y,{}.x,DC.y;" // b = input_addr < ssbo_end ? -1 : 0
|
||||||
"AND.U.CC RC.x,RC.x,RC.y;" // cond = a && b
|
"AND.U.CC RC.x,RC.x,RC.y;" // cond = a && b
|
||||||
"IF NE.x;" // if cond
|
"IF NE.x;" // if cond
|
||||||
"SUB.U64 DC.x,{}.x,DC.x;", // offset = input_addr - ssbo_addr
|
"SUB.U64 DC.x,{}.x,DC.x;", // offset = input_addr - ssbo_addr
|
||||||
ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8,
|
ssbo.cbuf_index, ssbo.cbuf_offset, ssbo_align_mask, ssbo.cbuf_index,
|
||||||
ssbo_align_mask, address, address, address);
|
ssbo.cbuf_offset + 8, address, address, address);
|
||||||
if (pointer_based) {
|
if (pointer_based) {
|
||||||
ctx.Add("PK64.U DC.y,c[{}];" // host_ssbo = cbuf
|
ctx.Add("PK64.U DC.y,c[{}];" // host_ssbo = cbuf
|
||||||
"ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset
|
"ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset
|
||||||
|
|||||||
@@ -618,8 +618,7 @@ std::string EmitContext::DefineGlobalMemoryFunctions() {
|
|||||||
|
|
||||||
const auto size_vec{fmt::format("uvec2({},{})", size_xy[0], size_xy[1])};
|
const auto size_vec{fmt::format("uvec2({},{})", size_xy[0], size_xy[1])};
|
||||||
const auto comp_lhs{fmt::format("(addr>={})", ssbo_addr)};
|
const auto comp_lhs{fmt::format("(addr>={})", ssbo_addr)};
|
||||||
const auto comp_rhs{fmt::format("(addr<(packUint2x32(uvec2({},{}))+uint64_t({})))",
|
const auto comp_rhs{fmt::format("(addr<({}+uint64_t({})))", ssbo_addr, size_vec)};
|
||||||
addr_xy[0], addr_xy[1], size_vec)};
|
|
||||||
const auto comparison{fmt::format("if({}&&{}){{", comp_lhs, comp_rhs)};
|
const auto comparison{fmt::format("if({}&&{}){{", comp_lhs, comp_rhs)};
|
||||||
func += comparison;
|
func += comparison;
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ struct RescalingLayout {
|
|||||||
struct RenderAreaLayout {
|
struct RenderAreaLayout {
|
||||||
std::array<f32, 4> render_area;
|
std::array<f32, 4> render_area;
|
||||||
};
|
};
|
||||||
struct GlobalPointerLayout {
|
|
||||||
std::array<u32, 2> table;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
constexpr u32 GLOBAL_POINTER_LAYOUT_OFFSET = 64;
|
|
||||||
constexpr u32 RESCALING_LAYOUT_WORDS_OFFSET = offsetof(RescalingLayout, rescaling_textures);
|
constexpr u32 RESCALING_LAYOUT_WORDS_OFFSET = offsetof(RescalingLayout, rescaling_textures);
|
||||||
constexpr u32 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET = offsetof(RescalingLayout, down_factor);
|
constexpr u32 RESCALING_LAYOUT_DOWN_FACTOR_OFFSET = offsetof(RescalingLayout, down_factor);
|
||||||
constexpr u32 RENDERAREA_LAYOUT_OFFSET = offsetof(RenderAreaLayout, render_area);
|
constexpr u32 RENDERAREA_LAYOUT_OFFSET = offsetof(RenderAreaLayout, render_area);
|
||||||
|
|||||||
@@ -486,9 +486,9 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
|
|||||||
DefineTextures(program.info, texture_binding, bindings.texture_scaling_index);
|
DefineTextures(program.info, texture_binding, bindings.texture_scaling_index);
|
||||||
DefineImages(program.info, image_binding, bindings.image_scaling_index);
|
DefineImages(program.info, image_binding, bindings.image_scaling_index);
|
||||||
DefineAttributeMemAccess(program.info);
|
DefineAttributeMemAccess(program.info);
|
||||||
|
DefineGlobalMemoryFunctions(program);
|
||||||
DefineRescalingInput(program.info);
|
DefineRescalingInput(program.info);
|
||||||
DefineRenderArea(program.info);
|
DefineRenderArea(program.info);
|
||||||
DefineGlobalMemoryFunctions(program);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitContext::~EmitContext() = default;
|
EmitContext::~EmitContext() = default;
|
||||||
@@ -911,48 +911,12 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
if (!info.uses_global_memory || !profile.support_int64) {
|
if (!info.uses_global_memory || !profile.support_int64) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct Access {
|
|
||||||
const StorageDefinitions* ssbo;
|
|
||||||
Id word;
|
|
||||||
Id address;
|
|
||||||
};
|
|
||||||
const Id zero{u32_zero_value};
|
const Id zero{u32_zero_value};
|
||||||
const Id scope{Const(static_cast<u32>(spv::Scope::Device))};
|
const Id scope{Const(static_cast<u32>(spv::Scope::Device))};
|
||||||
const Id align_mask{Const(~(static_cast<u32>(profile.min_ssbo_alignment) - 1U))};
|
const Id align_mask{Const(~(static_cast<u32>(profile.min_ssbo_alignment) - 1U))};
|
||||||
Id physical_u32{};
|
const auto word_pointer{[&](Id ssbo, Id word, u32 element) {
|
||||||
Id physical_u32x4{};
|
return OpAccessChain(storage_types.U32.element, ssbo, zero,
|
||||||
if (uses_global_pointers) {
|
OpIAdd(U32[1], word, Const(element)));
|
||||||
AddCapability(spv::Capability::PhysicalStorageBufferAddresses);
|
|
||||||
AddExtension("SPV_KHR_physical_storage_buffer");
|
|
||||||
SetMemoryModel(spv::AddressingModel::PhysicalStorageBuffer64, spv::MemoryModel::GLSL450);
|
|
||||||
physical_u32 = TypePointer(spv::StorageClass::PhysicalStorageBuffer, U32[1]);
|
|
||||||
physical_u32x4 = TypePointer(spv::StorageClass::PhysicalStorageBuffer, U32[4]);
|
|
||||||
}
|
|
||||||
const auto word_pointer{[&](const Access& access, u32 element) {
|
|
||||||
if (access.ssbo) {
|
|
||||||
return OpAccessChain(storage_types.U32.element, access.ssbo->U32, zero,
|
|
||||||
OpIAdd(U32[1], access.word, Const(element)));
|
|
||||||
}
|
|
||||||
return OpConvertUToPtr(physical_u32,
|
|
||||||
OpIAdd(U64, access.address, Constant(U64, u64{element} * 4)));
|
|
||||||
}};
|
|
||||||
const auto load_word{[&](const Access& access, u32 element) {
|
|
||||||
if (access.ssbo) {
|
|
||||||
return OpLoad(U32[1], word_pointer(access, element));
|
|
||||||
}
|
|
||||||
return OpLoad(U32[1], word_pointer(access, element), spv::MemoryAccessMask::Aligned, 4U);
|
|
||||||
}};
|
|
||||||
const auto store_word{[&](const Access& access, u32 element, Id value) {
|
|
||||||
if (access.ssbo) {
|
|
||||||
OpStore(word_pointer(access, element), value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
OpStore(word_pointer(access, element), value, spv::MemoryAccessMask::Aligned, 4U);
|
|
||||||
}};
|
|
||||||
const auto load_entry{[&](Id address) {
|
|
||||||
const Id entry{OpLoad(U32[4], OpConvertUToPtr(physical_u32x4, address),
|
|
||||||
spv::MemoryAccessMask::Aligned, 16U)};
|
|
||||||
return std::pair{entry, OpBitcast(U64, OpVectorShuffle(U32[2], entry, entry, 0U, 1U))};
|
|
||||||
}};
|
}};
|
||||||
const auto cbuf_word{[&](u32 index, u32 offset) {
|
const auto cbuf_word{[&](u32 index, u32 offset) {
|
||||||
if (profile.support_descriptor_aliasing) {
|
if (profile.support_descriptor_aliasing) {
|
||||||
@@ -974,19 +938,7 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
const Id addr{OpFunctionParameter(U64)};
|
const Id addr{OpFunctionParameter(U64)};
|
||||||
const Id value{OpFunctionParameter(value_type)};
|
const Id value{OpFunctionParameter(value_type)};
|
||||||
const bool returns_value{result_type.value != void_id.value};
|
const bool returns_value{result_type.value != void_id.value};
|
||||||
const auto finish{[&](Id result) {
|
|
||||||
if (returns_value) {
|
|
||||||
OpReturnValue(result);
|
|
||||||
} else {
|
|
||||||
OpReturn();
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
AddLabel();
|
AddLabel();
|
||||||
Id entry_index{};
|
|
||||||
if (uses_global_pointers) {
|
|
||||||
entry_index = AddLocalVariable(TypePointer(spv::StorageClass::Function, U32[1]),
|
|
||||||
spv::StorageClass::Function, zero);
|
|
||||||
}
|
|
||||||
const Id addr_words{OpBitcast(U32[2], addr)};
|
const Id addr_words{OpBitcast(U32[2], addr)};
|
||||||
const Id addr_low{OpCompositeExtract(U32[1], addr_words, 0U)};
|
const Id addr_low{OpCompositeExtract(U32[1], addr_words, 0U)};
|
||||||
const Id addr_high{OpCompositeExtract(U32[1], addr_words, 1U)};
|
const Id addr_high{OpCompositeExtract(U32[1], addr_words, 1U)};
|
||||||
@@ -995,7 +947,8 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
if (!desc.is_global_fallback) {
|
if (!desc.is_global_fallback) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const Id ssbo_low{cbuf_word(desc.cbuf_index, desc.cbuf_offset)};
|
const Id ssbo_low{
|
||||||
|
OpBitwiseAnd(U32[1], cbuf_word(desc.cbuf_index, desc.cbuf_offset), align_mask)};
|
||||||
const Id ssbo_high{cbuf_word(desc.cbuf_index, desc.cbuf_offset + 4)};
|
const Id ssbo_high{cbuf_word(desc.cbuf_index, desc.cbuf_offset + 4)};
|
||||||
const Id ssbo_size{cbuf_word(desc.cbuf_index, desc.cbuf_offset + 8)};
|
const Id ssbo_size{cbuf_word(desc.cbuf_index, desc.cbuf_offset + 8)};
|
||||||
const Id offset{OpISub(U32[1], addr_low, ssbo_low)};
|
const Id offset{OpISub(U32[1], addr_low, ssbo_low)};
|
||||||
@@ -1008,55 +961,15 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
OpSelectionMerge(else_label, spv::SelectionControlMask::MaskNone);
|
OpSelectionMerge(else_label, spv::SelectionControlMask::MaskNone);
|
||||||
OpBranchConditional(cond, then_label, else_label);
|
OpBranchConditional(cond, then_label, else_label);
|
||||||
AddLabel(then_label);
|
AddLabel(then_label);
|
||||||
const Id aligned_offset{
|
const Id word{OpShiftRightLogical(U32[1], offset, Const(2U))};
|
||||||
OpISub(U32[1], addr_low, OpBitwiseAnd(U32[1], ssbo_low, align_mask))};
|
const Id result{callback(ssbos[index], word, offset, value)};
|
||||||
const Id word{OpShiftRightLogical(U32[1], aligned_offset, Const(2U))};
|
if (returns_value) {
|
||||||
finish(callback(Access{&ssbos[index], word, Id{}}, aligned_offset, value));
|
OpReturnValue(result);
|
||||||
|
} else {
|
||||||
|
OpReturn();
|
||||||
|
}
|
||||||
AddLabel(else_label);
|
AddLabel(else_label);
|
||||||
}
|
}
|
||||||
if (uses_global_pointers) {
|
|
||||||
const Id table_pointer{
|
|
||||||
OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[2]),
|
|
||||||
rescaling_push_constants, Const(global_pointer_member_index))};
|
|
||||||
const Id count_pointer{
|
|
||||||
OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]),
|
|
||||||
rescaling_push_constants, Const(global_pointer_member_index + 1))};
|
|
||||||
const Id table{OpBitcast(U64, OpLoad(U32[2], table_pointer))};
|
|
||||||
const Id count{OpLoad(U32[1], count_pointer)};
|
|
||||||
const Id header_label{OpLabel()};
|
|
||||||
const Id body_label{OpLabel()};
|
|
||||||
const Id hit_label{OpLabel()};
|
|
||||||
const Id skip_label{OpLabel()};
|
|
||||||
const Id continue_label{OpLabel()};
|
|
||||||
const Id merge_label{OpLabel()};
|
|
||||||
OpBranch(header_label);
|
|
||||||
AddLabel(header_label);
|
|
||||||
const Id entry{OpLoad(U32[1], entry_index)};
|
|
||||||
const Id in_table{OpULessThan(U1, entry, count)};
|
|
||||||
OpLoopMerge(merge_label, continue_label, spv::LoopControlMask::MaskNone);
|
|
||||||
OpBranchConditional(in_table, body_label, merge_label);
|
|
||||||
AddLabel(body_label);
|
|
||||||
const Id entry_address{OpIAdd(
|
|
||||||
U64, table, OpUConvert(U64, OpShiftLeftLogical(U32[1], entry, Const(5U))))};
|
|
||||||
const auto [guest, guest_base]{load_entry(entry_address)};
|
|
||||||
const Id guest_offset{OpISub(U64, addr, guest_base)};
|
|
||||||
const Id guest_size{OpUConvert(U64, OpCompositeExtract(U32[1], guest, 2U))};
|
|
||||||
const Id hit{OpULessThan(U1, guest_offset, guest_size)};
|
|
||||||
OpSelectionMerge(skip_label, spv::SelectionControlMask::MaskNone);
|
|
||||||
OpBranchConditional(hit, hit_label, skip_label);
|
|
||||||
AddLabel(hit_label);
|
|
||||||
const Id host_base{
|
|
||||||
load_entry(OpIAdd(U64, entry_address, Constant(U64, u64{16}))).second};
|
|
||||||
const Id target{OpBitwiseAnd(U64, OpIAdd(U64, host_base, guest_offset),
|
|
||||||
Constant(U64, ~u64{3}))};
|
|
||||||
finish(callback(Access{nullptr, Id{}, target}, addr_low, value));
|
|
||||||
AddLabel(skip_label);
|
|
||||||
OpBranch(continue_label);
|
|
||||||
AddLabel(continue_label);
|
|
||||||
OpStore(entry_index, OpIAdd(U32[1], entry, Const(1U)));
|
|
||||||
OpBranch(header_label);
|
|
||||||
AddLabel(merge_label);
|
|
||||||
}
|
|
||||||
if (returns_value) {
|
if (returns_value) {
|
||||||
OpReturnValue(ConstantNull(result_type));
|
OpReturnValue(ConstantNull(result_type));
|
||||||
} else {
|
} else {
|
||||||
@@ -1074,13 +987,13 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
OpShiftRightLogical(U32[1], word, Const(2U)));
|
OpShiftRightLogical(U32[1], word, Const(2U)));
|
||||||
}};
|
}};
|
||||||
const auto load{[&](Id type, u32 count) {
|
const auto load{[&](Id type, u32 count) {
|
||||||
return [&, type, count](const Access& access, Id, Id) {
|
return [&, type, count](const StorageDefinitions& ssbo, Id word, Id, Id) {
|
||||||
if (count > 1 && access.ssbo && profile.support_descriptor_aliasing) {
|
if (count > 1 && profile.support_descriptor_aliasing) {
|
||||||
return OpLoad(type, vector_pointer(*access.ssbo, access.word, count));
|
return OpLoad(type, vector_pointer(ssbo, word, count));
|
||||||
}
|
}
|
||||||
std::array<Id, 4> words{};
|
std::array<Id, 4> words{};
|
||||||
for (u32 element = 0; element < count; ++element) {
|
for (u32 element = 0; element < count; ++element) {
|
||||||
words[element] = load_word(access, element);
|
words[element] = OpLoad(U32[1], word_pointer(ssbo.U32, word, element));
|
||||||
}
|
}
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
return words[0];
|
return words[0];
|
||||||
@@ -1089,24 +1002,25 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
const auto store{[&](u32 count) {
|
const auto store{[&](u32 count) {
|
||||||
return [&, count](const Access& access, Id, Id value) {
|
return [&, count](const StorageDefinitions& ssbo, Id word, Id, Id value) {
|
||||||
if (count > 1 && access.ssbo && profile.support_descriptor_aliasing) {
|
if (count > 1 && profile.support_descriptor_aliasing) {
|
||||||
OpStore(vector_pointer(*access.ssbo, access.word, count), value);
|
OpStore(vector_pointer(ssbo, word, count), value);
|
||||||
return Id{};
|
return Id{};
|
||||||
}
|
}
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
store_word(access, 0, value);
|
OpStore(word_pointer(ssbo.U32, word, 0), value);
|
||||||
return Id{};
|
return Id{};
|
||||||
}
|
}
|
||||||
for (u32 element = 0; element < count; ++element) {
|
for (u32 element = 0; element < count; ++element) {
|
||||||
store_word(access, element, OpCompositeExtract(U32[1], value, element));
|
OpStore(word_pointer(ssbo.U32, word, element),
|
||||||
|
OpCompositeExtract(U32[1], value, element));
|
||||||
}
|
}
|
||||||
return Id{};
|
return Id{};
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
const auto extract{[&](bool is_signed, u32 count) {
|
const auto extract{[&](bool is_signed, u32 count) {
|
||||||
return [&, is_signed, count](const Access& access, Id offset, Id) {
|
return [&, is_signed, count](const StorageDefinitions& ssbo, Id word, Id offset, Id) {
|
||||||
const Id loaded{load_word(access, 0)};
|
const Id loaded{OpLoad(U32[1], word_pointer(ssbo.U32, word, 0))};
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
return OpBitFieldSExtract(U32[1], loaded, bits(offset, count), Const(count));
|
return OpBitFieldSExtract(U32[1], loaded, bits(offset, count), Const(count));
|
||||||
}
|
}
|
||||||
@@ -1114,36 +1028,28 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
const auto insert{[&](u32 count) {
|
const auto insert{[&](u32 count) {
|
||||||
return [&, count](const Access& access, Id offset, Id value) {
|
return [&, count](const StorageDefinitions& ssbo, Id word, Id offset, Id value) {
|
||||||
AtomicBitFieldInsert(word_pointer(access, 0), value, bits(offset, count),
|
AtomicBitFieldInsert(word_pointer(ssbo.U32, word, 0), value, bits(offset, count),
|
||||||
Const(count));
|
Const(count));
|
||||||
return Id{};
|
return Id{};
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
const auto atomic{[&](Id (Sirit::Module::*func)(Id, Id, Id, Id, Id)) {
|
const auto atomic{[&](Id (Sirit::Module::*func)(Id, Id, Id, Id, Id)) {
|
||||||
return [&, func](const Access& access, Id, Id value) {
|
return [&, func](const StorageDefinitions& ssbo, Id word, Id, Id value) {
|
||||||
return (this->*func)(U32[1], word_pointer(access, 0), scope, zero, value);
|
return (this->*func)(U32[1], word_pointer(ssbo.U32, word, 0), scope, zero, value);
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
const auto cas{[&](Id type, Id helper) {
|
const auto cas{[&](Id type, Id helper) {
|
||||||
return [&, type, helper](const Access& access, Id, Id value) {
|
return [&, type, helper](const StorageDefinitions& ssbo, Id word, Id, Id value) {
|
||||||
if (!access.ssbo) {
|
return OpFunctionCall(type, helper, word, value, ssbo.U32);
|
||||||
return ConstantNull(type);
|
|
||||||
}
|
|
||||||
return OpFunctionCall(type, helper, access.word, value, access.ssbo->U32);
|
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
const auto packed{[&](bool is_half, Id helper) {
|
const auto packed{[&](bool is_half, Id helper) {
|
||||||
return [&, is_half, helper](const Access& access, Id, Id value) {
|
return [&, is_half, helper](const StorageDefinitions& ssbo, Id word, Id, Id value) {
|
||||||
if (!access.ssbo) {
|
|
||||||
return ConstantNull(U32[1]);
|
|
||||||
}
|
|
||||||
const Id ssbo{access.ssbo->U32};
|
|
||||||
if (is_half) {
|
if (is_half) {
|
||||||
return OpBitcast(U32[1], OpFunctionCall(F16[2], helper, access.word, value, ssbo));
|
return OpBitcast(U32[1], OpFunctionCall(F16[2], helper, word, value, ssbo.U32));
|
||||||
}
|
}
|
||||||
return OpPackHalf2x16(U32[1],
|
return OpPackHalf2x16(U32[1], OpFunctionCall(F32[2], helper, word, value, ssbo.U32));
|
||||||
OpFunctionCall(F32[2], helper, access.word, value, ssbo));
|
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
for (const IR::Block* const block : program.post_order_blocks) {
|
for (const IR::Block* const block : program.post_order_blocks) {
|
||||||
@@ -1253,9 +1159,7 @@ void EmitContext::DefineGlobalMemoryFunctions(const IR::Program& program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmitContext::DefineRescalingInput(const Info& info) {
|
void EmitContext::DefineRescalingInput(const Info& info) {
|
||||||
uses_global_pointers = info.uses_global_pointers && profile.support_buffer_device_address &&
|
if (!info.uses_rescaling_uniform) {
|
||||||
profile.support_int64 && profile.unified_descriptor_binding;
|
|
||||||
if (!info.uses_rescaling_uniform && !uses_global_pointers) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (profile.unified_descriptor_binding) {
|
if (profile.unified_descriptor_binding) {
|
||||||
@@ -1266,7 +1170,7 @@ void EmitContext::DefineRescalingInput(const Info& info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmitContext::DefineRescalingInputPushConstant() {
|
void EmitContext::DefineRescalingInputPushConstant() {
|
||||||
boost::container::static_vector<Id, 5> members{};
|
boost::container::static_vector<Id, 3> members{};
|
||||||
u32 member_index{0};
|
u32 member_index{0};
|
||||||
|
|
||||||
rescaling_textures_type = TypeArray(U32[1], Const(4u));
|
rescaling_textures_type = TypeArray(U32[1], Const(4u));
|
||||||
@@ -1283,11 +1187,6 @@ void EmitContext::DefineRescalingInputPushConstant() {
|
|||||||
members.push_back(F32[1]);
|
members.push_back(F32[1]);
|
||||||
rescaling_downfactor_member_index = member_index++;
|
rescaling_downfactor_member_index = member_index++;
|
||||||
}
|
}
|
||||||
if (uses_global_pointers) {
|
|
||||||
members.push_back(U32[2]);
|
|
||||||
members.push_back(U32[1]);
|
|
||||||
global_pointer_member_index = member_index;
|
|
||||||
}
|
|
||||||
const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))};
|
const Id push_constant_struct{TypeStruct(std::span(members.data(), members.size()))};
|
||||||
Decorate(push_constant_struct, spv::Decoration::Block);
|
Decorate(push_constant_struct, spv::Decoration::Block);
|
||||||
Name(push_constant_struct, "ResolutionInfo");
|
Name(push_constant_struct, "ResolutionInfo");
|
||||||
@@ -1306,14 +1205,6 @@ void EmitContext::DefineRescalingInputPushConstant() {
|
|||||||
static_cast<u32>(offsetof(RescalingLayout, down_factor)));
|
static_cast<u32>(offsetof(RescalingLayout, down_factor)));
|
||||||
MemberName(push_constant_struct, rescaling_downfactor_member_index, "down_factor");
|
MemberName(push_constant_struct, rescaling_downfactor_member_index, "down_factor");
|
||||||
}
|
}
|
||||||
if (uses_global_pointers) {
|
|
||||||
MemberDecorate(push_constant_struct, global_pointer_member_index, spv::Decoration::Offset,
|
|
||||||
GLOBAL_POINTER_LAYOUT_OFFSET);
|
|
||||||
MemberDecorate(push_constant_struct, global_pointer_member_index + 1,
|
|
||||||
spv::Decoration::Offset,
|
|
||||||
GLOBAL_POINTER_LAYOUT_OFFSET +
|
|
||||||
static_cast<u32>(offsetof(GlobalPointerLayout, count)));
|
|
||||||
}
|
|
||||||
const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)};
|
const Id pointer_type{TypePointer(spv::StorageClass::PushConstant, push_constant_struct)};
|
||||||
rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant);
|
rescaling_push_constants = AddGlobalVariable(pointer_type, spv::StorageClass::PushConstant);
|
||||||
Name(rescaling_push_constants, "rescaling_push_constants");
|
Name(rescaling_push_constants, "rescaling_push_constants");
|
||||||
|
|||||||
@@ -307,8 +307,6 @@ public:
|
|||||||
u32 rescaling_textures_member_index{};
|
u32 rescaling_textures_member_index{};
|
||||||
u32 rescaling_images_member_index{};
|
u32 rescaling_images_member_index{};
|
||||||
u32 rescaling_downfactor_member_index{};
|
u32 rescaling_downfactor_member_index{};
|
||||||
u32 global_pointer_member_index{};
|
|
||||||
bool uses_global_pointers{};
|
|
||||||
u32 texture_rescaling_index{};
|
u32 texture_rescaling_index{};
|
||||||
u32 image_rescaling_index{};
|
u32 image_rescaling_index{};
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ struct StorageInfo {
|
|||||||
StorageBufferSet set;
|
StorageBufferSet set;
|
||||||
StorageInstVector to_replace;
|
StorageInstVector to_replace;
|
||||||
StorageWritesSet writes;
|
StorageWritesSet writes;
|
||||||
bool pointers{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns true when the instruction is a global memory instruction
|
/// Returns true when the instruction is a global memory instruction
|
||||||
@@ -336,8 +335,7 @@ std::optional<LowAddrInfo> TrackLowAddress(IR::Inst* inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to track the storage buffer address used by a global memory instruction
|
/// Tries to track the storage buffer address used by a global memory instruction
|
||||||
StorageBufferSet Track(const IR::Value& value, const Bias* bias, const LocalStores& local_stores,
|
StorageBufferSet Track(const IR::Value& value, const Bias* bias, const LocalStores& local_stores) {
|
||||||
bool& from_memory) {
|
|
||||||
const auto pred{[bias](const IR::Inst* inst) -> std::optional<StorageBufferAddr> {
|
const auto pred{[bias](const IR::Inst* inst) -> std::optional<StorageBufferAddr> {
|
||||||
if (inst->GetOpcode() != IR::Opcode::GetCbufU32 &&
|
if (inst->GetOpcode() != IR::Opcode::GetCbufU32 &&
|
||||||
inst->GetOpcode() != IR::Opcode::GetCbufU32x2) {
|
inst->GetOpcode() != IR::Opcode::GetCbufU32x2) {
|
||||||
@@ -388,8 +386,6 @@ StorageBufferSet Track(const IR::Value& value, const Bias* bias, const LocalStor
|
|||||||
}
|
}
|
||||||
switch (inst->GetOpcode()) {
|
switch (inst->GetOpcode()) {
|
||||||
case IR::Opcode::LoadLocal:
|
case IR::Opcode::LoadLocal:
|
||||||
from_memory |=
|
|
||||||
!inst->Arg(0).IsImmediate() || !local_stores.contains(inst->Arg(0).U32());
|
|
||||||
if (inst->Arg(0).IsImmediate()) {
|
if (inst->Arg(0).IsImmediate()) {
|
||||||
const auto [begin, end]{local_stores.equal_range(inst->Arg(0).U32())};
|
const auto [begin, end]{local_stores.equal_range(inst->Arg(0).U32())};
|
||||||
for (auto it = begin; it != end; ++it) {
|
for (auto it = begin; it != end; ++it) {
|
||||||
@@ -409,7 +405,6 @@ StorageBufferSet Track(const IR::Value& value, const Bias* bias, const LocalStor
|
|||||||
case IR::Opcode::GetCbufU32:
|
case IR::Opcode::GetCbufU32:
|
||||||
case IR::Opcode::GetCbufF32:
|
case IR::Opcode::GetCbufF32:
|
||||||
case IR::Opcode::GetCbufU32x2:
|
case IR::Opcode::GetCbufU32x2:
|
||||||
continue;
|
|
||||||
case IR::Opcode::LoadSharedU8:
|
case IR::Opcode::LoadSharedU8:
|
||||||
case IR::Opcode::LoadSharedS8:
|
case IR::Opcode::LoadSharedS8:
|
||||||
case IR::Opcode::LoadSharedU16:
|
case IR::Opcode::LoadSharedU16:
|
||||||
@@ -417,13 +412,11 @@ StorageBufferSet Track(const IR::Value& value, const Bias* bias, const LocalStor
|
|||||||
case IR::Opcode::LoadSharedU32:
|
case IR::Opcode::LoadSharedU32:
|
||||||
case IR::Opcode::LoadSharedU64:
|
case IR::Opcode::LoadSharedU64:
|
||||||
case IR::Opcode::LoadSharedU128:
|
case IR::Opcode::LoadSharedU128:
|
||||||
from_memory = true;
|
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (IsGlobalMemory(*inst) || inst->MayHaveSideEffects()) {
|
if (IsGlobalMemory(*inst) || inst->MayHaveSideEffects()) {
|
||||||
from_memory = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (size_t arg = 0; arg < inst->NumArgs(); ++arg) {
|
for (size_t arg = 0; arg < inst->NumArgs(); ++arg) {
|
||||||
@@ -464,21 +457,18 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageInfo& info,
|
|||||||
const std::optional<LowAddrInfo> low_addr_info{TrackLowAddress(&inst)};
|
const std::optional<LowAddrInfo> low_addr_info{TrackLowAddress(&inst)};
|
||||||
if (!low_addr_info) {
|
if (!low_addr_info) {
|
||||||
// Failed to track the low address, use NVN fallbacks
|
// Failed to track the low address, use NVN fallbacks
|
||||||
info.pointers = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// First try to find storage buffers in the NVN address
|
// First try to find storage buffers in the NVN address
|
||||||
const IR::U32 low_addr{low_addr_info->value};
|
const IR::U32 low_addr{low_addr_info->value};
|
||||||
bool from_memory{};
|
StorageBufferSet candidates{Track(low_addr, &nvn_bias, local_stores)};
|
||||||
StorageBufferSet candidates{Track(low_addr, &nvn_bias, local_stores, from_memory)};
|
|
||||||
if (candidates.empty()) {
|
if (candidates.empty()) {
|
||||||
// If it fails, track without a bias
|
// If it fails, track without a bias
|
||||||
candidates = Track(low_addr, nullptr, local_stores, from_memory);
|
candidates = Track(low_addr, nullptr, local_stores);
|
||||||
}
|
}
|
||||||
if (candidates.size() != 1) {
|
if (candidates.size() != 1) {
|
||||||
// If that also fails, use NVN fallbacks
|
// If that also fails, use NVN fallbacks
|
||||||
LOG_WARNING(Shader, "Storage buffer failed to track, using global memory fallbacks");
|
LOG_WARNING(Shader, "Storage buffer failed to track, using global memory fallbacks");
|
||||||
info.pointers |= from_memory;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const StorageBufferAddr storage_buffer{*candidates.begin()};
|
const StorageBufferAddr storage_buffer{*candidates.begin()};
|
||||||
@@ -625,7 +615,6 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateIn
|
|||||||
.is_written = info.writes.contains(storage_buffer),
|
.is_written = info.writes.contains(storage_buffer),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
program.info.uses_global_pointers = info.pointers;
|
|
||||||
for (const StorageInst& storage_inst : info.to_replace) {
|
for (const StorageInst& storage_inst : info.to_replace) {
|
||||||
const StorageBufferAddr storage_buffer{storage_inst.storage_buffer};
|
const StorageBufferAddr storage_buffer{storage_inst.storage_buffer};
|
||||||
const auto it{info.set.find(storage_inst.storage_buffer)};
|
const auto it{info.set.find(storage_inst.storage_buffer)};
|
||||||
@@ -639,7 +628,6 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JoinStorageInfo(Info& base, Info& source) {
|
void JoinStorageInfo(Info& base, Info& source) {
|
||||||
base.uses_global_pointers |= source.uses_global_pointers;
|
|
||||||
auto& descriptors = base.storage_buffers_descriptors;
|
auto& descriptors = base.storage_buffers_descriptors;
|
||||||
for (auto& desc : source.storage_buffers_descriptors) {
|
for (auto& desc : source.storage_buffers_descriptors) {
|
||||||
auto it{std::ranges::find_if(descriptors, [&desc](const auto& existing) {
|
auto it{std::ranges::find_if(descriptors, [&desc](const auto& existing) {
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ struct Profile {
|
|||||||
bool support_typeless_image_loads{};
|
bool support_typeless_image_loads{};
|
||||||
bool support_demote_to_helper_invocation{};
|
bool support_demote_to_helper_invocation{};
|
||||||
bool support_int64_atomics{};
|
bool support_int64_atomics{};
|
||||||
bool support_buffer_device_address{};
|
|
||||||
bool support_shared_int64_atomics{};
|
bool support_shared_int64_atomics{};
|
||||||
bool support_derivative_control{};
|
bool support_derivative_control{};
|
||||||
bool support_geometry_shader_passthrough{};
|
bool support_geometry_shader_passthrough{};
|
||||||
|
|||||||
@@ -312,7 +312,6 @@ struct Info {
|
|||||||
bool uses_atomic_s32_max{};
|
bool uses_atomic_s32_max{};
|
||||||
bool uses_int64_bit_atomics{};
|
bool uses_int64_bit_atomics{};
|
||||||
bool uses_global_memory{};
|
bool uses_global_memory{};
|
||||||
bool uses_global_pointers{};
|
|
||||||
bool uses_atomic_image_u32{};
|
bool uses_atomic_image_u32{};
|
||||||
bool uses_shadow_lod{};
|
bool uses_shadow_lod{};
|
||||||
bool uses_rescaling_uniform{};
|
bool uses_rescaling_uniform{};
|
||||||
|
|||||||
@@ -123,8 +123,6 @@ void BufferCache<P>::TickFrame() {
|
|||||||
if (total_used_memory >= minimum_memory || heap_pressure) {
|
if (total_used_memory >= minimum_memory || heap_pressure) {
|
||||||
RunGarbageCollector();
|
RunGarbageCollector();
|
||||||
}
|
}
|
||||||
std::erase_if(pointer_ranges,
|
|
||||||
[this](const PointerRange& range) { return range.frame + 2 < frame_tick; });
|
|
||||||
++frame_tick;
|
++frame_tick;
|
||||||
delayed_destruction_ring.Tick();
|
delayed_destruction_ring.Tick();
|
||||||
|
|
||||||
@@ -1146,7 +1144,6 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
|
|||||||
|
|
||||||
if (is_written) {
|
if (is_written) {
|
||||||
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
||||||
RecordPointerRange(binding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (NEEDS_BIND_STORAGE_INDEX) {
|
if constexpr (NEEDS_BIND_STORAGE_INDEX) {
|
||||||
@@ -1287,7 +1284,6 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
|
|||||||
|
|
||||||
if (is_written) {
|
if (is_written) {
|
||||||
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
|
||||||
RecordPointerRange(binding);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (NEEDS_BIND_STORAGE_INDEX) {
|
if constexpr (NEEDS_BIND_STORAGE_INDEX) {
|
||||||
@@ -1345,7 +1341,6 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
|||||||
if (current_draw_indirect) {
|
if (current_draw_indirect) {
|
||||||
UpdateDrawIndirect();
|
UpdateDrawIndirect();
|
||||||
}
|
}
|
||||||
UpdatePointerRanges();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1356,7 +1351,6 @@ void BufferCache<P>::DoUpdateComputeBuffers() {
|
|||||||
UpdateComputeUniformBuffers();
|
UpdateComputeUniformBuffers();
|
||||||
UpdateComputeStorageBuffers();
|
UpdateComputeStorageBuffers();
|
||||||
UpdateComputeTextureBuffers();
|
UpdateComputeTextureBuffers();
|
||||||
UpdatePointerRanges();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1502,72 +1496,6 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
|
||||||
void BufferCache<P>::UpdatePointerRanges() {
|
|
||||||
if (!pointer_table_requested) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (PointerRange& range : pointer_ranges) {
|
|
||||||
range.buffer_id = NULL_BUFFER_ID;
|
|
||||||
if (gpu_memory->GpuToCpuAddress(range.gpu_addr) == range.device_addr) {
|
|
||||||
range.buffer_id = FindBuffer(range.device_addr, range.size, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
|
||||||
void BufferCache<P>::RecordPointerRange(const Binding& binding) {
|
|
||||||
if (!record_pointer_ranges) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto it = std::ranges::find(pointer_ranges, binding.gpu_addr, &PointerRange::gpu_addr);
|
|
||||||
if (it != pointer_ranges.end()) {
|
|
||||||
it->device_addr = binding.device_addr;
|
|
||||||
it->size = (std::max)(it->size, binding.size);
|
|
||||||
it->frame = frame_tick;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pointer_ranges.size() < MAX_POINTER_RANGES) {
|
|
||||||
pointer_ranges.push_back({binding.gpu_addr, binding.device_addr, binding.size, frame_tick,
|
|
||||||
NULL_BUFFER_ID});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
|
||||||
void BufferCache<P>::RequestPointerTable(bool enable) noexcept {
|
|
||||||
pointer_table_requested = enable;
|
|
||||||
record_pointer_ranges |= enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
|
||||||
std::array<u32, 3> BufferCache<P>::BindHostPointerTable(bool is_written) {
|
|
||||||
std::array<u32, 3> table{};
|
|
||||||
if constexpr (!IS_OPENGL) {
|
|
||||||
const size_t capacity = (std::max)(pointer_ranges.size(), size_t{1});
|
|
||||||
const auto upload = runtime.UploadStagingBuffer(capacity * sizeof(std::array<u64, 4>));
|
|
||||||
u32 count = 0;
|
|
||||||
for (const PointerRange& range : pointer_ranges) {
|
|
||||||
if (range.buffer_id == NULL_BUFFER_ID) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Buffer& buffer = slot_buffers[range.buffer_id];
|
|
||||||
TouchBuffer(buffer, range.buffer_id);
|
|
||||||
SynchronizeBuffer(buffer, range.device_addr, range.size);
|
|
||||||
if (is_written) {
|
|
||||||
MarkWrittenBuffer(range.buffer_id, range.device_addr, range.size);
|
|
||||||
}
|
|
||||||
const u64 host_address = buffer.DeviceAddress() + buffer.Offset(range.device_addr);
|
|
||||||
const std::array<u64, 4> entry{range.gpu_addr, range.size, host_address, 0};
|
|
||||||
std::memcpy(upload.mapped_span.data() + count * sizeof(entry), entry.data(),
|
|
||||||
sizeof(entry));
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
const u64 address = upload.device_address + upload.offset;
|
|
||||||
table = {static_cast<u32>(address), static_cast<u32>(address >> 32), count};
|
|
||||||
}
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
|
void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
|
||||||
ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
|
ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
|
||||||
|
|||||||
@@ -270,10 +270,6 @@ public:
|
|||||||
|
|
||||||
void BindHostComputeBuffers();
|
void BindHostComputeBuffers();
|
||||||
|
|
||||||
void RequestPointerTable(bool enable) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] std::array<u32, 3> BindHostPointerTable(bool is_written);
|
|
||||||
|
|
||||||
void SetUniformBuffersState(const std::array<u32, NUM_STAGES>& mask,
|
void SetUniformBuffersState(const std::array<u32, NUM_STAGES>& mask,
|
||||||
const UniformBufferSizes* sizes);
|
const UniformBufferSizes* sizes);
|
||||||
|
|
||||||
@@ -435,10 +431,6 @@ private:
|
|||||||
|
|
||||||
void UpdateStorageBuffers(size_t stage);
|
void UpdateStorageBuffers(size_t stage);
|
||||||
|
|
||||||
void UpdatePointerRanges();
|
|
||||||
|
|
||||||
void RecordPointerRange(const Binding& binding);
|
|
||||||
|
|
||||||
void UpdateTextureBuffers(size_t stage);
|
void UpdateTextureBuffers(size_t stage);
|
||||||
|
|
||||||
void UpdateTransformFeedbackBuffers();
|
void UpdateTransformFeedbackBuffers();
|
||||||
@@ -571,17 +563,6 @@ private:
|
|||||||
std::vector<MultiRangeSegment> graphics_segments;
|
std::vector<MultiRangeSegment> graphics_segments;
|
||||||
std::vector<MultiRangeSegment> compute_segments;
|
std::vector<MultiRangeSegment> compute_segments;
|
||||||
u64 frame_tick = 0;
|
u64 frame_tick = 0;
|
||||||
struct PointerRange {
|
|
||||||
GPUVAddr gpu_addr;
|
|
||||||
DAddr device_addr;
|
|
||||||
u32 size;
|
|
||||||
u64 frame;
|
|
||||||
BufferId buffer_id;
|
|
||||||
};
|
|
||||||
static constexpr size_t MAX_POINTER_RANGES = 256;
|
|
||||||
std::vector<PointerRange> pointer_ranges;
|
|
||||||
bool record_pointer_ranges = false;
|
|
||||||
bool pointer_table_requested = false;
|
|
||||||
u64 total_used_memory = 0;
|
u64 total_used_memory = 0;
|
||||||
u64 device_local_memory = 0;
|
u64 device_local_memory = 0;
|
||||||
u64 minimum_memory = 0;
|
u64 minimum_memory = 0;
|
||||||
|
|||||||
@@ -243,13 +243,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
|
vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
|
||||||
using Shader::Backend::SPIRV::GLOBAL_POINTER_LAYOUT_OFFSET;
|
using Shader::Backend::SPIRV::RenderAreaLayout;
|
||||||
using Shader::Backend::SPIRV::GlobalPointerLayout;
|
using Shader::Backend::SPIRV::RescalingLayout;
|
||||||
|
const u32 size_offset = is_compute ? sizeof(RescalingLayout::down_factor) : 0u;
|
||||||
const VkPushConstantRange range{
|
const VkPushConstantRange range{
|
||||||
.stageFlags = static_cast<VkShaderStageFlags>(
|
.stageFlags = static_cast<VkShaderStageFlags>(
|
||||||
is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS),
|
is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS),
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = GLOBAL_POINTER_LAYOUT_OFFSET + static_cast<u32>(sizeof(GlobalPointerLayout)),
|
.size = static_cast<u32>(sizeof(RescalingLayout)) - size_offset +
|
||||||
|
static_cast<u32>(sizeof(RenderAreaLayout)),
|
||||||
};
|
};
|
||||||
return device->GetLogical().CreatePipelineLayout({
|
return device->GetLogical().CreatePipelineLayout({
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
using Shader::ImageBufferDescriptor;
|
using Shader::ImageBufferDescriptor;
|
||||||
using Shader::Backend::SPIRV::GLOBAL_POINTER_LAYOUT_OFFSET;
|
|
||||||
using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
|
using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
|
||||||
using Tegra::Texture::TexturePair;
|
using Tegra::Texture::TexturePair;
|
||||||
|
|
||||||
@@ -246,14 +245,8 @@ bool ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
|||||||
std::ranges::for_each(info.texture_buffer_descriptors, add_buffer);
|
std::ranges::for_each(info.texture_buffer_descriptors, add_buffer);
|
||||||
std::ranges::for_each(info.image_buffer_descriptors, add_buffer);
|
std::ranges::for_each(info.image_buffer_descriptors, add_buffer);
|
||||||
|
|
||||||
const bool uses_pointers{info.uses_global_pointers && device.IsBufferDeviceAddressSupported()};
|
|
||||||
buffer_cache.RequestPointerTable(uses_pointers);
|
|
||||||
buffer_cache.UpdateComputeBuffers();
|
buffer_cache.UpdateComputeBuffers();
|
||||||
buffer_cache.BindHostComputeBuffers();
|
buffer_cache.BindHostComputeBuffers();
|
||||||
std::array<u32, 3> pointer_table{};
|
|
||||||
if (uses_pointers) {
|
|
||||||
pointer_table = buffer_cache.BindHostPointerTable(info.stores_global_memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
RescalingPushConstant rescaling;
|
RescalingPushConstant rescaling;
|
||||||
const VideoCommon::SamplerId* samplers_it{samplers.data()};
|
const VideoCommon::SamplerId* samplers_it{samplers.data()};
|
||||||
@@ -295,7 +288,7 @@ bool ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
|||||||
|
|
||||||
const bool is_rescaling = !info.texture_descriptors.empty() || !info.image_descriptors.empty();
|
const bool is_rescaling = !info.texture_descriptors.empty() || !info.image_descriptors.empty();
|
||||||
scheduler.Record([this, descriptor_data, is_rescaling, descriptor_buffer_offset,
|
scheduler.Record([this, descriptor_data, is_rescaling, descriptor_buffer_offset,
|
||||||
descriptor_buffer_chunk, bind_descriptor_buffer, uses_pointers, pointer_table,
|
descriptor_buffer_chunk, bind_descriptor_buffer,
|
||||||
rescaling_data = rescaling.Data()](vk::CommandBuffer cmdbuf) {
|
rescaling_data = rescaling.Data()](vk::CommandBuffer cmdbuf) {
|
||||||
if (bind_descriptor_buffer) {
|
if (bind_descriptor_buffer) {
|
||||||
const VkDescriptorBufferBindingInfoEXT binding_info{
|
const VkDescriptorBufferBindingInfoEXT binding_info{
|
||||||
@@ -306,11 +299,6 @@ bool ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
|
||||||
if (uses_pointers) {
|
|
||||||
cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT,
|
|
||||||
GLOBAL_POINTER_LAYOUT_OFFSET, sizeof(pointer_table),
|
|
||||||
pointer_table.data());
|
|
||||||
}
|
|
||||||
if (!descriptor_set_layout) {
|
if (!descriptor_set_layout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace {
|
|||||||
using boost::container::small_vector;
|
using boost::container::small_vector;
|
||||||
using boost::container::static_vector;
|
using boost::container::static_vector;
|
||||||
using Shader::ImageBufferDescriptor;
|
using Shader::ImageBufferDescriptor;
|
||||||
using Shader::Backend::SPIRV::GLOBAL_POINTER_LAYOUT_OFFSET;
|
|
||||||
using Shader::Backend::SPIRV::RENDERAREA_LAYOUT_OFFSET;
|
using Shader::Backend::SPIRV::RENDERAREA_LAYOUT_OFFSET;
|
||||||
using Shader::Backend::SPIRV::RESCALING_LAYOUT_DOWN_FACTOR_OFFSET;
|
using Shader::Backend::SPIRV::RESCALING_LAYOUT_DOWN_FACTOR_OFFSET;
|
||||||
using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
|
using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
|
||||||
@@ -302,9 +301,6 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
num_image_elements += Shader::NumDescriptors(info->texture_descriptors);
|
num_image_elements += Shader::NumDescriptors(info->texture_descriptors);
|
||||||
num_image_elements += Shader::NumDescriptors(info->image_descriptors);
|
num_image_elements += Shader::NumDescriptors(info->image_descriptors);
|
||||||
num_descriptor_entries += NumDescriptorEntries(*info);
|
num_descriptor_entries += NumDescriptorEntries(*info);
|
||||||
uses_global_pointers |=
|
|
||||||
info->uses_global_pointers && device.IsBufferDeviceAddressSupported();
|
|
||||||
stores_global_pointers |= info->stores_global_memory;
|
|
||||||
}
|
}
|
||||||
fragment_has_color0_output = stage_infos[NUM_STAGES - 1].stores_frag_color[0];
|
fragment_has_color0_output = stage_infos[NUM_STAGES - 1].stores_frag_color[0];
|
||||||
|
|
||||||
@@ -540,7 +536,6 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_cache.RequestPointerTable(uses_global_pointers);
|
|
||||||
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
||||||
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
||||||
|
|
||||||
@@ -576,9 +571,6 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||||||
if constexpr (Spec::enabled_stages[4]) {
|
if constexpr (Spec::enabled_stages[4]) {
|
||||||
prepare_stage(4);
|
prepare_stage(4);
|
||||||
}
|
}
|
||||||
if (uses_global_pointers) {
|
|
||||||
pointer_table = buffer_cache.BindHostPointerTable(stores_global_pointers);
|
|
||||||
}
|
|
||||||
texture_cache.UpdateRenderTargets(false);
|
texture_cache.UpdateRenderTargets(false);
|
||||||
texture_cache.CheckFeedbackLoop(std::span<const VideoCommon::ImageViewInOut>{views.data(),
|
texture_cache.CheckFeedbackLoop(std::span<const VideoCommon::ImageViewInOut>{views.data(),
|
||||||
views.size()});
|
views.size()});
|
||||||
@@ -664,8 +656,7 @@ bool GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
|||||||
descriptor_buffer_offset, descriptor_buffer_chunk, bind_descriptor_buffer,
|
descriptor_buffer_offset, descriptor_buffer_chunk, bind_descriptor_buffer,
|
||||||
rescaling_data = rescaling.Data(), is_rescaling, update_rescaling,
|
rescaling_data = rescaling.Data(), is_rescaling, update_rescaling,
|
||||||
uses_render_area = render_area.uses_render_area,
|
uses_render_area = render_area.uses_render_area,
|
||||||
render_area_data = render_area.words,
|
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
|
||||||
table = pointer_table](vk::CommandBuffer cmdbuf) {
|
|
||||||
if (bind_descriptor_buffer) {
|
if (bind_descriptor_buffer) {
|
||||||
const VkDescriptorBufferBindingInfoEXT binding_info{
|
const VkDescriptorBufferBindingInfoEXT binding_info{
|
||||||
descriptor_buffer_ring.BindingInfo(descriptor_buffer_chunk)};
|
descriptor_buffer_ring.BindingInfo(descriptor_buffer_chunk)};
|
||||||
@@ -692,10 +683,6 @@ bool GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
|||||||
RENDERAREA_LAYOUT_OFFSET, sizeof(render_area_data),
|
RENDERAREA_LAYOUT_OFFSET, sizeof(render_area_data),
|
||||||
&render_area_data);
|
&render_area_data);
|
||||||
}
|
}
|
||||||
if (uses_global_pointers) {
|
|
||||||
cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_ALL_GRAPHICS,
|
|
||||||
GLOBAL_POINTER_LAYOUT_OFFSET, sizeof(table), table.data());
|
|
||||||
}
|
|
||||||
if (!descriptor_set_layout) {
|
if (!descriptor_set_layout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,9 +168,6 @@ private:
|
|||||||
size_t num_image_elements{};
|
size_t num_image_elements{};
|
||||||
u32 num_textures{};
|
u32 num_textures{};
|
||||||
bool fragment_has_color0_output{};
|
bool fragment_has_color0_output{};
|
||||||
bool uses_global_pointers{};
|
|
||||||
bool stores_global_pointers{};
|
|
||||||
std::array<u32, 3> pointer_table{};
|
|
||||||
|
|
||||||
vk::DescriptorSetLayout descriptor_set_layout;
|
vk::DescriptorSetLayout descriptor_set_layout;
|
||||||
DescriptorAllocator descriptor_allocator;
|
DescriptorAllocator descriptor_allocator;
|
||||||
|
|||||||
@@ -421,7 +421,6 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
.support_demote_to_helper_invocation =
|
.support_demote_to_helper_invocation =
|
||||||
device.IsExtShaderDemoteToHelperInvocationSupported(),
|
device.IsExtShaderDemoteToHelperInvocationSupported(),
|
||||||
.support_int64_atomics = device.IsExtShaderAtomicInt64Supported(),
|
.support_int64_atomics = device.IsExtShaderAtomicInt64Supported(),
|
||||||
.support_buffer_device_address = device.IsBufferDeviceAddressSupported(),
|
|
||||||
.support_shared_int64_atomics = device.IsSharedInt64AtomicsSupported(),
|
.support_shared_int64_atomics = device.IsSharedInt64AtomicsSupported(),
|
||||||
.support_derivative_control = true,
|
.support_derivative_control = true,
|
||||||
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
||||||
|
|||||||
Reference in New Issue
Block a user