diff options
| author | 2019-12-16 01:26:11 -0300 | |
|---|---|---|
| committer | 2019-12-16 01:26:11 -0300 | |
| commit | eac075692be0df873df04cbe8e09296f64d1dfe1 (patch) | |
| tree | ba39ab7d01d91a606aabd41f84ed11455b283459 /src | |
| parent | Merge pull request #3222 from ReinUsesLisp/maxwell-to-vk (diff) | |
| parent | Shader_IR: Correct TLD4S Depth Compare. (diff) | |
| download | yuzu-eac075692be0df873df04cbe8e09296f64d1dfe1.tar.gz yuzu-eac075692be0df873df04cbe8e09296f64d1dfe1.tar.xz yuzu-eac075692be0df873df04cbe8e09296f64d1dfe1.zip | |
Merge pull request #3219 from FernandoS27/fix-bindless
Corrections and fixes to TLD4S & bindless samplers failing
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 29 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 133 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 6 |
4 files changed, 124 insertions, 47 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 290d929df..d6a2cc8b8 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -1292,6 +1292,7 @@ union Instruction { | |||
| 1292 | BitField<50, 1, u64> dc_flag; | 1292 | BitField<50, 1, u64> dc_flag; |
| 1293 | BitField<51, 1, u64> aoffi_flag; | 1293 | BitField<51, 1, u64> aoffi_flag; |
| 1294 | BitField<52, 2, u64> component; | 1294 | BitField<52, 2, u64> component; |
| 1295 | BitField<55, 1, u64> fp16_flag; | ||
| 1295 | 1296 | ||
| 1296 | bool UsesMiscMode(TextureMiscMode mode) const { | 1297 | bool UsesMiscMode(TextureMiscMode mode) const { |
| 1297 | switch (mode) { | 1298 | switch (mode) { |
| @@ -1972,7 +1973,7 @@ private: | |||
| 1972 | INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"), | 1973 | INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"), |
| 1973 | INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"), | 1974 | INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"), |
| 1974 | INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"), | 1975 | INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"), |
| 1975 | INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), | 1976 | INST("11011111--00----", Id::TLD4S, Type::Texture, "TLD4S"), |
| 1976 | INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), | 1977 | INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), |
| 1977 | INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), | 1978 | INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), |
| 1978 | INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"), | 1979 | INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index fa7049bbe..d1ae4be6d 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1076,7 +1076,7 @@ private: | |||
| 1076 | } | 1076 | } |
| 1077 | 1077 | ||
| 1078 | std::string GenerateTexture(Operation operation, const std::string& function_suffix, | 1078 | std::string GenerateTexture(Operation operation, const std::string& function_suffix, |
| 1079 | const std::vector<TextureIR>& extras) { | 1079 | const std::vector<TextureIR>& extras, bool sepparate_dc = false) { |
| 1080 | constexpr std::array coord_constructors = {"float", "vec2", "vec3", "vec4"}; | 1080 | constexpr std::array coord_constructors = {"float", "vec2", "vec3", "vec4"}; |
| 1081 | 1081 | ||
| 1082 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | 1082 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
| @@ -1091,7 +1091,8 @@ private: | |||
| 1091 | expr += "Offset"; | 1091 | expr += "Offset"; |
| 1092 | } | 1092 | } |
| 1093 | expr += '(' + GetSampler(meta->sampler) + ", "; | 1093 | expr += '(' + GetSampler(meta->sampler) + ", "; |
| 1094 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1); | 1094 | expr += coord_constructors.at(count + (has_array ? 1 : 0) + |
| 1095 | (has_shadow && !sepparate_dc ? 1 : 0) - 1); | ||
| 1095 | expr += '('; | 1096 | expr += '('; |
| 1096 | for (std::size_t i = 0; i < count; ++i) { | 1097 | for (std::size_t i = 0; i < count; ++i) { |
| 1097 | expr += Visit(operation[i]).AsFloat(); | 1098 | expr += Visit(operation[i]).AsFloat(); |
| @@ -1104,9 +1105,14 @@ private: | |||
| 1104 | expr += ", float(" + Visit(meta->array).AsInt() + ')'; | 1105 | expr += ", float(" + Visit(meta->array).AsInt() + ')'; |
| 1105 | } | 1106 | } |
| 1106 | if (has_shadow) { | 1107 | if (has_shadow) { |
| 1107 | expr += ", " + Visit(meta->depth_compare).AsFloat(); | 1108 | if (sepparate_dc) { |
| 1109 | expr += "), " + Visit(meta->depth_compare).AsFloat(); | ||
| 1110 | } else { | ||
| 1111 | expr += ", " + Visit(meta->depth_compare).AsFloat() + ')'; | ||
| 1112 | } | ||
| 1113 | } else { | ||
| 1114 | expr += ')'; | ||
| 1108 | } | 1115 | } |
| 1109 | expr += ')'; | ||
| 1110 | 1116 | ||
| 1111 | for (const auto& variant : extras) { | 1117 | for (const auto& variant : extras) { |
| 1112 | if (const auto argument = std::get_if<TextureArgument>(&variant)) { | 1118 | if (const auto argument = std::get_if<TextureArgument>(&variant)) { |
| @@ -1706,10 +1712,17 @@ private: | |||
| 1706 | ASSERT(meta); | 1712 | ASSERT(meta); |
| 1707 | 1713 | ||
| 1708 | const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; | 1714 | const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; |
| 1709 | return {GenerateTexture(operation, "Gather", | 1715 | if (meta->sampler.IsShadow()) { |
| 1710 | {TextureAoffi{}, TextureArgument{type, meta->component}}) + | 1716 | return {GenerateTexture(operation, "Gather", {TextureAoffi{}}, true) + |
| 1711 | GetSwizzle(meta->element), | 1717 | GetSwizzle(meta->element), |
| 1712 | Type::Float}; | 1718 | Type::Float}; |
| 1719 | } else { | ||
| 1720 | return {GenerateTexture(operation, "Gather", | ||
| 1721 | {TextureAoffi{}, TextureArgument{type, meta->component}}, | ||
| 1722 | false) + | ||
| 1723 | GetSwizzle(meta->element), | ||
| 1724 | Type::Float}; | ||
| 1725 | } | ||
| 1713 | } | 1726 | } |
| 1714 | 1727 | ||
| 1715 | Expression TextureQueryDimensions(Operation operation) { | 1728 | Expression TextureQueryDimensions(Operation operation) { |
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index da8e886df..994c05611 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -107,8 +107,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 107 | break; | 107 | break; |
| 108 | } | 108 | } |
| 109 | case OpCode::Id::TLD4S: { | 109 | case OpCode::Id::TLD4S: { |
| 110 | UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), | 110 | const bool uses_aoffi = instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI); |
| 111 | "AOFFI is not implemented"); | 111 | UNIMPLEMENTED_IF_MSG(uses_aoffi, "AOFFI is not implemented"); |
| 112 | 112 | ||
| 113 | const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC); | 113 | const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC); |
| 114 | const Node op_a = GetRegister(instr.gpr8); | 114 | const Node op_a = GetRegister(instr.gpr8); |
| @@ -116,29 +116,40 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 116 | 116 | ||
| 117 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. | 117 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. |
| 118 | std::vector<Node> coords; | 118 | std::vector<Node> coords; |
| 119 | Node dc_reg; | ||
| 119 | if (depth_compare) { | 120 | if (depth_compare) { |
| 120 | // Note: TLD4S coordinate encoding works just like TEXS's | 121 | // Note: TLD4S coordinate encoding works just like TEXS's |
| 121 | const Node op_y = GetRegister(instr.gpr8.Value() + 1); | 122 | const Node op_y = GetRegister(instr.gpr8.Value() + 1); |
| 122 | coords.push_back(op_a); | 123 | coords.push_back(op_a); |
| 123 | coords.push_back(op_y); | 124 | coords.push_back(op_y); |
| 124 | coords.push_back(op_b); | 125 | dc_reg = uses_aoffi ? GetRegister(instr.gpr20.Value() + 1) : op_b; |
| 125 | } else { | 126 | } else { |
| 126 | coords.push_back(op_a); | 127 | coords.push_back(op_a); |
| 127 | coords.push_back(op_b); | 128 | if (uses_aoffi) { |
| 129 | const Node op_y = GetRegister(instr.gpr8.Value() + 1); | ||
| 130 | coords.push_back(op_y); | ||
| 131 | } else { | ||
| 132 | coords.push_back(op_b); | ||
| 133 | } | ||
| 134 | dc_reg = {}; | ||
| 128 | } | 135 | } |
| 129 | const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); | 136 | const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); |
| 130 | 137 | ||
| 131 | const SamplerInfo info{TextureType::Texture2D, false, depth_compare}; | 138 | const SamplerInfo info{TextureType::Texture2D, false, depth_compare}; |
| 132 | const auto& sampler = GetSampler(instr.sampler, info); | 139 | const Sampler& sampler = *GetSampler(instr.sampler, info); |
| 133 | 140 | ||
| 134 | Node4 values; | 141 | Node4 values; |
| 135 | for (u32 element = 0; element < values.size(); ++element) { | 142 | for (u32 element = 0; element < values.size(); ++element) { |
| 136 | auto coords_copy = coords; | 143 | auto coords_copy = coords; |
| 137 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element}; | 144 | MetaTexture meta{sampler, {}, dc_reg, {}, {}, {}, {}, component, element}; |
| 138 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 145 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 139 | } | 146 | } |
| 140 | 147 | ||
| 141 | WriteTexsInstructionFloat(bb, instr, values, true); | 148 | if (instr.tld4s.fp16_flag) { |
| 149 | WriteTexsInstructionHalfFloat(bb, instr, values, true); | ||
| 150 | } else { | ||
| 151 | WriteTexsInstructionFloat(bb, instr, values, true); | ||
| 152 | } | ||
| 142 | break; | 153 | break; |
| 143 | } | 154 | } |
| 144 | case OpCode::Id::TXD_B: | 155 | case OpCode::Id::TXD_B: |
| @@ -154,9 +165,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 154 | const auto texture_type = instr.txd.texture_type.Value(); | 165 | const auto texture_type = instr.txd.texture_type.Value(); |
| 155 | const auto coord_count = GetCoordCount(texture_type); | 166 | const auto coord_count = GetCoordCount(texture_type); |
| 156 | 167 | ||
| 157 | const auto& sampler = is_bindless | 168 | const Sampler* sampler = is_bindless |
| 158 | ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) | 169 | ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) |
| 159 | : GetSampler(instr.sampler, {{texture_type, false, false}}); | 170 | : GetSampler(instr.sampler, {{texture_type, false, false}}); |
| 171 | Node4 values; | ||
| 172 | if (sampler == nullptr) { | ||
| 173 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 174 | values[element] = Immediate(0); | ||
| 175 | } | ||
| 176 | WriteTexInstructionFloat(bb, instr, values); | ||
| 177 | break; | ||
| 178 | } | ||
| 160 | if (is_bindless) { | 179 | if (is_bindless) { |
| 161 | base_reg++; | 180 | base_reg++; |
| 162 | } | 181 | } |
| @@ -170,9 +189,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 170 | derivates.push_back(GetRegister(derivate_reg + derivate + 1)); | 189 | derivates.push_back(GetRegister(derivate_reg + derivate + 1)); |
| 171 | } | 190 | } |
| 172 | 191 | ||
| 173 | Node4 values; | ||
| 174 | for (u32 element = 0; element < values.size(); ++element) { | 192 | for (u32 element = 0; element < values.size(); ++element) { |
| 175 | MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element}; | 193 | MetaTexture meta{*sampler, {}, {}, {}, derivates, {}, {}, {}, element}; |
| 176 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); | 194 | values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); |
| 177 | } | 195 | } |
| 178 | 196 | ||
| @@ -187,9 +205,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 187 | // TODO: The new commits on the texture refactor, change the way samplers work. | 205 | // 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 | 206 | // Sadly, not all texture instructions specify the type of texture their sampler |
| 189 | // uses. This must be fixed at a later instance. | 207 | // uses. This must be fixed at a later instance. |
| 190 | const auto& sampler = | 208 | const Sampler* sampler = |
| 191 | is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); | 209 | is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); |
| 192 | 210 | ||
| 211 | if (sampler == nullptr) { | ||
| 212 | u32 indexer = 0; | ||
| 213 | for (u32 element = 0; element < 4; ++element) { | ||
| 214 | if (!instr.txq.IsComponentEnabled(element)) { | ||
| 215 | continue; | ||
| 216 | } | ||
| 217 | const Node value = Immediate(0); | ||
| 218 | SetTemporary(bb, indexer++, value); | ||
| 219 | } | ||
| 220 | for (u32 i = 0; i < indexer; ++i) { | ||
| 221 | SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); | ||
| 222 | } | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | |||
| 193 | u32 indexer = 0; | 226 | u32 indexer = 0; |
| 194 | switch (instr.txq.query_type) { | 227 | switch (instr.txq.query_type) { |
| 195 | case Tegra::Shader::TextureQueryType::Dimension: { | 228 | case Tegra::Shader::TextureQueryType::Dimension: { |
| @@ -197,7 +230,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 197 | if (!instr.txq.IsComponentEnabled(element)) { | 230 | if (!instr.txq.IsComponentEnabled(element)) { |
| 198 | continue; | 231 | continue; |
| 199 | } | 232 | } |
| 200 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; | 233 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; |
| 201 | const Node value = | 234 | const Node value = |
| 202 | Operation(OperationCode::TextureQueryDimensions, meta, | 235 | Operation(OperationCode::TextureQueryDimensions, meta, |
| 203 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); | 236 | GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); |
| @@ -223,9 +256,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 223 | 256 | ||
| 224 | auto texture_type = instr.tmml.texture_type.Value(); | 257 | auto texture_type = instr.tmml.texture_type.Value(); |
| 225 | const bool is_array = instr.tmml.array != 0; | 258 | const bool is_array = instr.tmml.array != 0; |
| 226 | const auto& sampler = | 259 | const Sampler* sampler = |
| 227 | is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); | 260 | is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); |
| 228 | 261 | ||
| 262 | if (sampler == nullptr) { | ||
| 263 | u32 indexer = 0; | ||
| 264 | for (u32 element = 0; element < 2; ++element) { | ||
| 265 | if (!instr.tmml.IsComponentEnabled(element)) { | ||
| 266 | continue; | ||
| 267 | } | ||
| 268 | const Node value = Immediate(0); | ||
| 269 | SetTemporary(bb, indexer++, value); | ||
| 270 | } | ||
| 271 | for (u32 i = 0; i < indexer; ++i) { | ||
| 272 | SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); | ||
| 273 | } | ||
| 274 | break; | ||
| 275 | } | ||
| 276 | |||
| 229 | std::vector<Node> coords; | 277 | std::vector<Node> coords; |
| 230 | 278 | ||
| 231 | // TODO: Add coordinates for different samplers once other texture types are implemented. | 279 | // TODO: Add coordinates for different samplers once other texture types are implemented. |
| @@ -251,7 +299,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 251 | continue; | 299 | continue; |
| 252 | } | 300 | } |
| 253 | auto params = coords; | 301 | auto params = coords; |
| 254 | MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; | 302 | MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; |
| 255 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); | 303 | const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); |
| 256 | SetTemporary(bb, indexer++, value); | 304 | SetTemporary(bb, indexer++, value); |
| 257 | } | 305 | } |
| @@ -307,7 +355,7 @@ ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sample | |||
| 307 | sampler->is_buffer != 0}; | 355 | sampler->is_buffer != 0}; |
| 308 | } | 356 | } |
| 309 | 357 | ||
| 310 | const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | 358 | const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, |
| 311 | std::optional<SamplerInfo> sampler_info) { | 359 | std::optional<SamplerInfo> sampler_info) { |
| 312 | const auto offset = static_cast<u32>(sampler.index.Value()); | 360 | const auto offset = static_cast<u32>(sampler.index.Value()); |
| 313 | const auto info = GetSamplerInfo(sampler_info, offset); | 361 | const auto info = GetSamplerInfo(sampler_info, offset); |
| @@ -319,21 +367,24 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||
| 319 | if (it != used_samplers.end()) { | 367 | if (it != used_samplers.end()) { |
| 320 | ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && | 368 | ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && |
| 321 | it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); | 369 | it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); |
| 322 | return *it; | 370 | return &(*it); |
| 323 | } | 371 | } |
| 324 | 372 | ||
| 325 | // Otherwise create a new mapping for this sampler | 373 | // Otherwise create a new mapping for this sampler |
| 326 | const auto next_index = static_cast<u32>(used_samplers.size()); | 374 | 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, | 375 | return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, |
| 328 | info.is_buffer); | 376 | info.is_buffer); |
| 329 | } | 377 | } |
| 330 | 378 | ||
| 331 | const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | 379 | const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, |
| 332 | std::optional<SamplerInfo> sampler_info) { | 380 | std::optional<SamplerInfo> sampler_info) { |
| 333 | const Node sampler_register = GetRegister(reg); | 381 | const Node sampler_register = GetRegister(reg); |
| 334 | const auto [base_sampler, buffer, offset] = | 382 | const auto [base_sampler, buffer, offset] = |
| 335 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); | 383 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); |
| 336 | ASSERT(base_sampler != nullptr); | 384 | ASSERT(base_sampler != nullptr); |
| 385 | if (base_sampler == nullptr) { | ||
| 386 | return nullptr; | ||
| 387 | } | ||
| 337 | 388 | ||
| 338 | const auto info = GetSamplerInfo(sampler_info, offset, buffer); | 389 | const auto info = GetSamplerInfo(sampler_info, offset, buffer); |
| 339 | 390 | ||
| @@ -346,13 +397,13 @@ const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, | |||
| 346 | if (it != used_samplers.end()) { | 397 | if (it != used_samplers.end()) { |
| 347 | ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && | 398 | ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && |
| 348 | it->IsShadow() == info.is_shadow); | 399 | it->IsShadow() == info.is_shadow); |
| 349 | return *it; | 400 | return &(*it); |
| 350 | } | 401 | } |
| 351 | 402 | ||
| 352 | // Otherwise create a new mapping for this sampler | 403 | // Otherwise create a new mapping for this sampler |
| 353 | const auto next_index = static_cast<u32>(used_samplers.size()); | 404 | 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, | 405 | return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, |
| 355 | info.is_shadow, info.is_buffer); | 406 | info.is_shadow, info.is_buffer); |
| 356 | } | 407 | } |
| 357 | 408 | ||
| 358 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { | 409 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { |
| @@ -395,14 +446,14 @@ void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr, const | |||
| 395 | } | 446 | } |
| 396 | 447 | ||
| 397 | void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr, | 448 | void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr, |
| 398 | const Node4& components) { | 449 | const Node4& components, bool ignore_mask) { |
| 399 | // TEXS.F16 destionation registers are packed in two registers in pairs (just like any half | 450 | // TEXS.F16 destionation registers are packed in two registers in pairs (just like any half |
| 400 | // float instruction). | 451 | // float instruction). |
| 401 | 452 | ||
| 402 | Node4 values; | 453 | Node4 values; |
| 403 | u32 dest_elem = 0; | 454 | u32 dest_elem = 0; |
| 404 | for (u32 component = 0; component < 4; ++component) { | 455 | for (u32 component = 0; component < 4; ++component) { |
| 405 | if (!instr.texs.IsComponentEnabled(component)) | 456 | if (!instr.texs.IsComponentEnabled(component) && !ignore_mask) |
| 406 | continue; | 457 | continue; |
| 407 | values[dest_elem++] = components[component]; | 458 | values[dest_elem++] = components[component]; |
| 408 | } | 459 | } |
| @@ -438,8 +489,15 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 438 | "This method is not supported."); | 489 | "This method is not supported."); |
| 439 | 490 | ||
| 440 | const SamplerInfo info{texture_type, is_array, is_shadow, false}; | 491 | const SamplerInfo info{texture_type, is_array, is_shadow, false}; |
| 441 | const auto& sampler = | 492 | const Sampler* sampler = |
| 442 | is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); | 493 | is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); |
| 494 | Node4 values; | ||
| 495 | if (sampler == nullptr) { | ||
| 496 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 497 | values[element] = Immediate(0); | ||
| 498 | } | ||
| 499 | return values; | ||
| 500 | } | ||
| 443 | 501 | ||
| 444 | const bool lod_needed = process_mode == TextureProcessMode::LZ || | 502 | const bool lod_needed = process_mode == TextureProcessMode::LZ || |
| 445 | process_mode == TextureProcessMode::LL || | 503 | process_mode == TextureProcessMode::LL || |
| @@ -478,10 +536,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, | |||
| 478 | } | 536 | } |
| 479 | } | 537 | } |
| 480 | 538 | ||
| 481 | Node4 values; | ||
| 482 | for (u32 element = 0; element < values.size(); ++element) { | 539 | for (u32 element = 0; element < values.size(); ++element) { |
| 483 | auto copy_coords = coords; | 540 | auto copy_coords = coords; |
| 484 | MetaTexture meta{sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; | 541 | MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, bias, lod, {}, element}; |
| 485 | values[element] = Operation(read_method, meta, std::move(copy_coords)); | 542 | values[element] = Operation(read_method, meta, std::move(copy_coords)); |
| 486 | } | 543 | } |
| 487 | 544 | ||
| @@ -594,8 +651,15 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de | |||
| 594 | u64 parameter_register = instr.gpr20.Value(); | 651 | u64 parameter_register = instr.gpr20.Value(); |
| 595 | 652 | ||
| 596 | const SamplerInfo info{texture_type, is_array, depth_compare, false}; | 653 | const SamplerInfo info{texture_type, is_array, depth_compare, false}; |
| 597 | const auto& sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) | 654 | const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) |
| 598 | : GetSampler(instr.sampler, info); | 655 | : GetSampler(instr.sampler, info); |
| 656 | Node4 values; | ||
| 657 | if (sampler == nullptr) { | ||
| 658 | for (u32 element = 0; element < values.size(); ++element) { | ||
| 659 | values[element] = Immediate(0); | ||
| 660 | } | ||
| 661 | return values; | ||
| 662 | } | ||
| 599 | 663 | ||
| 600 | std::vector<Node> aoffi; | 664 | std::vector<Node> aoffi; |
| 601 | if (is_aoffi) { | 665 | if (is_aoffi) { |
| @@ -610,10 +674,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)) | 674 | const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component)) |
| 611 | : Immediate(static_cast<u32>(instr.tld4.component)); | 675 | : Immediate(static_cast<u32>(instr.tld4.component)); |
| 612 | 676 | ||
| 613 | Node4 values; | ||
| 614 | for (u32 element = 0; element < values.size(); ++element) { | 677 | for (u32 element = 0; element < values.size(); ++element) { |
| 615 | auto coords_copy = coords; | 678 | auto coords_copy = coords; |
| 616 | MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, | 679 | MetaTexture meta{*sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, |
| 617 | element}; | 680 | element}; |
| 618 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); | 681 | values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); |
| 619 | } | 682 | } |
| @@ -642,7 +705,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 642 | // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; | 705 | // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; |
| 643 | // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; | 706 | // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; |
| 644 | 707 | ||
| 645 | const auto& sampler = GetSampler(instr.sampler); | 708 | const auto& sampler = *GetSampler(instr.sampler); |
| 646 | 709 | ||
| 647 | Node4 values; | 710 | Node4 values; |
| 648 | for (u32 element = 0; element < values.size(); ++element) { | 711 | for (u32 element = 0; element < values.size(); ++element) { |
| @@ -655,7 +718,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { | |||
| 655 | } | 718 | } |
| 656 | 719 | ||
| 657 | Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { | 720 | Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { |
| 658 | const auto& sampler = GetSampler(instr.sampler); | 721 | const Sampler& sampler = *GetSampler(instr.sampler); |
| 659 | 722 | ||
| 660 | const std::size_t type_coord_count = GetCoordCount(texture_type); | 723 | const std::size_t type_coord_count = GetCoordCount(texture_type); |
| 661 | const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; | 724 | 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..04ae5f822 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. |
| @@ -338,7 +338,7 @@ private: | |||
| 338 | void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | 338 | void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, |
| 339 | const Node4& components, bool ignore_mask = false); | 339 | const Node4& components, bool ignore_mask = false); |
| 340 | void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, | 340 | void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, |
| 341 | const Node4& components); | 341 | const Node4& components, bool ignore_mask = false); |
| 342 | 342 | ||
| 343 | Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, | 343 | Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, |
| 344 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, | 344 | Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, |