Shader_IR: Address Feedback.
This commit is contained in:
		
				
					committed by
					
						 FernandoS27
						FernandoS27
					
				
			
			
				
	
			
			
			
						parent
						
							e3afd6595a
						
					
				
				
					commit
					be856a38d6
				
			| @@ -72,7 +72,7 @@ struct HashableStruct { | |||||||
|  |  | ||||||
| struct PairHash { | struct PairHash { | ||||||
|     template <class T1, class T2> |     template <class T1, class T2> | ||||||
|     std::size_t operator()(const std::pair<T1, T2>& pair) const { |     std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept { | ||||||
|         std::size_t seed = std::hash<T1>()(pair.first); |         std::size_t seed = std::hash<T1>()(pair.first); | ||||||
|         boost::hash_combine(seed, std::hash<T2>()(pair.second)); |         boost::hash_combine(seed, std::hash<T2>()(pair.second)); | ||||||
|         return seed; |         return seed; | ||||||
|   | |||||||
| @@ -34,6 +34,10 @@ struct SamplerDescriptor { | |||||||
|         return raw == rhs.raw; |         return raw == rhs.raw; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     bool operator!=(const SamplerDescriptor& rhs) const noexcept { | ||||||
|  |         return !operator==(rhs); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) { |     static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) { | ||||||
|         SamplerDescriptor result; |         SamplerDescriptor result; | ||||||
|         switch (tic_texture_type) { |         switch (tic_texture_type) { | ||||||
| @@ -73,13 +77,12 @@ struct SamplerDescriptor { | |||||||
|             result.is_buffer.Assign(0); |             result.is_buffer.Assign(0); | ||||||
|             result.is_shadow.Assign(0); |             result.is_shadow.Assign(0); | ||||||
|             return result; |             return result; | ||||||
|         case Tegra::Texture::TextureType::Texture1DBuffer: { |         case Tegra::Texture::TextureType::Texture1DBuffer: | ||||||
|             result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D); |             result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D); | ||||||
|             result.is_array.Assign(0); |             result.is_array.Assign(0); | ||||||
|             result.is_buffer.Assign(1); |             result.is_buffer.Assign(1); | ||||||
|             result.is_shadow.Assign(0); |             result.is_shadow.Assign(0); | ||||||
|             return result; |             return result; | ||||||
|         } |  | ||||||
|         case Tegra::Texture::TextureType::Texture2DNoMipmap: |         case Tegra::Texture::TextureType::Texture2DNoMipmap: | ||||||
|             result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D); |             result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D); | ||||||
|             result.is_array.Assign(0); |             result.is_array.Assign(0); | ||||||
| @@ -105,7 +108,7 @@ static_assert(std::is_trivially_copyable_v<SamplerDescriptor>); | |||||||
|  |  | ||||||
| class ConstBufferEngineInterface { | class ConstBufferEngineInterface { | ||||||
| public: | public: | ||||||
|     virtual ~ConstBufferEngineInterface() {} |     virtual ~ConstBufferEngineInterface() = default; | ||||||
|     virtual u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const = 0; |     virtual u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const = 0; | ||||||
|     virtual SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const = 0; |     virtual SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const = 0; | ||||||
|     virtual SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer, |     virtual SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer, | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, | |||||||
|                                      Tegra::Engines::ConstBufferEngineInterface& engine) |                                      Tegra::Engines::ConstBufferEngineInterface& engine) | ||||||
|     : stage{shader_stage}, engine{&engine} {} |     : stage{shader_stage}, engine{&engine} {} | ||||||
|  |  | ||||||
|  | ConstBufferLocker::~ConstBufferLocker() = default; | ||||||
|  |  | ||||||
| std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { | std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { | ||||||
|     const std::pair<u32, u32> key = {buffer, offset}; |     const std::pair<u32, u32> key = {buffer, offset}; | ||||||
|     const auto iter = keys.find(key); |     const auto iter = keys.find(key); | ||||||
| @@ -29,7 +31,7 @@ std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { | |||||||
|         return iter->second; |         return iter->second; | ||||||
|     } |     } | ||||||
|     if (!engine) { |     if (!engine) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     const u32 value = engine->AccessConstBuffer32(stage, buffer, offset); |     const u32 value = engine->AccessConstBuffer32(stage, buffer, offset); | ||||||
|     keys.emplace(key, value); |     keys.emplace(key, value); | ||||||
| @@ -43,7 +45,7 @@ std::optional<SamplerDescriptor> ConstBufferLocker::ObtainBoundSampler(u32 offse | |||||||
|         return iter->second; |         return iter->second; | ||||||
|     } |     } | ||||||
|     if (!engine) { |     if (!engine) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset); |     const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset); | ||||||
|     bound_samplers.emplace(key, value); |     bound_samplers.emplace(key, value); | ||||||
| @@ -58,7 +60,7 @@ std::optional<Tegra::Engines::SamplerDescriptor> ConstBufferLocker::ObtainBindle | |||||||
|         return iter->second; |         return iter->second; | ||||||
|     } |     } | ||||||
|     if (!engine) { |     if (!engine) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset); |     const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset); | ||||||
|     bindless_samplers.emplace(key, value); |     bindless_samplers.emplace(key, value); | ||||||
|   | |||||||
| @@ -16,6 +16,11 @@ using BoundSamplerMap = std::unordered_map<u32, Tegra::Engines::SamplerDescripto | |||||||
| using BindlessSamplerMap = | using BindlessSamplerMap = | ||||||
|     std::unordered_map<std::pair<u32, u32>, Tegra::Engines::SamplerDescriptor, Common::PairHash>; |     std::unordered_map<std::pair<u32, u32>, Tegra::Engines::SamplerDescriptor, Common::PairHash>; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader | ||||||
|  |  * compiler. with it, the shader can obtain required data from GPU state and store it for disk | ||||||
|  |  * shader compilation. | ||||||
|  |  **/ | ||||||
| class ConstBufferLocker { | class ConstBufferLocker { | ||||||
| public: | public: | ||||||
|     explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage); |     explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage); | ||||||
| @@ -23,6 +28,8 @@ public: | |||||||
|     explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, |     explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, | ||||||
|                                Tegra::Engines::ConstBufferEngineInterface& engine); |                                Tegra::Engines::ConstBufferEngineInterface& engine); | ||||||
|  |  | ||||||
|  |     ~ConstBufferLocker(); | ||||||
|  |  | ||||||
|     /// Retrieves a key from the locker, if it's registered, it will give the registered value, if |     /// Retrieves a key from the locker, if it's registered, it will give the registered value, if | ||||||
|     /// not it will obtain it from maxwell3d and register it. |     /// not it will obtain it from maxwell3d and register it. | ||||||
|     std::optional<u32> ObtainKey(u32 buffer, u32 offset); |     std::optional<u32> ObtainKey(u32 buffer, u32 offset); | ||||||
|   | |||||||
| @@ -41,14 +41,10 @@ BlockBranchInfo MakeBranchInfo(Args&&... args) { | |||||||
|     return std::make_shared<BranchData>(T(std::forward<Args>(args)...)); |     return std::make_shared<BranchData>(T(std::forward<Args>(args)...)); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool BlockBranchInfoAreEqual(BlockBranchInfo first, BlockBranchInfo second) { |  | ||||||
|     return false; //(*first) == (*second); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool BlockBranchIsIgnored(BlockBranchInfo first) { | bool BlockBranchIsIgnored(BlockBranchInfo first) { | ||||||
|     bool ignore = false; |     bool ignore = false; | ||||||
|     if (std::holds_alternative<SingleBranch>(*first)) { |     if (std::holds_alternative<SingleBranch>(*first)) { | ||||||
|         auto branch = std::get_if<SingleBranch>(first.get()); |         const auto branch = std::get_if<SingleBranch>(first.get()); | ||||||
|         ignore = branch->ignore; |         ignore = branch->ignore; | ||||||
|     } |     } | ||||||
|     return ignore; |     return ignore; | ||||||
| @@ -151,10 +147,10 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|     const Instruction instr = {state.program_code[pos]}; |     const Instruction instr = {state.program_code[pos]}; | ||||||
|     const auto opcode = OpCode::Decode(instr); |     const auto opcode = OpCode::Decode(instr); | ||||||
|     if (opcode->get().GetId() != OpCode::Id::BRX) { |     if (opcode->get().GetId() != OpCode::Id::BRX) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     if (instr.brx.constant_buffer != 0) { |     if (instr.brx.constant_buffer != 0) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     track_register = instr.gpr8.Value(); |     track_register = instr.gpr8.Value(); | ||||||
|     result.relative_position = instr.brx.GetBranchExtend(); |     result.relative_position = instr.brx.GetBranchExtend(); | ||||||
| @@ -172,8 +168,8 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|         if (opcode->get().GetId() == OpCode::Id::LD_C) { |         if (opcode->get().GetId() == OpCode::Id::LD_C) { | ||||||
|             if (instr.gpr0.Value() == track_register && |             if (instr.gpr0.Value() == track_register && | ||||||
|                 instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) { |                 instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) { | ||||||
|                 result.buffer = instr.cbuf36.index; |                 result.buffer = instr.cbuf36.index.Value(); | ||||||
|                 result.offset = instr.cbuf36.GetOffset(); |                 result.offset = static_cast<u32>(instr.cbuf36.GetOffset()); | ||||||
|                 track_register = instr.gpr8.Value(); |                 track_register = instr.gpr8.Value(); | ||||||
|                 pos--; |                 pos--; | ||||||
|                 found_track = true; |                 found_track = true; | ||||||
| @@ -184,7 +180,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!found_track) { |     if (!found_track) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     found_track = false; |     found_track = false; | ||||||
|  |  | ||||||
| @@ -194,7 +190,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|             pos--; |             pos--; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         const Instruction instr = {state.program_code[pos]}; |         const Instruction instr = state.program_code[pos]; | ||||||
|         const auto opcode = OpCode::Decode(instr); |         const auto opcode = OpCode::Decode(instr); | ||||||
|         if (opcode->get().GetId() == OpCode::Id::SHL_IMM) { |         if (opcode->get().GetId() == OpCode::Id::SHL_IMM) { | ||||||
|             if (instr.gpr0.Value() == track_register) { |             if (instr.gpr0.Value() == track_register) { | ||||||
| @@ -208,7 +204,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!found_track) { |     if (!found_track) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     found_track = false; |     found_track = false; | ||||||
|  |  | ||||||
| @@ -218,7 +214,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|             pos--; |             pos--; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         const Instruction instr = {state.program_code[pos]}; |         const Instruction instr = state.program_code[pos]; | ||||||
|         const auto opcode = OpCode::Decode(instr); |         const auto opcode = OpCode::Decode(instr); | ||||||
|         if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) { |         if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) { | ||||||
|             if (instr.gpr0.Value() == track_register) { |             if (instr.gpr0.Value() == track_register) { | ||||||
| @@ -233,9 +229,9 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!found_track) { |     if (!found_track) { | ||||||
|         return {}; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     return {result}; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { | std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { | ||||||
| @@ -440,8 +436,8 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) | |||||||
|                     branches.emplace_back(value, target); |                     branches.emplace_back(value, target); | ||||||
|                 } |                 } | ||||||
|                 parse_info.end_address = offset; |                 parse_info.end_address = offset; | ||||||
|                 parse_info.branch_info = |                 parse_info.branch_info = MakeBranchInfo<MultiBranch>( | ||||||
|                     MakeBranchInfo<MultiBranch>(static_cast<u32>(instr.gpr8.Value()), branches); |                     static_cast<u32>(instr.gpr8.Value()), std::move(branches)); | ||||||
|  |  | ||||||
|                 return {ParseResult::ControlCaught, parse_info}; |                 return {ParseResult::ControlCaught, parse_info}; | ||||||
|             } else { |             } else { | ||||||
| @@ -486,7 +482,7 @@ bool TryInspectAddress(CFGRebuildState& state) { | |||||||
|         current_block.end = address - 1; |         current_block.end = address - 1; | ||||||
|         new_block.branch = current_block.branch; |         new_block.branch = current_block.branch; | ||||||
|         BlockBranchInfo forward_branch = MakeBranchInfo<SingleBranch>(); |         BlockBranchInfo forward_branch = MakeBranchInfo<SingleBranch>(); | ||||||
|         auto branch = std::get_if<SingleBranch>(forward_branch.get()); |         const auto branch = std::get_if<SingleBranch>(forward_branch.get()); | ||||||
|         branch->address = address; |         branch->address = address; | ||||||
|         branch->ignore = true; |         branch->ignore = true; | ||||||
|         current_block.branch = forward_branch; |         current_block.branch = forward_branch; | ||||||
| @@ -504,7 +500,7 @@ bool TryInspectAddress(CFGRebuildState& state) { | |||||||
|     BlockInfo& block_info = CreateBlockInfo(state, address, parse_info.end_address); |     BlockInfo& block_info = CreateBlockInfo(state, address, parse_info.end_address); | ||||||
|     block_info.branch = parse_info.branch_info; |     block_info.branch = parse_info.branch_info; | ||||||
|     if (std::holds_alternative<SingleBranch>(*block_info.branch)) { |     if (std::holds_alternative<SingleBranch>(*block_info.branch)) { | ||||||
|         auto branch = std::get_if<SingleBranch>(block_info.branch.get()); |         const auto branch = std::get_if<SingleBranch>(block_info.branch.get()); | ||||||
|         if (branch->condition.IsUnconditional()) { |         if (branch->condition.IsUnconditional()) { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
| @@ -550,7 +546,7 @@ bool TryQuery(CFGRebuildState& state) { | |||||||
|     gather_labels(q2.ssy_stack, state.ssy_labels, block); |     gather_labels(q2.ssy_stack, state.ssy_labels, block); | ||||||
|     gather_labels(q2.pbk_stack, state.pbk_labels, block); |     gather_labels(q2.pbk_stack, state.pbk_labels, block); | ||||||
|     if (std::holds_alternative<SingleBranch>(*block.branch)) { |     if (std::holds_alternative<SingleBranch>(*block.branch)) { | ||||||
|         auto branch = std::get_if<SingleBranch>(block.branch.get()); |         const auto branch = std::get_if<SingleBranch>(block.branch.get()); | ||||||
|         if (!branch->condition.IsUnconditional()) { |         if (!branch->condition.IsUnconditional()) { | ||||||
|             q2.address = block.end + 1; |             q2.address = block.end + 1; | ||||||
|             state.queries.push_back(q2); |             state.queries.push_back(q2); | ||||||
| @@ -573,8 +569,8 @@ bool TryQuery(CFGRebuildState& state) { | |||||||
|         state.queries.push_back(std::move(conditional_query)); |         state.queries.push_back(std::move(conditional_query)); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     auto multi_branch = std::get_if<MultiBranch>(block.branch.get()); |     const auto multi_branch = std::get_if<MultiBranch>(block.branch.get()); | ||||||
|     for (auto& branch_case : multi_branch->branches) { |     for (const auto& branch_case : multi_branch->branches) { | ||||||
|         Query conditional_query{q2}; |         Query conditional_query{q2}; | ||||||
|         conditional_query.address = branch_case.address; |         conditional_query.address = branch_case.address; | ||||||
|         state.queries.push_back(std::move(conditional_query)); |         state.queries.push_back(std::move(conditional_query)); | ||||||
| @@ -612,7 +608,7 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) { | |||||||
|         return MakeExpr<ExprBoolean>(true); |         return MakeExpr<ExprBoolean>(true); | ||||||
|     }); |     }); | ||||||
|     if (std::holds_alternative<SingleBranch>(*branch_info)) { |     if (std::holds_alternative<SingleBranch>(*branch_info)) { | ||||||
|         auto branch = std::get_if<SingleBranch>(branch_info.get()); |         const auto branch = std::get_if<SingleBranch>(branch_info.get()); | ||||||
|         if (branch->address < 0) { |         if (branch->address < 0) { | ||||||
|             if (branch->kill) { |             if (branch->kill) { | ||||||
|                 mm.InsertReturn(get_expr(branch->condition), true); |                 mm.InsertReturn(get_expr(branch->condition), true); | ||||||
| @@ -624,8 +620,8 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) { | |||||||
|         mm.InsertGoto(get_expr(branch->condition), branch->address); |         mm.InsertGoto(get_expr(branch->condition), branch->address); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     auto multi_branch = std::get_if<MultiBranch>(branch_info.get()); |     const auto multi_branch = std::get_if<MultiBranch>(branch_info.get()); | ||||||
|     for (auto& branch_case : multi_branch->branches) { |     for (const auto& branch_case : multi_branch->branches) { | ||||||
|         mm.InsertGoto(MakeExpr<ExprGprEqual>(multi_branch->gpr, branch_case.cmp_value), |         mm.InsertGoto(MakeExpr<ExprGprEqual>(multi_branch->gpr, branch_case.cmp_value), | ||||||
|                       branch_case.address); |                       branch_case.address); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -51,6 +51,10 @@ public: | |||||||
|                std::tie(b.condition, b.address, b.kill, b.is_sync, b.is_brk, b.ignore); |                std::tie(b.condition, b.address, b.kill, b.is_sync, b.is_brk, b.ignore); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     bool operator!=(const SingleBranch& b) const { | ||||||
|  |         return !operator==(b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     Condition condition{}; |     Condition condition{}; | ||||||
|     s32 address{exit_branch}; |     s32 address{exit_branch}; | ||||||
|     bool kill{}; |     bool kill{}; | ||||||
| @@ -67,7 +71,7 @@ struct CaseBranch { | |||||||
|  |  | ||||||
| class MultiBranch { | class MultiBranch { | ||||||
| public: | public: | ||||||
|     MultiBranch(u32 gpr, std::vector<CaseBranch>& branches) |     MultiBranch(u32 gpr, std::vector<CaseBranch>&& branches) | ||||||
|         : gpr{gpr}, branches{std::move(branches)} {} |         : gpr{gpr}, branches{std::move(branches)} {} | ||||||
|  |  | ||||||
|     u32 gpr{}; |     u32 gpr{}; | ||||||
|   | |||||||
| @@ -155,7 +155,7 @@ void ShaderIR::Decode() { | |||||||
|         [[fallthrough]]; |         [[fallthrough]]; | ||||||
|     case CompileDepth::BruteForce: { |     case CompileDepth::BruteForce: { | ||||||
|         coverage_begin = main_offset; |         coverage_begin = main_offset; | ||||||
|         const u32 shader_end = program_code.size(); |         const std::size_t shader_end = program_code.size(); | ||||||
|         coverage_end = shader_end; |         coverage_end = shader_end; | ||||||
|         for (u32 label = main_offset; label < shader_end; label++) { |         for (u32 label = main_offset; label < shader_end; label++) { | ||||||
|             basic_blocks.insert({label, DecodeRange(label, label + 1)}); |             basic_blocks.insert({label, DecodeRange(label, label + 1)}); | ||||||
|   | |||||||
| @@ -284,7 +284,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||||||
|  |  | ||||||
| const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | ||||||
|                                     std::optional<SamplerInfo> sampler_info) { |                                     std::optional<SamplerInfo> sampler_info) { | ||||||
|     const auto offset = static_cast<std::size_t>(sampler.index.Value()); |     const auto offset = static_cast<u32>(sampler.index.Value()); | ||||||
|  |  | ||||||
|     Tegra::Shader::TextureType type; |     Tegra::Shader::TextureType type; | ||||||
|     bool is_array; |     bool is_array; | ||||||
| @@ -293,9 +293,7 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||||||
|         type = sampler_info->type; |         type = sampler_info->type; | ||||||
|         is_array = sampler_info->is_array; |         is_array = sampler_info->is_array; | ||||||
|         is_shadow = sampler_info->is_shadow; |         is_shadow = sampler_info->is_shadow; | ||||||
|     } else { |     } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) { | ||||||
|         auto sampler = locker.ObtainBoundSampler(offset); |  | ||||||
|         if (sampler) { |  | ||||||
|         type = sampler->texture_type.Value(); |         type = sampler->texture_type.Value(); | ||||||
|         is_array = sampler->is_array.Value() != 0; |         is_array = sampler->is_array.Value() != 0; | ||||||
|         is_shadow = sampler->is_shadow.Value() != 0; |         is_shadow = sampler->is_shadow.Value() != 0; | ||||||
| @@ -304,7 +302,6 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||||||
|         is_array = false; |         is_array = false; | ||||||
|         is_shadow = false; |         is_shadow = false; | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // If this sampler has already been used, return the existing mapping. |     // If this sampler has already been used, return the existing mapping. | ||||||
|     const auto itr = |     const auto itr = | ||||||
| @@ -320,7 +317,7 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||||||
|     const std::size_t next_index = used_samplers.size(); |     const std::size_t next_index = used_samplers.size(); | ||||||
|     const Sampler entry{offset, next_index, type, is_array, is_shadow}; |     const Sampler entry{offset, next_index, type, is_array, is_shadow}; | ||||||
|     return *used_samplers.emplace(entry).first; |     return *used_samplers.emplace(entry).first; | ||||||
| } | } // namespace VideoCommon::Shader | ||||||
|  |  | ||||||
| const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | ||||||
|                                             std::optional<SamplerInfo> sampler_info) { |                                             std::optional<SamplerInfo> sampler_info) { | ||||||
| @@ -336,9 +333,7 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | |||||||
|         type = sampler_info->type; |         type = sampler_info->type; | ||||||
|         is_array = sampler_info->is_array; |         is_array = sampler_info->is_array; | ||||||
|         is_shadow = sampler_info->is_shadow; |         is_shadow = sampler_info->is_shadow; | ||||||
|     } else { |     } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) { | ||||||
|         auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); |  | ||||||
|         if (sampler) { |  | ||||||
|         type = sampler->texture_type.Value(); |         type = sampler->texture_type.Value(); | ||||||
|         is_array = sampler->is_array.Value() != 0; |         is_array = sampler->is_array.Value() != 0; | ||||||
|         is_shadow = sampler->is_shadow.Value() != 0; |         is_shadow = sampler->is_shadow.Value() != 0; | ||||||
| @@ -347,7 +342,6 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | |||||||
|         is_array = false; |         is_array = false; | ||||||
|         is_shadow = false; |         is_shadow = false; | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // If this sampler has already been used, return the existing mapping. |     // If this sampler has already been used, return the existing mapping. | ||||||
|     const auto itr = |     const auto itr = | ||||||
|   | |||||||
| @@ -127,6 +127,10 @@ public: | |||||||
|         return gpr == b.gpr && value == b.value; |         return gpr == b.gpr && value == b.value; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     bool operator!=(const ExprGprEqual& b) const { | ||||||
|  |         return !operator==(b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     u32 gpr; |     u32 gpr; | ||||||
|     u32 value; |     u32 value; | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user