From fe392fff2425c10c9683a4058c779d352b9855ec Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 26 Mar 2019 17:56:16 -0400 Subject: Unify both sampler types. --- .../renderer_opengl/gl_shader_decompiler.h | 3 +- .../renderer_opengl/gl_shader_disk_cache.cpp | 9 ++++-- src/video_core/shader/decode/texture.cpp | 22 +++++++------ src/video_core/shader/shader_ir.h | 36 +++++++++++++++++----- 4 files changed, 48 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h index 4e04ab2f8..9f7b7272e 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.h +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h @@ -58,6 +58,7 @@ private: struct ShaderEntries { std::vector const_buffers; std::vector samplers; + std::vector bindless_samplers; std::vector global_memory_entries; std::array clip_distances{}; std::size_t shader_length{}; @@ -68,4 +69,4 @@ std::string GetCommonDeclarations(); ProgramResult Decompile(const VideoCommon::Shader::ShaderIR& ir, Maxwell::ShaderStage stage, const std::string& suffix); -} // namespace OpenGL::GLShader \ No newline at end of file +} // namespace OpenGL::GLShader 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 6a95af6f6..e27740383 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -319,16 +319,18 @@ std::optional ShaderDiskCacheOpenGL::LoadDecompiledEn u32 type{}; u8 is_array{}; u8 is_shadow{}; + u8 is_bindless{}; if (file.ReadBytes(&offset, sizeof(u64)) != sizeof(u64) || file.ReadBytes(&index, sizeof(u64)) != sizeof(u64) || file.ReadBytes(&type, sizeof(u32)) != sizeof(u32) || file.ReadBytes(&is_array, sizeof(u8)) != sizeof(u8) || - file.ReadBytes(&is_shadow, sizeof(u8)) != sizeof(u8)) { + file.ReadBytes(&is_shadow, sizeof(u8)) != sizeof(u8) || + file.ReadBytes(&is_bindless, sizeof(u8)) != sizeof(u8)) { return {}; } entry.entries.samplers.emplace_back( static_cast(offset), static_cast(index), - static_cast(type), is_array != 0, is_shadow != 0, false); + static_cast(type), is_array != 0, is_shadow != 0, is_bindless != 0); } u32 global_memory_count{}; @@ -388,7 +390,8 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(FileUtil::IOFile& file, u64 uniqu file.WriteObject(static_cast(sampler.GetIndex())) != 1 || file.WriteObject(static_cast(sampler.GetType())) != 1 || file.WriteObject(static_cast(sampler.IsArray() ? 1 : 0)) != 1 || - file.WriteObject(static_cast(sampler.IsShadow() ? 1 : 0)) != 1) { + file.WriteObject(static_cast(sampler.IsShadow() ? 1 : 0)) != 1 || + file.WriteObject(static_cast(sampler.IsBindless() ? 1 : 0)) != 1) { return false; } } diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 23f2ad999..3ac04f6b7 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -267,7 +267,7 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu // Otherwise create a new mapping for this sampler const std::size_t next_index = used_samplers.size(); - const Sampler entry{offset, next_index, type, is_array, is_shadow, false}; + const Sampler entry{offset, next_index, type, is_array, is_shadow}; return *used_samplers.emplace(entry).first; } @@ -281,20 +281,22 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, ASSERT(cbuf_offset_imm != nullptr); const auto cbuf_offset = cbuf_offset_imm->GetValue(); const auto cbuf_index = cbuf->GetIndex(); - const std::pair cbuf_pair = {cbuf_index, cbuf_offset}; + const u64 cbuf_key = (cbuf_index << 32) | cbuf_offset; // If this sampler has already been used, return the existing mapping. - if (used_bindless_samplers.count(cbuf_pair) > 0) { - const auto& sampler = used_bindless_samplers[cbuf_pair]; - ASSERT(sampler.GetType() == type && sampler.IsArray() == is_array && - sampler.IsShadow() == is_shadow); - return sampler; + const auto itr = + std::find_if(used_samplers.begin(), used_samplers.end(), + [&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; }); + if (itr != used_samplers.end()) { + ASSERT(itr->GetType() == type && itr->IsArray() == is_array && + itr->IsShadow() == is_shadow); + return *itr; } // Otherwise create a new mapping for this sampler - const std::size_t next_index = used_bindless_samplers.size(); - const Sampler entry{0, next_index, type, is_array, is_shadow, true}; - return (*used_bindless_samplers.emplace(std::make_pair(cbuf_pair, entry)).first).second; + const std::size_t next_index = used_samplers.size(); + const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow}; + return *used_samplers.emplace(entry).first; } void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 712dc3ddb..773c71fa5 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -196,12 +196,24 @@ enum class ExitMethod { class Sampler { public: - Sampler() = default; + // Use this constructor for binded Samplers + explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, + bool is_array, bool is_shadow) + : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, + is_bindless{false} {} + + // Use this constructor for bindless Samplers + explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index, + Tegra::Shader::TextureType type, bool is_array, bool is_shadow) + : offset{(static_cast(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, is_array{is_array}, + is_shadow{is_shadow}, is_bindless{true} {} + + // Use this only for serialization/deserialization explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, bool is_array, bool is_shadow, bool is_bindless) - : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, is_bindless{is_bindless} {} + : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, + is_bindless{is_bindless} {} - ~Sampler() = default; std::size_t GetOffset() const { return offset; @@ -223,6 +235,14 @@ public: return is_shadow; } + bool IsBindless() const { + return is_bindless; + } + + std::pair GetBindlessCBuf() { + return {offset >> 32, offset & 0x00000000FFFFFFFFULL}; + } + bool operator<(const Sampler& rhs) const { return std::tie(offset, index, type, is_array, is_shadow) < std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_array, rhs.is_shadow); @@ -234,8 +254,8 @@ private: std::size_t offset{}; std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. 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_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_bindless{}; ///< Whether this sampler belongs to a bindless texture or not. }; @@ -735,8 +755,9 @@ private: Tegra::Shader::TextureType type, bool is_array, bool is_shadow); // Accesses a texture sampler for a bindless texture. - const Sampler& GetBindlessSampler(const Tegra::Shader::Register& reg, Tegra::Shader::TextureType type, - bool is_array, bool is_shadow); + const Sampler& GetBindlessSampler(const Tegra::Shader::Register& reg, + Tegra::Shader::TextureType type, bool is_array, + bool is_shadow); /// Extracts a sequence of bits from a node Node BitfieldExtract(Node value, u32 offset, u32 bits); @@ -845,7 +866,6 @@ private: std::set used_output_attributes; std::map used_cbufs; std::set used_samplers; - std::map, Sampler> used_bindless_samplers; std::array used_clip_distances{}; std::set used_global_memory_bases; -- cgit v1.2.3