summaryrefslogtreecommitdiff
path: root/src/video_core/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader')
-rw-r--r--src/video_core/shader/const_buffer_locker.cpp1
-rw-r--r--src/video_core/shader/const_buffer_locker.h3
-rw-r--r--src/video_core/shader/decode/texture.cpp111
-rw-r--r--src/video_core/shader/node.h14
-rw-r--r--src/video_core/shader/shader_ir.h13
5 files changed, 72 insertions, 70 deletions
diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp
index fe467608e..b65399f91 100644
--- a/src/video_core/shader/const_buffer_locker.cpp
+++ b/src/video_core/shader/const_buffer_locker.cpp
@@ -9,6 +9,7 @@
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/engines/maxwell_3d.h" 11#include "video_core/engines/maxwell_3d.h"
12#include "video_core/engines/shader_type.h"
12#include "video_core/shader/const_buffer_locker.h" 13#include "video_core/shader/const_buffer_locker.h"
13 14
14namespace VideoCommon::Shader { 15namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h
index 600e2f3c3..50a8ce42a 100644
--- a/src/video_core/shader/const_buffer_locker.h
+++ b/src/video_core/shader/const_buffer_locker.h
@@ -8,6 +8,7 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/hash.h" 9#include "common/hash.h"
10#include "video_core/engines/const_buffer_engine_interface.h" 10#include "video_core/engines/const_buffer_engine_interface.h"
11#include "video_core/engines/shader_type.h"
11 12
12namespace VideoCommon::Shader { 13namespace VideoCommon::Shader {
13 14
@@ -20,7 +21,7 @@ using BindlessSamplerMap =
20 * The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader 21 * The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader
21 * compiler. with it, the shader can obtain required data from GPU state and store it for disk 22 * compiler. with it, the shader can obtain required data from GPU state and store it for disk
22 * shader compilation. 23 * shader compilation.
23 **/ 24 */
24class ConstBufferLocker { 25class ConstBufferLocker {
25public: 26public:
26 explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage); 27 explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage);
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index bb926a132..b094e5a06 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -128,8 +128,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
128 } 128 }
129 const Node component = Immediate(static_cast<u32>(instr.tld4s.component)); 129 const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
130 130
131 const auto& sampler = 131 const SamplerInfo info{TextureType::Texture2D, false, depth_compare};
132 GetSampler(instr.sampler, {{TextureType::Texture2D, false, depth_compare}}); 132 const auto& sampler = GetSampler(instr.sampler, info);
133 133
134 Node4 values; 134 Node4 values;
135 for (u32 element = 0; element < values.size(); ++element) { 135 for (u32 element = 0; element < values.size(); ++element) {
@@ -149,7 +149,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
149 // Sadly, not all texture instructions specify the type of texture their sampler 149 // Sadly, not all texture instructions specify the type of texture their sampler
150 // uses. This must be fixed at a later instance. 150 // uses. This must be fixed at a later instance.
151 const auto& sampler = 151 const auto& sampler =
152 is_bindless ? GetBindlessSampler(instr.gpr8, {}) : GetSampler(instr.sampler, {}); 152 is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler);
153 153
154 u32 indexer = 0; 154 u32 indexer = 0;
155 switch (instr.txq.query_type) { 155 switch (instr.txq.query_type) {
@@ -185,8 +185,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
185 auto texture_type = instr.tmml.texture_type.Value(); 185 auto texture_type = instr.tmml.texture_type.Value();
186 const bool is_array = instr.tmml.array != 0; 186 const bool is_array = instr.tmml.array != 0;
187 const auto& sampler = 187 const auto& sampler =
188 is_bindless ? GetBindlessSampler(instr.gpr20, {{texture_type, is_array, false}}) 188 is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler);
189 : GetSampler(instr.sampler, {{texture_type, is_array, false}});
190 189
191 std::vector<Node> coords; 190 std::vector<Node> coords;
192 191
@@ -254,67 +253,50 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
254 return pc; 253 return pc;
255} 254}
256 255
257const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, 256ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sampler_info, u32 offset,
258 std::optional<SamplerInfo> sampler_info) { 257 std::optional<u32> buffer) {
259 const auto offset = static_cast<u32>(sampler.index.Value());
260
261 TextureType type;
262 bool is_array;
263 bool is_shadow;
264 if (sampler_info) { 258 if (sampler_info) {
265 type = sampler_info->type; 259 return *sampler_info;
266 is_array = sampler_info->is_array; 260 }
267 is_shadow = sampler_info->is_shadow; 261 const auto sampler =
268 } else if (const auto sampler = locker.ObtainBoundSampler(offset)) { 262 buffer ? locker.ObtainBindlessSampler(*buffer, offset) : locker.ObtainBoundSampler(offset);
269 type = sampler->texture_type.Value(); 263 if (!sampler) {
270 is_array = sampler->is_array.Value() != 0;
271 is_shadow = sampler->is_shadow.Value() != 0;
272 } else {
273 LOG_WARNING(HW_GPU, "Unknown sampler info"); 264 LOG_WARNING(HW_GPU, "Unknown sampler info");
274 type = TextureType::Texture2D; 265 return SamplerInfo{TextureType::Texture2D, false, false, false};
275 is_array = false;
276 is_shadow = false;
277 } 266 }
267 return SamplerInfo{sampler->texture_type, sampler->is_array != 0, sampler->is_shadow != 0,
268 sampler->is_buffer != 0};
269}
270
271const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
272 std::optional<SamplerInfo> sampler_info) {
273 const auto offset = static_cast<u32>(sampler.index.Value());
274 const auto info = GetSamplerInfo(sampler_info, offset);
278 275
279 // If this sampler has already been used, return the existing mapping. 276 // If this sampler has already been used, return the existing mapping.
280 const auto it = 277 const auto it =
281 std::find_if(used_samplers.begin(), used_samplers.end(), 278 std::find_if(used_samplers.begin(), used_samplers.end(),
282 [offset](const Sampler& entry) { return entry.GetOffset() == offset; }); 279 [offset](const Sampler& entry) { return entry.GetOffset() == offset; });
283 if (it != used_samplers.end()) { 280 if (it != used_samplers.end()) {
284 ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && 281 ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array &&
285 it->IsShadow() == is_shadow); 282 it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer);
286 return *it; 283 return *it;
287 } 284 }
288 285
289 // Otherwise create a new mapping for this sampler 286 // Otherwise create a new mapping for this sampler
290 const auto next_index = static_cast<u32>(used_samplers.size()); 287 const auto next_index = static_cast<u32>(used_samplers.size());
291 return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow)); 288 return used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
289 info.is_buffer);
292} 290}
293 291
294const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, 292const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
295 std::optional<SamplerInfo> sampler_info) { 293 std::optional<SamplerInfo> sampler_info) {
296 const Node sampler_register = GetRegister(reg); 294 const Node sampler_register = GetRegister(reg);
297 const auto [base_sampler, buffer, offset] = 295 const auto [base_sampler, buffer, offset] =
298 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 296 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
299 ASSERT(base_sampler != nullptr); 297 ASSERT(base_sampler != nullptr);
300 298
301 TextureType type; 299 const auto info = GetSamplerInfo(sampler_info, offset, buffer);
302 bool is_array;
303 bool is_shadow;
304 if (sampler_info) {
305 type = sampler_info->type;
306 is_array = sampler_info->is_array;
307 is_shadow = sampler_info->is_shadow;
308 } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) {
309 type = sampler->texture_type.Value();
310 is_array = sampler->is_array.Value() != 0;
311 is_shadow = sampler->is_shadow.Value() != 0;
312 } else {
313 LOG_WARNING(HW_GPU, "Unknown sampler info");
314 type = TextureType::Texture2D;
315 is_array = false;
316 is_shadow = false;
317 }
318 300
319 // If this sampler has already been used, return the existing mapping. 301 // If this sampler has already been used, return the existing mapping.
320 const auto it = 302 const auto it =
@@ -323,15 +305,15 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
323 return entry.GetBuffer() == buffer && entry.GetOffset() == offset; 305 return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
324 }); 306 });
325 if (it != used_samplers.end()) { 307 if (it != used_samplers.end()) {
326 ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && 308 ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array &&
327 it->IsShadow() == is_shadow); 309 it->IsShadow() == info.is_shadow);
328 return *it; 310 return *it;
329 } 311 }
330 312
331 // Otherwise create a new mapping for this sampler 313 // Otherwise create a new mapping for this sampler
332 const auto next_index = static_cast<u32>(used_samplers.size()); 314 const auto next_index = static_cast<u32>(used_samplers.size());
333 return used_samplers.emplace_back( 315 return used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
334 Sampler(next_index, offset, buffer, type, is_array, is_shadow)); 316 info.is_shadow, info.is_buffer);
335} 317}
336 318
337void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 319void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
@@ -416,17 +398,16 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
416 (texture_type == TextureType::TextureCube && is_array && is_shadow), 398 (texture_type == TextureType::TextureCube && is_array && is_shadow),
417 "This method is not supported."); 399 "This method is not supported.");
418 400
401 const SamplerInfo info{texture_type, is_array, is_shadow, false};
419 const auto& sampler = 402 const auto& sampler =
420 is_bindless ? GetBindlessSampler(*bindless_reg, {{texture_type, is_array, is_shadow}}) 403 is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info);
421 : GetSampler(instr.sampler, {{texture_type, is_array, is_shadow}});
422 404
423 const bool lod_needed = process_mode == TextureProcessMode::LZ || 405 const bool lod_needed = process_mode == TextureProcessMode::LZ ||
424 process_mode == TextureProcessMode::LL || 406 process_mode == TextureProcessMode::LL ||
425 process_mode == TextureProcessMode::LLA; 407 process_mode == TextureProcessMode::LLA;
426 408
427 // LOD selection (either via bias or explicit textureLod) not 409 // LOD selection (either via bias or explicit textureLod) not supported in GL for
428 // supported in GL for sampler2DArrayShadow and 410 // sampler2DArrayShadow and samplerCubeArrayShadow.
429 // samplerCubeArrayShadow.
430 const bool gl_lod_supported = 411 const bool gl_lod_supported =
431 !((texture_type == Tegra::Shader::TextureType::Texture2D && is_array && is_shadow) || 412 !((texture_type == Tegra::Shader::TextureType::Texture2D && is_array && is_shadow) ||
432 (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && is_shadow)); 413 (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && is_shadow));
@@ -436,8 +417,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
436 417
437 UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported); 418 UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported);
438 419
439 Node bias = {}; 420 Node bias;
440 Node lod = {}; 421 Node lod;
441 if (process_mode != TextureProcessMode::None && gl_lod_supported) { 422 if (process_mode != TextureProcessMode::None && gl_lod_supported) {
442 switch (process_mode) { 423 switch (process_mode) {
443 case TextureProcessMode::LZ: 424 case TextureProcessMode::LZ:
@@ -573,10 +554,9 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
573 554
574 u64 parameter_register = instr.gpr20.Value(); 555 u64 parameter_register = instr.gpr20.Value();
575 556
576 const auto& sampler = 557 const SamplerInfo info{texture_type, is_array, depth_compare, false};
577 is_bindless 558 const auto& sampler = is_bindless ? GetBindlessSampler(parameter_register++, info)
578 ? GetBindlessSampler(parameter_register++, {{texture_type, is_array, depth_compare}}) 559 : GetSampler(instr.sampler, info);
579 : GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}});
580 560
581 std::vector<Node> aoffi; 561 std::vector<Node> aoffi;
582 if (is_aoffi) { 562 if (is_aoffi) {
@@ -623,7 +603,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
623 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; 603 // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr};
624 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; 604 // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr};
625 605
626 const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}}); 606 const auto& sampler = GetSampler(instr.sampler);
627 607
628 Node4 values; 608 Node4 values;
629 for (u32 element = 0; element < values.size(); ++element) { 609 for (u32 element = 0; element < values.size(); ++element) {
@@ -636,6 +616,8 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
636} 616}
637 617
638Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { 618Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) {
619 const auto& sampler = GetSampler(instr.sampler);
620
639 const std::size_t type_coord_count = GetCoordCount(texture_type); 621 const std::size_t type_coord_count = GetCoordCount(texture_type);
640 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; 622 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL;
641 623
@@ -659,7 +641,14 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
659 // When lod is used always is in gpr20 641 // When lod is used always is in gpr20
660 const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0); 642 const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0);
661 643
662 const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}}); 644 // Fill empty entries from the guest sampler.
645 const std::size_t entry_coord_count = GetCoordCount(sampler.GetType());
646 if (type_coord_count != entry_coord_count) {
647 LOG_WARNING(HW_GPU, "Bound and built texture types mismatch");
648 }
649 for (std::size_t i = type_coord_count; i < entry_coord_count; ++i) {
650 coords.push_back(GetRegister(Register::ZeroIndex));
651 }
663 652
664 Node4 values; 653 Node4 values;
665 for (u32 element = 0; element < values.size(); ++element) { 654 for (u32 element = 0; element < values.size(); ++element) {
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 54217e6a4..44d85d434 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -225,14 +225,15 @@ class Sampler {
225public: 225public:
226 /// This constructor is for bound samplers 226 /// This constructor is for bound samplers
227 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type, 227 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
228 bool is_array, bool is_shadow) 228 bool is_array, bool is_shadow, bool is_buffer)
229 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow} {} 229 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
230 is_buffer{is_buffer} {}
230 231
231 /// This constructor is for bindless samplers 232 /// This constructor is for bindless samplers
232 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type, 233 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
233 bool is_array, bool is_shadow) 234 bool is_array, bool is_shadow, bool is_buffer)
234 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array}, 235 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
235 is_shadow{is_shadow}, is_bindless{true} {} 236 is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true} {}
236 237
237 constexpr u32 GetIndex() const { 238 constexpr u32 GetIndex() const {
238 return index; 239 return index;
@@ -258,6 +259,10 @@ public:
258 return is_shadow; 259 return is_shadow;
259 } 260 }
260 261
262 constexpr bool IsBuffer() const {
263 return is_buffer;
264 }
265
261 constexpr bool IsBindless() const { 266 constexpr bool IsBindless() const {
262 return is_bindless; 267 return is_bindless;
263 } 268 }
@@ -270,6 +275,7 @@ private:
270 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) 275 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
271 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. 276 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not.
272 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. 277 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
278 bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler.
273 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. 279 bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
274}; 280};
275 281
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 76a849818..2f71a50d2 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -179,6 +179,7 @@ private:
179 Tegra::Shader::TextureType type; 179 Tegra::Shader::TextureType type;
180 bool is_array; 180 bool is_array;
181 bool is_shadow; 181 bool is_shadow;
182 bool is_buffer;
182 }; 183 };
183 184
184 void Decode(); 185 void Decode();
@@ -303,13 +304,17 @@ private:
303 /// Returns a predicate combiner operation 304 /// Returns a predicate combiner operation
304 OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation); 305 OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);
305 306
307 /// Queries the missing sampler info from the execution context.
308 SamplerInfo GetSamplerInfo(std::optional<SamplerInfo> sampler_info, u32 offset,
309 std::optional<u32> buffer = std::nullopt);
310
306 /// Accesses a texture sampler 311 /// Accesses a texture sampler
307 const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler, 312 const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler,
308 std::optional<SamplerInfo> sampler_info); 313 std::optional<SamplerInfo> sampler_info = std::nullopt);
309 314
310 // Accesses a texture sampler for a bindless texture. 315 /// Accesses a texture sampler for a bindless texture.
311 const Sampler& GetBindlessSampler(const Tegra::Shader::Register& reg, 316 const Sampler& GetBindlessSampler(Tegra::Shader::Register reg,
312 std::optional<SamplerInfo> sampler_info); 317 std::optional<SamplerInfo> sampler_info = std::nullopt);
313 318
314 /// Accesses an image. 319 /// Accesses an image.
315 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type); 320 Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type);