glsl: Implement indexed attribute loads
This commit is contained in:
		| @@ -104,8 +104,22 @@ std::string_view SamplerType(TextureType type, bool is_depth) { | |||||||
|  |  | ||||||
| std::string_view ImageType(TextureType type) { | std::string_view ImageType(TextureType type) { | ||||||
|     switch (type) { |     switch (type) { | ||||||
|  |     case TextureType::Color1D: | ||||||
|  |         return "uimage1D"; | ||||||
|  |     case TextureType::ColorArray1D: | ||||||
|  |         return "uimage1DArray"; | ||||||
|     case TextureType::Color2D: |     case TextureType::Color2D: | ||||||
|         return "uimage2D"; |         return "uimage2D"; | ||||||
|  |     case TextureType::ColorArray2D: | ||||||
|  |         return "uimage2DArray"; | ||||||
|  |     case TextureType::Color3D: | ||||||
|  |         return "uimage3D"; | ||||||
|  |     case TextureType::ColorCube: | ||||||
|  |         return "uimageCube"; | ||||||
|  |     case TextureType::ColorArrayCube: | ||||||
|  |         return "uimageCubeArray"; | ||||||
|  |     case TextureType::Buffer: | ||||||
|  |         return "uimageBuffer"; | ||||||
|     default: |     default: | ||||||
|         throw NotImplementedException("Image type: {}", type); |         throw NotImplementedException("Image type: {}", type); | ||||||
|     } |     } | ||||||
| @@ -250,6 +264,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||||||
|         break; |         break; | ||||||
|     case Stage::Fragment: |     case Stage::Fragment: | ||||||
|         stage_name = "fs"; |         stage_name = "fs"; | ||||||
|  |         position_name = "gl_FragCoord"; | ||||||
|         break; |         break; | ||||||
|     case Stage::Compute: |     case Stage::Compute: | ||||||
|         stage_name = "cs"; |         stage_name = "cs"; | ||||||
| @@ -449,6 +464,33 @@ void EmitContext::DefineHelperFunctions() { | |||||||
|     if (info.uses_global_memory) { |     if (info.uses_global_memory) { | ||||||
|         header += DefineGlobalMemoryFunctions(); |         header += DefineGlobalMemoryFunctions(); | ||||||
|     } |     } | ||||||
|  |     if (info.loads_indexed_attributes) { | ||||||
|  |         const bool is_array{stage == Stage::Geometry}; | ||||||
|  |         const auto vertex_arg{is_array ? ",uint vertex" : ""}; | ||||||
|  |         std::string func{ | ||||||
|  |             fmt::format("float IndexedAttrLoad(int offset{}){{int base_index=offset>>2;uint " | ||||||
|  |                         "masked_index=uint(base_index)&3u;switch(base_index>>2){{", | ||||||
|  |                         vertex_arg)}; | ||||||
|  |         if (info.loads_position) { | ||||||
|  |             func += fmt::format("case {}:", static_cast<u32>(IR::Attribute::PositionX) >> 2); | ||||||
|  |             const auto position_idx{is_array ? "gl_in[vertex]." : ""}; | ||||||
|  |             func += fmt::format("return {}{}[masked_index];", position_idx, position_name); | ||||||
|  |         } | ||||||
|  |         const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; | ||||||
|  |         for (u32 i = 0; i < info.input_generics.size(); ++i) { | ||||||
|  |             if (!info.input_generics[i].used) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             const auto vertex_idx{is_array ? "[vertex]" : ""}; | ||||||
|  |             func += fmt::format("case {}:", base_attribute_value + i); | ||||||
|  |             func += fmt::format("return in_attr{}{}[masked_index];", i, vertex_idx); | ||||||
|  |         } | ||||||
|  |         func += "default: return 0.0;}}"; | ||||||
|  |         header += func; | ||||||
|  |     } | ||||||
|  |     if (info.stores_indexed_attributes) { | ||||||
|  |         // TODO | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| std::string EmitContext::DefineGlobalMemoryFunctions() { | std::string EmitContext::DefineGlobalMemoryFunctions() { | ||||||
|   | |||||||
| @@ -150,6 +150,7 @@ public: | |||||||
|  |  | ||||||
|     Stage stage{}; |     Stage stage{}; | ||||||
|     std::string_view stage_name = "invalid"; |     std::string_view stage_name = "invalid"; | ||||||
|  |     std::string_view position_name = "gl_Position"; | ||||||
|  |  | ||||||
|     std::vector<u32> texture_buffer_bindings; |     std::vector<u32> texture_buffer_bindings; | ||||||
|     std::vector<u32> image_buffer_bindings; |     std::vector<u32> image_buffer_bindings; | ||||||
|   | |||||||
| @@ -206,26 +206,12 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||||||
|     case IR::Attribute::PositionX: |     case IR::Attribute::PositionX: | ||||||
|     case IR::Attribute::PositionY: |     case IR::Attribute::PositionY: | ||||||
|     case IR::Attribute::PositionZ: |     case IR::Attribute::PositionZ: | ||||||
|     case IR::Attribute::PositionW: |     case IR::Attribute::PositionW: { | ||||||
|         switch (ctx.stage) { |         const bool is_array{IsInputArray(ctx.stage)}; | ||||||
|         case Stage::VertexA: |         const auto input_decorator{is_array ? fmt::format("gl_in[{}].", vertex) : ""}; | ||||||
|         case Stage::VertexB: |         ctx.AddF32("{}={}{}.{};", inst, input_decorator, ctx.position_name, swizzle); | ||||||
|             ctx.AddF32("{}=gl_Position.{};", inst, swizzle); |  | ||||||
|             break; |  | ||||||
|         case Stage::TessellationEval: |  | ||||||
|             ctx.AddF32("{}=gl_TessCoord.{};", inst, swizzle); |  | ||||||
|             break; |  | ||||||
|         case Stage::TessellationControl: |  | ||||||
|         case Stage::Geometry: |  | ||||||
|             ctx.AddF32("{}=gl_in[{}].gl_Position.{};", inst, vertex, swizzle); |  | ||||||
|             break; |  | ||||||
|         case Stage::Fragment: |  | ||||||
|             ctx.AddF32("{}=gl_FragCoord.{};", inst, swizzle); |  | ||||||
|             break; |  | ||||||
|         default: |  | ||||||
|             throw NotImplementedException("Get Position for stage {}", ctx.stage); |  | ||||||
|         } |  | ||||||
|         break; |         break; | ||||||
|  |     } | ||||||
|     case IR::Attribute::PointSpriteS: |     case IR::Attribute::PointSpriteS: | ||||||
|     case IR::Attribute::PointSpriteT: |     case IR::Attribute::PointSpriteT: | ||||||
|         ctx.AddF32("{}=gl_PointCoord.{};", inst, swizzle); |         ctx.AddF32("{}=gl_PointCoord.{};", inst, swizzle); | ||||||
| @@ -311,6 +297,20 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, std::string_view offset, | ||||||
|  |                              std::string_view vertex) { | ||||||
|  |     const bool is_array{ctx.stage == Stage::Geometry}; | ||||||
|  |     const auto vertex_arg{is_array ? fmt::format(",{}", vertex) : ""}; | ||||||
|  |     ctx.AddF32("{}=IndexedAttrLoad(int({}){});", inst, offset, vertex_arg); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void EmitSetAttributeIndexed([[maybe_unused]] EmitContext& ctx, | ||||||
|  |                              [[maybe_unused]] std::string_view offset, | ||||||
|  |                              [[maybe_unused]] std::string_view value, | ||||||
|  |                              [[maybe_unused]] std::string_view vertex) { | ||||||
|  |     NotImplemented(); | ||||||
|  | } | ||||||
|  |  | ||||||
| void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch) { | void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch) { | ||||||
|     if (!IR::IsGeneric(patch)) { |     if (!IR::IsGeneric(patch)) { | ||||||
|         throw NotImplementedException("Non-generic patch load"); |         throw NotImplementedException("Non-generic patch load"); | ||||||
|   | |||||||
| @@ -72,7 +72,8 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, | |||||||
|                       std::string_view vertex); |                       std::string_view vertex); | ||||||
| void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, | void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view value, | ||||||
|                       std::string_view vertex); |                       std::string_view vertex); | ||||||
| void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex); | void EmitGetAttributeIndexed(EmitContext& ctx, IR::Inst& inst, std::string_view offset, | ||||||
|  |                              std::string_view vertex); | ||||||
| void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, | void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, | ||||||
|                              std::string_view vertex); |                              std::string_view vertex); | ||||||
| void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch); | void EmitGetPatch(EmitContext& ctx, IR::Inst& inst, IR::Patch patch); | ||||||
|   | |||||||
| @@ -124,15 +124,6 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) { | |||||||
|     NotImplemented(); |     NotImplemented(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmitGetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view vertex) { |  | ||||||
|     NotImplemented(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void EmitSetAttributeIndexed(EmitContext& ctx, std::string_view offset, std::string_view value, |  | ||||||
|                              std::string_view vertex) { |  | ||||||
|     NotImplemented(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void EmitSetSampleMask(EmitContext& ctx, std::string_view value) { | void EmitSetSampleMask(EmitContext& ctx, std::string_view value) { | ||||||
|     NotImplemented(); |     NotImplemented(); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user