|
|
|
@ -338,55 +338,73 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { |
|
|
|
ctx.AddEntryPoint(execution_model, main, "main", interfaces); |
|
|
|
} |
|
|
|
|
|
|
|
void SetupDenormControl(const Profile& profile, const IR::Program& program, EmitContext& ctx, |
|
|
|
Id main_func) { |
|
|
|
const Info& info{program.info}; |
|
|
|
if (info.uses_fp32_denorms_flush && info.uses_fp32_denorms_preserve) { |
|
|
|
LOG_DEBUG(Shader_SPIRV, "Fp32 denorm flush and preserve on the same shader"); |
|
|
|
} else if (info.uses_fp32_denorms_flush) { |
|
|
|
void SetupDenormControl(const Profile& profile, IR::Program const& program, EmitContext& ctx, Id main_func) { |
|
|
|
Info const& info = program.info; |
|
|
|
switch (info.fp32_denorm) { |
|
|
|
case Shader::FloatDenormKind::None: |
|
|
|
default: |
|
|
|
break; |
|
|
|
case Shader::FloatDenormKind::DenormFlushToZero: |
|
|
|
if (profile.support_fp32_denorm_flush) { |
|
|
|
ctx.AddCapability(spv::Capability::DenormFlushToZero); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 32U); |
|
|
|
} else if(!profile.uses_ftz_as_default) { |
|
|
|
LOG_WARNING(Shader_SPIRV, "f32.ftz requested but not supported"); |
|
|
|
} |
|
|
|
break; |
|
|
|
case Shader::FloatDenormKind::RoundingModeRTE: |
|
|
|
if (profile.support_fp32_round_rte) { |
|
|
|
ctx.AddCapability(spv::Capability::RoundingModeRTE); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::RoundingModeRTE, 32U); |
|
|
|
} else { |
|
|
|
// Drivers will most likely flush denorms by default, no need to warn
|
|
|
|
LOG_WARNING(Shader_SPIRV, "f32.rte requested but not supported"); |
|
|
|
} |
|
|
|
} else if (info.uses_fp32_denorms_preserve) { |
|
|
|
break; |
|
|
|
case Shader::FloatDenormKind::DenormPreserve: |
|
|
|
if (profile.support_fp32_denorm_preserve) { |
|
|
|
ctx.AddCapability(spv::Capability::DenormPreserve); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 32U); |
|
|
|
} else { |
|
|
|
LOG_DEBUG(Shader_SPIRV, "Fp32 denorm preserve used in shader without host support"); |
|
|
|
LOG_WARNING(Shader_SPIRV, "f32.pre requested but not supported"); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
if (!profile.support_separate_denorm_behavior || profile.has_broken_fp16_float_controls) { |
|
|
|
// No separate denorm behavior
|
|
|
|
return; |
|
|
|
} |
|
|
|
if (info.uses_fp16_denorms_flush && info.uses_fp16_denorms_preserve) { |
|
|
|
LOG_DEBUG(Shader_SPIRV, "Fp16 denorm flush and preserve on the same shader"); |
|
|
|
} else if (info.uses_fp16_denorms_flush) { |
|
|
|
if (profile.support_fp16_denorm_flush) { |
|
|
|
|
|
|
|
// No separate denorm behavior
|
|
|
|
bool can_fp16 = !(!profile.support_separate_denorm_behavior || profile.has_broken_fp16_float_controls); |
|
|
|
switch (info.fp16_denorm) { |
|
|
|
case Shader::FloatDenormKind::None: |
|
|
|
default: |
|
|
|
break; |
|
|
|
case Shader::FloatDenormKind::DenormFlushToZero: |
|
|
|
if (can_fp16 && profile.support_fp16_denorm_flush) { |
|
|
|
ctx.AddCapability(spv::Capability::DenormFlushToZero); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 16U); |
|
|
|
} else if(!profile.uses_ftz_as_default) { |
|
|
|
LOG_WARNING(Shader_SPIRV, "f16.ftz requested but not supported"); |
|
|
|
} |
|
|
|
break; |
|
|
|
case Shader::FloatDenormKind::RoundingModeRTE: |
|
|
|
if (can_fp16 && profile.support_fp16_round_rte) { |
|
|
|
ctx.AddCapability(spv::Capability::RoundingModeRTE); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::RoundingModeRTE, 16U); |
|
|
|
} else { |
|
|
|
// Same as fp32, no need to warn as most drivers will flush by default
|
|
|
|
LOG_WARNING(Shader_SPIRV, "f16.rte requested but not supported"); |
|
|
|
} |
|
|
|
} else if (info.uses_fp16_denorms_preserve) { |
|
|
|
if (profile.support_fp16_denorm_preserve) { |
|
|
|
break; |
|
|
|
case Shader::FloatDenormKind::DenormPreserve: |
|
|
|
if (can_fp16 && profile.support_fp16_denorm_preserve) { |
|
|
|
ctx.AddCapability(spv::Capability::DenormPreserve); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); |
|
|
|
} else { |
|
|
|
LOG_DEBUG(Shader_SPIRV, "Fp16 denorm preserve used in shader without host support"); |
|
|
|
LOG_WARNING(Shader_SPIRV, "f16.pre requested but not supported"); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void SetupSignedNanCapabilities(const Profile& profile, const IR::Program& program, |
|
|
|
EmitContext& ctx, Id main_func) { |
|
|
|
if (profile.has_broken_fp16_float_controls && program.info.uses_fp16) { |
|
|
|
return; |
|
|
|
} |
|
|
|
if (program.info.uses_fp16 && profile.support_fp16_signed_zero_nan_preserve) { |
|
|
|
void SetupSignedNanCapabilities(const Profile& profile, const IR::Program& program, EmitContext& ctx, Id main_func) { |
|
|
|
if (!profile.has_broken_fp16_float_controls && program.info.uses_fp16 && profile.support_fp16_signed_zero_nan_preserve) { |
|
|
|
ctx.AddCapability(spv::Capability::SignedZeroInfNanPreserve); |
|
|
|
ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 16U); |
|
|
|
} |
|
|
|
|