Merge pull request #2565 from ReinUsesLisp/track-indirect
shader/track: Track indirect buffers
This commit is contained in:
		
						commit
						b56e7f870a
					
				| @ -95,12 +95,8 @@ const Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::Image | ||||
| const Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, | ||||
|                                         Tegra::Shader::ImageType type) { | ||||
|     const Node image_register{GetRegister(reg)}; | ||||
|     const Node base_image{ | ||||
|     const auto [base_image, cbuf_index, cbuf_offset]{ | ||||
|         TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; | ||||
|     const auto cbuf{std::get_if<CbufNode>(&*base_image)}; | ||||
|     const auto cbuf_offset_imm{std::get_if<ImmediateNode>(&*cbuf->GetOffset())}; | ||||
|     const auto cbuf_offset{cbuf_offset_imm->GetValue()}; | ||||
|     const auto cbuf_index{cbuf->GetIndex()}; | ||||
|     const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; | ||||
| 
 | ||||
|     // If this image has already been used, return the existing mapping.
 | ||||
|  | ||||
| @ -297,18 +297,13 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeB | ||||
|     const auto addr_register{GetRegister(instr.gmem.gpr)}; | ||||
|     const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; | ||||
| 
 | ||||
|     const Node base_address{ | ||||
|         TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))}; | ||||
|     const auto cbuf = std::get_if<CbufNode>(&*base_address); | ||||
|     ASSERT(cbuf != nullptr); | ||||
|     const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset()); | ||||
|     ASSERT(cbuf_offset_imm != nullptr); | ||||
|     const auto cbuf_offset = cbuf_offset_imm->GetValue(); | ||||
|     const auto [base_address, index, offset] = | ||||
|         TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); | ||||
|     ASSERT(base_address != nullptr); | ||||
| 
 | ||||
|     bb.push_back( | ||||
|         Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", cbuf->GetIndex(), cbuf_offset))); | ||||
|     bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); | ||||
| 
 | ||||
|     const GlobalMemoryBase descriptor{cbuf->GetIndex(), cbuf_offset}; | ||||
|     const GlobalMemoryBase descriptor{index, offset}; | ||||
|     const auto& [entry, is_new] = used_global_memory.try_emplace(descriptor); | ||||
|     auto& usage = entry->second; | ||||
|     if (is_write) { | ||||
|  | ||||
| @ -308,13 +308,9 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu | ||||
| const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, TextureType type, | ||||
|                                             bool is_array, bool is_shadow) { | ||||
|     const Node sampler_register = GetRegister(reg); | ||||
|     const Node base_sampler = | ||||
|     const auto [base_sampler, cbuf_index, cbuf_offset] = | ||||
|         TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); | ||||
|     const auto cbuf = std::get_if<CbufNode>(&*base_sampler); | ||||
|     const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset()); | ||||
|     ASSERT(cbuf_offset_imm != nullptr); | ||||
|     const auto cbuf_offset = cbuf_offset_imm->GetValue(); | ||||
|     const auto cbuf_index = cbuf->GetIndex(); | ||||
|     ASSERT(base_sampler != nullptr); | ||||
|     const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); | ||||
| 
 | ||||
|     // If this sampler has already been used, return the existing mapping.
 | ||||
|  | ||||
| @ -61,7 +61,16 @@ Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) { | ||||
|     const auto [entry, is_new] = used_cbufs.try_emplace(index); | ||||
|     entry->second.MarkAsUsedIndirect(); | ||||
| 
 | ||||
|     const Node final_offset = Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset)); | ||||
|     const Node final_offset = [&]() { | ||||
|         // Attempt to inline constant buffer without a variable offset. This is done to allow
 | ||||
|         // tracking LDC calls.
 | ||||
|         if (const auto gpr = std::get_if<GprNode>(&*node)) { | ||||
|             if (gpr->GetIndex() == Register::ZeroIndex) { | ||||
|                 return Immediate(offset); | ||||
|             } | ||||
|         } | ||||
|         return Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset)); | ||||
|     }(); | ||||
|     return MakeNode<CbufNode>(index, final_offset); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -328,7 +328,7 @@ private: | ||||
|     void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b, | ||||
|                               Node op_c, Node imm_lut, bool sets_cc); | ||||
| 
 | ||||
|     Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; | ||||
|     std::tuple<Node, u32, u32> TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; | ||||
| 
 | ||||
|     std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; | ||||
| 
 | ||||
|  | ||||
| @ -32,39 +32,44 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, | ||||
|     } | ||||
|     return {}; | ||||
| } | ||||
| } // namespace
 | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const { | ||||
| std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, | ||||
|                                                s64 cursor) const { | ||||
|     if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { | ||||
|         // Cbuf found, but it has to be immediate
 | ||||
|         return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr; | ||||
|         // Constant buffer found, test if it's an immediate
 | ||||
|         const auto offset = cbuf->GetOffset(); | ||||
|         if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { | ||||
|             return {tracked, cbuf->GetIndex(), immediate->GetValue()}; | ||||
|         } | ||||
|         return {}; | ||||
|     } | ||||
|     if (const auto gpr = std::get_if<GprNode>(&*tracked)) { | ||||
|         if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) { | ||||
|             return nullptr; | ||||
|             return {}; | ||||
|         } | ||||
|         // Reduce the cursor in one to avoid infinite loops when the instruction sets the same
 | ||||
|         // register that it uses as operand
 | ||||
|         const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1); | ||||
|         if (!source) { | ||||
|             return nullptr; | ||||
|             return {}; | ||||
|         } | ||||
|         return TrackCbuf(source, code, new_cursor); | ||||
|     } | ||||
|     if (const auto operation = std::get_if<OperationNode>(&*tracked)) { | ||||
|         for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) { | ||||
|             if (const auto found = TrackCbuf((*operation)[i], code, cursor)) { | ||||
|                 // Cbuf found in operand
 | ||||
|             if (auto found = TrackCbuf((*operation)[i], code, cursor); std::get<0>(found)) { | ||||
|                 // Cbuf found in operand.
 | ||||
|                 return found; | ||||
|             } | ||||
|         } | ||||
|         return nullptr; | ||||
|         return {}; | ||||
|     } | ||||
|     if (const auto conditional = std::get_if<ConditionalNode>(&*tracked)) { | ||||
|         const auto& conditional_code = conditional->GetCode(); | ||||
|         return TrackCbuf(tracked, conditional_code, static_cast<s64>(conditional_code.size())); | ||||
|     } | ||||
|     return nullptr; | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Fernando Sahmkow
						Fernando Sahmkow