| 
									
										
										
										
											2021-05-05 02:19:08 -03:00
										 |  |  | // Copyright 2021 yuzu Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  | #include <string_view>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 21:04:09 -03:00
										 |  |  | #include "shader_recompiler/backend/bindings.h"
 | 
					
						
							| 
									
										
										
										
											2021-05-07 06:31:30 -03:00
										 |  |  | #include "shader_recompiler/backend/glasm/emit_context.h"
 | 
					
						
							| 
									
										
										
										
											2021-05-08 16:28:52 -03:00
										 |  |  | #include "shader_recompiler/frontend/ir/program.h"
 | 
					
						
							| 
									
										
										
										
											2021-05-05 02:19:08 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 06:31:30 -03:00
										 |  |  | namespace Shader::Backend::GLASM { | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  | namespace { | 
					
						
							|  |  |  | std::string_view InterpDecorator(Interpolation interp) { | 
					
						
							|  |  |  |     switch (interp) { | 
					
						
							|  |  |  |     case Interpolation::Smooth: | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  |     case Interpolation::Flat: | 
					
						
							|  |  |  |         return "FLAT "; | 
					
						
							|  |  |  |     case Interpolation::NoPerspective: | 
					
						
							|  |  |  |         return "NOPERSPECTIVE "; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     throw InvalidArgument("Invalid interpolation {}", interp); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:56:59 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool IsInputArray(Stage stage) { | 
					
						
							|  |  |  |     return stage == Stage::Geometry || stage == Stage::TessellationControl || | 
					
						
							|  |  |  |            stage == Stage::TessellationEval; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  | } // Anonymous namespace
 | 
					
						
							| 
									
										
										
										
											2021-05-07 06:31:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  | EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, | 
					
						
							|  |  |  |                          const RuntimeInfo& runtime_info_) | 
					
						
							| 
									
										
										
										
											2021-05-22 18:29:43 -03:00
										 |  |  |     : info{program.info}, profile{profile_}, runtime_info{runtime_info_} { | 
					
						
							| 
									
										
										
										
											2021-05-08 16:28:52 -03:00
										 |  |  |     // FIXME: Temporary partial implementation
 | 
					
						
							|  |  |  |     u32 cbuf_index{}; | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     for (const auto& desc : info.constant_buffer_descriptors) { | 
					
						
							| 
									
										
										
										
											2021-05-08 16:28:52 -03:00
										 |  |  |         if (desc.count != 1) { | 
					
						
							|  |  |  |             throw NotImplementedException("Constant buffer descriptor array"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); | 
					
						
							|  |  |  |         ++cbuf_index; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     for (const auto& desc : info.storage_buffers_descriptors) { | 
					
						
							| 
									
										
										
										
											2021-05-08 16:28:52 -03:00
										 |  |  |         if (desc.count != 1) { | 
					
						
							|  |  |  |             throw NotImplementedException("Storage buffer descriptor array"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) { | 
					
						
							| 
									
										
										
										
											2021-05-08 16:28:52 -03:00
										 |  |  |         Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-19 16:32:03 -03:00
										 |  |  |     stage = program.stage; | 
					
						
							| 
									
										
										
										
											2021-05-10 18:21:28 -03:00
										 |  |  |     switch (program.stage) { | 
					
						
							|  |  |  |     case Stage::VertexA: | 
					
						
							|  |  |  |     case Stage::VertexB: | 
					
						
							|  |  |  |         stage_name = "vertex"; | 
					
						
							| 
									
										
										
										
											2021-05-20 17:28:09 -03:00
										 |  |  |         attrib_name = "vertex"; | 
					
						
							| 
									
										
										
										
											2021-05-10 18:21:28 -03:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case Stage::TessellationControl: | 
					
						
							|  |  |  |     case Stage::TessellationEval: | 
					
						
							| 
									
										
										
										
											2021-05-20 17:28:09 -03:00
										 |  |  |         stage_name = "primitive"; | 
					
						
							|  |  |  |         attrib_name = "primitive"; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-05-10 18:21:28 -03:00
										 |  |  |     case Stage::Geometry: | 
					
						
							|  |  |  |         stage_name = "primitive"; | 
					
						
							| 
									
										
										
										
											2021-05-20 17:28:09 -03:00
										 |  |  |         attrib_name = "vertex"; | 
					
						
							| 
									
										
										
										
											2021-05-10 18:21:28 -03:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case Stage::Fragment: | 
					
						
							|  |  |  |         stage_name = "fragment"; | 
					
						
							| 
									
										
										
										
											2021-05-20 17:28:09 -03:00
										 |  |  |         attrib_name = "fragment"; | 
					
						
							| 
									
										
										
										
											2021-05-10 18:21:28 -03:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case Stage::Compute: | 
					
						
							| 
									
										
										
										
											2021-05-19 16:51:28 -03:00
										 |  |  |         stage_name = "invocation"; | 
					
						
							| 
									
										
										
										
											2021-05-10 18:21:28 -03:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-20 17:28:09 -03:00
										 |  |  |     const std::string_view attr_stage{stage == Stage::Fragment ? "fragment" : "vertex"}; | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     for (size_t index = 0; index < info.input_generics.size(); ++index) { | 
					
						
							|  |  |  |         const auto& generic{info.input_generics[index]}; | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  |         if (generic.used) { | 
					
						
							|  |  |  |             Add("{}ATTRIB in_attr{}[]={{{}.attrib[{}..{}]}};", | 
					
						
							| 
									
										
										
										
											2021-05-20 17:28:09 -03:00
										 |  |  |                 InterpDecorator(generic.interpolation), index, attr_stage, index, index); | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:56:59 -03:00
										 |  |  |     if (IsInputArray(stage) && info.loads_position) { | 
					
						
							| 
									
										
										
										
											2021-05-20 19:21:38 -03:00
										 |  |  |         Add("ATTRIB vertex_position=vertex.position;"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-20 20:36:04 -03:00
										 |  |  |     if (info.uses_invocation_id) { | 
					
						
							|  |  |  |         Add("ATTRIB primitive_invocation=primitive.invocation;"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-20 21:00:17 -03:00
										 |  |  |     if (info.stores_tess_level_outer) { | 
					
						
							|  |  |  |         Add("OUTPUT result_patch_tessouter[]={{result.patch.tessouter[0..3]}};"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (info.stores_tess_level_inner) { | 
					
						
							|  |  |  |         Add("OUTPUT result_patch_tessinner[]={{result.patch.tessinner[0..1]}};"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-20 21:54:02 -03:00
										 |  |  |     if (info.stores_clip_distance) { | 
					
						
							|  |  |  |         Add("OUTPUT result_clip[]={{result.clip[0..7]}};"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-20 21:00:17 -03:00
										 |  |  |     for (size_t index = 0; index < info.uses_patches.size(); ++index) { | 
					
						
							|  |  |  |         if (!info.uses_patches[index]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-20 22:08:56 -03:00
										 |  |  |         if (stage == Stage::TessellationControl) { | 
					
						
							| 
									
										
										
										
											2021-05-21 02:56:59 -03:00
										 |  |  |             Add("OUTPUT result_patch_attrib{}[]={{result.patch.attrib[{}..{}]}};" | 
					
						
							|  |  |  |                 "ATTRIB primitive_out_patch_attrib{}[]={{primitive.out.patch.attrib[{}..{}]}};", | 
					
						
							|  |  |  |                 index, index, index, index, index, index); | 
					
						
							| 
									
										
										
										
											2021-05-20 21:00:17 -03:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             Add("ATTRIB primitive_patch_attrib{}[]={{primitive.patch.attrib[{}..{}]}};", index, | 
					
						
							|  |  |  |                 index, index); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     for (size_t index = 0; index < info.stores_frag_color.size(); ++index) { | 
					
						
							|  |  |  |         if (!info.stores_frag_color[index]) { | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (index == 0) { | 
					
						
							|  |  |  |             Add("OUTPUT frag_color0=result.color;"); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-05-16 17:52:30 -03:00
										 |  |  |             Add("OUTPUT frag_color{}=result.color[{}];", index, index); | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     for (size_t index = 0; index < info.stores_generics.size(); ++index) { | 
					
						
							|  |  |  |         if (info.stores_generics[index]) { | 
					
						
							| 
									
										
										
										
											2021-05-15 18:14:29 -03:00
										 |  |  |             Add("OUTPUT out_attr{}[]={{result.attrib[{}..{}]}};", index, index, index); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     image_buffer_bindings.reserve(info.image_buffer_descriptors.size()); | 
					
						
							|  |  |  |     for (const auto& desc : info.image_buffer_descriptors) { | 
					
						
							| 
									
										
										
										
											2021-05-20 02:18:52 -03:00
										 |  |  |         image_buffer_bindings.push_back(bindings.image); | 
					
						
							|  |  |  |         bindings.image += desc.count; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     image_bindings.reserve(info.image_descriptors.size()); | 
					
						
							|  |  |  |     for (const auto& desc : info.image_descriptors) { | 
					
						
							| 
									
										
										
										
											2021-05-20 02:18:52 -03:00
										 |  |  |         image_bindings.push_back(bindings.image); | 
					
						
							|  |  |  |         bindings.image += desc.count; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     texture_buffer_bindings.reserve(info.texture_buffer_descriptors.size()); | 
					
						
							|  |  |  |     for (const auto& desc : info.texture_buffer_descriptors) { | 
					
						
							| 
									
										
										
										
											2021-05-19 02:05:24 -03:00
										 |  |  |         texture_buffer_bindings.push_back(bindings.texture); | 
					
						
							|  |  |  |         bindings.texture += desc.count; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-21 02:12:32 -03:00
										 |  |  |     texture_bindings.reserve(info.texture_descriptors.size()); | 
					
						
							|  |  |  |     for (const auto& desc : info.texture_descriptors) { | 
					
						
							| 
									
										
										
										
											2021-05-19 02:05:24 -03:00
										 |  |  |         texture_bindings.push_back(bindings.texture); | 
					
						
							| 
									
										
										
										
											2021-05-18 21:04:09 -03:00
										 |  |  |         bindings.texture += desc.count; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-08 16:28:52 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-07 06:31:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // namespace Shader::Backend::GLASM
 |