Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,8 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
state->float16DenormPreserve = floatControls.shaderDenormPreserveFloat16 == VK_TRUE &&
floatControls.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
if (state->float16DenormPreserve && std::find(state->capabilities.begin(), state->capabilities.end(), static_cast<std::uint32_t>(spv::CapabilityDenormPreserve)) == state->capabilities.end()) state->capabilities.push_back(spv::CapabilityDenormPreserve);
static const bool nativeFloat32FlushToZero = std::getenv("APS5_NATIVE_F32_FTZ") != nullptr;
if (nativeFloat32FlushToZero && floatControls.shaderDenormFlushToZeroFloat32 == VK_TRUE && floatControls.denormBehaviorIndependence != VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE) state->capabilities.push_back(spv::CapabilityDenormFlushToZero);
deviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
deviceExtensions.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME);
state->capabilities.push_back(4448);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ Module Inspect(const CompiledShader& compiled, const State& state, const VkPhysi
capability == spv::CapabilityFloat16 ||
capability == spv::CapabilityRoundingModeRTE ||
capability == spv::CapabilityDenormPreserve ||
capability == spv::CapabilityDenormFlushToZero ||
capability == spv::CapabilityFloat64 ||
capability == spv::CapabilityStorageBuffer8BitAccess ||
capability == spv::CapabilityPhysicalStorageBufferAddresses ||
Expand Down Expand Up @@ -371,7 +372,7 @@ Module Inspect(const CompiledShader& compiled, const State& state, const VkPhysi
for (std::size_t i = 5; i < count; ++i) Require(module.interface.insert(instruction[i]).second, "duplicate SPIR-V interface ID");
break;
case spv::OpExecutionMode:
if (count == 4 && (instruction[2] == spv::ExecutionModeSignedZeroInfNanPreserve || instruction[2] == spv::ExecutionModeRoundingModeRTE || instruction[2] == spv::ExecutionModeDenormPreserve)) {
if (count == 4 && (instruction[2] == spv::ExecutionModeSignedZeroInfNanPreserve || instruction[2] == spv::ExecutionModeRoundingModeRTE || instruction[2] == spv::ExecutionModeDenormPreserve || instruction[2] == spv::ExecutionModeDenormFlushToZero)) {
Require(instruction[3] == 16u || instruction[3] == 32u || instruction[3] == 64u, "float controls execution modes require Float16, Float32 or Float64");
executionModeTargets.insert(instruction[1]);
break;
Expand Down
10 changes: 10 additions & 0 deletions core/shader/recompiler/Recompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ std::uint32_t ShaderPreparationContext::ResourcePrograms() const {
IrProgram PrepareResourceProgram(const RecompileRequest& request) {
return PrepareResourceProgram(request, nullptr);
}
bool nativeFloat32FlushToZero(const RecompileRequest& request) {
const auto& capabilities = request.target.supportedCapabilities;
if (std::ranges::find(capabilities, static_cast<std::uint32_t>(spv::CapabilityDenormFlushToZero)) == capabilities.end()) return false;
static const bool pixelOnly = std::getenv("APS5_NATIVE_F32_FTZ_PIXEL_ONLY") != nullptr;
if (pixelOnly && request.shader.stage != ShaderStage::Fragment) return false;
return !request.context.floatMode.has_value() || ((request.context.floatMode->floatMode >> 4u) & 3u) == 0u;
}


IrProgram PrepareResourceProgram(const RecompileRequest& request, ShaderPreparationContext* preparation) {
frontEndBuilds.fetch_add(1, std::memory_order_relaxed);
Expand All @@ -210,6 +218,7 @@ IrProgram PrepareResourceProgram(const RecompileRequest& request, ShaderPreparat
const auto supports = [&](spv::Capability capability) { return std::ranges::find(request.target.supportedCapabilities, static_cast<std::uint32_t>(capability)) != request.target.supportedCapabilities.end(); };
translateOptions.nativeFloat16 = supports(spv::CapabilityFloat16) && supports(spv::CapabilityRoundingModeRTE) && supports(spv::CapabilityDenormPreserve);
translateOptions.floatMode = request.context.floatMode;
translateOptions.nativeFloat32FlushToZero = nativeFloat32FlushToZero(request);
translateOptions.inputInfo = inputInfo;

constexpr InstructionTranslator translator;
Expand Down Expand Up @@ -531,6 +540,7 @@ CompiledVariant emitVariant(const RecompileRequest& request, IrProgram& program)
targetOptions.fragmentDescriptorSet = request.target.registrationModules;
targetOptions.float16DenormPreserve = request.target.float16DenormPreserve;
targetOptions.spannedWaves = request.target.spannedWaves;
targetOptions.float32FlushToZero = nativeFloat32FlushToZero(request);

constexpr SpirvEmitter spirvEmitter;
CompiledShaderArtifact result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct SpirvTargetOptions {
bool nonConstantImageOffsets = false;
bool narrowSubgroupClock = false;
bool float64DenormPreserve = false;
bool float32FlushToZero = false;
bool registrationModules = false;
bool fragmentDescriptorSet = false;
bool float16DenormPreserve = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ struct SpirvEmitterState {
std::uint32_t spannedExchangeVariable = 0;
bool narrowSubgroupClock = false;
bool float64DenormPreserve = false;
bool float32FlushToZero = false;
bool registrationModules = false;
bool fragmentDescriptorSet = false;
bool float16DenormPreserve = false;
Expand Down
1 change: 1 addition & 0 deletions core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ std::vector<std::uint32_t> SpirvEmitter::Emit(const IrProgram& program, const Sh
state.nonConstantImageOffsets = target.nonConstantImageOffsets;
state.narrowSubgroupClock = target.narrowSubgroupClock;
state.float64DenormPreserve = target.float64DenormPreserve;
state.float32FlushToZero = target.float32FlushToZero;
state.registrationModules = target.registrationModules;
state.fragmentDescriptorSet = target.fragmentDescriptorSet;
state.float16DenormPreserve = target.float16DenormPreserve;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ void DefineModule(SpirvEmitterState& state) {
state.module.EmitCapability(spv::CapabilitySignedZeroInfNanPreserve);
state.module.EmitExtension("SPV_KHR_float_controls");
state.module.AddExecutionMode(state.mainFunc, spv::ExecutionModeSignedZeroInfNanPreserve, 32u);
if (state.float32FlushToZero) {
state.module.EmitCapability(spv::CapabilityDenormFlushToZero);
state.module.AddExecutionMode(state.mainFunc, spv::ExecutionModeDenormFlushToZero, 32u);
}
if (state.requirements.float64) {
if (std::find(state.supportedCapabilities.begin(), state.supportedCapabilities.end(), static_cast<std::uint32_t>(spv::CapabilityFloat64)) == state.supportedCapabilities.end()) {
throw std::runtime_error("64-bit float instructions need the Float64 capability, which the device lacks");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct TranslateOptions {
std::uint64_t shaderHash = 0;
bool fragmentShaderBarycentricEnabled = false;
bool nativeFloat16 = false;
bool nativeFloat32FlushToZero = false;
std::optional<ShaderFloatMode> floatMode;
ShaderStageInputInfo inputInfo;
const EmbeddedFetchPlan* embeddedFetch = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class TranslationContext {
}
void SetEntryRounding(const RoundingState& state) { setRounding(state); }
void SetNativeFloat16(bool enabled) { nativeFloat16 = enabled; }
void SetNativeFloat32FlushToZero(bool enabled) { nativeFloat32FlushToZero = enabled; }
void AddBranchCondition(const BasicBlock& source, BlockInfo& info);
void TranslateCodeTableLoad(const RdnaInstruction& instruction, const ControlFlowGraph::CodeTableLoad& table);
void TranslateUnlinkedCall(const RdnaInstruction& instruction);
Expand Down Expand Up @@ -369,6 +370,7 @@ class TranslationContext {
RoundingState rounding;
bool ieeeMode = false;
bool nativeFloat16 = false;
bool nativeFloat32FlushToZero = false;
IrBuilder ir;
IrBlock& block;
IrU1 instructionBranchCondition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ IrProgram InstructionTranslator::Translate(const RdnaProgram& decoded, const Con
context.SetPixelInput(options.inputInfo.pixel, options.fragmentShaderBarycentricEnabled);
context.SetFloatMode(options.floatMode);
context.SetNativeFloat16(options.nativeFloat16);
context.SetNativeFloat32FlushToZero(options.nativeFloat32FlushToZero);
context.SetEntryRounding(entryRounding.at(cfgBlock.id));
for (std::uint32_t index = cfgBlock.instructionBegin; index < cfgBlock.instructionEnd; index++) {
const auto& instruction = decoded.instructions[index];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ std::uint32_t TranslationContext::f32DenormalFlushFor(const RdnaInstruction& ins
if (denormals == 1u || denormals == 2u) {
throw std::runtime_error("f32 denormal mode " + std::to_string(denormals) + " at pc " + std::to_string(inst.programCounter) + " is not implemented");
}
if (denormals == 0u && nativeFloat32FlushToZero) return 0u;
return denormals == 0u ? flush : 0u;
}

Expand Down
Loading