summaryrefslogtreecommitdiff
path: root/src/video_core/shader/decode
diff options
context:
space:
mode:
authorGravatar bunnei2020-02-01 20:41:40 -0500
committerGravatar GitHub2020-02-01 20:41:40 -0500
commitb5bbe7e752d5d36839a86638bfaa4b4c348497cd (patch)
treeb16b3f8ce5ec6233f9f822ad56418d74f0cd47ae /src/video_core/shader/decode
parentMerge pull request #3268 from CJBok/deadzone (diff)
parentShader_IR: Address feedback. (diff)
downloadyuzu-b5bbe7e752d5d36839a86638bfaa4b4c348497cd.tar.gz
yuzu-b5bbe7e752d5d36839a86638bfaa4b4c348497cd.tar.xz
yuzu-b5bbe7e752d5d36839a86638bfaa4b4c348497cd.zip
Merge pull request #3282 from FernandoS27/indexed-samplers
Partially implement Indexed samplers in general and specific code in GLSL
Diffstat (limited to 'src/video_core/shader/decode')
-rw-r--r--src/video_core/shader/decode/texture.cpp110
1 files changed, 73 insertions, 37 deletions
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 0b567e39d..d980535b1 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -144,7 +144,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
144 Node4 values; 144 Node4 values;
145 for (u32 element = 0; element < values.size(); ++element) { 145 for (u32 element = 0; element < values.size(); ++element) {
146 auto coords_copy = coords; 146 auto coords_copy = coords;
147 MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, {}, {}, component, element}; 147 MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {},
148 {}, {}, component, element, {}};
148 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); 149 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
149 } 150 }
150 151
@@ -167,9 +168,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
167 const auto derivate_reg = instr.gpr20.Value(); 168 const auto derivate_reg = instr.gpr20.Value();
168 const auto texture_type = instr.txd.texture_type.Value(); 169 const auto texture_type = instr.txd.texture_type.Value();
169 const auto coord_count = GetCoordCount(texture_type); 170 const auto coord_count = GetCoordCount(texture_type);
170 171 Node index_var{};
171 const Sampler* sampler = 172 const Sampler* sampler =
172 is_bindless ? GetBindlessSampler(base_reg, {{texture_type, is_array, false}}) 173 is_bindless ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false}})
173 : GetSampler(instr.sampler, {{texture_type, is_array, false}}); 174 : GetSampler(instr.sampler, {{texture_type, is_array, false}});
174 Node4 values; 175 Node4 values;
175 if (sampler == nullptr) { 176 if (sampler == nullptr) {
@@ -200,7 +201,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
200 } 201 }
201 202
202 for (u32 element = 0; element < values.size(); ++element) { 203 for (u32 element = 0; element < values.size(); ++element) {
203 MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element}; 204 MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates,
205 {}, {}, {}, element, index_var};
204 values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); 206 values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords);
205 } 207 }
206 208
@@ -215,8 +217,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
215 // TODO: The new commits on the texture refactor, change the way samplers work. 217 // TODO: The new commits on the texture refactor, change the way samplers work.
216 // Sadly, not all texture instructions specify the type of texture their sampler 218 // Sadly, not all texture instructions specify the type of texture their sampler
217 // uses. This must be fixed at a later instance. 219 // uses. This must be fixed at a later instance.
220 Node index_var{};
218 const Sampler* sampler = 221 const Sampler* sampler =
219 is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); 222 is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler);
220 223
221 if (sampler == nullptr) { 224 if (sampler == nullptr) {
222 u32 indexer = 0; 225 u32 indexer = 0;
@@ -240,7 +243,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
240 if (!instr.txq.IsComponentEnabled(element)) { 243 if (!instr.txq.IsComponentEnabled(element)) {
241 continue; 244 continue;
242 } 245 }
243 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; 246 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var};
244 const Node value = 247 const Node value =
245 Operation(OperationCode::TextureQueryDimensions, meta, 248 Operation(OperationCode::TextureQueryDimensions, meta,
246 GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); 249 GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0)));
@@ -266,8 +269,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
266 269
267 auto texture_type = instr.tmml.texture_type.Value(); 270 auto texture_type = instr.tmml.texture_type.Value();
268 const bool is_array = instr.tmml.array != 0; 271 const bool is_array = instr.tmml.array != 0;
272 Node index_var{};
269 const Sampler* sampler = 273 const Sampler* sampler =
270 is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); 274 is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler);
271 275
272 if (sampler == nullptr) { 276 if (sampler == nullptr) {
273 u32 indexer = 0; 277 u32 indexer = 0;
@@ -309,7 +313,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
309 continue; 313 continue;
310 } 314 }
311 auto params = coords; 315 auto params = coords;
312 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; 316 MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var};
313 const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); 317 const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
314 SetTemporary(bb, indexer++, value); 318 SetTemporary(bb, indexer++, value);
315 } 319 }
@@ -383,37 +387,65 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
383 // Otherwise create a new mapping for this sampler 387 // Otherwise create a new mapping for this sampler
384 const auto next_index = static_cast<u32>(used_samplers.size()); 388 const auto next_index = static_cast<u32>(used_samplers.size());
385 return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, 389 return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
386 info.is_buffer); 390 info.is_buffer, false);
387} 391}
388 392
389const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, 393const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var,
390 std::optional<SamplerInfo> sampler_info) { 394 std::optional<SamplerInfo> sampler_info) {
391 const Node sampler_register = GetRegister(reg); 395 const Node sampler_register = GetRegister(reg);
392 const auto [base_sampler, buffer, offset] = 396 const auto [base_node, tracked_sampler_info] =
393 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 397 TrackBindlessSampler(sampler_register, global_code, static_cast<s64>(global_code.size()));
394 ASSERT(base_sampler != nullptr); 398 ASSERT(base_node != nullptr);
395 if (base_sampler == nullptr) { 399 if (base_node == nullptr) {
396 return nullptr; 400 return nullptr;
397 } 401 }
398 402
399 const auto info = GetSamplerInfo(sampler_info, offset, buffer); 403 if (const auto bindless_sampler_info =
404 std::get_if<BindlessSamplerNode>(&*tracked_sampler_info)) {
405 const u32 buffer = bindless_sampler_info->GetIndex();
406 const u32 offset = bindless_sampler_info->GetOffset();
407 const auto info = GetSamplerInfo(sampler_info, offset, buffer);
408
409 // If this sampler has already been used, return the existing mapping.
410 const auto it =
411 std::find_if(used_samplers.begin(), used_samplers.end(),
412 [buffer = buffer, offset = offset](const Sampler& entry) {
413 return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
414 });
415 if (it != used_samplers.end()) {
416 ASSERT(it->IsBindless() && it->GetType() == info.type &&
417 it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow);
418 return &*it;
419 }
400 420
401 // If this sampler has already been used, return the existing mapping. 421 // Otherwise create a new mapping for this sampler
402 const auto it = 422 const auto next_index = static_cast<u32>(used_samplers.size());
403 std::find_if(used_samplers.begin(), used_samplers.end(), 423 return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
404 [buffer = buffer, offset = offset](const Sampler& entry) { 424 info.is_shadow, info.is_buffer, false);
405 return entry.GetBuffer() == buffer && entry.GetOffset() == offset; 425 } else if (const auto array_sampler_info =
406 }); 426 std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
407 if (it != used_samplers.end()) { 427 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4;
408 ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && 428 index_var = GetCustomVariable(array_sampler_info->GetIndexVar());
409 it->IsShadow() == info.is_shadow); 429 const auto info = GetSamplerInfo(sampler_info, base_offset);
410 return &*it; 430
411 } 431 // If this sampler has already been used, return the existing mapping.
432 const auto it = std::find_if(
433 used_samplers.begin(), used_samplers.end(),
434 [base_offset](const Sampler& entry) { return entry.GetOffset() == base_offset; });
435 if (it != used_samplers.end()) {
436 ASSERT(!it->IsBindless() && it->GetType() == info.type &&
437 it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow &&
438 it->IsBuffer() == info.is_buffer && it->IsIndexed());
439 return &*it;
440 }
412 441
413 // Otherwise create a new mapping for this sampler 442 uses_indexed_samplers = true;
414 const auto next_index = static_cast<u32>(used_samplers.size()); 443 // Otherwise create a new mapping for this sampler
415 return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, 444 const auto next_index = static_cast<u32>(used_samplers.size());
416 info.is_shadow, info.is_buffer); 445 return &used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array,
446 info.is_shadow, info.is_buffer, true);
447 }
448 return nullptr;
417} 449}
418 450
419void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 451void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
@@ -499,8 +531,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
499 "This method is not supported."); 531 "This method is not supported.");
500 532
501 const SamplerInfo info{texture_type, is_array, is_shadow, false}; 533 const SamplerInfo info{texture_type, is_array, is_shadow, false};
502 const Sampler* sampler = 534 Node index_var{};
503 is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); 535 const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, index_var, info)
536 : GetSampler(instr.sampler, info);
504 Node4 values; 537 Node4 values;
505 if (sampler == nullptr) { 538 if (sampler == nullptr) {
506 for (u32 element = 0; element < values.size(); ++element) { 539 for (u32 element = 0; element < values.size(); ++element) {
@@ -548,7 +581,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
548 581
549 for (u32 element = 0; element < values.size(); ++element) { 582 for (u32 element = 0; element < values.size(); ++element) {
550 auto copy_coords = coords; 583 auto copy_coords = coords;
551 MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, lod, {}, element}; 584 MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias,
585 lod, {}, element, index_var};
552 values[element] = Operation(read_method, meta, std::move(copy_coords)); 586 values[element] = Operation(read_method, meta, std::move(copy_coords));
553 } 587 }
554 588
@@ -663,7 +697,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
663 u64 parameter_register = instr.gpr20.Value(); 697 u64 parameter_register = instr.gpr20.Value();
664 698
665 const SamplerInfo info{texture_type, is_array, depth_compare, false}; 699 const SamplerInfo info{texture_type, is_array, depth_compare, false};
666 const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) 700 Node index_var{};
701 const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, index_var, info)
667 : GetSampler(instr.sampler, info); 702 : GetSampler(instr.sampler, info);
668 Node4 values; 703 Node4 values;
669 if (sampler == nullptr) { 704 if (sampler == nullptr) {
@@ -692,7 +727,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
692 for (u32 element = 0; element < values.size(); ++element) { 727 for (u32 element = 0; element < values.size(); ++element) {
693 auto coords_copy = coords; 728 auto coords_copy = coords;
694 MetaTexture meta{ 729 MetaTexture meta{
695 *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element}; 730 *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element,
731 index_var};
696 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); 732 values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
697 } 733 }
698 734
@@ -725,7 +761,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
725 Node4 values; 761 Node4 values;
726 for (u32 element = 0; element < values.size(); ++element) { 762 for (u32 element = 0; element < values.size(); ++element) {
727 auto coords_copy = coords; 763 auto coords_copy = coords;
728 MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element}; 764 MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element, {}};
729 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 765 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
730 } 766 }
731 767
@@ -775,7 +811,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
775 Node4 values; 811 Node4 values;
776 for (u32 element = 0; element < values.size(); ++element) { 812 for (u32 element = 0; element < values.size(); ++element) {
777 auto coords_copy = coords; 813 auto coords_copy = coords;
778 MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element}; 814 MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}};
779 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 815 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
780 } 816 }
781 return values; 817 return values;