summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-27 04:59:58 -0300
committerGravatar ameerj2021-07-22 21:51:24 -0400
commitdbd882ddeb1a1a9233c0085d0b8ccb022db385b2 (patch)
tree5a8456364cc41a0a53acf93e22e3f9ce855bd413 /src
parentspirv: Remove dependencies on Environment when generating SPIR-V (diff)
downloadyuzu-dbd882ddeb1a1a9233c0085d0b8ccb022db385b2.tar.gz
yuzu-dbd882ddeb1a1a9233c0085d0b8ccb022db385b2.tar.xz
yuzu-dbd882ddeb1a1a9233c0085d0b8ccb022db385b2.zip
shader: Better interpolation and disabled attributes support
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp29
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp29
-rw-r--r--src/shader_recompiler/frontend/maxwell/program.cpp35
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp10
-rw-r--r--src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp2
-rw-r--r--src/shader_recompiler/profile.h1
-rw-r--r--src/shader_recompiler/shader_info.h13
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp3
9 files changed, 101 insertions, 25 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 4d5dabcbf..a8ca33c1d 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -76,6 +76,8 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) {
76 return ctx.TypeVector(ctx.TypeInt(32, true), 4); 76 return ctx.TypeVector(ctx.TypeInt(32, true), 4);
77 case AttributeType::UnsignedInt: 77 case AttributeType::UnsignedInt:
78 return ctx.U32[4]; 78 return ctx.U32[4];
79 case AttributeType::Disabled:
80 break;
79 } 81 }
80 throw InvalidArgument("Invalid attribute type {}", type); 82 throw InvalidArgument("Invalid attribute type {}", type);
81} 83}
@@ -305,15 +307,36 @@ void EmitContext::DefineInputs(const Info& info) {
305 if (info.loads_front_face) { 307 if (info.loads_front_face) {
306 front_face = DefineInput(*this, U1, spv::BuiltIn::FrontFacing); 308 front_face = DefineInput(*this, U1, spv::BuiltIn::FrontFacing);
307 } 309 }
308 for (size_t index = 0; index < info.loads_generics.size(); ++index) { 310 for (size_t index = 0; index < info.input_generics.size(); ++index) {
309 if (!info.loads_generics[index]) { 311 const InputVarying generic{info.input_generics[index]};
312 if (!generic.used) {
310 continue; 313 continue;
311 } 314 }
312 const Id type{GetAttributeType(*this, profile.generic_input_types[index])}; 315 const AttributeType input_type{profile.generic_input_types[index]};
316 if (input_type == AttributeType::Disabled) {
317 continue;
318 }
319 const Id type{GetAttributeType(*this, input_type)};
313 const Id id{DefineInput(*this, type)}; 320 const Id id{DefineInput(*this, type)};
314 Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); 321 Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
315 Name(id, fmt::format("in_attr{}", index)); 322 Name(id, fmt::format("in_attr{}", index));
316 input_generics[index] = id; 323 input_generics[index] = id;
324
325 if (stage != Stage::Fragment) {
326 continue;
327 }
328 switch (generic.interpolation) {
329 case Interpolation::Smooth:
330 // Default
331 // Decorate(id, spv::Decoration::Smooth);
332 break;
333 case Interpolation::NoPerspective:
334 Decorate(id, spv::Decoration::NoPerspective);
335 break;
336 case Interpolation::Flat:
337 Decorate(id, spv::Decoration::Flat);
338 break;
339 }
317 } 340 }
318} 341}
319 342
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 6fa16eb80..4cbc2aec1 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -10,16 +10,23 @@
10 10
11namespace Shader::Backend::SPIRV { 11namespace Shader::Backend::SPIRV {
12namespace { 12namespace {
13std::tuple<Id, Id, bool> AttrTypes(EmitContext& ctx, u32 index) { 13struct AttrInfo {
14 const bool is_first_reader{ctx.stage == Stage::VertexB}; 14 Id pointer;
15 Id id;
16 bool needs_cast;
17};
18
19std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) {
15 const AttributeType type{ctx.profile.generic_input_types.at(index)}; 20 const AttributeType type{ctx.profile.generic_input_types.at(index)};
16 switch (type) { 21 switch (type) {
17 case AttributeType::Float: 22 case AttributeType::Float:
18 return {ctx.input_f32, ctx.F32[1], false}; 23 return AttrInfo{ctx.input_f32, ctx.F32[1], false};
19 case AttributeType::UnsignedInt: 24 case AttributeType::UnsignedInt:
20 return {ctx.input_u32, ctx.U32[1], true}; 25 return AttrInfo{ctx.input_u32, ctx.U32[1], true};
21 case AttributeType::SignedInt: 26 case AttributeType::SignedInt:
22 return {ctx.input_s32, ctx.TypeInt(32, true), true}; 27 return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true};
28 case AttributeType::Disabled:
29 return std::nullopt;
23 } 30 }
24 throw InvalidArgument("Invalid attribute type {}", type); 31 throw InvalidArgument("Invalid attribute type {}", type);
25} 32}
@@ -129,11 +136,15 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr) {
129 const auto element_id{[&] { return ctx.Constant(ctx.U32[1], element); }}; 136 const auto element_id{[&] { return ctx.Constant(ctx.U32[1], element); }};
130 if (IR::IsGeneric(attr)) { 137 if (IR::IsGeneric(attr)) {
131 const u32 index{IR::GenericAttributeIndex(attr)}; 138 const u32 index{IR::GenericAttributeIndex(attr)};
132 const auto [pointer_type, type, needs_cast]{AttrTypes(ctx, index)}; 139 const std::optional<AttrInfo> type{AttrTypes(ctx, index)};
140 if (!type) {
141 // Attribute is disabled
142 return ctx.Constant(ctx.F32[1], 0.0f);
143 }
133 const Id generic_id{ctx.input_generics.at(index)}; 144 const Id generic_id{ctx.input_generics.at(index)};
134 const Id pointer{ctx.OpAccessChain(pointer_type, generic_id, element_id())}; 145 const Id pointer{ctx.OpAccessChain(type->pointer, generic_id, element_id())};
135 const Id value{ctx.OpLoad(type, pointer)}; 146 const Id value{ctx.OpLoad(type->id, pointer)};
136 return needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; 147 return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value;
137 } 148 }
138 switch (attr) { 149 switch (attr) {
139 case IR::Attribute::PositionX: 150 case IR::Attribute::PositionX:
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp
index 6efaf6ee0..a914a91f4 100644
--- a/src/shader_recompiler/frontend/maxwell/program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/program.cpp
@@ -27,6 +27,40 @@ static void RemoveUnreachableBlocks(IR::Program& program) {
27 }); 27 });
28} 28}
29 29
30static void CollectInterpolationInfo(Environment& env, IR::Program& program) {
31 if (program.stage != Stage::Fragment) {
32 return;
33 }
34 const ProgramHeader& sph{env.SPH()};
35 for (size_t index = 0; index < program.info.input_generics.size(); ++index) {
36 std::optional<PixelImap> imap;
37 for (const PixelImap value : sph.ps.GenericInputMap(static_cast<u32>(index))) {
38 if (value == PixelImap::Unused) {
39 continue;
40 }
41 if (imap && imap != value) {
42 throw NotImplementedException("Per component interpolation");
43 }
44 imap = value;
45 }
46 if (!imap) {
47 continue;
48 }
49 program.info.input_generics[index].interpolation = [&] {
50 switch (*imap) {
51 case PixelImap::Unused:
52 case PixelImap::Perspective:
53 return Interpolation::Smooth;
54 case PixelImap::Constant:
55 return Interpolation::Flat;
56 case PixelImap::ScreenLinear:
57 return Interpolation::NoPerspective;
58 }
59 throw NotImplementedException("Unknown interpolation {}", *imap);
60 }();
61 }
62}
63
30IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool, 64IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool,
31 Environment& env, Flow::CFG& cfg) { 65 Environment& env, Flow::CFG& cfg) {
32 IR::Program program; 66 IR::Program program;
@@ -51,6 +85,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
51 Optimization::IdentityRemovalPass(program); 85 Optimization::IdentityRemovalPass(program);
52 Optimization::VerificationPass(program); 86 Optimization::VerificationPass(program);
53 Optimization::CollectShaderInfoPass(program); 87 Optimization::CollectShaderInfoPass(program);
88 CollectInterpolationInfo(env, program);
54 return program; 89 return program;
55} 90}
56 91
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
index 516ffec2d..54bc1e34c 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp
@@ -151,16 +151,8 @@ void TranslatorVisitor::IPA(u64 insn) {
151 value = ir.FPMul(value, position_w); 151 value = ir.FPMul(value, position_w);
152 } 152 }
153 } 153 }
154 switch (ipa.interpolation_mode) { 154 if (ipa.interpolation_mode == InterpolationMode::Multiply) {
155 case InterpolationMode::Pass:
156 break;
157 case InterpolationMode::Multiply:
158 value = ir.FPMul(value, F(ipa.multiplier)); 155 value = ir.FPMul(value, F(ipa.multiplier));
159 break;
160 case InterpolationMode::Constant:
161 throw NotImplementedException("IPA.CONSTANT");
162 case InterpolationMode::Sc:
163 throw NotImplementedException("IPA.SC");
164 } 156 }
165 157
166 // Saturated IPAs are generally generated out of clamped varyings. 158 // Saturated IPAs are generally generated out of clamped varyings.
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
index 0ec0d4c01..60be67228 100644
--- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
+++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
@@ -28,7 +28,7 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) {
28 28
29void GetAttribute(Info& info, IR::Attribute attribute) { 29void GetAttribute(Info& info, IR::Attribute attribute) {
30 if (IR::IsGeneric(attribute)) { 30 if (IR::IsGeneric(attribute)) {
31 info.loads_generics.at(IR::GenericAttributeIndex(attribute)) = true; 31 info.input_generics.at(IR::GenericAttributeIndex(attribute)).used = true;
32 return; 32 return;
33 } 33 }
34 switch (attribute) { 34 switch (attribute) {
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 41550bfc6..e26047751 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -14,6 +14,7 @@ enum class AttributeType : u8 {
14 Float, 14 Float,
15 SignedInt, 15 SignedInt,
16 UnsignedInt, 16 UnsignedInt,
17 Disabled,
17}; 18};
18 19
19struct Profile { 20struct Profile {
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index 8ab66bb2a..9111159f3 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -31,6 +31,17 @@ enum class TextureType : u32 {
31 ShadowArrayCube, 31 ShadowArrayCube,
32}; 32};
33 33
34enum class Interpolation {
35 Smooth,
36 Flat,
37 NoPerspective,
38};
39
40struct InputVarying {
41 Interpolation interpolation{Interpolation::Smooth};
42 bool used{false};
43};
44
34struct TextureDescriptor { 45struct TextureDescriptor {
35 TextureType type; 46 TextureType type;
36 u32 cbuf_index; 47 u32 cbuf_index;
@@ -58,7 +69,7 @@ struct Info {
58 bool uses_local_invocation_id{}; 69 bool uses_local_invocation_id{};
59 bool uses_subgroup_invocation_id{}; 70 bool uses_subgroup_invocation_id{};
60 71
61 std::array<bool, 32> loads_generics{}; 72 std::array<InputVarying, 32> input_generics{};
62 bool loads_position{}; 73 bool loads_position{};
63 bool loads_instance_id{}; 74 bool loads_instance_id{};
64 bool loads_vertex_id{}; 75 bool loads_vertex_id{};
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 82536b9d6..278509bf0 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -221,10 +221,10 @@ void GraphicsPipeline::MakePipeline(const Device& device, const FixedPipelineSta
221 } 221 }
222 } 222 }
223 static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes; 223 static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes;
224 const auto& input_attributes = stage_infos[0].loads_generics; 224 const auto& input_attributes = stage_infos[0].input_generics;
225 for (size_t index = 0; index < state.attributes.size(); ++index) { 225 for (size_t index = 0; index < state.attributes.size(); ++index) {
226 const auto& attribute = state.attributes[index]; 226 const auto& attribute = state.attributes[index];
227 if (!attribute.enabled || !input_attributes[index]) { 227 if (!attribute.enabled || !input_attributes[index].used) {
228 continue; 228 continue;
229 } 229 }
230 vertex_attributes.push_back({ 230 vertex_attributes.push_back({
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 251559b16..69dd945b2 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -755,6 +755,9 @@ ComputePipeline PipelineCache::CreateComputePipeline(ShaderPools& pools,
755} 755}
756 756
757static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribute& attr) { 757static Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribute& attr) {
758 if (attr.enabled == 0) {
759 return Shader::AttributeType::Disabled;
760 }
758 switch (attr.Type()) { 761 switch (attr.Type()) {
759 case Maxwell::VertexAttribute::Type::SignedNorm: 762 case Maxwell::VertexAttribute::Type::SignedNorm:
760 case Maxwell::VertexAttribute::Type::UnsignedNorm: 763 case Maxwell::VertexAttribute::Type::UnsignedNorm: