shader: Add denorm flush support
This commit is contained in:
parent
6db69990da
commit
e2bc05b17d
20 changed files with 260 additions and 93 deletions
|
@ -14,8 +14,6 @@
|
|||
#include "shader_recompiler/frontend/ir/microinstruction.h"
|
||||
#include "shader_recompiler/frontend/ir/program.h"
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
namespace Shader::Backend::SPIRV {
|
||||
namespace {
|
||||
template <class Func>
|
||||
|
@ -113,9 +111,61 @@ Id TypeId(const EmitContext& ctx, IR::Type type) {
|
|||
throw NotImplementedException("Phi node type {}", type);
|
||||
}
|
||||
}
|
||||
|
||||
void SetupDenormControl(const Profile& profile, const IR::Program& program, EmitContext& ctx,
|
||||
Id main_func) {
|
||||
if (!profile.support_float_controls) {
|
||||
return;
|
||||
}
|
||||
const Info& info{program.info};
|
||||
if (!info.uses_fp32_denorms_flush && !info.uses_fp32_denorms_preserve &&
|
||||
!info.uses_fp16_denorms_flush && !info.uses_fp16_denorms_preserve) {
|
||||
return;
|
||||
}
|
||||
ctx.AddExtension("SPV_KHR_float_controls");
|
||||
|
||||
if (info.uses_fp32_denorms_flush && info.uses_fp32_denorms_preserve) {
|
||||
// LOG_ERROR(HW_GPU, "Fp32 denorm flush and preserve on the same shader");
|
||||
} else if (info.uses_fp32_denorms_flush) {
|
||||
if (profile.support_fp32_denorm_flush) {
|
||||
ctx.AddCapability(spv::Capability::DenormFlushToZero);
|
||||
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 32U);
|
||||
} else {
|
||||
// Drivers will most likely flush denorms by default, no need to warn
|
||||
}
|
||||
} else if (info.uses_fp32_denorms_preserve) {
|
||||
if (profile.support_fp32_denorm_preserve) {
|
||||
ctx.AddCapability(spv::Capability::DenormPreserve);
|
||||
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 32U);
|
||||
} else {
|
||||
// LOG_WARNING(HW_GPU, "Fp32 denorm preserve used in shader without host support");
|
||||
}
|
||||
}
|
||||
if (!profile.support_separate_denorm_behavior) {
|
||||
// No separate denorm behavior
|
||||
return;
|
||||
}
|
||||
if (info.uses_fp16_denorms_flush && info.uses_fp16_denorms_preserve) {
|
||||
// LOG_ERROR(HW_GPU, "Fp16 denorm flush and preserve on the same shader");
|
||||
} else if (info.uses_fp16_denorms_flush) {
|
||||
if (profile.support_fp16_denorm_flush) {
|
||||
ctx.AddCapability(spv::Capability::DenormFlushToZero);
|
||||
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U);
|
||||
} else {
|
||||
// Same as fp32, no need to warn as most drivers will flush by default
|
||||
}
|
||||
} else if (info.uses_fp32_denorms_preserve) {
|
||||
if (profile.support_fp16_denorm_preserve) {
|
||||
ctx.AddCapability(spv::Capability::DenormPreserve);
|
||||
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U);
|
||||
} else {
|
||||
// LOG_WARNING(HW_GPU, "Fp16 denorm preserve used in shader without host support");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) {
|
||||
std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) {
|
||||
EmitContext ctx{program};
|
||||
const Id void_function{ctx.TypeFunction(ctx.void_id)};
|
||||
// FIXME: Forward declare functions (needs sirit support)
|
||||
|
@ -131,10 +181,11 @@ std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) {
|
|||
ctx.OpFunctionEnd();
|
||||
}
|
||||
boost::container::small_vector<Id, 32> interfaces;
|
||||
if (program.info.uses_workgroup_id) {
|
||||
const Info& info{program.info};
|
||||
if (info.uses_workgroup_id) {
|
||||
interfaces.push_back(ctx.workgroup_id);
|
||||
}
|
||||
if (program.info.uses_local_invocation_id) {
|
||||
if (info.uses_local_invocation_id) {
|
||||
interfaces.push_back(ctx.local_invocation_id);
|
||||
}
|
||||
const std::span interfaces_span(interfaces.data(), interfaces.size());
|
||||
|
@ -144,6 +195,8 @@ std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) {
|
|||
ctx.AddExecutionMode(func, spv::ExecutionMode::LocalSize, workgroup_size[0], workgroup_size[1],
|
||||
workgroup_size[2]);
|
||||
|
||||
SetupDenormControl(profile, program, ctx, func);
|
||||
|
||||
return ctx.Assemble();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue