summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_context.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-20 19:11:56 -0300
committerGravatar ameerj2021-07-22 21:51:23 -0400
commit76c8a962ac4eae77e71d66a72c448930240339f9 (patch)
tree267bdb72f0fad43779080cd1907dd8159a6c7154 /src/shader_recompiler/backend/spirv/emit_context.cpp
parentshader: Refactor half floating instructions (diff)
downloadyuzu-76c8a962ac4eae77e71d66a72c448930240339f9.tar.gz
yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.tar.xz
yuzu-76c8a962ac4eae77e71d66a72c448930240339f9.zip
spirv: Implement VertexId and InstanceId, refactor code
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp191
1 files changed, 111 insertions, 80 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 6c8f16562..4a4de3676 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -48,6 +48,25 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
48 } 48 }
49 throw InvalidArgument("Invalid texture type {}", desc.type); 49 throw InvalidArgument("Invalid texture type {}", desc.type);
50} 50}
51
52Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin,
53 spv::StorageClass storage_class) {
54 const Id pointer_type{ctx.TypePointer(storage_class, type)};
55 const Id id{ctx.AddGlobalVariable(pointer_type, storage_class)};
56 if (builtin) {
57 ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin);
58 }
59 ctx.interfaces.push_back(id);
60 return id;
61}
62
63Id DefineInput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) {
64 return DefineVariable(ctx, type, builtin, spv::StorageClass::Input);
65}
66
67Id DefineOutput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) {
68 return DefineVariable(ctx, type, builtin, spv::StorageClass::Output);
69}
51} // Anonymous namespace 70} // Anonymous namespace
52 71
53void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) { 72void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_view name) {
@@ -144,59 +163,8 @@ void EmitContext::DefineCommonConstants() {
144} 163}
145 164
146void EmitContext::DefineInterfaces(const Info& info, Stage stage) { 165void EmitContext::DefineInterfaces(const Info& info, Stage stage) {
147 const auto define{ 166 DefineInputs(info, stage);
148 [this](Id type, std::optional<spv::BuiltIn> builtin, spv::StorageClass storage_class) { 167 DefineOutputs(info, stage);
149 const Id pointer_type{TypePointer(storage_class, type)};
150 const Id id{AddGlobalVariable(pointer_type, storage_class)};
151 if (builtin) {
152 Decorate(id, spv::Decoration::BuiltIn, *builtin);
153 }
154 interfaces.push_back(id);
155 return id;
156 }};
157 using namespace std::placeholders;
158 const auto define_input{std::bind(define, _1, _2, spv::StorageClass::Input)};
159 const auto define_output{std::bind(define, _1, _2, spv::StorageClass::Output)};
160
161 if (info.uses_workgroup_id) {
162 workgroup_id = define_input(U32[3], spv::BuiltIn::WorkgroupId);
163 }
164 if (info.uses_local_invocation_id) {
165 local_invocation_id = define_input(U32[3], spv::BuiltIn::LocalInvocationId);
166 }
167 if (info.loads_position) {
168 const bool is_fragment{stage != Stage::Fragment};
169 const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord};
170 input_position = define_input(F32[4], built_in);
171 }
172 for (size_t i = 0; i < info.loads_generics.size(); ++i) {
173 if (info.loads_generics[i]) {
174 // FIXME: Declare size from input
175 input_generics[i] = define_input(F32[4], std::nullopt);
176 Decorate(input_generics[i], spv::Decoration::Location, static_cast<u32>(i));
177 Name(input_generics[i], fmt::format("in_attr{}", i));
178 }
179 }
180 if (info.stores_position) {
181 output_position = define_output(F32[4], spv::BuiltIn::Position);
182 }
183 for (size_t i = 0; i < info.stores_generics.size(); ++i) {
184 if (info.stores_generics[i]) {
185 output_generics[i] = define_output(F32[4], std::nullopt);
186 Decorate(output_generics[i], spv::Decoration::Location, static_cast<u32>(i));
187 Name(output_generics[i], fmt::format("out_attr{}", i));
188 }
189 }
190 if (stage == Stage::Fragment) {
191 for (size_t i = 0; i < 8; ++i) {
192 if (!info.stores_frag_color[i]) {
193 continue;
194 }
195 frag_color[i] = define_output(F32[4], std::nullopt);
196 Decorate(frag_color[i], spv::Decoration::Location, static_cast<u32>(i));
197 Name(frag_color[i], fmt::format("frag_color{}", i));
198 }
199 }
200} 168}
201 169
202void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { 170void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
@@ -225,33 +193,6 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
225 } 193 }
226} 194}
227 195
228void EmitContext::DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type,
229 u32 binding, Id type, char type_char, u32 element_size) {
230 const Id array_type{TypeArray(type, Constant(U32[1], 65536U / element_size))};
231 Decorate(array_type, spv::Decoration::ArrayStride, element_size);
232
233 const Id struct_type{TypeStruct(array_type)};
234 Name(struct_type, fmt::format("cbuf_block_{}{}", type_char, element_size * CHAR_BIT));
235 Decorate(struct_type, spv::Decoration::Block);
236 MemberName(struct_type, 0, "data");
237 MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U);
238
239 const Id struct_pointer_type{TypePointer(spv::StorageClass::Uniform, struct_type)};
240 const Id uniform_type{TypePointer(spv::StorageClass::Uniform, type)};
241 uniform_types.*member_type = uniform_type;
242
243 for (const ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) {
244 const Id id{AddGlobalVariable(struct_pointer_type, spv::StorageClass::Uniform)};
245 Decorate(id, spv::Decoration::Binding, binding);
246 Decorate(id, spv::Decoration::DescriptorSet, 0U);
247 Name(id, fmt::format("c{}", desc.index));
248 for (size_t i = 0; i < desc.count; ++i) {
249 cbufs[desc.index + i].*member_type = id;
250 }
251 binding += desc.count;
252 }
253}
254
255void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { 196void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) {
256 if (info.storage_buffers_descriptors.empty()) { 197 if (info.storage_buffers_descriptors.empty()) {
257 return; 198 return;
@@ -311,4 +252,94 @@ void EmitContext::DefineLabels(IR::Program& program) {
311 } 252 }
312} 253}
313 254
255void EmitContext::DefineInputs(const Info& info, Stage stage) {
256 if (info.uses_workgroup_id) {
257 workgroup_id = DefineInput(*this, U32[3], spv::BuiltIn::WorkgroupId);
258 }
259 if (info.uses_local_invocation_id) {
260 local_invocation_id = DefineInput(*this, U32[3], spv::BuiltIn::LocalInvocationId);
261 }
262 if (info.loads_position) {
263 const bool is_fragment{stage != Stage::Fragment};
264 const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord};
265 input_position = DefineInput(*this, F32[4], built_in);
266 }
267 if (info.loads_instance_id) {
268 if (profile.support_vertex_instance_id) {
269 instance_id = DefineInput(*this, U32[1], spv::BuiltIn::InstanceId);
270 } else {
271 instance_index = DefineInput(*this, U32[1], spv::BuiltIn::InstanceIndex);
272 base_instance = DefineInput(*this, U32[1], spv::BuiltIn::BaseInstance);
273 }
274 }
275 if (info.loads_vertex_id) {
276 if (profile.support_vertex_instance_id) {
277 vertex_id = DefineInput(*this, U32[1], spv::BuiltIn::VertexId);
278 } else {
279 vertex_index = DefineInput(*this, U32[1], spv::BuiltIn::VertexIndex);
280 base_vertex = DefineInput(*this, U32[1], spv::BuiltIn::BaseVertex);
281 }
282 }
283 for (size_t index = 0; index < info.loads_generics.size(); ++index) {
284 if (!info.loads_generics[index]) {
285 continue;
286 }
287 // FIXME: Declare size from input
288 const Id id{DefineInput(*this, F32[4])};
289 Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
290 Name(id, fmt::format("in_attr{}", index));
291 input_generics[index] = id;
292 }
293}
294
295void EmitContext::DefineConstantBuffers(const Info& info, Id UniformDefinitions::*member_type,
296 u32 binding, Id type, char type_char, u32 element_size) {
297 const Id array_type{TypeArray(type, Constant(U32[1], 65536U / element_size))};
298 Decorate(array_type, spv::Decoration::ArrayStride, element_size);
299
300 const Id struct_type{TypeStruct(array_type)};
301 Name(struct_type, fmt::format("cbuf_block_{}{}", type_char, element_size * CHAR_BIT));
302 Decorate(struct_type, spv::Decoration::Block);
303 MemberName(struct_type, 0, "data");
304 MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U);
305
306 const Id struct_pointer_type{TypePointer(spv::StorageClass::Uniform, struct_type)};
307 const Id uniform_type{TypePointer(spv::StorageClass::Uniform, type)};
308 uniform_types.*member_type = uniform_type;
309
310 for (const ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) {
311 const Id id{AddGlobalVariable(struct_pointer_type, spv::StorageClass::Uniform)};
312 Decorate(id, spv::Decoration::Binding, binding);
313 Decorate(id, spv::Decoration::DescriptorSet, 0U);
314 Name(id, fmt::format("c{}", desc.index));
315 for (size_t i = 0; i < desc.count; ++i) {
316 cbufs[desc.index + i].*member_type = id;
317 }
318 binding += desc.count;
319 }
320}
321
322void EmitContext::DefineOutputs(const Info& info, Stage stage) {
323 if (info.stores_position) {
324 output_position = DefineOutput(*this, F32[4], spv::BuiltIn::Position);
325 }
326 for (size_t i = 0; i < info.stores_generics.size(); ++i) {
327 if (info.stores_generics[i]) {
328 output_generics[i] = DefineOutput(*this, F32[4]);
329 Decorate(output_generics[i], spv::Decoration::Location, static_cast<u32>(i));
330 Name(output_generics[i], fmt::format("out_attr{}", i));
331 }
332 }
333 if (stage == Stage::Fragment) {
334 for (size_t i = 0; i < 8; ++i) {
335 if (!info.stores_frag_color[i]) {
336 continue;
337 }
338 frag_color[i] = DefineOutput(*this, F32[4]);
339 Decorate(frag_color[i], spv::Decoration::Location, static_cast<u32>(i));
340 Name(frag_color[i], fmt::format("frag_color{}", i));
341 }
342 }
343}
344
314} // namespace Shader::Backend::SPIRV 345} // namespace Shader::Backend::SPIRV