summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp45
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h15
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp12
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp39
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp33
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.h8
-rw-r--r--src/video_core/shader/decode/texture.cpp102
-rw-r--r--src/video_core/shader/node.h14
-rw-r--r--src/video_core/shader/shader_ir.h13
9 files changed, 107 insertions, 174 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 05f8e511b..b76de71ec 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -271,9 +271,9 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
const auto stage = static_cast<Maxwell::ShaderStage>(index == 0 ? 0 : index - 1);
SetupDrawConstBuffers(stage, shader);
SetupDrawGlobalMemory(stage, shader);
- const auto texture_buffer_usage{SetupDrawTextures(stage, shader, base_bindings)};
+ SetupDrawTextures(stage, shader, base_bindings);
- const ProgramVariant variant{base_bindings, primitive_mode, texture_buffer_usage};
+ const ProgramVariant variant{base_bindings, primitive_mode};
const auto [program_handle, next_bindings] = shader->GetProgramHandle(variant);
switch (program) {
@@ -303,7 +303,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
// When VertexA is enabled, we have dual vertex shaders
if (program == Maxwell::ShaderProgram::VertexA) {
// VertexB was combined with VertexA, so we skip the VertexB iteration
- index++;
+ ++index;
}
base_bindings = next_bindings;
@@ -732,11 +732,10 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
}
auto kernel = shader_cache.GetComputeKernel(code_addr);
- ProgramVariant variant;
- variant.texture_buffer_usage = SetupComputeTextures(kernel);
+ SetupComputeTextures(kernel);
SetupComputeImages(kernel);
- const auto [program, next_bindings] = kernel->GetProgramHandle(variant);
+ const auto [program, next_bindings] = kernel->GetProgramHandle({});
state.draw.shader_program = program;
state.draw.program_pipeline = 0;
@@ -918,9 +917,8 @@ void RasterizerOpenGL::SetupGlobalMemory(const GLShader::GlobalMemoryEntry& entr
bind_ssbo_pushbuffer.Push(ssbo, buffer_offset, static_cast<GLsizeiptr>(size));
}
-TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stage,
- const Shader& shader,
- BaseBindings base_bindings) {
+void RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stage, const Shader& shader,
+ BaseBindings base_bindings) {
MICROPROFILE_SCOPE(OpenGL_Texture);
const auto& gpu = system.GPU();
const auto& maxwell3d = gpu.Maxwell3D();
@@ -929,8 +927,6 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.textures),
"Exceeded the number of active textures.");
- TextureBufferUsage texture_buffer_usage{0};
-
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
const auto texture = [&] {
@@ -943,15 +939,11 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
return maxwell3d.GetTextureInfo(tex_handle);
}();
- if (SetupTexture(base_bindings.sampler + bindpoint, texture, entry)) {
- texture_buffer_usage.set(bindpoint);
- }
+ SetupTexture(base_bindings.sampler + bindpoint, texture, entry);
}
-
- return texture_buffer_usage;
}
-TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) {
+void RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) {
MICROPROFILE_SCOPE(OpenGL_Texture);
const auto& compute = system.GPU().KeplerCompute();
const auto& entries = kernel->GetShaderEntries().samplers;
@@ -959,8 +951,6 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel)
ASSERT_MSG(entries.size() <= std::size(state.textures),
"Exceeded the number of active textures.");
- TextureBufferUsage texture_buffer_usage{0};
-
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
const auto texture = [&] {
@@ -972,34 +962,29 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel)
return compute.GetTextureInfo(tex_handle);
}();
- if (SetupTexture(bindpoint, texture, entry)) {
- texture_buffer_usage.set(bindpoint);
- }
+ SetupTexture(bindpoint, texture, entry);
}
-
- return texture_buffer_usage;
}
-bool RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture,
+void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture,
const GLShader::SamplerEntry& entry) {
- state.samplers[binding] = sampler_cache.GetSampler(texture.tsc);
-
const auto view = texture_cache.GetTextureSurface(texture.tic, entry);
if (!view) {
// Can occur when texture addr is null or its memory is unmapped/invalid
+ state.samplers[binding] = 0;
state.textures[binding] = 0;
- return false;
+ return;
}
state.textures[binding] = view->GetTexture();
if (view->GetSurfaceParams().IsBuffer()) {
- return true;
+ return;
}
+ state.samplers[binding] = sampler_cache.GetSampler(texture.tsc);
// Apply swizzle to textures that are not buffers.
view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
texture.tic.w_source);
- return false;
}
void RasterizerOpenGL::SetupComputeImages(const Shader& shader) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index bd6fe5c3a..0e0819d59 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -107,16 +107,15 @@ private:
/// Syncs all the state, shaders, render targets and textures setting before a draw call.
void DrawPrelude();
- /// Configures the current textures to use for the draw command. Returns shaders texture buffer
- /// usage.
- TextureBufferUsage SetupDrawTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
- const Shader& shader, BaseBindings base_bindings);
+ /// Configures the current textures to use for the draw command.
+ void SetupDrawTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
+ BaseBindings base_bindings);
- /// Configures the textures used in a compute shader. Returns texture buffer usage.
- TextureBufferUsage SetupComputeTextures(const Shader& kernel);
+ /// Configures the textures used in a compute shader.
+ void SetupComputeTextures(const Shader& kernel);
- /// Configures a texture. Returns true when the texture is a texture buffer.
- bool SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture,
+ /// Configures a texture.
+ void SetupTexture(u32 binding, const Tegra::Texture::FullTextureInfo& texture,
const GLShader::SamplerEntry& entry);
/// Configures images in a compute shader.
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 04a239a39..7ce06a978 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -270,7 +270,6 @@ CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramTy
auto base_bindings{variant.base_bindings};
const auto primitive_mode{variant.primitive_mode};
- const auto texture_buffer_usage{variant.texture_buffer_usage};
std::string source = fmt::format(R"(// {}
#version 430 core
@@ -317,17 +316,6 @@ CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramTy
fmt::format("#define IMAGE_BINDING_{} {}\n", image.GetIndex(), base_bindings.image++);
}
- // Transform 1D textures to texture samplers by declaring its preprocessor macros.
- for (std::size_t i = 0; i < texture_buffer_usage.size(); ++i) {
- if (!texture_buffer_usage.test(i)) {
- continue;
- }
- source += fmt::format("#define SAMPLER_{}_IS_BUFFER\n", i);
- }
- if (texture_buffer_usage.any()) {
- source += '\n';
- }
-
if (program_type == ProgramType::Geometry) {
const auto [glsl_topology, debug_name, max_vertices] =
GetPrimitiveDescription(primitive_mode);
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 4f2b49170..51c80bf32 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -658,9 +658,11 @@ private:
const std::string description{"layout (binding = SAMPLER_BINDING_" +
std::to_string(sampler.GetIndex()) + ") uniform"};
std::string sampler_type = [&]() {
+ if (sampler.IsBuffer()) {
+ return "samplerBuffer";
+ }
switch (sampler.GetType()) {
case Tegra::Shader::TextureType::Texture1D:
- // Special cased, read below.
return "sampler1D";
case Tegra::Shader::TextureType::Texture2D:
return "sampler2D";
@@ -680,19 +682,7 @@ private:
sampler_type += "Shadow";
}
- if (sampler.GetType() == Tegra::Shader::TextureType::Texture1D) {
- // 1D textures can be aliased to texture buffers, hide the declarations behind a
- // preprocessor flag and use one or the other from the GPU state. This has to be
- // done because shaders don't have enough information to determine the texture type.
- EmitIfdefIsBuffer(sampler);
- code.AddLine("{} samplerBuffer {};", description, name);
- code.AddLine("#else");
- code.AddLine("{} {} {};", description, sampler_type, name);
- code.AddLine("#endif");
- } else {
- // The other texture types (2D, 3D and cubes) don't have this issue.
- code.AddLine("{} {} {};", description, sampler_type, name);
- }
+ code.AddLine("{} {} {};", description, sampler_type, name);
}
if (!samplers.empty()) {
code.AddNewLine();
@@ -1749,27 +1739,14 @@ private:
expr += ", ";
}
- // Store a copy of the expression without the lod to be used with texture buffers
- std::string expr_buffer = expr;
-
- if (meta->lod) {
+ if (meta->lod && !meta->sampler.IsBuffer()) {
expr += ", ";
expr += Visit(meta->lod).AsInt();
}
expr += ')';
expr += GetSwizzle(meta->element);
- expr_buffer += ')';
- expr_buffer += GetSwizzle(meta->element);
-
- const std::string tmp{code.GenerateTemporary()};
- EmitIfdefIsBuffer(meta->sampler);
- code.AddLine("float {} = {};", tmp, expr_buffer);
- code.AddLine("#else");
- code.AddLine("float {} = {};", tmp, expr);
- code.AddLine("#endif");
-
- return {tmp, Type::Float};
+ return {std::move(expr), Type::Float};
}
Expression ImageLoad(Operation operation) {
@@ -2214,10 +2191,6 @@ private:
return GetDeclarationWithSuffix(static_cast<u32>(image.GetIndex()), "image");
}
- void EmitIfdefIsBuffer(const Sampler& sampler) {
- code.AddLine("#ifdef SAMPLER_{}_IS_BUFFER", sampler.GetIndex());
- }
-
std::string GetDeclarationWithSuffix(u32 index, std::string_view name) const {
return fmt::format("{}_{}_{}", name, index, suffix);
}
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 184a565e6..3f4daf28d 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -28,34 +28,35 @@ using VideoCommon::Shader::KeyMap;
namespace {
+using ShaderCacheVersionHash = std::array<u8, 64>;
+
+enum class TransferableEntryKind : u32 {
+ Raw,
+ Usage,
+};
+
struct ConstBufferKey {
- u32 cbuf;
- u32 offset;
- u32 value;
+ u32 cbuf{};
+ u32 offset{};
+ u32 value{};
};
struct BoundSamplerKey {
- u32 offset;
- Tegra::Engines::SamplerDescriptor sampler;
+ u32 offset{};
+ Tegra::Engines::SamplerDescriptor sampler{};
};
struct BindlessSamplerKey {
- u32 cbuf;
- u32 offset;
- Tegra::Engines::SamplerDescriptor sampler;
-};
-
-using ShaderCacheVersionHash = std::array<u8, 64>;
-
-enum class TransferableEntryKind : u32 {
- Raw,
- Usage,
+ u32 cbuf{};
+ u32 offset{};
+ Tegra::Engines::SamplerDescriptor sampler{};
};
-constexpr u32 NativeVersion = 5;
+constexpr u32 NativeVersion = 6;
// Making sure sizes doesn't change by accident
static_assert(sizeof(BaseBindings) == 16);
+static_assert(sizeof(ProgramVariant) == 20);
ShaderCacheVersionHash GetShaderCacheVersionHash() {
ShaderCacheVersionHash hash{};
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.h b/src/video_core/renderer_opengl/gl_shader_disk_cache.h
index db23ada93..55311dc6d 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h
@@ -4,7 +4,6 @@
#pragma once
-#include <bitset>
#include <optional>
#include <string>
#include <tuple>
@@ -37,7 +36,6 @@ struct ShaderDiskCacheDump;
using ProgramCode = std::vector<u64>;
using ShaderDumpsMap = std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>;
-using TextureBufferUsage = std::bitset<64>;
/// Allocated bindings used by an OpenGL shader program
struct BaseBindings {
@@ -61,11 +59,10 @@ static_assert(std::is_trivially_copyable_v<BaseBindings>);
struct ProgramVariant {
BaseBindings base_bindings;
GLenum primitive_mode{};
- TextureBufferUsage texture_buffer_usage{};
bool operator==(const ProgramVariant& rhs) const {
- return std::tie(base_bindings, primitive_mode, texture_buffer_usage) ==
- std::tie(rhs.base_bindings, rhs.primitive_mode, rhs.texture_buffer_usage);
+ return std::tie(base_bindings, primitive_mode) ==
+ std::tie(rhs.base_bindings, rhs.primitive_mode);
}
bool operator!=(const ProgramVariant& rhs) const {
@@ -112,7 +109,6 @@ template <>
struct hash<OpenGL::ProgramVariant> {
std::size_t operator()(const OpenGL::ProgramVariant& variant) const noexcept {
return std::hash<OpenGL::BaseBindings>()(variant.base_bindings) ^
- std::hash<OpenGL::TextureBufferUsage>()(variant.texture_buffer_usage) ^
(static_cast<std::size_t>(variant.primitive_mode) << 6);
}
};
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index bb926a132..695fdbd24 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) {
@@ -149,7 +149,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) {
@@ -185,8 +185,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;
@@ -254,67 +253,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 =
@@ -323,15 +305,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) {
@@ -416,17 +398,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));
@@ -436,8 +417,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:
@@ -573,10 +554,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) {
@@ -623,7 +603,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) {
@@ -659,7 +639,7 @@ 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}});
+ const auto& sampler = GetSampler(instr.sampler);
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 54217e6a4..44d85d434 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -225,14 +225,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;
@@ -258,6 +259,10 @@ public:
return is_shadow;
}
+ constexpr bool IsBuffer() const {
+ return is_buffer;
+ }
+
constexpr bool IsBindless() const {
return is_bindless;
}
@@ -270,6 +275,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);