glasm: Implement indirect attribute loads
This commit is contained in:
		| @@ -30,9 +30,8 @@ bool IsInputArray(Stage stage) { | ||||
|  | ||||
| EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, | ||||
|                          const RuntimeInfo& runtime_info_) | ||||
|     : profile{profile_}, runtime_info{runtime_info_} { | ||||
|     : info{program.info}, profile{profile_}, runtime_info{runtime_info_} { | ||||
|     // FIXME: Temporary partial implementation | ||||
|     const auto& info{program.info}; | ||||
|     u32 cbuf_index{}; | ||||
|     for (const auto& desc : info.constant_buffer_descriptors) { | ||||
|         if (desc.count != 1) { | ||||
|   | ||||
| @@ -58,6 +58,7 @@ public: | ||||
|  | ||||
|     std::string code; | ||||
|     RegAlloc reg_alloc{*this}; | ||||
|     const Info& info; | ||||
|     const Profile& profile; | ||||
|     const RuntimeInfo& runtime_info; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" | ||||
| #include "shader_recompiler/frontend/ir/value.h" | ||||
| #include "shader_recompiler/profile.h" | ||||
| #include "shader_recompiler/shader_info.h" | ||||
|  | ||||
| namespace Shader::Backend::GLASM { | ||||
| namespace { | ||||
| @@ -153,9 +154,67 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, | ||||
|     } | ||||
| } | ||||
|  | ||||
| void EmitGetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, | ||||
|                              [[maybe_unused]] ScalarU32 vertex) { | ||||
|     throw NotImplementedException("GLASM instruction"); | ||||
| void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex) { | ||||
|     // RC.x = base_index | ||||
|     // RC.y = masked_index | ||||
|     // RC.z = compare_index | ||||
|     ctx.Add("SHR.S RC.x,{},2;" | ||||
|             "AND.S RC.y,RC.x,3;" | ||||
|             "SHR.S RC.z,{},4;", | ||||
|             offset, offset); | ||||
|  | ||||
|     const Register ret{ctx.reg_alloc.Define(inst)}; | ||||
|     u32 num_endifs{}; | ||||
|     const auto read{[&](u32 compare_index, const std::array<std::string, 4>& values) { | ||||
|         ++num_endifs; | ||||
|         ctx.Add("SEQ.S.CC RC.w,RC.z,{};" // compare_index | ||||
|                 "IF NE.w;" | ||||
|                 // X | ||||
|                 "SEQ.S.CC RC.w,RC.y,0;" | ||||
|                 "IF NE.w;" | ||||
|                 "MOV {}.x,{};" | ||||
|                 "ELSE;" | ||||
|                 // Y | ||||
|                 "SEQ.S.CC RC.w,RC.y,1;" | ||||
|                 "IF NE.w;" | ||||
|                 "MOV {}.x,{};" | ||||
|                 "ELSE;" | ||||
|                 // Z | ||||
|                 "SEQ.S.CC RC.w,RC.y,2;" | ||||
|                 "IF NE.w;" | ||||
|                 "MOV {}.x,{};" | ||||
|                 "ELSE;" | ||||
|                 // W | ||||
|                 "MOV {}.x,{};" | ||||
|                 "ENDIF;" | ||||
|                 "ENDIF;" | ||||
|                 "ENDIF;" | ||||
|                 "ELSE;", | ||||
|                 compare_index, ret, values[0], ret, values[1], ret, values[2], ret, values[3]); | ||||
|     }}; | ||||
|     const auto read_swizzled{[&](u32 compare_index, std::string_view value) { | ||||
|         const std::array values{fmt::format("{}.x", value), fmt::format("{}.y", value), | ||||
|                                 fmt::format("{}.z", value), fmt::format("{}.w", value)}; | ||||
|         read(compare_index, values); | ||||
|     }}; | ||||
|     if (ctx.info.loads_position) { | ||||
|         const u32 index{static_cast<u32>(IR::Attribute::PositionX)}; | ||||
|         if (IsInputArray(ctx.stage)) { | ||||
|             read_swizzled(index, fmt::format("vertex_position{}", VertexIndex(ctx, vertex))); | ||||
|         } else { | ||||
|             read_swizzled(index, fmt::format("{}.position", ctx.attrib_name)); | ||||
|         } | ||||
|     } | ||||
|     const u32 base_attribute_value{static_cast<u32>(IR::Attribute::Generic0X) >> 2}; | ||||
|     for (u32 index = 0; index < ctx.info.input_generics.size(); ++index) { | ||||
|         if (!ctx.info.input_generics[index].used) { | ||||
|             continue; | ||||
|         } | ||||
|         read_swizzled(index, fmt::format("in_attr{}{}[0]", index, VertexIndex(ctx, vertex))); | ||||
|     } | ||||
|     for (u32 i = 0; i < num_endifs; ++i) { | ||||
|         ctx.Add("ENDIF;"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] ScalarU32 offset, | ||||
|   | ||||
| @@ -51,7 +51,7 @@ void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | ||||
| void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); | ||||
| void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, ScalarU32 vertex); | ||||
| void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, ScalarF32 value, ScalarU32 vertex); | ||||
| void EmitGetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarU32 vertex); | ||||
| void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, ScalarS32 offset, ScalarU32 vertex); | ||||
| void EmitSetAttributeIndexed(EmitContext& ctx, ScalarU32 offset, ScalarF32 value, ScalarU32 vertex); | ||||
| void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch); | ||||
| void EmitSetPatch(EmitContext& ctx, IR::Patch patch, ScalarF32 value); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user