summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/decode/texture.cpp125
-rw-r--r--src/video_core/shader/shader_ir.h24
2 files changed, 87 insertions, 62 deletions
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 193368c29..8f0bb996e 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -139,7 +139,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
139 } 139 }
140 const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); 140 const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
141 141
142 const SamplerInfo info{TextureType::Texture2D, false, is_depth_compare, false}; 142 SamplerInfo info;
143 info.is_shadow = is_depth_compare;
143 const std::optional<Sampler> sampler = GetSampler(instr.sampler, info); 144 const std::optional<Sampler> sampler = GetSampler(instr.sampler, info);
144 145
145 Node4 values; 146 Node4 values;
@@ -164,20 +165,20 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
164 "AOFFI is not implemented"); 165 "AOFFI is not implemented");
165 166
166 const bool is_array = instr.txd.is_array != 0; 167 const bool is_array = instr.txd.is_array != 0;
167 u64 base_reg = instr.gpr8.Value();
168 const auto derivate_reg = instr.gpr20.Value(); 168 const auto derivate_reg = instr.gpr20.Value();
169 const auto texture_type = instr.txd.texture_type.Value(); 169 const auto texture_type = instr.txd.texture_type.Value();
170 const auto coord_count = GetCoordCount(texture_type); 170 const auto coord_count = GetCoordCount(texture_type);
171 Node index_var{}; 171 u64 base_reg = instr.gpr8.Value();
172 const std::optional<Sampler> sampler = 172 Node index_var;
173 is_bindless 173 SamplerInfo info;
174 ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false, false}}) 174 info.type = texture_type;
175 : GetSampler(instr.sampler, {{texture_type, is_array, false, false}}); 175 info.is_array = is_array;
176 const std::optional<Sampler> sampler = is_bindless
177 ? GetBindlessSampler(base_reg, info, index_var)
178 : GetSampler(instr.sampler, info);
176 Node4 values; 179 Node4 values;
177 if (!sampler) { 180 if (!sampler) {
178 for (u32 element = 0; element < values.size(); ++element) { 181 std::generate(values.begin(), values.end(), [this] { return Immediate(0); });
179 values[element] = Immediate(0);
180 }
181 WriteTexInstructionFloat(bb, instr, values); 182 WriteTexInstructionFloat(bb, instr, values);
182 break; 183 break;
183 } 184 }
@@ -215,12 +216,10 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
215 is_bindless = true; 216 is_bindless = true;
216 [[fallthrough]]; 217 [[fallthrough]];
217 case OpCode::Id::TXQ: { 218 case OpCode::Id::TXQ: {
218 // TODO: The new commits on the texture refactor, change the way samplers work. 219 Node index_var;
219 // Sadly, not all texture instructions specify the type of texture their sampler 220 const std::optional<Sampler> sampler = is_bindless
220 // uses. This must be fixed at a later instance. 221 ? GetBindlessSampler(instr.gpr8, {}, index_var)
221 Node index_var{}; 222 : GetSampler(instr.sampler, {});
222 const std::optional<Sampler> sampler =
223 is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler);
224 223
225 if (!sampler) { 224 if (!sampler) {
226 u32 indexer = 0; 225 u32 indexer = 0;
@@ -268,10 +267,15 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
268 UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), 267 UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
269 "NDV is not implemented"); 268 "NDV is not implemented");
270 269
271 auto texture_type = instr.tmml.texture_type.Value(); 270 const auto texture_type = instr.tmml.texture_type.Value();
272 Node index_var{}; 271 const bool is_array = instr.tmml.array != 0;
272 SamplerInfo info;
273 info.type = texture_type;
274 info.is_array = is_array;
275 Node index_var;
273 const std::optional<Sampler> sampler = 276 const std::optional<Sampler> sampler =
274 is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler); 277 is_bindless ? GetBindlessSampler(instr.gpr20, info, index_var)
278 : GetSampler(instr.sampler, info);
275 279
276 if (!sampler) { 280 if (!sampler) {
277 u32 indexer = 0; 281 u32 indexer = 0;
@@ -300,12 +304,11 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
300 coords.push_back(GetRegister(instr.gpr8.Value() + 1)); 304 coords.push_back(GetRegister(instr.gpr8.Value() + 1));
301 break; 305 break;
302 default: 306 default:
303 UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<u32>(texture_type)); 307 UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<int>(texture_type));
304 308
305 // Fallback to interpreting as a 2D texture for now 309 // Fallback to interpreting as a 2D texture for now
306 coords.push_back(GetRegister(instr.gpr8.Value() + 0)); 310 coords.push_back(GetRegister(instr.gpr8.Value() + 0));
307 coords.push_back(GetRegister(instr.gpr8.Value() + 1)); 311 coords.push_back(GetRegister(instr.gpr8.Value() + 1));
308 texture_type = TextureType::Texture2D;
309 } 312 }
310 u32 indexer = 0; 313 u32 indexer = 0;
311 for (u32 element = 0; element < 2; ++element) { 314 for (u32 element = 0; element < 2; ++element) {
@@ -354,23 +357,30 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
354 return pc; 357 return pc;
355} 358}
356 359
357ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sampler_info, u32 offset, 360ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(SamplerInfo info, u32 offset,
358 std::optional<u32> buffer) { 361 std::optional<u32> buffer) {
359 if (sampler_info) { 362 if (info.IsComplete()) {
360 return *sampler_info; 363 return info;
361 } 364 }
362 const auto sampler = buffer ? registry.ObtainBindlessSampler(*buffer, offset) 365 const auto sampler = buffer ? registry.ObtainBindlessSampler(*buffer, offset)
363 : registry.ObtainBoundSampler(offset); 366 : registry.ObtainBoundSampler(offset);
364 if (!sampler) { 367 if (!sampler) {
365 LOG_WARNING(HW_GPU, "Unknown sampler info"); 368 LOG_WARNING(HW_GPU, "Unknown sampler info");
366 return SamplerInfo{TextureType::Texture2D, false, false, false}; 369 info.type = info.type.value_or(Tegra::Shader::TextureType::Texture2D);
367 } 370 info.is_array = info.is_array.value_or(false);
368 return SamplerInfo{sampler->texture_type, sampler->is_array != 0, sampler->is_shadow != 0, 371 info.is_shadow = info.is_shadow.value_or(false);
369 sampler->is_buffer != 0}; 372 info.is_buffer = info.is_buffer.value_or(false);
373 return info;
374 }
375 info.type = info.type.value_or(sampler->texture_type);
376 info.is_array = info.is_array.value_or(sampler->is_array != 0);
377 info.is_shadow = info.is_shadow.value_or(sampler->is_shadow != 0);
378 info.is_buffer = info.is_buffer.value_or(sampler->is_buffer != 0);
379 return info;
370} 380}
371 381
372std::optional<Sampler> ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, 382std::optional<Sampler> ShaderIR::GetSampler(Tegra::Shader::Sampler sampler,
373 std::optional<SamplerInfo> sampler_info) { 383 SamplerInfo sampler_info) {
374 const auto offset = static_cast<u32>(sampler.index.Value()); 384 const auto offset = static_cast<u32>(sampler.index.Value());
375 const auto info = GetSamplerInfo(sampler_info, offset); 385 const auto info = GetSamplerInfo(sampler_info, offset);
376 386
@@ -385,12 +395,12 @@ std::optional<Sampler> ShaderIR::GetSampler(const Tegra::Shader::Sampler& sample
385 395
386 // Otherwise create a new mapping for this sampler 396 // Otherwise create a new mapping for this sampler
387 const auto next_index = static_cast<u32>(used_samplers.size()); 397 const auto next_index = static_cast<u32>(used_samplers.size());
388 return used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, 398 return used_samplers.emplace_back(next_index, offset, *info.type, *info.is_array,
389 info.is_buffer, false); 399 *info.is_shadow, *info.is_buffer, false);
390} 400}
391 401
392std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, 402std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, SamplerInfo info,
393 std::optional<SamplerInfo> sampler_info) { 403 Node& index_var) {
394 const Node sampler_register = GetRegister(reg); 404 const Node sampler_register = GetRegister(reg);
395 const auto [base_node, tracked_sampler_info] = 405 const auto [base_node, tracked_sampler_info] =
396 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size())); 406 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size()));
@@ -403,7 +413,7 @@ std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
403 std::get_if<BindlessSamplerNode>(&*tracked_sampler_info)) { 413 std::get_if<BindlessSamplerNode>(&*tracked_sampler_info)) {
404 const u32 buffer = bindless_sampler_info->GetIndex(); 414 const u32 buffer = bindless_sampler_info->GetIndex();
405 const u32 offset = bindless_sampler_info->GetOffset(); 415 const u32 offset = bindless_sampler_info->GetOffset();
406 const auto info = GetSamplerInfo(sampler_info, offset, buffer); 416 info = GetSamplerInfo(info, offset, buffer);
407 417
408 // If this sampler has already been used, return the existing mapping. 418 // If this sampler has already been used, return the existing mapping.
409 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(), 419 const auto it = std::find_if(used_samplers.begin(), used_samplers.end(),
@@ -418,13 +428,13 @@ std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
418 428
419 // Otherwise create a new mapping for this sampler 429 // Otherwise create a new mapping for this sampler
420 const auto next_index = static_cast<u32>(used_samplers.size()); 430 const auto next_index = static_cast<u32>(used_samplers.size());
421 return used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, 431 return used_samplers.emplace_back(next_index, offset, buffer, *info.type, *info.is_array,
422 info.is_shadow, info.is_buffer, false); 432 *info.is_shadow, *info.is_buffer, false);
423 } 433 }
424 if (const auto array_sampler_info = std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { 434 if (const auto array_sampler_info = std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
425 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; 435 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4;
426 index_var = GetCustomVariable(array_sampler_info->GetIndexVar()); 436 index_var = GetCustomVariable(array_sampler_info->GetIndexVar());
427 const auto info = GetSamplerInfo(sampler_info, base_offset); 437 info = GetSamplerInfo(info, base_offset);
428 438
429 // If this sampler has already been used, return the existing mapping. 439 // If this sampler has already been used, return the existing mapping.
430 const auto it = std::find_if( 440 const auto it = std::find_if(
@@ -440,8 +450,8 @@ std::optional<Sampler> ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
440 uses_indexed_samplers = true; 450 uses_indexed_samplers = true;
441 // Otherwise create a new mapping for this sampler 451 // Otherwise create a new mapping for this sampler
442 const auto next_index = static_cast<u32>(used_samplers.size()); 452 const auto next_index = static_cast<u32>(used_samplers.size());
443 return used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array, 453 return used_samplers.emplace_back(next_index, base_offset, *info.type, *info.is_array,
444 info.is_shadow, info.is_buffer, true); 454 *info.is_shadow, *info.is_buffer, true);
445 } 455 }
446 return std::nullopt; 456 return std::nullopt;
447} 457}
@@ -528,11 +538,16 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
528 ASSERT_MSG(texture_type != TextureType::Texture3D || !is_array || !is_shadow, 538 ASSERT_MSG(texture_type != TextureType::Texture3D || !is_array || !is_shadow,
529 "Illegal texture type"); 539 "Illegal texture type");
530 540
531 const SamplerInfo info{texture_type, is_array, is_shadow, false}; 541 SamplerInfo info;
542 info.type = texture_type;
543 info.is_array = is_array;
544 info.is_shadow = is_shadow;
545 info.is_buffer = false;
546
532 Node index_var; 547 Node index_var;
533 std::optional<Sampler> sampler = is_bindless 548 const std::optional<Sampler> sampler = is_bindless
534 ? GetBindlessSampler(*bindless_reg, index_var, info) 549 ? GetBindlessSampler(*bindless_reg, info, index_var)
535 : GetSampler(instr.sampler, info); 550 : GetSampler(instr.sampler, info);
536 if (!sampler) { 551 if (!sampler) {
537 return {Immediate(0), Immediate(0), Immediate(0), Immediate(0)}; 552 return {Immediate(0), Immediate(0), Immediate(0), Immediate(0)};
538 } 553 }
@@ -683,10 +698,14 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
683 698
684 u64 parameter_register = instr.gpr20.Value(); 699 u64 parameter_register = instr.gpr20.Value();
685 700
686 const SamplerInfo info{texture_type, is_array, depth_compare, false}; 701 SamplerInfo info;
687 Node index_var{}; 702 info.type = texture_type;
703 info.is_array = is_array;
704 info.is_shadow = depth_compare;
705
706 Node index_var;
688 const std::optional<Sampler> sampler = 707 const std::optional<Sampler> sampler =
689 is_bindless ? GetBindlessSampler(parameter_register++, index_var, info) 708 is_bindless ? GetBindlessSampler(parameter_register++, info, index_var)
690 : GetSampler(instr.sampler, info); 709 : GetSampler(instr.sampler, info);
691 Node4 values; 710 Node4 values;
692 if (!sampler) { 711 if (!sampler) {
@@ -744,12 +763,12 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
744 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; 763 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr};
745 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; 764 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr};
746 765
747 const auto& sampler = *GetSampler(instr.sampler); 766 const std::optional<Sampler> sampler = GetSampler(instr.sampler, {});
748 767
749 Node4 values; 768 Node4 values;
750 for (u32 element = 0; element < values.size(); ++element) { 769 for (u32 element = 0; element < values.size(); ++element) {
751 auto coords_copy = coords; 770 auto coords_copy = coords;
752 MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element, {}}; 771 MetaTexture meta{*sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element, {}};
753 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 772 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
754 } 773 }
755 774
@@ -757,7 +776,11 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
757} 776}
758 777
759Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { 778Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) {
760 const Sampler& sampler = *GetSampler(instr.sampler); 779 SamplerInfo info;
780 info.type = texture_type;
781 info.is_array = is_array;
782 info.is_shadow = false;
783 const std::optional<Sampler> sampler = GetSampler(instr.sampler, info);
761 784
762 const std::size_t type_coord_count = GetCoordCount(texture_type); 785 const std::size_t type_coord_count = GetCoordCount(texture_type);
763 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; 786 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL;
@@ -785,7 +808,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
785 Node4 values; 808 Node4 values;
786 for (u32 element = 0; element < values.size(); ++element) { 809 for (u32 element = 0; element < values.size(); ++element) {
787 auto coords_copy = coords; 810 auto coords_copy = coords;
788 MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}}; 811 MetaTexture meta{*sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}};
789 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 812 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
790 } 813 }
791 return values; 814 return values;
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index ae5e414cb..748d73087 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -191,10 +191,14 @@ private:
191 friend class ASTDecoder; 191 friend class ASTDecoder;
192 192
193 struct SamplerInfo { 193 struct SamplerInfo {
194 Tegra::Shader::TextureType type; 194 std::optional<Tegra::Shader::TextureType> type;
195 bool is_array; 195 std::optional<bool> is_array;
196 bool is_shadow; 196 std::optional<bool> is_shadow;
197 bool is_buffer; 197 std::optional<bool> is_buffer;
198
199 constexpr bool IsComplete() const noexcept {
200 return type && is_array && is_shadow && is_buffer;
201 }
198 }; 202 };
199 203
200 void Decode(); 204 void Decode();
@@ -327,17 +331,15 @@ private:
327 OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation); 331 OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);
328 332
329 /// Queries the missing sampler info from the execution context. 333 /// Queries the missing sampler info from the execution context.
330 SamplerInfo GetSamplerInfo(std::optional<SamplerInfo> sampler_info, u32 offset, 334 SamplerInfo GetSamplerInfo(SamplerInfo info, u32 offset,
331 std::optional<u32> buffer = std::nullopt); 335 std::optional<u32> buffer = std::nullopt);
332 336
333 /// Accesses a texture sampler 337 /// Accesses a texture sampler.
334 std::optional<Sampler> GetSampler(const Tegra::Shader::Sampler& sampler, 338 std::optional<Sampler> GetSampler(Tegra::Shader::Sampler sampler, SamplerInfo info);
335 std::optional<SamplerInfo> sampler_info = std::nullopt);
336 339
337 /// Accesses a texture sampler for a bindless texture. 340 /// Accesses a texture sampler for a bindless texture.
338 std::optional<Sampler> GetBindlessSampler( 341 std::optional<Sampler> GetBindlessSampler(Tegra::Shader::Register reg, SamplerInfo info,
339 Tegra::Shader::Register reg, Node& index_var, 342 Node& index_var);
340 std::optional<SamplerInfo> sampler_info = std::nullopt);
341 343
342 /// Accesses an image. 344 /// Accesses an image.
343 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); 345 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type);