diff options
| author | 2019-03-26 17:05:23 -0400 | |
|---|---|---|
| committer | 2019-04-08 11:23:42 -0400 | |
| commit | e28fd3d0a533695242d17350dd929ad3bb56c429 (patch) | |
| tree | a1cc9ed6da8143f1f314dd47bf482f48dca80145 /src | |
| parent | Implement Const Buffer Accessor (diff) | |
| download | yuzu-e28fd3d0a533695242d17350dd929ad3bb56c429.tar.gz yuzu-e28fd3d0a533695242d17350dd929ad3bb56c429.tar.xz yuzu-e28fd3d0a533695242d17350dd929ad3bb56c429.zip | |
Implement Bindless Samplers and TEX_B in the IR.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 58 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 31 |
4 files changed, 77 insertions, 16 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 7f613370b..2edd3245e 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -1309,6 +1309,7 @@ public: | |||
| 1309 | LDG, // Load from global memory | 1309 | LDG, // Load from global memory |
| 1310 | STG, // Store in global memory | 1310 | STG, // Store in global memory |
| 1311 | TEX, | 1311 | TEX, |
| 1312 | TEX_B, // Texture Load Bindless | ||
| 1312 | TXQ, // Texture Query | 1313 | TXQ, // Texture Query |
| 1313 | TEXS, // Texture Fetch with scalar/non-vec4 source/destinations | 1314 | TEXS, // Texture Fetch with scalar/non-vec4 source/destinations |
| 1314 | TLDS, // Texture Load with scalar/non-vec4 source/destinations | 1315 | TLDS, // Texture Load with scalar/non-vec4 source/destinations |
| @@ -1577,6 +1578,7 @@ private: | |||
| 1577 | INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), | 1578 | INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), |
| 1578 | INST("1110111011011---", Id::STG, Type::Memory, "STG"), | 1579 | INST("1110111011011---", Id::STG, Type::Memory, "STG"), |
| 1579 | INST("110000----111---", Id::TEX, Type::Texture, "TEX"), | 1580 | INST("110000----111---", Id::TEX, Type::Texture, "TEX"), |
| 1581 | INST("1101111010111---", Id::TEX_B, Type::Texture, "TEX_B"), | ||
| 1580 | INST("1101111101001---", Id::TXQ, Type::Texture, "TXQ"), | 1582 | INST("1101111101001---", Id::TXQ, Type::Texture, "TXQ"), |
| 1581 | INST("1101-00---------", Id::TEXS, Type::Texture, "TEXS"), | 1583 | INST("1101-00---------", Id::TEXS, Type::Texture, "TEXS"), |
| 1582 | INST("1101101---------", Id::TLDS, Type::Texture, "TLDS"), | 1584 | INST("1101101---------", Id::TLDS, Type::Texture, "TLDS"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 8a43eb157..6a95af6f6 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -328,7 +328,7 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn | |||
| 328 | } | 328 | } |
| 329 | entry.entries.samplers.emplace_back( | 329 | entry.entries.samplers.emplace_back( |
| 330 | static_cast<std::size_t>(offset), static_cast<std::size_t>(index), | 330 | static_cast<std::size_t>(offset), static_cast<std::size_t>(index), |
| 331 | static_cast<Tegra::Shader::TextureType>(type), is_array != 0, is_shadow != 0); | 331 | static_cast<Tegra::Shader::TextureType>(type), is_array != 0, is_shadow != 0, false); |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | u32 global_memory_count{}; | 334 | u32 global_memory_count{}; |
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index a775b402b..23f2ad999 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -57,6 +57,23 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 57 | GetTexCode(instr, texture_type, process_mode, depth_compare, is_array, is_aoffi)); | 57 | GetTexCode(instr, texture_type, process_mode, depth_compare, is_array, is_aoffi)); |
| 58 | break; | 58 | break; |
| 59 | } | 59 | } |
| 60 | case OpCode::Id::TEX_B: { | ||
| 61 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(TextureMiscMode::AOFFI), | ||
| 62 | "AOFFI is not implemented"); | ||
| 63 | |||
| 64 | if (instr.tex.UsesMiscMode(TextureMiscMode::NODEP)) { | ||
| 65 | LOG_WARNING(HW_GPU, "TEX.NODEP implementation is incomplete"); | ||
| 66 | } | ||
| 67 | |||
| 68 | const TextureType texture_type{instr.tex.texture_type}; | ||
| 69 | const bool is_array = instr.tex.array != 0; | ||
| 70 | const bool depth_compare = instr.tex.UsesMiscMode(TextureMiscMode::DC); | ||
| 71 | const auto process_mode = instr.tex.GetTextureProcessMode(); | ||
| 72 | WriteTexInstructionFloat(bb, instr, | ||
| 73 | GetTexCode(instr, texture_type, process_mode, depth_compare, | ||
| 74 | is_array, true, instr.gpr20)); | ||
| 75 | break; | ||
| 76 | } | ||
| 60 | case OpCode::Id::TEXS: { | 77 | case OpCode::Id::TEXS: { |
| 61 | const TextureType texture_type{instr.texs.GetTextureType()}; | 78 | const TextureType texture_type{instr.texs.GetTextureType()}; |
| 62 | const bool is_array{instr.texs.IsArrayTexture()}; | 79 | const bool is_array{instr.texs.IsArrayTexture()}; |
| @@ -250,10 +267,36 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu | |||
| 250 | 267 | ||
| 251 | // Otherwise create a new mapping for this sampler | 268 | // Otherwise create a new mapping for this sampler |
| 252 | const std::size_t next_index = used_samplers.size(); | 269 | const std::size_t next_index = used_samplers.size(); |
| 253 | const Sampler entry{offset, next_index, type, is_array, is_shadow}; | 270 | const Sampler entry{offset, next_index, type, is_array, is_shadow, false}; |
| 254 | return *used_samplers.emplace(entry).first; | 271 | return *used_samplers.emplace(entry).first; |
| 255 | } | 272 | } |
| 256 | 273 | ||
| 274 | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | ||
| 275 | TextureType type, bool is_array, bool is_shadow) { | ||
| 276 | |||
| 277 | const Node sampler_register = GetRegister(reg); | ||
| 278 | const Node base_sampler = TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); | ||
| 279 | const auto cbuf = std::get_if<CbufNode>(base_sampler); | ||
| 280 | const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset()); | ||
| 281 | ASSERT(cbuf_offset_imm != nullptr); | ||
| 282 | const auto cbuf_offset = cbuf_offset_imm->GetValue(); | ||
| 283 | const auto cbuf_index = cbuf->GetIndex(); | ||
| 284 | const std::pair<u32, u32> cbuf_pair = {cbuf_index, cbuf_offset}; | ||
| 285 | |||
| 286 | // If this sampler has already been used, return the existing mapping. | ||
| 287 | if (used_bindless_samplers.count(cbuf_pair) > 0) { | ||
| 288 | const auto& sampler = used_bindless_samplers[cbuf_pair]; | ||
| 289 | ASSERT(sampler.GetType() == type && sampler.IsArray() == is_array && | ||
| 290 | sampler.IsShadow() == is_shadow); | ||
| 291 | return sampler; | ||
| 292 | } | ||
| 293 | |||
| 294 | // Otherwise create a new mapping for this sampler | ||
| 295 | const std::size_t next_index = used_bindless_samplers.size(); | ||
| 296 | const Sampler entry{0, next_index, type, is_array, is_shadow, true}; | ||
| 297 | return (*used_bindless_samplers.emplace(std::make_pair(cbuf_pair, entry)).first).second; | ||
| 298 | } | ||
| 299 | |||
| 257 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { | 300 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { |
| 258 | u32 dest_elem = 0; | 301 | u32 dest_elem = 0; |
| 259 | for (u32 elem = 0; elem < 4; ++elem) { | 302 | for (u32 elem = 0; elem < 4; ++elem) { |
| @@ -325,8 +368,8 @@ void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr, | |||
| 325 | 368 | ||
| 326 | Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | 369 | Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, |
| 327 | TextureProcessMode process_mode, std::vector<Node> coords, | 370 | TextureProcessMode process_mode, std::vector<Node> coords, |
| 328 | Node array, Node depth_compare, u32 bias_offset, | 371 | Node array, Node depth_compare, u32 bias_offset, std::vector<Node> aoffi, bool is_bindless, |
| 329 | std::vector<Node> aoffi) { | 372 | Register bindless_reg) { |
| 330 | const bool is_array = array; | 373 | const bool is_array = array; |
| 331 | const bool is_shadow = depth_compare; | 374 | const bool is_shadow = depth_compare; |
| 332 | 375 | ||
| @@ -334,7 +377,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 334 | (texture_type == TextureType::TextureCube && is_array && is_shadow), | 377 | (texture_type == TextureType::TextureCube && is_array && is_shadow), |
| 335 | "This method is not supported."); | 378 | "This method is not supported."); |
| 336 | 379 | ||
| 337 | const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, is_shadow); | 380 | const auto& sampler = !is_bindless |
| 381 | ? GetSampler(instr.sampler, texture_type, is_array, is_shadow) | ||
| 382 | : GetBindlessSampler(bindless_reg, texture_type, is_array, is_shadow); | ||
| 338 | 383 | ||
| 339 | const bool lod_needed = process_mode == TextureProcessMode::LZ || | 384 | const bool lod_needed = process_mode == TextureProcessMode::LZ || |
| 340 | process_mode == TextureProcessMode::LL || | 385 | process_mode == TextureProcessMode::LL || |
| @@ -384,7 +429,7 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 384 | 429 | ||
| 385 | Node4 ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, | 430 | Node4 ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, |
| 386 | TextureProcessMode process_mode, bool depth_compare, bool is_array, | 431 | TextureProcessMode process_mode, bool depth_compare, bool is_array, |
| 387 | bool is_aoffi) { | 432 | bool is_aoffi, bool is_bindless, Register bindless_reg) { |
| 388 | const bool lod_bias_enabled{ | 433 | const bool lod_bias_enabled{ |
| 389 | (process_mode != TextureProcessMode::None && process_mode != TextureProcessMode::LZ)}; | 434 | (process_mode != TextureProcessMode::None && process_mode != TextureProcessMode::LZ)}; |
| 390 | 435 | ||
| @@ -423,7 +468,8 @@ Node4 ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, | |||
| 423 | dc = GetRegister(parameter_register++); | 468 | dc = GetRegister(parameter_register++); |
| 424 | } | 469 | } |
| 425 | 470 | ||
| 426 | return GetTextureCode(instr, texture_type, process_mode, coords, array, dc, 0, aoffi); | 471 | return GetTextureCode(instr, texture_type, process_mode, coords, array, dc, 0, aoffi, is_bindless, |
| 472 | bindless_reg); | ||
| 427 | } | 473 | } |
| 428 | 474 | ||
| 429 | Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, | 475 | Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 4888998d3..712dc3ddb 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -196,9 +196,12 @@ enum class ExitMethod { | |||
| 196 | 196 | ||
| 197 | class Sampler { | 197 | class Sampler { |
| 198 | public: | 198 | public: |
| 199 | Sampler() = default; | ||
| 199 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | 200 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, |
| 200 | bool is_array, bool is_shadow) | 201 | bool is_array, bool is_shadow, bool is_bindless) |
| 201 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow} {} | 202 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, is_bindless{is_bindless} {} |
| 203 | |||
| 204 | ~Sampler() = default; | ||
| 202 | 205 | ||
| 203 | std::size_t GetOffset() const { | 206 | std::size_t GetOffset() const { |
| 204 | return offset; | 207 | return offset; |
| @@ -233,6 +236,7 @@ private: | |||
| 233 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | 236 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) |
| 234 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. | 237 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. |
| 235 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. | 238 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. |
| 239 | bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. | ||
| 236 | }; | 240 | }; |
| 237 | 241 | ||
| 238 | class ConstBuffer { | 242 | class ConstBuffer { |
| @@ -730,6 +734,10 @@ private: | |||
| 730 | const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler, | 734 | const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler, |
| 731 | Tegra::Shader::TextureType type, bool is_array, bool is_shadow); | 735 | Tegra::Shader::TextureType type, bool is_array, bool is_shadow); |
| 732 | 736 | ||
| 737 | // Accesses a texture sampler for a bindless texture. | ||
| 738 | const Sampler& GetBindlessSampler(const Tegra::Shader::Register& reg, Tegra::Shader::TextureType type, | ||
| 739 | bool is_array, bool is_shadow); | ||
| 740 | |||
| 733 | /// Extracts a sequence of bits from a node | 741 | /// Extracts a sequence of bits from a node |
| 734 | Node BitfieldExtract(Node value, u32 offset, u32 bits); | 742 | Node BitfieldExtract(Node value, u32 offset, u32 bits); |
| 735 | 743 | ||
| @@ -741,9 +749,11 @@ private: | |||
| 741 | void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | 749 | void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, |
| 742 | const Node4& components); | 750 | const Node4& components); |
| 743 | 751 | ||
| 744 | Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 752 | Node4 GetTexCode( |
| 745 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, | 753 | Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 746 | bool is_array, bool is_aoffi); | 754 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, bool is_array, |
| 755 | bool is_aoffi, bool is_bindless = false, | ||
| 756 | Tegra::Shader::Register bindless_reg = static_cast<Tegra::Shader::Register>(0)); | ||
| 747 | 757 | ||
| 748 | Node4 GetTexsCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 758 | Node4 GetTexsCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 749 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, | 759 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, |
| @@ -760,10 +770,12 @@ private: | |||
| 760 | bool lod_bias_enabled, std::size_t max_coords, std::size_t max_inputs); | 770 | bool lod_bias_enabled, std::size_t max_coords, std::size_t max_inputs); |
| 761 | 771 | ||
| 762 | std::vector<Node> GetAoffiCoordinates(Node aoffi_reg, std::size_t coord_count, bool is_tld4); | 772 | std::vector<Node> GetAoffiCoordinates(Node aoffi_reg, std::size_t coord_count, bool is_tld4); |
| 763 | 773 | ||
| 764 | Node4 GetTextureCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 774 | Node4 GetTextureCode( |
| 765 | Tegra::Shader::TextureProcessMode process_mode, std::vector<Node> coords, | 775 | Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 766 | Node array, Node depth_compare, u32 bias_offset, std::vector<Node> aoffi); | 776 | Tegra::Shader::TextureProcessMode process_mode, std::vector<Node> coords, Node array, |
| 777 | Node depth_compare, u32 bias_offset, std::vector<Node> aoffi, bool is_bindless = false, | ||
| 778 | Tegra::Shader::Register bindless_reg = static_cast<Tegra::Shader::Register>(0)); | ||
| 767 | 779 | ||
| 768 | Node GetVideoOperand(Node op, bool is_chunk, bool is_signed, Tegra::Shader::VideoType type, | 780 | Node GetVideoOperand(Node op, bool is_chunk, bool is_signed, Tegra::Shader::VideoType type, |
| 769 | u64 byte_height); | 781 | u64 byte_height); |
| @@ -833,6 +845,7 @@ private: | |||
| 833 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; | 845 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; |
| 834 | std::map<u32, ConstBuffer> used_cbufs; | 846 | std::map<u32, ConstBuffer> used_cbufs; |
| 835 | std::set<Sampler> used_samplers; | 847 | std::set<Sampler> used_samplers; |
| 848 | std::map<std::pair<u32, u32>, Sampler> used_bindless_samplers; | ||
| 836 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | 849 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; |
| 837 | std::set<GlobalMemoryBase> used_global_memory_bases; | 850 | std::set<GlobalMemoryBase> used_global_memory_bases; |
| 838 | 851 | ||