summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-03-26 17:05:23 -0400
committerGravatar FernandoS272019-04-08 11:23:42 -0400
commite28fd3d0a533695242d17350dd929ad3bb56c429 (patch)
treea1cc9ed6da8143f1f314dd47bf482f48dca80145 /src
parentImplement Const Buffer Accessor (diff)
downloadyuzu-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.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp2
-rw-r--r--src/video_core/shader/decode/texture.cpp58
-rw-r--r--src/video_core/shader/shader_ir.h31
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
274const 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
257void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 300void 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
326Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, 369Node4 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
385Node4 ShaderIR::GetTexCode(Instruction instr, TextureType texture_type, 430Node4 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
429Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type, 475Node4 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
197class Sampler { 197class Sampler {
198public: 198public:
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
238class ConstBuffer { 242class 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