summaryrefslogtreecommitdiff
path: root/src/video_core/shader/decode
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-10-28 02:31:05 -0300
committerGravatar ReinUsesLisp2019-10-29 20:53:48 -0300
commita993df1ee294b861eef4f35fccabeecd05754f2a (patch)
tree04150cb66c138c75f6a4fc47218bb2255af7e234 /src/video_core/shader/decode
parentMerge pull request #3004 from ReinUsesLisp/maxwell3d-cleanup (diff)
downloadyuzu-a993df1ee294b861eef4f35fccabeecd05754f2a.tar.gz
yuzu-a993df1ee294b861eef4f35fccabeecd05754f2a.tar.xz
yuzu-a993df1ee294b861eef4f35fccabeecd05754f2a.zip
shader/node: Unpack bindless texture encoding
Bindless textures were using u64 to pack the buffer and offset from where they come from. Drop this in favor of separated entries in the struct. Remove the usage of std::set in favor of std::list (it's not std::vector to avoid reference invalidations) for samplers and images.
Diffstat (limited to 'src/video_core/shader/decode')
-rw-r--r--src/video_core/shader/decode/image.cpp50
-rw-r--r--src/video_core/shader/decode/texture.cpp59
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
145Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { 145Image& 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
155Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { 160Image& 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
170Image* 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 &image; 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
322const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, 322const 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
362void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 365void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {