summaryrefslogtreecommitdiffstats
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.cpp11
-rw-r--r--src/video_core/shader/const_buffer_locker.h4
-rw-r--r--src/video_core/shader/decode/other.cpp2
-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
6 files changed, 78 insertions, 77 deletions
diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp
index fe467608e..a4a0319eb 100644
--- a/src/video_core/shader/const_buffer_locker.cpp
+++ b/src/video_core/shader/const_buffer_locker.cpp
@@ -2,13 +2,12 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#pragma once
-
#include <algorithm>
-#include <memory>
-#include "common/assert.h"
+#include <tuple>
+
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
+#include "video_core/engines/shader_type.h"
#include "video_core/shader/const_buffer_locker.h"
namespace VideoCommon::Shader {
@@ -103,8 +102,8 @@ bool ConstBufferLocker::IsConsistent() const {
}
bool ConstBufferLocker::HasEqualKeys(const ConstBufferLocker& rhs) const {
- return keys == rhs.keys && bound_samplers == rhs.bound_samplers &&
- bindless_samplers == rhs.bindless_samplers;
+ return std::tie(keys, bound_samplers, bindless_samplers) ==
+ std::tie(rhs.keys, rhs.bound_samplers, rhs.bindless_samplers);
}
} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h
index 600e2f3c3..d32e2d657 100644
--- a/src/video_core/shader/const_buffer_locker.h
+++ b/src/video_core/shader/const_buffer_locker.h
@@ -4,10 +4,12 @@
#pragma once
+#include <optional>
#include <unordered_map>
#include "common/common_types.h"
#include "common/hash.h"
#include "video_core/engines/const_buffer_engine_interface.h"
+#include "video_core/engines/shader_type.h"
namespace VideoCommon::Shader {
@@ -20,7 +22,7 @@ using BindlessSamplerMap =
* The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader
* compiler. with it, the shader can obtain required data from GPU state and store it for disk
* shader compilation.
- **/
+ */
class ConstBufferLocker {
public:
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage);
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index 116b95f76..17cd45d3c 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -256,7 +256,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
break;
}
case OpCode::Id::DEPBAR: {
- LOG_WARNING(HW_GPU, "DEPBAR instruction is stubbed");
+ LOG_DEBUG(HW_GPU, "DEPBAR instruction is stubbed");
break;
}
default:
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 9afba2495..da8e886df 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) {
}
const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
- const auto& sampler =
- GetSampler(instr.sampler, {{TextureType::Texture2D, false, depth_compare}});
+ const SamplerInfo info{TextureType::Texture2D, false, depth_compare};
+ const auto& sampler = GetSampler(instr.sampler, info);
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {
@@ -188,7 +188,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
// Sadly, not all texture instructions specify the type of texture their sampler
// uses. This must be fixed at a later instance.
const auto& sampler =
- is_bindless ? GetBindlessSampler(instr.gpr8, {}) : GetSampler(instr.sampler, {});
+ is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler);
u32 indexer = 0;
switch (instr.txq.query_type) {
@@ -224,8 +224,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
auto texture_type = instr.tmml.texture_type.Value();
const bool is_array = instr.tmml.array != 0;
const auto& sampler =
- is_bindless ? GetBindlessSampler(instr.gpr20, {{texture_type, is_array, false}})
- : GetSampler(instr.sampler, {{texture_type, is_array, false}});
+ is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler);
std::vector<Node> coords;
@@ -293,67 +292,50 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
return pc;
}
-const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
- std::optional<SamplerInfo> sampler_info) {
- const auto offset = static_cast<u32>(sampler.index.Value());
-
- TextureType type;
- bool is_array;
- bool is_shadow;
+ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional<SamplerInfo> sampler_info, u32 offset,
+ std::optional<u32> buffer) {
if (sampler_info) {
- type = sampler_info->type;
- is_array = sampler_info->is_array;
- is_shadow = sampler_info->is_shadow;
- } else if (const auto sampler = locker.ObtainBoundSampler(offset)) {
- type = sampler->texture_type.Value();
- is_array = sampler->is_array.Value() != 0;
- is_shadow = sampler->is_shadow.Value() != 0;
- } else {
+ return *sampler_info;
+ }
+ const auto sampler =
+ buffer ? locker.ObtainBindlessSampler(*buffer, offset) : locker.ObtainBoundSampler(offset);
+ if (!sampler) {
LOG_WARNING(HW_GPU, "Unknown sampler info");
- type = TextureType::Texture2D;
- is_array = false;
- is_shadow = false;
+ return SamplerInfo{TextureType::Texture2D, false, false, false};
}
+ return SamplerInfo{sampler->texture_type, sampler->is_array != 0, sampler->is_shadow != 0,
+ sampler->is_buffer != 0};
+}
+
+const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
+ std::optional<SamplerInfo> sampler_info) {
+ const auto offset = static_cast<u32>(sampler.index.Value());
+ const auto info = GetSamplerInfo(sampler_info, offset);
// If this sampler has already been used, return the existing mapping.
const auto it =
std::find_if(used_samplers.begin(), used_samplers.end(),
[offset](const Sampler& entry) { return entry.GetOffset() == offset; });
if (it != used_samplers.end()) {
- ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
- it->IsShadow() == is_shadow);
+ ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array &&
+ it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer);
return *it;
}
// Otherwise create a new mapping for this sampler
const auto next_index = static_cast<u32>(used_samplers.size());
- return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow));
+ return used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
+ info.is_buffer);
}
-const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
+const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
std::optional<SamplerInfo> sampler_info) {
const Node sampler_register = GetRegister(reg);
const auto [base_sampler, buffer, offset] =
TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
ASSERT(base_sampler != nullptr);
- TextureType type;
- bool is_array;
- bool is_shadow;
- if (sampler_info) {
- type = sampler_info->type;
- is_array = sampler_info->is_array;
- is_shadow = sampler_info->is_shadow;
- } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) {
- type = sampler->texture_type.Value();
- is_array = sampler->is_array.Value() != 0;
- is_shadow = sampler->is_shadow.Value() != 0;
- } else {
- LOG_WARNING(HW_GPU, "Unknown sampler info");
- type = TextureType::Texture2D;
- is_array = false;
- is_shadow = false;
- }
+ const auto info = GetSamplerInfo(sampler_info, offset, buffer);
// If this sampler has already been used, return the existing mapping.
const auto it =
@@ -362,15 +344,15 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
});
if (it != used_samplers.end()) {
- ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
- it->IsShadow() == is_shadow);
+ ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array &&
+ it->IsShadow() == info.is_shadow);
return *it;
}
// Otherwise create a new mapping for this sampler
const auto next_index = static_cast<u32>(used_samplers.size());
- return used_samplers.emplace_back(
- Sampler(next_index, offset, buffer, type, is_array, is_shadow));
+ return used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
+ info.is_shadow, info.is_buffer);
}
void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
@@ -455,17 +437,16 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
(texture_type == TextureType::TextureCube && is_array && is_shadow),
"This method is not supported.");
+ const SamplerInfo info{texture_type, is_array, is_shadow, false};
const auto& sampler =
- is_bindless ? GetBindlessSampler(*bindless_reg, {{texture_type, is_array, is_shadow}})
- : GetSampler(instr.sampler, {{texture_type, is_array, is_shadow}});
+ is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info);
const bool lod_needed = process_mode == TextureProcessMode::LZ ||
process_mode == TextureProcessMode::LL ||
process_mode == TextureProcessMode::LLA;
- // LOD selection (either via bias or explicit textureLod) not
- // supported in GL for sampler2DArrayShadow and
- // samplerCubeArrayShadow.
+ // LOD selection (either via bias or explicit textureLod) not supported in GL for
+ // sampler2DArrayShadow and samplerCubeArrayShadow.
const bool gl_lod_supported =
!((texture_type == Tegra::Shader::TextureType::Texture2D && is_array && is_shadow) ||
(texture_type == Tegra::Shader::TextureType::TextureCube && is_array && is_shadow));
@@ -475,8 +456,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported);
- Node bias = {};
- Node lod = {};
+ Node bias;
+ Node lod;
if (process_mode != TextureProcessMode::None && gl_lod_supported) {
switch (process_mode) {
case TextureProcessMode::LZ:
@@ -612,10 +593,9 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
u64 parameter_register = instr.gpr20.Value();
- const auto& sampler =
- is_bindless
- ? GetBindlessSampler(parameter_register++, {{texture_type, is_array, depth_compare}})
- : GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}});
+ const SamplerInfo info{texture_type, is_array, depth_compare, false};
+ const auto& sampler = is_bindless ? GetBindlessSampler(parameter_register++, info)
+ : GetSampler(instr.sampler, info);
std::vector<Node> aoffi;
if (is_aoffi) {
@@ -662,7 +642,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
// const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr};
// const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr};
- const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}});
+ const auto& sampler = GetSampler(instr.sampler);
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {
@@ -675,6 +655,8 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
}
Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) {
+ const auto& sampler = GetSampler(instr.sampler);
+
const std::size_t type_coord_count = GetCoordCount(texture_type);
const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL;
@@ -698,7 +680,14 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
// When lod is used always is in gpr20
const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0);
- const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}});
+ // Fill empty entries from the guest sampler.
+ const std::size_t entry_coord_count = GetCoordCount(sampler.GetType());
+ if (type_coord_count != entry_coord_count) {
+ LOG_WARNING(HW_GPU, "Bound and built texture types mismatch");
+ }
+ for (std::size_t i = type_coord_count; i < entry_coord_count; ++i) {
+ coords.push_back(GetRegister(Register::ZeroIndex));
+ }
Node4 values;
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 6c5046d3b..b2576bdd6 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -228,14 +228,15 @@ class Sampler {
public:
/// This constructor is for bound samplers
constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
- bool is_array, bool is_shadow)
- : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow} {}
+ bool is_array, bool is_shadow, bool is_buffer)
+ : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
+ is_buffer{is_buffer} {}
/// This constructor is for bindless samplers
constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
- bool is_array, bool is_shadow)
+ bool is_array, bool is_shadow, bool is_buffer)
: index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
- is_shadow{is_shadow}, is_bindless{true} {}
+ is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true} {}
constexpr u32 GetIndex() const {
return index;
@@ -261,6 +262,10 @@ public:
return is_shadow;
}
+ constexpr bool IsBuffer() const {
+ return is_buffer;
+ }
+
constexpr bool IsBindless() const {
return is_bindless;
}
@@ -273,6 +278,7 @@ private:
Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
bool is_array{}; ///< Whether the texture is being sampled as an array texture or not.
bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
+ bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler.
bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
};
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:
Tegra::Shader::TextureType type;
bool is_array;
bool is_shadow;
+ bool is_buffer;
};
void Decode();
@@ -303,13 +304,17 @@ private:
/// Returns a predicate combiner operation
OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);
+ /// Queries the missing sampler info from the execution context.
+ SamplerInfo GetSamplerInfo(std::optional<SamplerInfo> sampler_info, u32 offset,
+ std::optional<u32> buffer = std::nullopt);
+
/// Accesses a texture sampler
const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler,
- std::optional<SamplerInfo> sampler_info);
+ std::optional<SamplerInfo> sampler_info = std::nullopt);
- // Accesses a texture sampler for a bindless texture.
- const Sampler& GetBindlessSampler(const Tegra::Shader::Register& reg,
- std::optional<SamplerInfo> sampler_info);
+ /// Accesses a texture sampler for a bindless texture.
+ const Sampler& GetBindlessSampler(Tegra::Shader::Register reg,
+ std::optional<SamplerInfo> sampler_info = std::nullopt);
/// Accesses an image.
Image& GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type);