summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Rodrigo Locatti2019-12-16 01:26:11 -0300
committerGravatar GitHub2019-12-16 01:26:11 -0300
commiteac075692be0df873df04cbe8e09296f64d1dfe1 (patch)
treeba39ab7d01d91a606aabd41f84ed11455b283459 /src
parentMerge pull request #3222 from ReinUsesLisp/maxwell-to-vk (diff)
parentShader_IR: Correct TLD4S Depth Compare. (diff)
downloadyuzu-eac075692be0df873df04cbe8e09296f64d1dfe1.tar.gz
yuzu-eac075692be0df873df04cbe8e09296f64d1dfe1.tar.xz
yuzu-eac075692be0df873df04cbe8e09296f64d1dfe1.zip
Merge pull request #3219 from FernandoS27/fix-bindless
Corrections and fixes to TLD4S & bindless samplers failing
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp29
-rw-r--r--src/video_core/shader/decode/texture.cpp133
-rw-r--r--src/video_core/shader/shader_ir.h6
4 files changed, 124 insertions, 47 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 290d929df..d6a2cc8b8 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1292,6 +1292,7 @@ union Instruction {
1292 BitField<50, 1, u64> dc_flag; 1292 BitField<50, 1, u64> dc_flag;
1293 BitField<51, 1, u64> aoffi_flag; 1293 BitField<51, 1, u64> aoffi_flag;
1294 BitField<52, 2, u64> component; 1294 BitField<52, 2, u64> component;
1295 BitField<55, 1, u64> fp16_flag;
1295 1296
1296 bool UsesMiscMode(TextureMiscMode mode) const { 1297 bool UsesMiscMode(TextureMiscMode mode) const {
1297 switch (mode) { 1298 switch (mode) {
@@ -1972,7 +1973,7 @@ private:
1972 INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"), 1973 INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"),
1973 INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"), 1974 INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"),
1974 INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"), 1975 INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"),
1975 INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), 1976 INST("11011111--00----", Id::TLD4S, Type::Texture, "TLD4S"),
1976 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), 1977 INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"),
1977 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), 1978 INST("1101111101011---", Id::TMML, Type::Texture, "TMML"),
1978 INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"), 1979 INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index fa7049bbe..d1ae4be6d 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1076,7 +1076,7 @@ private:
1076 } 1076 }
1077 1077
1078 std::string GenerateTexture(Operation operation, const std::string& function_suffix, 1078 std::string GenerateTexture(Operation operation, const std::string& function_suffix,
1079 const std::vector<TextureIR>& extras) { 1079 const std::vector<TextureIR>& extras, bool sepparate_dc = false) {
1080 constexpr std::array coord_constructors = {"float", "vec2", "vec3", "vec4"}; 1080 constexpr std::array coord_constructors = {"float", "vec2", "vec3", "vec4"};
1081 1081
1082 const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); 1082 const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
@@ -1091,7 +1091,8 @@ private:
1091 expr += "Offset"; 1091 expr += "Offset";
1092 } 1092 }
1093 expr += '(' + GetSampler(meta->sampler) + ", "; 1093 expr += '(' + GetSampler(meta->sampler) + ", ";
1094 expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1); 1094 expr += coord_constructors.at(count + (has_array ? 1 : 0) +
1095 (has_shadow && !sepparate_dc ? 1 : 0) - 1);
1095 expr += '('; 1096 expr += '(';
1096 for (std::size_t i = 0; i < count; ++i) { 1097 for (std::size_t i = 0; i < count; ++i) {
1097 expr += Visit(operation[i]).AsFloat(); 1098 expr += Visit(operation[i]).AsFloat();
@@ -1104,9 +1105,14 @@ private:
1104 expr += ", float(" + Visit(meta->array).AsInt() + ')'; 1105 expr += ", float(" + Visit(meta->array).AsInt() + ')';
1105 } 1106 }
1106 if (has_shadow) { 1107 if (has_shadow) {
1107 expr += ", " + Visit(meta->depth_compare).AsFloat(); 1108 if (sepparate_dc) {
1109 expr += "), " + Visit(meta->depth_compare).AsFloat();
1110 } else {
1111 expr += ", " + Visit(meta->depth_compare).AsFloat() + ')';
1112 }
1113 } else {
1114 expr += ')';
1108 } 1115 }
1109 expr += ')';
1110 1116
1111 for (const auto& variant : extras) { 1117 for (const auto& variant : extras) {
1112 if (const auto argument = std::get_if<TextureArgument>(&variant)) { 1118 if (const auto argument = std::get_if<TextureArgument>(&variant)) {
@@ -1706,10 +1712,17 @@ private:
1706 ASSERT(meta); 1712 ASSERT(meta);
1707 1713
1708 const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; 1714 const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
1709 return {GenerateTexture(operation, "Gather", 1715 if (meta->sampler.IsShadow()) {
1710 {TextureAoffi{}, TextureArgument{type, meta->component}}) + 1716 return {GenerateTexture(operation, "Gather", {TextureAoffi{}}, true) +
1711 GetSwizzle(meta->element), 1717 GetSwizzle(meta->element),
1712 Type::Float}; 1718 Type::Float};
1719 } else {
1720 return {GenerateTexture(operation, "Gather",
1721 {TextureAoffi{}, TextureArgument{type, meta->component}},
1722 false) +
1723 GetSwizzle(meta->element),
1724 Type::Float};
1725 }
1713 } 1726 }
1714 1727
1715 Expression TextureQueryDimensions(Operation operation) { 1728 Expression TextureQueryDimensions(Operation operation) {
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index da8e886df..994c05611 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -107,8 +107,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
107 break; 107 break;
108 } 108 }
109 case OpCode::Id::TLD4S: { 109 case OpCode::Id::TLD4S: {
110 UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), 110 const bool uses_aoffi = instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI);
111 "AOFFI is not implemented"); 111 UNIMPLEMENTED_IF_MSG(uses_aoffi, "AOFFI is not implemented");
112 112
113 const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC); 113 const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC);
114 const Node op_a = GetRegister(instr.gpr8); 114 const Node op_a = GetRegister(instr.gpr8);
@@ -116,29 +116,40 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
116 116
117 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. 117 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
118 std::vector<Node> coords; 118 std::vector<Node> coords;
119 Node dc_reg;
119 if (depth_compare) { 120 if (depth_compare) {
120 // Note: TLD4S coordinate encoding works just like TEXS's 121 // Note: TLD4S coordinate encoding works just like TEXS's
121 const Node op_y = GetRegister(instr.gpr8.Value() + 1); 122 const Node op_y = GetRegister(instr.gpr8.Value() + 1);
122 coords.push_back(op_a); 123 coords.push_back(op_a);
123 coords.push_back(op_y); 124 coords.push_back(op_y);
124 coords.push_back(op_b); 125 dc_reg = uses_aoffi ? GetRegister(instr.gpr20.Value() + 1) : op_b;
125 } else { 126 } else {
126 coords.push_back(op_a); 127 coords.push_back(op_a);
127 coords.push_back(op_b); 128 if (uses_aoffi) {
129 const Node op_y = GetRegister(instr.gpr8.Value() + 1);
130 coords.push_back(op_y);
131 } else {
132 coords.push_back(op_b);
133 }
134 dc_reg = {};
128 } 135 }
129 const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); 136 const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
130 137
131 const SamplerInfo info{TextureType::Texture2D, false, depth_compare}; 138 const SamplerInfo info{TextureType::Texture2D, false, depth_compare};
132 const auto& sampler = GetSampler(instr.sampler, info); 139 const Sampler& sampler = *GetSampler(instr.sampler, info);
133 140
134 Node4 values; 141 Node4 values;
135 for (u32 element = 0; element < values.size(); ++element) { 142 for (u32 element = 0; element < values.size(); ++element) {
136 auto coords_copy = coords; 143 auto coords_copy = coords;
137 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element}; 144 MetaTexture meta{sampler, {}, dc_reg, {}, {}, {}, {}, component, element};
138 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); 145 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
139 } 146 }
140 147
141 WriteTexsInstructionFloat(bb, instr, values, true); 148 if (instr.tld4s.fp16_flag) {
149 WriteTexsInstructionHalfFloat(bb, instr, values, true);
150 } else {
151 WriteTexsInstructionFloat(bb, instr, values, true);
152 }
142 break; 153 break;
143 } 154 }
144 case OpCode::Id::TXD_B: 155 case OpCode::Id::TXD_B:
@@ -154,9 +165,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
154 const auto texture_type = instr.txd.texture_type.Value(); 165 const auto texture_type = instr.txd.texture_type.Value();
155 const auto coord_count = GetCoordCount(texture_type); 166 const auto coord_count = GetCoordCount(texture_type);
156 167
157 const auto& sampler = is_bindless 168 const Sampler* sampler = is_bindless
158 ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) 169 ? GetBindlessSampler(base_reg, {{texture_type, false, false}})
159 : GetSampler(instr.sampler, {{texture_type, false, false}}); 170 : GetSampler(instr.sampler, {{texture_type, false, false}});
171 Node4 values;
172 if (sampler == nullptr) {
173 for (u32 element = 0; element < values.size(); ++element) {
174 values[element] = Immediate(0);
175 }
176 WriteTexInstructionFloat(bb, instr, values);
177 break;
178 }
160 if (is_bindless) { 179 if (is_bindless) {
161 base_reg++; 180 base_reg++;
162 } 181 }
@@ -170,9 +189,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
170 derivates.push_back(GetRegister(derivate_reg + derivate + 1)); 189 derivates.push_back(GetRegister(derivate_reg + derivate + 1));
171 } 190 }
172 191
173 Node4 values;
174 for (u32 element = 0; element < values.size(); ++element) { 192 for (u32 element = 0; element < values.size(); ++element) {
175 MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element}; 193 MetaTexture meta{*sampler, {}, {}, {}, derivates, {}, {}, {}, element};
176 values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); 194 values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords);
177 } 195 }
178 196
@@ -187,9 +205,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
187 // TODO: The new commits on the texture refactor, change the way samplers work. 205 // TODO: The new commits on the texture refactor, change the way samplers work.
188 // Sadly, not all texture instructions specify the type of texture their sampler 206 // Sadly, not all texture instructions specify the type of texture their sampler
189 // uses. This must be fixed at a later instance. 207 // uses. This must be fixed at a later instance.
190 const auto& sampler = 208 const Sampler* sampler =
191 is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); 209 is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler);
192 210
211 if (sampler == nullptr) {
212 u32 indexer = 0;
213 for (u32 element = 0; element < 4; ++element) {
214 if (!instr.txq.IsComponentEnabled(element)) {
215 continue;
216 }
217 const Node value = Immediate(0);
218 SetTemporary(bb, indexer++, value);
219 }
220 for (u32 i = 0; i < indexer; ++i) {
221 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
222 }
223 break;
224 }
225
193 u32 indexer = 0; 226 u32 indexer = 0;
194 switch (instr.txq.query_type) { 227 switch (instr.txq.query_type) {
195 case Tegra::Shader::TextureQueryType::Dimension: { 228 case Tegra::Shader::TextureQueryType::Dimension: {
@@ -197,7 +230,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
197 if (!instr.txq.IsComponentEnabled(element)) { 230 if (!instr.txq.IsComponentEnabled(element)) {
198 continue; 231 continue;
199 } 232 }
200 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; 233 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element};
201 const Node value = 234 const Node value =
202 Operation(OperationCode::TextureQueryDimensions, meta, 235 Operation(OperationCode::TextureQueryDimensions, meta,
203 GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); 236 GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0)));
@@ -223,9 +256,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
223 256
224 auto texture_type = instr.tmml.texture_type.Value(); 257 auto texture_type = instr.tmml.texture_type.Value();
225 const bool is_array = instr.tmml.array != 0; 258 const bool is_array = instr.tmml.array != 0;
226 const auto& sampler = 259 const Sampler* sampler =
227 is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); 260 is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler);
228 261
262 if (sampler == nullptr) {
263 u32 indexer = 0;
264 for (u32 element = 0; element < 2; ++element) {
265 if (!instr.tmml.IsComponentEnabled(element)) {
266 continue;
267 }
268 const Node value = Immediate(0);
269 SetTemporary(bb, indexer++, value);
270 }
271 for (u32 i = 0; i < indexer; ++i) {
272 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
273 }
274 break;
275 }
276
229 std::vector<Node> coords; 277 std::vector<Node> coords;
230 278
231 // TODO: Add coordinates for different samplers once other texture types are implemented. 279 // TODO: Add coordinates for different samplers once other texture types are implemented.
@@ -251,7 +299,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
251 continue; 299 continue;
252 } 300 }
253 auto params = coords; 301 auto params = coords;
254 MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; 302 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element};
255 const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); 303 const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
256 SetTemporary(bb, indexer++, value); 304 SetTemporary(bb, indexer++, value);
257 } 305 }
@@ -307,7 +355,7 @@ ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sample
307 sampler->is_buffer != 0}; 355 sampler->is_buffer != 0};
308} 356}
309 357
310const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, 358const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
311 std::optional<SamplerInfo> sampler_info) { 359 std::optional<SamplerInfo> sampler_info) {
312 const auto offset = static_cast<u32>(sampler.index.Value()); 360 const auto offset = static_cast<u32>(sampler.index.Value());
313 const auto info = GetSamplerInfo(sampler_info, offset); 361 const auto info = GetSamplerInfo(sampler_info, offset);
@@ -319,21 +367,24 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
319 if (it != used_samplers.end()) { 367 if (it != used_samplers.end()) {
320 ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && 368 ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array &&
321 it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); 369 it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer);
322 return *it; 370 return &(*it);
323 } 371 }
324 372
325 // Otherwise create a new mapping for this sampler 373 // Otherwise create a new mapping for this sampler
326 const auto next_index = static_cast<u32>(used_samplers.size()); 374 const auto next_index = static_cast<u32>(used_samplers.size());
327 return used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, 375 return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
328 info.is_buffer); 376 info.is_buffer);
329} 377}
330 378
331const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, 379const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
332 std::optional<SamplerInfo> sampler_info) { 380 std::optional<SamplerInfo> sampler_info) {
333 const Node sampler_register = GetRegister(reg); 381 const Node sampler_register = GetRegister(reg);
334 const auto [base_sampler, buffer, offset] = 382 const auto [base_sampler, buffer, offset] =
335 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 383 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
336 ASSERT(base_sampler != nullptr); 384 ASSERT(base_sampler != nullptr);
385 if (base_sampler == nullptr) {
386 return nullptr;
387 }
337 388
338 const auto info = GetSamplerInfo(sampler_info, offset, buffer); 389 const auto info = GetSamplerInfo(sampler_info, offset, buffer);
339 390
@@ -346,13 +397,13 @@ const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
346 if (it != used_samplers.end()) { 397 if (it != used_samplers.end()) {
347 ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && 398 ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array &&
348 it->IsShadow() == info.is_shadow); 399 it->IsShadow() == info.is_shadow);
349 return *it; 400 return &(*it);
350 } 401 }
351 402
352 // Otherwise create a new mapping for this sampler 403 // Otherwise create a new mapping for this sampler
353 const auto next_index = static_cast<u32>(used_samplers.size()); 404 const auto next_index = static_cast<u32>(used_samplers.size());
354 return used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, 405 return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
355 info.is_shadow, info.is_buffer); 406 info.is_shadow, info.is_buffer);
356} 407}
357 408
358void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 409void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
@@ -395,14 +446,14 @@ void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr, const
395} 446}
396 447
397void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr, 448void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr,
398 const Node4& components) { 449 const Node4& components, bool ignore_mask) {
399 // TEXS.F16 destionation registers are packed in two registers in pairs (just like any half 450 // TEXS.F16 destionation registers are packed in two registers in pairs (just like any half
400 // float instruction). 451 // float instruction).
401 452
402 Node4 values; 453 Node4 values;
403 u32 dest_elem = 0; 454 u32 dest_elem = 0;
404 for (u32 component = 0; component < 4; ++component) { 455 for (u32 component = 0; component < 4; ++component) {
405 if (!instr.texs.IsComponentEnabled(component)) 456 if (!instr.texs.IsComponentEnabled(component) && !ignore_mask)
406 continue; 457 continue;
407 values[dest_elem++] = components[component]; 458 values[dest_elem++] = components[component];
408 } 459 }
@@ -438,8 +489,15 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
438 "This method is not supported."); 489 "This method is not supported.");
439 490
440 const SamplerInfo info{texture_type, is_array, is_shadow, false}; 491 const SamplerInfo info{texture_type, is_array, is_shadow, false};
441 const auto& sampler = 492 const Sampler* sampler =
442 is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); 493 is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info);
494 Node4 values;
495 if (sampler == nullptr) {
496 for (u32 element = 0; element < values.size(); ++element) {
497 values[element] = Immediate(0);
498 }
499 return values;
500 }
443 501
444 const bool lod_needed = process_mode == TextureProcessMode::LZ || 502 const bool lod_needed = process_mode == TextureProcessMode::LZ ||
445 process_mode == TextureProcessMode::LL || 503 process_mode == TextureProcessMode::LL ||
@@ -478,10 +536,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
478 } 536 }
479 } 537 }
480 538
481 Node4 values;
482 for (u32 element = 0; element < values.size(); ++element) { 539 for (u32 element = 0; element < values.size(); ++element) {
483 auto copy_coords = coords; 540 auto copy_coords = coords;
484 MetaTexture meta{sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; 541 MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element};
485 values[element] = Operation(read_method, meta, std::move(copy_coords)); 542 values[element] = Operation(read_method, meta, std::move(copy_coords));
486 } 543 }
487 544
@@ -594,8 +651,15 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
594 u64 parameter_register = instr.gpr20.Value(); 651 u64 parameter_register = instr.gpr20.Value();
595 652
596 const SamplerInfo info{texture_type, is_array, depth_compare, false}; 653 const SamplerInfo info{texture_type, is_array, depth_compare, false};
597 const auto& sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) 654 const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info)
598 : GetSampler(instr.sampler, info); 655 : GetSampler(instr.sampler, info);
656 Node4 values;
657 if (sampler == nullptr) {
658 for (u32 element = 0; element < values.size(); ++element) {
659 values[element] = Immediate(0);
660 }
661 return values;
662 }
599 663
600 std::vector<Node> aoffi; 664 std::vector<Node> aoffi;
601 if (is_aoffi) { 665 if (is_aoffi) {
@@ -610,10 +674,9 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
610 const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component)) 674 const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component))
611 : Immediate(static_cast<u32>(instr.tld4.component)); 675 : Immediate(static_cast<u32>(instr.tld4.component));
612 676
613 Node4 values;
614 for (u32 element = 0; element < values.size(); ++element) { 677 for (u32 element = 0; element < values.size(); ++element) {
615 auto coords_copy = coords; 678 auto coords_copy = coords;
616 MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, 679 MetaTexture meta{*sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component,
617 element}; 680 element};
618 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); 681 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
619 } 682 }
@@ -642,7 +705,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
642 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; 705 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr};
643 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; 706 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr};
644 707
645 const auto& sampler = GetSampler(instr.sampler); 708 const auto& sampler = *GetSampler(instr.sampler);
646 709
647 Node4 values; 710 Node4 values;
648 for (u32 element = 0; element < values.size(); ++element) { 711 for (u32 element = 0; element < values.size(); ++element) {
@@ -655,7 +718,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
655} 718}
656 719
657Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { 720Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) {
658 const auto& sampler = GetSampler(instr.sampler); 721 const Sampler& sampler = *GetSampler(instr.sampler);
659 722
660 const std::size_t type_coord_count = GetCoordCount(texture_type); 723 const std::size_t type_coord_count = GetCoordCount(texture_type);
661 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; 724 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL;
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 580f84fcb..04ae5f822 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -313,11 +313,11 @@ private:
313 std::optional<u32> buffer = std::nullopt); 313 std::optional<u32> buffer = std::nullopt);
314 314
315 /// Accesses a texture sampler 315 /// Accesses a texture sampler
316 const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler, 316 const Sampler* GetSampler(const Tegra::Shader::Sampler& sampler,
317 std::optional<SamplerInfo> sampler_info = std::nullopt); 317 std::optional<SamplerInfo> sampler_info = std::nullopt);
318 318
319 /// Accesses a texture sampler for a bindless texture. 319 /// Accesses a texture sampler for a bindless texture.
320 const Sampler& GetBindlessSampler(Tegra::Shader::Register reg, 320 const Sampler* GetBindlessSampler(Tegra::Shader::Register reg,
321 std::optional<SamplerInfo> sampler_info = std::nullopt); 321 std::optional<SamplerInfo> sampler_info = std::nullopt);
322 322
323 /// Accesses an image. 323 /// Accesses an image.
@@ -338,7 +338,7 @@ private:
338 void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, 338 void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
339 const Node4& components, bool ignore_mask = false); 339 const Node4& components, bool ignore_mask = false);
340 void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, 340 void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
341 const Node4& components); 341 const Node4& components, bool ignore_mask = false);
342 342
343 Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, 343 Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type,
344 Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, 344 Tegra::Shader::TextureProcessMode process_mode, bool depth_compare,