diff options
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/image.cpp | 50 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 59 |
2 files changed, 55 insertions, 54 deletions
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index b02d2cb95..d2fe4ec5d 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -143,39 +143,37 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { | 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { |
| 146 | const auto offset{static_cast<std::size_t>(image.index.Value())}; | 146 | const auto offset = static_cast<u32>(image.index.Value()); |
| 147 | if (const auto existing_image = TryUseExistingImage(offset, type)) { | 147 | |
| 148 | return *existing_image; | 148 | const auto it = |
| 149 | std::find_if(std::begin(used_images), std::end(used_images), | ||
| 150 | [offset](const Image& entry) { return entry.GetOffset() == offset; }); | ||
| 151 | if (it != std::end(used_images)) { | ||
| 152 | ASSERT(!it->IsBindless() && it->GetType() == it->GetType()); | ||
| 153 | return *it; | ||
| 149 | } | 154 | } |
| 150 | 155 | ||
| 151 | const std::size_t next_index{used_images.size()}; | 156 | const auto next_index = static_cast<u32>(used_images.size()); |
| 152 | return used_images.emplace(offset, Image{offset, next_index, type}).first->second; | 157 | return used_images.emplace_back(next_index, offset, type); |
| 153 | } | 158 | } |
| 154 | 159 | ||
| 155 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { | 160 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { |
| 156 | const Node image_register{GetRegister(reg)}; | 161 | const Node image_register = GetRegister(reg); |
| 157 | const auto [base_image, cbuf_index, cbuf_offset]{ | 162 | const auto [base_image, buffer, offset] = |
| 158 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; | 163 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size())); |
| 159 | const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; | 164 | |
| 160 | 165 | const auto it = | |
| 161 | if (const auto image = TryUseExistingImage(cbuf_key, type)) { | 166 | std::find_if(std::begin(used_images), std::end(used_images), |
| 162 | return *image; | 167 | [buffer = buffer, offset = offset](const Image& entry) { |
| 163 | } | 168 | return entry.GetBuffer() == buffer && entry.GetOffset() == offset; |
| 164 | 169 | }); | |
| 165 | const std::size_t next_index{used_images.size()}; | 170 | if (it != std::end(used_images)) { |
| 166 | return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type}) | 171 | ASSERT(it->IsBindless() && it->GetType() == it->GetType()); |
| 167 | .first->second; | 172 | return *it; |
| 168 | } | ||
| 169 | |||
| 170 | Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type) { | ||
| 171 | auto it = used_images.find(offset); | ||
| 172 | if (it == used_images.end()) { | ||
| 173 | return nullptr; | ||
| 174 | } | 173 | } |
| 175 | auto& image = it->second; | ||
| 176 | ASSERT(image.GetType() == type); | ||
| 177 | 174 | ||
| 178 | return ℑ | 175 | const auto next_index = static_cast<u32>(used_images.size()); |
| 176 | return used_images.emplace_back(next_index, offset, buffer, type); | ||
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | } // namespace VideoCommon::Shader | 179 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index d61e656b7..8d3d962c7 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -255,7 +255,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 255 | break; | 255 | break; |
| 256 | } | 256 | } |
| 257 | case OpCode::Id::TLDS: { | 257 | case OpCode::Id::TLDS: { |
| 258 | const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; | 258 | const TextureType texture_type{instr.tlds.GetTextureType()}; |
| 259 | const bool is_array{instr.tlds.IsArrayTexture()}; | 259 | const bool is_array{instr.tlds.IsArrayTexture()}; |
| 260 | 260 | ||
| 261 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), | 261 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), |
| @@ -286,77 +286,80 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||
| 286 | std::optional<SamplerInfo> sampler_info) { | 286 | std::optional<SamplerInfo> sampler_info) { |
| 287 | const auto offset = static_cast<u32>(sampler.index.Value()); | 287 | const auto offset = static_cast<u32>(sampler.index.Value()); |
| 288 | 288 | ||
| 289 | Tegra::Shader::TextureType type; | 289 | TextureType type; |
| 290 | bool is_array; | 290 | bool is_array; |
| 291 | bool is_shadow; | 291 | bool is_shadow; |
| 292 | if (sampler_info) { | 292 | if (sampler_info) { |
| 293 | type = sampler_info->type; | 293 | type = sampler_info->type; |
| 294 | is_array = sampler_info->is_array; | 294 | is_array = sampler_info->is_array; |
| 295 | is_shadow = sampler_info->is_shadow; | 295 | is_shadow = sampler_info->is_shadow; |
| 296 | } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) { | 296 | } else if (const auto sampler = locker.ObtainBoundSampler(offset)) { |
| 297 | type = sampler->texture_type.Value(); | 297 | type = sampler->texture_type.Value(); |
| 298 | is_array = sampler->is_array.Value() != 0; | 298 | is_array = sampler->is_array.Value() != 0; |
| 299 | is_shadow = sampler->is_shadow.Value() != 0; | 299 | is_shadow = sampler->is_shadow.Value() != 0; |
| 300 | } else { | 300 | } else { |
| 301 | type = Tegra::Shader::TextureType::Texture2D; | 301 | LOG_WARNING(HW_GPU, "Unknown sampler info"); |
| 302 | type = TextureType::Texture2D; | ||
| 302 | is_array = false; | 303 | is_array = false; |
| 303 | is_shadow = false; | 304 | is_shadow = false; |
| 304 | } | 305 | } |
| 305 | 306 | ||
| 306 | // If this sampler has already been used, return the existing mapping. | 307 | // If this sampler has already been used, return the existing mapping. |
| 307 | const auto itr = | 308 | const auto it = |
| 308 | std::find_if(used_samplers.begin(), used_samplers.end(), | 309 | std::find_if(used_samplers.begin(), used_samplers.end(), |
| 309 | [&](const Sampler& entry) { return entry.GetOffset() == offset; }); | 310 | [offset](const Sampler& entry) { return entry.GetOffset() == offset; }); |
| 310 | if (itr != used_samplers.end()) { | 311 | if (it != used_samplers.end()) { |
| 311 | ASSERT(itr->GetType() == type && itr->IsArray() == is_array && | 312 | ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && |
| 312 | itr->IsShadow() == is_shadow); | 313 | it->IsShadow() == is_shadow); |
| 313 | return *itr; | 314 | return *it; |
| 314 | } | 315 | } |
| 315 | 316 | ||
| 316 | // Otherwise create a new mapping for this sampler | 317 | // Otherwise create a new mapping for this sampler |
| 317 | const std::size_t next_index = used_samplers.size(); | 318 | const auto next_index = static_cast<u32>(used_samplers.size()); |
| 318 | const Sampler entry{offset, next_index, type, is_array, is_shadow}; | 319 | return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow)); |
| 319 | return *used_samplers.emplace(entry).first; | 320 | } |
| 320 | } // namespace VideoCommon::Shader | ||
| 321 | 321 | ||
| 322 | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | 322 | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, |
| 323 | std::optional<SamplerInfo> sampler_info) { | 323 | std::optional<SamplerInfo> sampler_info) { |
| 324 | const Node sampler_register = GetRegister(reg); | 324 | const Node sampler_register = GetRegister(reg); |
| 325 | const auto [base_sampler, cbuf_index, cbuf_offset] = | 325 | const auto [base_sampler, buffer, offset] = |
| 326 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); | 326 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); |
| 327 | ASSERT(base_sampler != nullptr); | 327 | ASSERT(base_sampler != nullptr); |
| 328 | const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); | 328 | |
| 329 | Tegra::Shader::TextureType type; | 329 | TextureType type; |
| 330 | bool is_array; | 330 | bool is_array; |
| 331 | bool is_shadow; | 331 | bool is_shadow; |
| 332 | if (sampler_info) { | 332 | if (sampler_info) { |
| 333 | type = sampler_info->type; | 333 | type = sampler_info->type; |
| 334 | is_array = sampler_info->is_array; | 334 | is_array = sampler_info->is_array; |
| 335 | is_shadow = sampler_info->is_shadow; | 335 | is_shadow = sampler_info->is_shadow; |
| 336 | } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) { | 336 | } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) { |
| 337 | type = sampler->texture_type.Value(); | 337 | type = sampler->texture_type.Value(); |
| 338 | is_array = sampler->is_array.Value() != 0; | 338 | is_array = sampler->is_array.Value() != 0; |
| 339 | is_shadow = sampler->is_shadow.Value() != 0; | 339 | is_shadow = sampler->is_shadow.Value() != 0; |
| 340 | } else { | 340 | } else { |
| 341 | type = Tegra::Shader::TextureType::Texture2D; | 341 | LOG_WARNING(HW_GPU, "Unknown sampler info"); |
| 342 | type = TextureType::Texture2D; | ||
| 342 | is_array = false; | 343 | is_array = false; |
| 343 | is_shadow = false; | 344 | is_shadow = false; |
| 344 | } | 345 | } |
| 345 | 346 | ||
| 346 | // If this sampler has already been used, return the existing mapping. | 347 | // If this sampler has already been used, return the existing mapping. |
| 347 | const auto itr = | 348 | const auto it = |
| 348 | std::find_if(used_samplers.begin(), used_samplers.end(), | 349 | std::find_if(used_samplers.begin(), used_samplers.end(), |
| 349 | [&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; }); | 350 | [buffer = buffer, offset = offset](const Sampler& entry) { |
| 350 | if (itr != used_samplers.end()) { | 351 | return entry.GetBuffer() == buffer && entry.GetOffset() == offset; |
| 351 | ASSERT(itr->GetType() == type && itr->IsArray() == is_array && | 352 | }); |
| 352 | itr->IsShadow() == is_shadow); | 353 | if (it != used_samplers.end()) { |
| 353 | return *itr; | 354 | ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && |
| 355 | it->IsShadow() == is_shadow); | ||
| 356 | return *it; | ||
| 354 | } | 357 | } |
| 355 | 358 | ||
| 356 | // Otherwise create a new mapping for this sampler | 359 | // Otherwise create a new mapping for this sampler |
| 357 | const std::size_t next_index = used_samplers.size(); | 360 | const auto next_index = static_cast<u32>(used_samplers.size()); |
| 358 | const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow}; | 361 | return used_samplers.emplace_back( |
| 359 | return *used_samplers.emplace(entry).first; | 362 | Sampler(next_index, offset, buffer, type, is_array, is_shadow)); |
| 360 | } | 363 | } |
| 361 | 364 | ||
| 362 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { | 365 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { |