feat(shader): add buffer device address support to shader profile

- Add support_buffer_device_address flag to shader Profile

- Add global_memory_tracking_failed flag to shader Info

- Track global memory instruction coverage in optimization pass

- Prepare infrastructure for global memory emulation via BDA
This commit is contained in:
Zephyron
2026-01-21 18:53:59 +10:00
parent 7af18a2aa8
commit 89a45a327f
5 changed files with 18 additions and 2 deletions

View File

@@ -31,10 +31,12 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset,
void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std::string_view expr,
std::string_view else_expr = {}) {
const size_t num_buffers{ctx.info.storage_buffers_descriptors.size()};
size_t buffers_processed{0};
for (size_t index = 0; index < num_buffers; ++index) {
if (!ctx.info.nvn_buffer_used[index]) {
continue;
}
++buffers_processed;
const auto& ssbo{ctx.info.storage_buffers_descriptors[index]};
const u64 ssbo_align_mask{~(ctx.profile.min_ssbo_alignment - 1U)};
ctx.Add("LDC.U64 DC.x,c{}[{}];" // unaligned_ssbo_addr
@@ -65,8 +67,7 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std
if (!else_expr.empty()) {
ctx.Add("{}", else_expr);
}
const size_t num_used_buffers{ctx.info.nvn_buffer_used.count()};
for (size_t index = 0; index < num_used_buffers; ++index) {
for (size_t index = 0; index < buffers_processed; ++index) {
ctx.Add("ENDIF;");
}
}

View File

@@ -110,6 +110,7 @@ void AddNVNStorageBuffers(IR::Program& program) {
throw InvalidArgument("Invalid stage {}", program.stage);
}()};
auto& descs{program.info.storage_buffers_descriptors};
for (u32 index = 0; index < num_buffers; ++index) {
if (!program.info.nvn_buffer_used[index]) {
continue;

View File

@@ -522,14 +522,26 @@ void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateInfo& host_info) {
StorageInfo info;
size_t total_global_memory_insts{0};
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (!IsGlobalMemory(inst)) {
continue;
}
++total_global_memory_insts;
CollectStorageBuffers(*block, inst, info);
}
}
// Log if some global memory instructions couldn't be tracked
// NOTE: Previously tried enabling all NVN buffers as fallback when tracking failed,
// but this caused crashes due to shader code accessing potentially invalid buffers.
// Now we just log a warning - untracked global memory ops will use default behavior.
const size_t tracked_insts{info.to_replace.size()};
if (total_global_memory_insts > 0 && tracked_insts < total_global_memory_insts) {
LOG_WARNING(Shader, "Global memory tracking: {} of {} instructions tracked. "
"Untracked ops may cause rendering issues.",
tracked_insts, total_global_memory_insts);
}
for (const StorageBufferAddr& storage_buffer : info.set) {
program.info.storage_buffers_descriptors.push_back({
.cbuf_index = storage_buffer.index,

View File

@@ -34,6 +34,7 @@ struct Profile {
bool support_int64_atomics{};
bool support_derivative_control{};
bool support_geometry_shader_passthrough{};
bool support_buffer_device_address{};
bool support_native_ndc{};
bool support_gl_nv_gpu_shader_5{};
bool support_gl_amd_gpu_shader_half_float{};

View File

@@ -313,6 +313,7 @@ struct Info {
bool uses_atomic_s32_max{};
bool uses_int64_bit_atomics{};
bool uses_global_memory{};
bool global_memory_tracking_failed{}; // True when some global memory ops couldn't be tracked
bool uses_atomic_image_u32{};
bool uses_shadow_lod{};
bool uses_rescaling_uniform{};