spirv: Fixes and Intel specific workarounds
This commit is contained in:
		| @@ -25,7 +25,8 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie | ||||
|     } | ||||
| } | ||||
|  | ||||
| EmitContext::EmitContext(IR::Program& program) : Sirit::Module(0x00010000) { | ||||
| EmitContext::EmitContext(const Profile& profile_, IR::Program& program) | ||||
|     : Sirit::Module(0x00010000), profile{profile_} { | ||||
|     AddCapability(spv::Capability::Shader); | ||||
|     DefineCommonTypes(program.info); | ||||
|     DefineCommonConstants(); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  | ||||
| #include "shader_recompiler/frontend/ir/program.h" | ||||
| #include "shader_recompiler/shader_info.h" | ||||
| #include "shader_recompiler/profile.h" | ||||
|  | ||||
| namespace Shader::Backend::SPIRV { | ||||
|  | ||||
| @@ -30,11 +31,13 @@ private: | ||||
|  | ||||
| class EmitContext final : public Sirit::Module { | ||||
| public: | ||||
|     explicit EmitContext(IR::Program& program); | ||||
|     explicit EmitContext(const Profile& profile, IR::Program& program); | ||||
|     ~EmitContext(); | ||||
|  | ||||
|     [[nodiscard]] Id Def(const IR::Value& value); | ||||
|  | ||||
|     const Profile& profile; | ||||
|  | ||||
|     Id void_id{}; | ||||
|     Id U1{}; | ||||
|     Id U16{}; | ||||
|   | ||||
| @@ -150,11 +150,11 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit | ||||
|     } 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); | ||||
|             ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 16U); | ||||
|         } else { | ||||
|             // Same as fp32, no need to warn as most drivers will flush by default | ||||
|         } | ||||
|     } else if (info.uses_fp32_denorms_preserve) { | ||||
|     } else if (info.uses_fp16_denorms_preserve) { | ||||
|         if (profile.support_fp16_denorm_preserve) { | ||||
|             ctx.AddCapability(spv::Capability::DenormPreserve); | ||||
|             ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); | ||||
| @@ -166,7 +166,7 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit | ||||
| } // Anonymous namespace | ||||
|  | ||||
| std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) { | ||||
|     EmitContext ctx{program}; | ||||
|     EmitContext ctx{profile, program}; | ||||
|     const Id void_function{ctx.TypeFunction(ctx.void_id)}; | ||||
|     // FIXME: Forward declare functions (needs sirit support) | ||||
|     Id func{}; | ||||
|   | ||||
| @@ -202,10 +202,10 @@ Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs); | ||||
| Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs); | ||||
| Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | ||||
| Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | ||||
| void EmitLogicalOr(EmitContext& ctx); | ||||
| void EmitLogicalAnd(EmitContext& ctx); | ||||
| void EmitLogicalXor(EmitContext& ctx); | ||||
| void EmitLogicalNot(EmitContext& ctx); | ||||
| Id EmitLogicalOr(EmitContext& ctx, Id a, Id b); | ||||
| Id EmitLogicalAnd(EmitContext& ctx, Id a, Id b); | ||||
| Id EmitLogicalXor(EmitContext& ctx, Id a, Id b); | ||||
| Id EmitLogicalNot(EmitContext& ctx, Id value); | ||||
| Id EmitConvertS16F16(EmitContext& ctx, Id value); | ||||
| Id EmitConvertS16F32(EmitContext& ctx, Id value); | ||||
| Id EmitConvertS16F64(EmitContext& ctx, Id value); | ||||
|   | ||||
| @@ -15,6 +15,13 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) { | ||||
|     return op; | ||||
| } | ||||
|  | ||||
| Id Saturate(EmitContext& ctx, Id type, Id value, Id zero, Id one) { | ||||
|     if (ctx.profile.has_broken_spirv_clamp) { | ||||
|         return ctx.OpFMin(type, ctx.OpFMax(type, value, zero), one); | ||||
|     } else { | ||||
|         return ctx.OpFClamp(type, value, zero, one); | ||||
|     } | ||||
| } | ||||
| } // Anonymous namespace | ||||
|  | ||||
| Id EmitFPAbs16(EmitContext& ctx, Id value) { | ||||
| @@ -144,19 +151,19 @@ void EmitFPLog2(EmitContext&) { | ||||
| Id EmitFPSaturate16(EmitContext& ctx, Id value) { | ||||
|     const Id zero{ctx.Constant(ctx.F16[1], u16{0})}; | ||||
|     const Id one{ctx.Constant(ctx.F16[1], u16{0x3c00})}; | ||||
|     return ctx.OpFClamp(ctx.F32[1], value, zero, one); | ||||
|     return Saturate(ctx, ctx.F16[1], value, zero, one); | ||||
| } | ||||
|  | ||||
| Id EmitFPSaturate32(EmitContext& ctx, Id value) { | ||||
|     const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})}; | ||||
|     const Id one{ctx.Constant(ctx.F32[1], f32{1.0})}; | ||||
|     return ctx.OpFClamp(ctx.F32[1], value, zero, one); | ||||
|     return Saturate(ctx, ctx.F32[1], value, zero, one); | ||||
| } | ||||
|  | ||||
| Id EmitFPSaturate64(EmitContext& ctx, Id value) { | ||||
|     const Id zero{ctx.Constant(ctx.F64[1], f64{0.0})}; | ||||
|     const Id one{ctx.Constant(ctx.F64[1], f64{1.0})}; | ||||
|     return ctx.OpFClamp(ctx.F64[1], value, zero, one); | ||||
|     return Saturate(ctx, ctx.F64[1], value, zero, one); | ||||
| } | ||||
|  | ||||
| Id EmitFPRoundEven16(EmitContext& ctx, Id value) { | ||||
|   | ||||
| @@ -6,20 +6,20 @@ | ||||
|  | ||||
| namespace Shader::Backend::SPIRV { | ||||
|  | ||||
| void EmitLogicalOr(EmitContext&) { | ||||
|     throw NotImplementedException("SPIR-V Instruction"); | ||||
| Id EmitLogicalOr(EmitContext& ctx, Id a, Id b) { | ||||
|     return ctx.OpLogicalOr(ctx.U1, a, b); | ||||
| } | ||||
|  | ||||
| void EmitLogicalAnd(EmitContext&) { | ||||
|     throw NotImplementedException("SPIR-V Instruction"); | ||||
| Id EmitLogicalAnd(EmitContext& ctx, Id a, Id b) { | ||||
|     return ctx.OpLogicalAnd(ctx.U1, a, b); | ||||
| } | ||||
|  | ||||
| void EmitLogicalXor(EmitContext&) { | ||||
|     throw NotImplementedException("SPIR-V Instruction"); | ||||
| Id EmitLogicalXor(EmitContext& ctx, Id a, Id b) { | ||||
|     return ctx.OpLogicalNotEqual(ctx.U1, a, b); | ||||
| } | ||||
|  | ||||
| void EmitLogicalNot(EmitContext&) { | ||||
|     throw NotImplementedException("SPIR-V Instruction"); | ||||
| Id EmitLogicalNot(EmitContext& ctx, Id value) { | ||||
|     return ctx.OpLogicalNot(ctx.U1, value); | ||||
| } | ||||
|  | ||||
| } // namespace Shader::Backend::SPIRV | ||||
|   | ||||
		Reference in New Issue
	
	Block a user