summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-01-05 18:36:21 -0400
committerGravatar FernandoS272020-01-24 16:43:31 -0400
commit037ea431ceb93e93274fdcf9fb724819639d04fd (patch)
tree7357dac5799959d2dc7dbe78346cb8cbd1a5400b /src
parentShader_IR: Setup Indexed Samplers on the IR (diff)
downloadyuzu-037ea431ceb93e93274fdcf9fb724819639d04fd.tar.gz
yuzu-037ea431ceb93e93274fdcf9fb724819639d04fd.tar.xz
yuzu-037ea431ceb93e93274fdcf9fb724819639d04fd.zip
Shader_IR: deduce size of indexed samplers
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/decode.cpp36
-rw-r--r--src/video_core/shader/decode/texture.cpp9
-rw-r--r--src/video_core/shader/node.h22
-rw-r--r--src/video_core/shader/shader_ir.h1
4 files changed, 60 insertions, 8 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 507614d59..dd2f68a3e 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -56,6 +56,29 @@ void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile* gpu_driver,
56 } 56 }
57} 57}
58 58
59std::optional<u32> TryDeduceSamplerSize(Sampler& sampler_to_deduce,
60 VideoCore::GuestDriverProfile* gpu_driver,
61 std::list<Sampler>& used_samplers) {
62 if (gpu_driver == nullptr) {
63 LOG_CRITICAL(HW_GPU, "GPU Driver profile has not been created yet");
64 return std::nullopt;
65 }
66 const u32 base_offset = sampler_to_deduce.GetOffset();
67 u32 max_offset{UINT_MAX};
68 for (const auto& sampler : used_samplers) {
69 if (sampler.IsBindless()) {
70 continue;
71 }
72 if (sampler.GetOffset() > base_offset) {
73 max_offset = std::min(sampler.GetOffset(), max_offset);
74 }
75 }
76 if (max_offset == UINT_MAX) {
77 return std::nullopt;
78 }
79 return ((max_offset - base_offset) * 4) / gpu_driver->GetTextureHandlerSize();
80}
81
59} // Anonymous namespace 82} // Anonymous namespace
60 83
61class ASTDecoder { 84class ASTDecoder {
@@ -342,6 +365,19 @@ void ShaderIR::PostDecode() {
342 // Deduce texture handler size if needed 365 // Deduce texture handler size if needed
343 auto gpu_driver = locker.AccessGuestDriverProfile(); 366 auto gpu_driver = locker.AccessGuestDriverProfile();
344 DeduceTextureHandlerSize(gpu_driver, used_samplers); 367 DeduceTextureHandlerSize(gpu_driver, used_samplers);
368 // Deduce Indexed Samplers
369 if (uses_indexed_samplers) {
370 for (auto& sampler : used_samplers) {
371 if (sampler.IsIndexed()) {
372 auto size = TryDeduceSamplerSize(sampler, gpu_driver, used_samplers);
373 if (size) {
374 sampler.SetSize(*size);
375 } else {
376 sampler.SetSize(1);
377 }
378 }
379 }
380 }
345} 381}
346 382
347} // namespace VideoCommon::Shader 383} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 886650d9e..e7c38f5d6 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -383,7 +383,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
383 // Otherwise create a new mapping for this sampler 383 // Otherwise create a new mapping for this sampler
384 const auto next_index = static_cast<u32>(used_samplers.size()); 384 const auto next_index = static_cast<u32>(used_samplers.size());
385 return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, 385 return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
386 info.is_buffer); 386 info.is_buffer, false);
387} 387}
388 388
389const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, 389const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
@@ -417,7 +417,7 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
417 // Otherwise create a new mapping for this sampler 417 // Otherwise create a new mapping for this sampler
418 const auto next_index = static_cast<u32>(used_samplers.size()); 418 const auto next_index = static_cast<u32>(used_samplers.size());
419 return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, 419 return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
420 info.is_shadow, info.is_buffer); 420 info.is_shadow, info.is_buffer, false);
421 } else if (const auto array_sampler_info = 421 } else if (const auto array_sampler_info =
422 std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) { 422 std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
423 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; 423 const u32 base_offset = array_sampler_info->GetBaseOffset() / 4;
@@ -430,14 +430,15 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
430 if (it != used_samplers.end()) { 430 if (it != used_samplers.end()) {
431 ASSERT(!it->IsBindless() && it->GetType() == info.type && 431 ASSERT(!it->IsBindless() && it->GetType() == info.type &&
432 it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow && 432 it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow &&
433 it->IsBuffer() == info.is_buffer); 433 it->IsBuffer() == info.is_buffer && it->IsIndexed());
434 return &*it; 434 return &*it;
435 } 435 }
436 436
437 uses_indexed_samplers = true;
437 // Otherwise create a new mapping for this sampler 438 // Otherwise create a new mapping for this sampler
438 const auto next_index = static_cast<u32>(used_samplers.size()); 439 const auto next_index = static_cast<u32>(used_samplers.size());
439 return &used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array, 440 return &used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array,
440 info.is_shadow, info.is_buffer); 441 info.is_shadow, info.is_buffer, true);
441 } 442 }
442 return nullptr; 443 return nullptr;
443} 444}
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index b370df8f9..2f29b9506 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -240,15 +240,15 @@ class Sampler {
240public: 240public:
241 /// This constructor is for bound samplers 241 /// This constructor is for bound samplers
242 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type, 242 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
243 bool is_array, bool is_shadow, bool is_buffer) 243 bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
244 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow}, 244 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
245 is_buffer{is_buffer} {} 245 is_buffer{is_buffer}, is_indexed{is_indexed} {}
246 246
247 /// This constructor is for bindless samplers 247 /// This constructor is for bindless samplers
248 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type, 248 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
249 bool is_array, bool is_shadow, bool is_buffer) 249 bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
250 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array}, 250 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
251 is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true} {} 251 is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true}, is_indexed{is_indexed} {}
252 252
253 constexpr u32 GetIndex() const { 253 constexpr u32 GetIndex() const {
254 return index; 254 return index;
@@ -282,16 +282,30 @@ public:
282 return is_bindless; 282 return is_bindless;
283 } 283 }
284 284
285 constexpr bool IsIndexed() const {
286 return is_indexed;
287 }
288
289 constexpr u32 Size() const {
290 return size;
291 }
292
293 void SetSize(u32 new_size) {
294 size = new_size;
295 }
296
285private: 297private:
286 u32 index{}; ///< Emulated index given for the this sampler. 298 u32 index{}; ///< Emulated index given for the this sampler.
287 u32 offset{}; ///< Offset in the const buffer from where the sampler is being read. 299 u32 offset{}; ///< Offset in the const buffer from where the sampler is being read.
288 u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers). 300 u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers).
301 u32 size{}; ///< Size of the sampler if indexed.
289 302
290 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) 303 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
291 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. 304 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not.
292 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. 305 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
293 bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler. 306 bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler.
294 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. 307 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
308 bool is_indexed{}; ///< Whether this sampler is an indexed array of textures.
295}; 309};
296 310
297/// Represents a tracked bindless sampler into a direct const buffer 311/// Represents a tracked bindless sampler into a direct const buffer
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index d85f14c97..121528346 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -435,6 +435,7 @@ private:
435 bool uses_instance_id{}; 435 bool uses_instance_id{};
436 bool uses_vertex_id{}; 436 bool uses_vertex_id{};
437 bool uses_warps{}; 437 bool uses_warps{};
438 bool uses_indexed_samplers{};
438 439
439 Tegra::Shader::Header header; 440 Tegra::Shader::Header header;
440}; 441};