mirror of
https://git.eden-emu.dev/archive/citron
synced 2026-03-23 01:56:08 -04:00
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:
@@ -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,
|
void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std::string_view expr,
|
||||||
std::string_view else_expr = {}) {
|
std::string_view else_expr = {}) {
|
||||||
const size_t num_buffers{ctx.info.storage_buffers_descriptors.size()};
|
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) {
|
for (size_t index = 0; index < num_buffers; ++index) {
|
||||||
if (!ctx.info.nvn_buffer_used[index]) {
|
if (!ctx.info.nvn_buffer_used[index]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
++buffers_processed;
|
||||||
const auto& ssbo{ctx.info.storage_buffers_descriptors[index]};
|
const auto& ssbo{ctx.info.storage_buffers_descriptors[index]};
|
||||||
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
|
||||||
@@ -65,8 +67,7 @@ void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std
|
|||||||
if (!else_expr.empty()) {
|
if (!else_expr.empty()) {
|
||||||
ctx.Add("{}", else_expr);
|
ctx.Add("{}", else_expr);
|
||||||
}
|
}
|
||||||
const size_t num_used_buffers{ctx.info.nvn_buffer_used.count()};
|
for (size_t index = 0; index < buffers_processed; ++index) {
|
||||||
for (size_t index = 0; index < num_used_buffers; ++index) {
|
|
||||||
ctx.Add("ENDIF;");
|
ctx.Add("ENDIF;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ void AddNVNStorageBuffers(IR::Program& program) {
|
|||||||
throw InvalidArgument("Invalid stage {}", program.stage);
|
throw InvalidArgument("Invalid stage {}", program.stage);
|
||||||
}()};
|
}()};
|
||||||
auto& descs{program.info.storage_buffers_descriptors};
|
auto& descs{program.info.storage_buffers_descriptors};
|
||||||
|
|
||||||
for (u32 index = 0; index < num_buffers; ++index) {
|
for (u32 index = 0; index < num_buffers; ++index) {
|
||||||
if (!program.info.nvn_buffer_used[index]) {
|
if (!program.info.nvn_buffer_used[index]) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -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) {
|
void GlobalMemoryToStorageBufferPass(IR::Program& program, const HostTranslateInfo& host_info) {
|
||||||
StorageInfo info;
|
StorageInfo info;
|
||||||
|
size_t total_global_memory_insts{0};
|
||||||
for (IR::Block* const block : program.post_order_blocks) {
|
for (IR::Block* const block : program.post_order_blocks) {
|
||||||
for (IR::Inst& inst : block->Instructions()) {
|
for (IR::Inst& inst : block->Instructions()) {
|
||||||
if (!IsGlobalMemory(inst)) {
|
if (!IsGlobalMemory(inst)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
++total_global_memory_insts;
|
||||||
CollectStorageBuffers(*block, inst, info);
|
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) {
|
for (const StorageBufferAddr& storage_buffer : info.set) {
|
||||||
program.info.storage_buffers_descriptors.push_back({
|
program.info.storage_buffers_descriptors.push_back({
|
||||||
.cbuf_index = storage_buffer.index,
|
.cbuf_index = storage_buffer.index,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ struct Profile {
|
|||||||
bool support_int64_atomics{};
|
bool support_int64_atomics{};
|
||||||
bool support_derivative_control{};
|
bool support_derivative_control{};
|
||||||
bool support_geometry_shader_passthrough{};
|
bool support_geometry_shader_passthrough{};
|
||||||
|
bool support_buffer_device_address{};
|
||||||
bool support_native_ndc{};
|
bool support_native_ndc{};
|
||||||
bool support_gl_nv_gpu_shader_5{};
|
bool support_gl_nv_gpu_shader_5{};
|
||||||
bool support_gl_amd_gpu_shader_half_float{};
|
bool support_gl_amd_gpu_shader_half_float{};
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ 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 global_memory_tracking_failed{}; // True when some global memory ops couldn't be tracked
|
||||||
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{};
|
||||||
|
|||||||
Reference in New Issue
Block a user