diff options
| author | 2019-12-11 13:07:30 -0400 | |
|---|---|---|
| committer | 2019-12-11 19:53:16 -0400 | |
| commit | 271a3264f33766524224462537685b6e5c691f9d (patch) | |
| tree | d97f52424561ab3abfac243f408e2b7e31d335de /src | |
| parent | Merge pull request #3218 from FernandoS27/tess-gl (diff) | |
| download | yuzu-271a3264f33766524224462537685b6e5c691f9d.tar.gz yuzu-271a3264f33766524224462537685b6e5c691f9d.tar.xz yuzu-271a3264f33766524224462537685b6e5c691f9d.zip | |
Shader_Ir: default failed tracks on bindless samplers to null values.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 97 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 4 |
2 files changed, 77 insertions, 24 deletions
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index da8e886df..67926afcb 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -129,7 +129,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 129 | const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); | 129 | const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); |
| 130 | 130 | ||
| 131 | const SamplerInfo info{TextureType::Texture2D, false, depth_compare}; | 131 | const SamplerInfo info{TextureType::Texture2D, false, depth_compare}; |
| 132 | const auto& sampler = GetSampler(instr.sampler, info); | 132 | const Sampler& sampler = *GetSampler(instr.sampler, info); |
| 133 | 133 | ||
| 134 | Node4 values; | 134 | Node4 values; |
| 135 | for (u32 element = 0; element < values.size(); ++element) { | 135 | for (u32 element = 0; element < values.size(); ++element) { |
| @@ -154,9 +154,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 154 | const auto texture_type = instr.txd.texture_type.Value(); | 154 | const auto texture_type = instr.txd.texture_type.Value(); |
| 155 | const auto coord_count = GetCoordCount(texture_type); | 155 | const auto coord_count = GetCoordCount(texture_type); |
| 156 | 156 | ||
| 157 | const auto& sampler = is_bindless | 157 | const Sampler* sampler = is_bindless |
| 158 | ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) | 158 | ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) |
| 159 | : GetSampler(instr.sampler, {{texture_type, false, false}}); | 159 | : GetSampler(instr.sampler, {{texture_type, false, false}}); |
| 160 | Node4 values; | ||
| 161 | if (sampler == nullptr) { | ||
| 162 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 163 | values[element] = Immediate(0); | ||
| 164 | } | ||
| 165 | WriteTexInstructionFloat(bb, instr, values); | ||
| 166 | break; | ||
| 167 | } | ||
| 160 | if (is_bindless) { | 168 | if (is_bindless) { |
| 161 | base_reg++; | 169 | base_reg++; |
| 162 | } | 170 | } |
| @@ -170,9 +178,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 170 | derivates.push_back(GetRegister(derivate_reg + derivate + 1)); | 178 | derivates.push_back(GetRegister(derivate_reg + derivate + 1)); |
| 171 | } | 179 | } |
| 172 | 180 | ||
| 173 | Node4 values; | ||
| 174 | for (u32 element = 0; element < values.size(); ++element) { | 181 | for (u32 element = 0; element < values.size(); ++element) { |
| 175 | MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element}; | 182 | MetaTexture meta{*sampler, {}, {}, {}, derivates, {}, {}, {}, element}; |
| 176 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); | 183 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); |
| 177 | } | 184 | } |
| 178 | 185 | ||
| @@ -187,9 +194,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 187 | // TODO: The new commits on the texture refactor, change the way samplers work. | 194 | // 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 | 195 | // Sadly, not all texture instructions specify the type of texture their sampler |
| 189 | // uses. This must be fixed at a later instance. | 196 | // uses. This must be fixed at a later instance. |
| 190 | const auto& sampler = | 197 | const Sampler* sampler = |
| 191 | is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); | 198 | is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); |
| 192 | 199 | ||
| 200 | if (sampler == nullptr) { | ||
| 201 | u32 indexer = 0; | ||
| 202 | for (u32 element = 0; element < 4; ++element) { | ||
| 203 | if (!instr.txq.IsComponentEnabled(element)) { | ||
| 204 | continue; | ||
| 205 | } | ||
| 206 | const Node value = Immediate(0); | ||
| 207 | SetTemporary(bb, indexer++, value); | ||
| 208 | } | ||
| 209 | for (u32 i = 0; i < indexer; ++i) { | ||
| 210 | SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); | ||
| 211 | } | ||
| 212 | break; | ||
| 213 | } | ||
| 214 | |||
| 193 | u32 indexer = 0; | 215 | u32 indexer = 0; |
| 194 | switch (instr.txq.query_type) { | 216 | switch (instr.txq.query_type) { |
| 195 | case Tegra::Shader::TextureQueryType::Dimension: { | 217 | case Tegra::Shader::TextureQueryType::Dimension: { |
| @@ -197,7 +219,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 197 | if (!instr.txq.IsComponentEnabled(element)) { | 219 | if (!instr.txq.IsComponentEnabled(element)) { |
| 198 | continue; | 220 | continue; |
| 199 | } | 221 | } |
| 200 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; | 222 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; |
| 201 | const Node value = | 223 | const Node value = |
| 202 | Operation(OperationCode::TextureQueryDimensions, meta, | 224 | Operation(OperationCode::TextureQueryDimensions, meta, |
| 203 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); | 225 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); |
| @@ -223,9 +245,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 223 | 245 | ||
| 224 | auto texture_type = instr.tmml.texture_type.Value(); | 246 | auto texture_type = instr.tmml.texture_type.Value(); |
| 225 | const bool is_array = instr.tmml.array != 0; | 247 | const bool is_array = instr.tmml.array != 0; |
| 226 | const auto& sampler = | 248 | const Sampler* sampler = |
| 227 | is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); | 249 | is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); |
| 228 | 250 | ||
| 251 | if (sampler == nullptr) { | ||
| 252 | u32 indexer = 0; | ||
| 253 | for (u32 element = 0; element < 2; ++element) { | ||
| 254 | if (!instr.tmml.IsComponentEnabled(element)) { | ||
| 255 | continue; | ||
| 256 | } | ||
| 257 | const Node value = Immediate(0); | ||
| 258 | SetTemporary(bb, indexer++, value); | ||
| 259 | } | ||
| 260 | for (u32 i = 0; i < indexer; ++i) { | ||
| 261 | SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); | ||
| 262 | } | ||
| 263 | break; | ||
| 264 | } | ||
| 265 | |||
| 229 | std::vector<Node> coords; | 266 | std::vector<Node> coords; |
| 230 | 267 | ||
| 231 | // TODO: Add coordinates for different samplers once other texture types are implemented. | 268 | // TODO: Add coordinates for different samplers once other texture types are implemented. |
| @@ -251,7 +288,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 251 | continue; | 288 | continue; |
| 252 | } | 289 | } |
| 253 | auto params = coords; | 290 | auto params = coords; |
| 254 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; | 291 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; |
| 255 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | 292 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); |
| 256 | SetTemporary(bb, indexer++, value); | 293 | SetTemporary(bb, indexer++, value); |
| 257 | } | 294 | } |
| @@ -307,7 +344,7 @@ ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sample | |||
| 307 | sampler->is_buffer != 0}; | 344 | sampler->is_buffer != 0}; |
| 308 | } | 345 | } |
| 309 | 346 | ||
| 310 | const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | 347 | const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, |
| 311 | std::optional<SamplerInfo> sampler_info) { | 348 | std::optional<SamplerInfo> sampler_info) { |
| 312 | const auto offset = static_cast<u32>(sampler.index.Value()); | 349 | const auto offset = static_cast<u32>(sampler.index.Value()); |
| 313 | const auto info = GetSamplerInfo(sampler_info, offset); | 350 | const auto info = GetSamplerInfo(sampler_info, offset); |
| @@ -319,21 +356,24 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||
| 319 | if (it != used_samplers.end()) { | 356 | if (it != used_samplers.end()) { |
| 320 | ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && | 357 | ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && |
| 321 | it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); | 358 | it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); |
| 322 | return *it; | 359 | return &(*it); |
| 323 | } | 360 | } |
| 324 | 361 | ||
| 325 | // Otherwise create a new mapping for this sampler | 362 | // Otherwise create a new mapping for this sampler |
| 326 | const auto next_index = static_cast<u32>(used_samplers.size()); | 363 | 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, | 364 | return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, |
| 328 | info.is_buffer); | 365 | info.is_buffer); |
| 329 | } | 366 | } |
| 330 | 367 | ||
| 331 | const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | 368 | const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, |
| 332 | std::optional<SamplerInfo> sampler_info) { | 369 | std::optional<SamplerInfo> sampler_info) { |
| 333 | const Node sampler_register = GetRegister(reg); | 370 | const Node sampler_register = GetRegister(reg); |
| 334 | const auto [base_sampler, buffer, offset] = | 371 | const auto [base_sampler, buffer, offset] = |
| 335 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); | 372 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); |
| 336 | ASSERT(base_sampler != nullptr); | 373 | ASSERT(base_sampler != nullptr); |
| 374 | if (base_sampler == nullptr) { | ||
| 375 | return nullptr; | ||
| 376 | } | ||
| 337 | 377 | ||
| 338 | const auto info = GetSamplerInfo(sampler_info, offset, buffer); | 378 | const auto info = GetSamplerInfo(sampler_info, offset, buffer); |
| 339 | 379 | ||
| @@ -346,12 +386,12 @@ const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | |||
| 346 | if (it != used_samplers.end()) { | 386 | if (it != used_samplers.end()) { |
| 347 | ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && | 387 | ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && |
| 348 | it->IsShadow() == info.is_shadow); | 388 | it->IsShadow() == info.is_shadow); |
| 349 | return *it; | 389 | return &(*it); |
| 350 | } | 390 | } |
| 351 | 391 | ||
| 352 | // Otherwise create a new mapping for this sampler | 392 | // Otherwise create a new mapping for this sampler |
| 353 | const auto next_index = static_cast<u32>(used_samplers.size()); | 393 | 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, | 394 | return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, |
| 355 | info.is_shadow, info.is_buffer); | 395 | info.is_shadow, info.is_buffer); |
| 356 | } | 396 | } |
| 357 | 397 | ||
| @@ -438,8 +478,15 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 438 | "This method is not supported."); | 478 | "This method is not supported."); |
| 439 | 479 | ||
| 440 | const SamplerInfo info{texture_type, is_array, is_shadow, false}; | 480 | const SamplerInfo info{texture_type, is_array, is_shadow, false}; |
| 441 | const auto& sampler = | 481 | const Sampler* sampler = |
| 442 | is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); | 482 | is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); |
| 483 | Node4 values; | ||
| 484 | if (sampler == nullptr) { | ||
| 485 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 486 | values[element] = Immediate(0); | ||
| 487 | } | ||
| 488 | return values; | ||
| 489 | } | ||
| 443 | 490 | ||
| 444 | const bool lod_needed = process_mode == TextureProcessMode::LZ || | 491 | const bool lod_needed = process_mode == TextureProcessMode::LZ || |
| 445 | process_mode == TextureProcessMode::LL || | 492 | process_mode == TextureProcessMode::LL || |
| @@ -478,10 +525,10 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 478 | } | 525 | } |
| 479 | } | 526 | } |
| 480 | 527 | ||
| 481 | Node4 values; | 528 | |
| 482 | for (u32 element = 0; element < values.size(); ++element) { | 529 | for (u32 element = 0; element < values.size(); ++element) { |
| 483 | auto copy_coords = coords; | 530 | auto copy_coords = coords; |
| 484 | MetaTexture meta{sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; | 531 | MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; |
| 485 | values[element] = Operation(read_method, meta, std::move(copy_coords)); | 532 | values[element] = Operation(read_method, meta, std::move(copy_coords)); |
| 486 | } | 533 | } |
| 487 | 534 | ||
| @@ -594,8 +641,15 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 594 | u64 parameter_register = instr.gpr20.Value(); | 641 | u64 parameter_register = instr.gpr20.Value(); |
| 595 | 642 | ||
| 596 | const SamplerInfo info{texture_type, is_array, depth_compare, false}; | 643 | const SamplerInfo info{texture_type, is_array, depth_compare, false}; |
| 597 | const auto& sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) | 644 | const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) |
| 598 | : GetSampler(instr.sampler, info); | 645 | : GetSampler(instr.sampler, info); |
| 646 | Node4 values; | ||
| 647 | if (sampler == nullptr) { | ||
| 648 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 649 | values[element] = Immediate(0); | ||
| 650 | } | ||
| 651 | return values; | ||
| 652 | } | ||
| 599 | 653 | ||
| 600 | std::vector<Node> aoffi; | 654 | std::vector<Node> aoffi; |
| 601 | if (is_aoffi) { | 655 | if (is_aoffi) { |
| @@ -610,10 +664,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)) | 664 | const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component)) |
| 611 | : Immediate(static_cast<u32>(instr.tld4.component)); | 665 | : Immediate(static_cast<u32>(instr.tld4.component)); |
| 612 | 666 | ||
| 613 | Node4 values; | ||
| 614 | for (u32 element = 0; element < values.size(); ++element) { | 667 | for (u32 element = 0; element < values.size(); ++element) { |
| 615 | auto coords_copy = coords; | 668 | auto coords_copy = coords; |
| 616 | MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, | 669 | MetaTexture meta{*sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, |
| 617 | element}; | 670 | element}; |
| 618 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 671 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 619 | } | 672 | } |
| @@ -642,7 +695,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 642 | // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; | 695 | // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; |
| 643 | // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; | 696 | // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; |
| 644 | 697 | ||
| 645 | const auto& sampler = GetSampler(instr.sampler); | 698 | const auto& sampler = *GetSampler(instr.sampler); |
| 646 | 699 | ||
| 647 | Node4 values; | 700 | Node4 values; |
| 648 | for (u32 element = 0; element < values.size(); ++element) { | 701 | for (u32 element = 0; element < values.size(); ++element) { |
| @@ -655,7 +708,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 655 | } | 708 | } |
| 656 | 709 | ||
| 657 | Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { | 710 | Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { |
| 658 | const auto& sampler = GetSampler(instr.sampler); | 711 | const Sampler& sampler = *GetSampler(instr.sampler); |
| 659 | 712 | ||
| 660 | const std::size_t type_coord_count = GetCoordCount(texture_type); | 713 | const std::size_t type_coord_count = GetCoordCount(texture_type); |
| 661 | const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; | 714 | 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..8324432ae 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. |