Merge pull request #10699 from liamwhite/conditional-barrier
shader_recompiler: remove barriers in conditional control flow when device lacks support
This commit is contained in:
commit
42b2bc204f
|
@ -216,6 +216,7 @@ add_library(shader_recompiler STATIC
|
||||||
frontend/maxwell/translate_program.h
|
frontend/maxwell/translate_program.h
|
||||||
host_translate_info.h
|
host_translate_info.h
|
||||||
ir_opt/collect_shader_info_pass.cpp
|
ir_opt/collect_shader_info_pass.cpp
|
||||||
|
ir_opt/conditional_barrier_pass.cpp
|
||||||
ir_opt/constant_propagation_pass.cpp
|
ir_opt/constant_propagation_pass.cpp
|
||||||
ir_opt/dead_code_elimination_pass.cpp
|
ir_opt/dead_code_elimination_pass.cpp
|
||||||
ir_opt/dual_vertex_pass.cpp
|
ir_opt/dual_vertex_pass.cpp
|
||||||
|
|
|
@ -289,6 +289,9 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
|
||||||
if (!host_info.support_int64) {
|
if (!host_info.support_int64) {
|
||||||
Optimization::LowerInt64ToInt32(program);
|
Optimization::LowerInt64ToInt32(program);
|
||||||
}
|
}
|
||||||
|
if (!host_info.support_conditional_barrier) {
|
||||||
|
Optimization::ConditionalBarrierPass(program);
|
||||||
|
}
|
||||||
Optimization::SsaRewritePass(program);
|
Optimization::SsaRewritePass(program);
|
||||||
|
|
||||||
Optimization::ConstantPropagationPass(env, program);
|
Optimization::ConstantPropagationPass(env, program);
|
||||||
|
|
|
@ -18,6 +18,8 @@ struct HostTranslateInfo {
|
||||||
bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS
|
bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS
|
||||||
bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry
|
bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry
|
||||||
///< passthrough shaders
|
///< passthrough shaders
|
||||||
|
bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional
|
||||||
|
///< control flow
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Shader
|
} // namespace Shader
|
||||||
|
|
44
src/shader_recompiler/ir_opt/conditional_barrier_pass.cpp
Normal file
44
src/shader_recompiler/ir_opt/conditional_barrier_pass.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "shader_recompiler/frontend/ir/program.h"
|
||||||
|
#include "shader_recompiler/ir_opt/passes.h"
|
||||||
|
|
||||||
|
namespace Shader::Optimization {
|
||||||
|
|
||||||
|
void ConditionalBarrierPass(IR::Program& program) {
|
||||||
|
s32 conditional_control_flow_count{0};
|
||||||
|
s32 conditional_return_count{0};
|
||||||
|
for (IR::AbstractSyntaxNode& node : program.syntax_list) {
|
||||||
|
switch (node.type) {
|
||||||
|
case IR::AbstractSyntaxNode::Type::If:
|
||||||
|
case IR::AbstractSyntaxNode::Type::Loop:
|
||||||
|
conditional_control_flow_count++;
|
||||||
|
break;
|
||||||
|
case IR::AbstractSyntaxNode::Type::EndIf:
|
||||||
|
case IR::AbstractSyntaxNode::Type::Repeat:
|
||||||
|
conditional_control_flow_count--;
|
||||||
|
break;
|
||||||
|
case IR::AbstractSyntaxNode::Type::Unreachable:
|
||||||
|
case IR::AbstractSyntaxNode::Type::Return:
|
||||||
|
if (conditional_control_flow_count > 0) {
|
||||||
|
conditional_return_count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IR::AbstractSyntaxNode::Type::Block:
|
||||||
|
for (IR::Inst& inst : node.data.block->Instructions()) {
|
||||||
|
if ((conditional_control_flow_count > 0 || conditional_return_count > 0) &&
|
||||||
|
inst.GetOpcode() == IR::Opcode::Barrier) {
|
||||||
|
LOG_WARNING(Shader, "Barrier within conditional control flow");
|
||||||
|
inst.ReplaceOpcode(IR::Opcode::Identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(conditional_control_flow_count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Shader::Optimization
|
|
@ -13,6 +13,7 @@ struct HostTranslateInfo;
|
||||||
namespace Shader::Optimization {
|
namespace Shader::Optimization {
|
||||||
|
|
||||||
void CollectShaderInfoPass(Environment& env, IR::Program& program);
|
void CollectShaderInfoPass(Environment& env, IR::Program& program);
|
||||||
|
void ConditionalBarrierPass(IR::Program& program);
|
||||||
void ConstantPropagationPass(Environment& env, IR::Program& program);
|
void ConstantPropagationPass(Environment& env, IR::Program& program);
|
||||||
void DeadCodeEliminationPass(IR::Program& program);
|
void DeadCodeEliminationPass(IR::Program& program);
|
||||||
void GlobalMemoryToStorageBufferPass(IR::Program& program);
|
void GlobalMemoryToStorageBufferPass(IR::Program& program);
|
||||||
|
|
|
@ -201,6 +201,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
|
||||||
use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() &&
|
use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() &&
|
||||||
!(is_amd || (is_intel && !is_linux)) && !strict_context_required;
|
!(is_amd || (is_intel && !is_linux)) && !strict_context_required;
|
||||||
use_driver_cache = is_nvidia;
|
use_driver_cache = is_nvidia;
|
||||||
|
supports_conditional_barriers = !is_intel;
|
||||||
|
|
||||||
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
|
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
|
||||||
LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
|
LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
|
||||||
|
|
|
@ -188,6 +188,10 @@ public:
|
||||||
return strict_context_required;
|
return strict_context_required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SupportsConditionalBarriers() const {
|
||||||
|
return supports_conditional_barriers;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool TestVariableAoffi();
|
static bool TestVariableAoffi();
|
||||||
static bool TestPreciseBug();
|
static bool TestPreciseBug();
|
||||||
|
@ -233,6 +237,7 @@ private:
|
||||||
bool has_bool_ref_bug{};
|
bool has_bool_ref_bug{};
|
||||||
bool can_report_memory{};
|
bool can_report_memory{};
|
||||||
bool strict_context_required{};
|
bool strict_context_required{};
|
||||||
|
bool supports_conditional_barriers{};
|
||||||
|
|
||||||
std::string vendor_name;
|
std::string vendor_name;
|
||||||
};
|
};
|
||||||
|
|
|
@ -239,6 +239,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
|
||||||
.support_snorm_render_buffer = false,
|
.support_snorm_render_buffer = false,
|
||||||
.support_viewport_index_layer = device.HasVertexViewportLayer(),
|
.support_viewport_index_layer = device.HasVertexViewportLayer(),
|
||||||
.support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(),
|
.support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(),
|
||||||
|
.support_conditional_barrier = device.SupportsConditionalBarriers(),
|
||||||
} {
|
} {
|
||||||
if (use_asynchronous_shaders) {
|
if (use_asynchronous_shaders) {
|
||||||
workers = CreateWorkers();
|
workers = CreateWorkers();
|
||||||
|
|
|
@ -386,6 +386,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT,
|
IsFormatSupported(VK_FORMAT_D24_UNORM_S8_UINT,
|
||||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, FormatType::Optimal);
|
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, FormatType::Optimal);
|
||||||
|
|
||||||
|
supports_conditional_barriers = !(is_intel_anv || is_intel_windows);
|
||||||
|
|
||||||
CollectPhysicalMemoryInfo();
|
CollectPhysicalMemoryInfo();
|
||||||
CollectToolingInfo();
|
CollectToolingInfo();
|
||||||
|
|
||||||
|
|
|
@ -585,6 +585,10 @@ public:
|
||||||
return properties.properties.limits.maxVertexInputBindings;
|
return properties.properties.limits.maxVertexInputBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SupportsConditionalBarriers() const {
|
||||||
|
return supports_conditional_barriers;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Checks if the physical device is suitable and configures the object state
|
/// Checks if the physical device is suitable and configures the object state
|
||||||
/// with all necessary info about its properties.
|
/// with all necessary info about its properties.
|
||||||
|
@ -688,6 +692,7 @@ private:
|
||||||
bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format.
|
bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format.
|
||||||
bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3.
|
bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3.
|
||||||
bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3.
|
bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3.
|
||||||
|
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
|
||||||
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
|
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
|
||||||
u32 sets_per_pool{}; ///< Sets per Description Pool
|
u32 sets_per_pool{}; ///< Sets per Description Pool
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue