diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.h | 3 | ||||
| -rw-r--r-- | src/video_core/shader/decode/image.cpp | 50 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 59 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 101 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 12 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 2 |
8 files changed, 116 insertions, 142 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 6a4d2c83a..d1e147db8 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -935,10 +935,9 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag | |||
| 935 | if (!entry.IsBindless()) { | 935 | if (!entry.IsBindless()) { |
| 936 | return maxwell3d.GetStageTexture(stage, entry.GetOffset()); | 936 | return maxwell3d.GetStageTexture(stage, entry.GetOffset()); |
| 937 | } | 937 | } |
| 938 | const auto cbuf = entry.GetBindlessCBuf(); | 938 | const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage); |
| 939 | Tegra::Texture::TextureHandle tex_handle; | 939 | const Tegra::Texture::TextureHandle tex_handle = |
| 940 | Tegra::Engines::ShaderType shader_type = static_cast<Tegra::Engines::ShaderType>(stage); | 940 | maxwell3d.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset()); |
| 941 | tex_handle.raw = maxwell3d.AccessConstBuffer32(shader_type, cbuf.first, cbuf.second); | ||
| 942 | return maxwell3d.GetTextureInfo(tex_handle); | 941 | return maxwell3d.GetTextureInfo(tex_handle); |
| 943 | }(); | 942 | }(); |
| 944 | 943 | ||
| @@ -966,10 +965,8 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) | |||
| 966 | if (!entry.IsBindless()) { | 965 | if (!entry.IsBindless()) { |
| 967 | return compute.GetTexture(entry.GetOffset()); | 966 | return compute.GetTexture(entry.GetOffset()); |
| 968 | } | 967 | } |
| 969 | const auto cbuf = entry.GetBindlessCBuf(); | 968 | const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32( |
| 970 | Tegra::Texture::TextureHandle tex_handle; | 969 | Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset()); |
| 971 | tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute, | ||
| 972 | cbuf.first, cbuf.second); | ||
| 973 | return compute.GetTextureInfo(tex_handle); | 970 | return compute.GetTextureInfo(tex_handle); |
| 974 | }(); | 971 | }(); |
| 975 | 972 | ||
| @@ -1012,10 +1009,8 @@ void RasterizerOpenGL::SetupComputeImages(const Shader& shader) { | |||
| 1012 | if (!entry.IsBindless()) { | 1009 | if (!entry.IsBindless()) { |
| 1013 | return compute.GetTexture(entry.GetOffset()).tic; | 1010 | return compute.GetTexture(entry.GetOffset()).tic; |
| 1014 | } | 1011 | } |
| 1015 | const auto cbuf = entry.GetBindlessCBuf(); | 1012 | const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32( |
| 1016 | Tegra::Texture::TextureHandle tex_handle; | 1013 | Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset()); |
| 1017 | tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute, | ||
| 1018 | cbuf.first, cbuf.second); | ||
| 1019 | return compute.GetTextureInfo(tex_handle).tic; | 1014 | return compute.GetTextureInfo(tex_handle).tic; |
| 1020 | }(); | 1015 | }(); |
| 1021 | SetupImage(bindpoint, tic, entry); | 1016 | SetupImage(bindpoint, tic, entry); |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 030550c53..92ee8459e 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -735,7 +735,7 @@ private: | |||
| 735 | 735 | ||
| 736 | void DeclareImages() { | 736 | void DeclareImages() { |
| 737 | const auto& images{ir.GetImages()}; | 737 | const auto& images{ir.GetImages()}; |
| 738 | for (const auto& [offset, image] : images) { | 738 | for (const auto& image : images) { |
| 739 | std::string qualifier = "coherent volatile"; | 739 | std::string qualifier = "coherent volatile"; |
| 740 | if (image.IsRead() && !image.IsWritten()) { | 740 | if (image.IsRead() && !image.IsWritten()) { |
| 741 | qualifier += " readonly"; | 741 | qualifier += " readonly"; |
| @@ -2466,16 +2466,16 @@ ShaderEntries GetEntries(const VideoCommon::Shader::ShaderIR& ir) { | |||
| 2466 | entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(), | 2466 | entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(), |
| 2467 | cbuf.first); | 2467 | cbuf.first); |
| 2468 | } | 2468 | } |
| 2469 | for (const auto& [base, usage] : ir.GetGlobalMemory()) { | ||
| 2470 | entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read, | ||
| 2471 | usage.is_written); | ||
| 2472 | } | ||
| 2469 | for (const auto& sampler : ir.GetSamplers()) { | 2473 | for (const auto& sampler : ir.GetSamplers()) { |
| 2470 | entries.samplers.emplace_back(sampler); | 2474 | entries.samplers.emplace_back(sampler); |
| 2471 | } | 2475 | } |
| 2472 | for (const auto& [offset, image] : ir.GetImages()) { | 2476 | for (const auto& image : ir.GetImages()) { |
| 2473 | entries.images.emplace_back(image); | 2477 | entries.images.emplace_back(image); |
| 2474 | } | 2478 | } |
| 2475 | for (const auto& [base, usage] : ir.GetGlobalMemory()) { | ||
| 2476 | entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read, | ||
| 2477 | usage.is_written); | ||
| 2478 | } | ||
| 2479 | entries.clip_distances = ir.GetClipDistances(); | 2479 | entries.clip_distances = ir.GetClipDistances(); |
| 2480 | entries.shader_length = ir.GetLength(); | 2480 | entries.shader_length = ir.GetLength(); |
| 2481 | return entries; | 2481 | return entries; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h index fead2a51e..b1e75e6cc 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.h +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h | |||
| @@ -82,10 +82,9 @@ private: | |||
| 82 | 82 | ||
| 83 | struct ShaderEntries { | 83 | struct ShaderEntries { |
| 84 | std::vector<ConstBufferEntry> const_buffers; | 84 | std::vector<ConstBufferEntry> const_buffers; |
| 85 | std::vector<GlobalMemoryEntry> global_memory_entries; | ||
| 85 | std::vector<SamplerEntry> samplers; | 86 | std::vector<SamplerEntry> samplers; |
| 86 | std::vector<SamplerEntry> bindless_samplers; | ||
| 87 | std::vector<ImageEntry> images; | 87 | std::vector<ImageEntry> images; |
| 88 | std::vector<GlobalMemoryEntry> global_memory_entries; | ||
| 89 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | 88 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; |
| 90 | std::size_t shader_length{}; | 89 | std::size_t shader_length{}; |
| 91 | }; | 90 | }; |
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index b02d2cb95..d2fe4ec5d 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -143,39 +143,37 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { | 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { |
| 146 | const auto offset{static_cast<std::size_t>(image.index.Value())}; | 146 | const auto offset = static_cast<u32>(image.index.Value()); |
| 147 | if (const auto existing_image = TryUseExistingImage(offset, type)) { | 147 | |
| 148 | return *existing_image; | 148 | const auto it = |
| 149 | std::find_if(std::begin(used_images), std::end(used_images), | ||
| 150 | [offset](const Image& entry) { return entry.GetOffset() == offset; }); | ||
| 151 | if (it != std::end(used_images)) { | ||
| 152 | ASSERT(!it->IsBindless() && it->GetType() == it->GetType()); | ||
| 153 | return *it; | ||
| 149 | } | 154 | } |
| 150 | 155 | ||
| 151 | const std::size_t next_index{used_images.size()}; | 156 | const auto next_index = static_cast<u32>(used_images.size()); |
| 152 | return used_images.emplace(offset, Image{offset, next_index, type}).first->second; | 157 | return used_images.emplace_back(next_index, offset, type); |
| 153 | } | 158 | } |
| 154 | 159 | ||
| 155 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { | 160 | Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { |
| 156 | const Node image_register{GetRegister(reg)}; | 161 | const Node image_register = GetRegister(reg); |
| 157 | const auto [base_image, cbuf_index, cbuf_offset]{ | 162 | const auto [base_image, buffer, offset] = |
| 158 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; | 163 | TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size())); |
| 159 | const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; | 164 | |
| 160 | 165 | const auto it = | |
| 161 | if (const auto image = TryUseExistingImage(cbuf_key, type)) { | 166 | std::find_if(std::begin(used_images), std::end(used_images), |
| 162 | return *image; | 167 | [buffer = buffer, offset = offset](const Image& entry) { |
| 163 | } | 168 | return entry.GetBuffer() == buffer && entry.GetOffset() == offset; |
| 164 | 169 | }); | |
| 165 | const std::size_t next_index{used_images.size()}; | 170 | if (it != std::end(used_images)) { |
| 166 | return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type}) | 171 | ASSERT(it->IsBindless() && it->GetType() == it->GetType()); |
| 167 | .first->second; | 172 | return *it; |
| 168 | } | ||
| 169 | |||
| 170 | Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type) { | ||
| 171 | auto it = used_images.find(offset); | ||
| 172 | if (it == used_images.end()) { | ||
| 173 | return nullptr; | ||
| 174 | } | 173 | } |
| 175 | auto& image = it->second; | ||
| 176 | ASSERT(image.GetType() == type); | ||
| 177 | 174 | ||
| 178 | return ℑ | 175 | const auto next_index = static_cast<u32>(used_images.size()); |
| 176 | return used_images.emplace_back(next_index, offset, buffer, type); | ||
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | } // namespace VideoCommon::Shader | 179 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 4c838c8bb..ca690b58b 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp | |||
| @@ -262,7 +262,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { | |||
| 262 | break; | 262 | break; |
| 263 | } | 263 | } |
| 264 | case OpCode::Id::TLDS: { | 264 | case OpCode::Id::TLDS: { |
| 265 | const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; | 265 | const TextureType texture_type{instr.tlds.GetTextureType()}; |
| 266 | const bool is_array{instr.tlds.IsArrayTexture()}; | 266 | const bool is_array{instr.tlds.IsArrayTexture()}; |
| 267 | 267 | ||
| 268 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), | 268 | UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), |
| @@ -293,77 +293,80 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, | |||
| 293 | std::optional<SamplerInfo> sampler_info) { | 293 | std::optional<SamplerInfo> sampler_info) { |
| 294 | const auto offset = static_cast<u32>(sampler.index.Value()); | 294 | const auto offset = static_cast<u32>(sampler.index.Value()); |
| 295 | 295 | ||
| 296 | Tegra::Shader::TextureType type; | 296 | TextureType type; |
| 297 | bool is_array; | 297 | bool is_array; |
| 298 | bool is_shadow; | 298 | bool is_shadow; |
| 299 | if (sampler_info) { | 299 | if (sampler_info) { |
| 300 | type = sampler_info->type; | 300 | type = sampler_info->type; |
| 301 | is_array = sampler_info->is_array; | 301 | is_array = sampler_info->is_array; |
| 302 | is_shadow = sampler_info->is_shadow; | 302 | is_shadow = sampler_info->is_shadow; |
| 303 | } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) { | 303 | } else if (const auto sampler = locker.ObtainBoundSampler(offset)) { |
| 304 | type = sampler->texture_type.Value(); | 304 | type = sampler->texture_type.Value(); |
| 305 | is_array = sampler->is_array.Value() != 0; | 305 | is_array = sampler->is_array.Value() != 0; |
| 306 | is_shadow = sampler->is_shadow.Value() != 0; | 306 | is_shadow = sampler->is_shadow.Value() != 0; |
| 307 | } else { | 307 | } else { |
| 308 | type = Tegra::Shader::TextureType::Texture2D; | 308 | LOG_WARNING(HW_GPU, "Unknown sampler info"); |
| 309 | type = TextureType::Texture2D; | ||
| 309 | is_array = false; | 310 | is_array = false; |
| 310 | is_shadow = false; | 311 | is_shadow = false; |
| 311 | } | 312 | } |
| 312 | 313 | ||
| 313 | // If this sampler has already been used, return the existing mapping. | 314 | // If this sampler has already been used, return the existing mapping. |
| 314 | const auto itr = | 315 | const auto it = |
| 315 | std::find_if(used_samplers.begin(), used_samplers.end(), | 316 | std::find_if(used_samplers.begin(), used_samplers.end(), |
| 316 | [&](const Sampler& entry) { return entry.GetOffset() == offset; }); | 317 | [offset](const Sampler& entry) { return entry.GetOffset() == offset; }); |
| 317 | if (itr != used_samplers.end()) { | 318 | if (it != used_samplers.end()) { |
| 318 | ASSERT(itr->GetType() == type && itr->IsArray() == is_array && | 319 | ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && |
| 319 | itr->IsShadow() == is_shadow); | 320 | it->IsShadow() == is_shadow); |
| 320 | return *itr; | 321 | return *it; |
| 321 | } | 322 | } |
| 322 | 323 | ||
| 323 | // Otherwise create a new mapping for this sampler | 324 | // Otherwise create a new mapping for this sampler |
| 324 | const std::size_t next_index = used_samplers.size(); | 325 | const auto next_index = static_cast<u32>(used_samplers.size()); |
| 325 | const Sampler entry{offset, next_index, type, is_array, is_shadow}; | 326 | return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow)); |
| 326 | return *used_samplers.emplace(entry).first; | 327 | } |
| 327 | } // namespace VideoCommon::Shader | ||
| 328 | 328 | ||
| 329 | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, | 329 | const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, |
| 330 | std::optional<SamplerInfo> sampler_info) { | 330 | std::optional<SamplerInfo> sampler_info) { |
| 331 | const Node sampler_register = GetRegister(reg); | 331 | const Node sampler_register = GetRegister(reg); |
| 332 | const auto [base_sampler, cbuf_index, cbuf_offset] = | 332 | const auto [base_sampler, buffer, offset] = |
| 333 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); | 333 | TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); |
| 334 | ASSERT(base_sampler != nullptr); | 334 | ASSERT(base_sampler != nullptr); |
| 335 | const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); | 335 | |
| 336 | Tegra::Shader::TextureType type; | 336 | TextureType type; |
| 337 | bool is_array; | 337 | bool is_array; |
| 338 | bool is_shadow; | 338 | bool is_shadow; |
| 339 | if (sampler_info) { | 339 | if (sampler_info) { |
| 340 | type = sampler_info->type; | 340 | type = sampler_info->type; |
| 341 | is_array = sampler_info->is_array; | 341 | is_array = sampler_info->is_array; |
| 342 | is_shadow = sampler_info->is_shadow; | 342 | is_shadow = sampler_info->is_shadow; |
| 343 | } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) { | 343 | } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) { |
| 344 | type = sampler->texture_type.Value(); | 344 | type = sampler->texture_type.Value(); |
| 345 | is_array = sampler->is_array.Value() != 0; | 345 | is_array = sampler->is_array.Value() != 0; |
| 346 | is_shadow = sampler->is_shadow.Value() != 0; | 346 | is_shadow = sampler->is_shadow.Value() != 0; |
| 347 | } else { | 347 | } else { |
| 348 | type = Tegra::Shader::TextureType::Texture2D; | 348 | LOG_WARNING(HW_GPU, "Unknown sampler info"); |
| 349 | type = TextureType::Texture2D; | ||
| 349 | is_array = false; | 350 | is_array = false; |
| 350 | is_shadow = false; | 351 | is_shadow = false; |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 353 | // If this sampler has already been used, return the existing mapping. | 354 | // If this sampler has already been used, return the existing mapping. |
| 354 | const auto itr = | 355 | const auto it = |
| 355 | std::find_if(used_samplers.begin(), used_samplers.end(), | 356 | std::find_if(used_samplers.begin(), used_samplers.end(), |
| 356 | [&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; }); | 357 | [buffer = buffer, offset = offset](const Sampler& entry) { |
| 357 | if (itr != used_samplers.end()) { | 358 | return entry.GetBuffer() == buffer && entry.GetOffset() == offset; |
| 358 | ASSERT(itr->GetType() == type && itr->IsArray() == is_array && | 359 | }); |
| 359 | itr->IsShadow() == is_shadow); | 360 | if (it != used_samplers.end()) { |
| 360 | return *itr; | 361 | ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array && |
| 362 | it->IsShadow() == is_shadow); | ||
| 363 | return *it; | ||
| 361 | } | 364 | } |
| 362 | 365 | ||
| 363 | // Otherwise create a new mapping for this sampler | 366 | // Otherwise create a new mapping for this sampler |
| 364 | const std::size_t next_index = used_samplers.size(); | 367 | const auto next_index = static_cast<u32>(used_samplers.size()); |
| 365 | const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow}; | 368 | return used_samplers.emplace_back( |
| 366 | return *used_samplers.emplace(entry).first; | 369 | Sampler(next_index, offset, buffer, type, is_array, is_shadow)); |
| 367 | } | 370 | } |
| 368 | 371 | ||
| 369 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { | 372 | void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 447fb5c1d..4300d9ff4 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -230,62 +230,49 @@ using NodeBlock = std::vector<Node>; | |||
| 230 | class Sampler { | 230 | class Sampler { |
| 231 | public: | 231 | public: |
| 232 | /// This constructor is for bound samplers | 232 | /// This constructor is for bound samplers |
| 233 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | 233 | constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type, |
| 234 | bool is_array, bool is_shadow) | 234 | bool is_array, bool is_shadow) |
| 235 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, | 235 | : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow} {} |
| 236 | is_bindless{false} {} | ||
| 237 | 236 | ||
| 238 | /// This constructor is for bindless samplers | 237 | /// This constructor is for bindless samplers |
| 239 | explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index, | 238 | constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type, |
| 240 | Tegra::Shader::TextureType type, bool is_array, bool is_shadow) | 239 | bool is_array, bool is_shadow) |
| 241 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, | 240 | : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array}, |
| 242 | is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {} | 241 | is_shadow{is_shadow}, is_bindless{true} {} |
| 243 | 242 | ||
| 244 | /// This constructor is for serialization/deserialization | 243 | constexpr u32 GetIndex() const { |
| 245 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | 244 | return index; |
| 246 | bool is_array, bool is_shadow, bool is_bindless) | 245 | } |
| 247 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, | 246 | |
| 248 | is_bindless{is_bindless} {} | 247 | constexpr u32 GetOffset() const { |
| 249 | |||
| 250 | std::size_t GetOffset() const { | ||
| 251 | return offset; | 248 | return offset; |
| 252 | } | 249 | } |
| 253 | 250 | ||
| 254 | std::size_t GetIndex() const { | 251 | constexpr u32 GetBuffer() const { |
| 255 | return index; | 252 | return buffer; |
| 256 | } | 253 | } |
| 257 | 254 | ||
| 258 | Tegra::Shader::TextureType GetType() const { | 255 | constexpr Tegra::Shader::TextureType GetType() const { |
| 259 | return type; | 256 | return type; |
| 260 | } | 257 | } |
| 261 | 258 | ||
| 262 | bool IsArray() const { | 259 | constexpr bool IsArray() const { |
| 263 | return is_array; | 260 | return is_array; |
| 264 | } | 261 | } |
| 265 | 262 | ||
| 266 | bool IsShadow() const { | 263 | constexpr bool IsShadow() const { |
| 267 | return is_shadow; | 264 | return is_shadow; |
| 268 | } | 265 | } |
| 269 | 266 | ||
| 270 | bool IsBindless() const { | 267 | constexpr bool IsBindless() const { |
| 271 | return is_bindless; | 268 | return is_bindless; |
| 272 | } | 269 | } |
| 273 | 270 | ||
| 274 | std::pair<u32, u32> GetBindlessCBuf() const { | ||
| 275 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; | ||
| 276 | } | ||
| 277 | |||
| 278 | bool operator<(const Sampler& rhs) const { | ||
| 279 | return std::tie(index, offset, type, is_array, is_shadow, is_bindless) < | ||
| 280 | std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow, | ||
| 281 | rhs.is_bindless); | ||
| 282 | } | ||
| 283 | |||
| 284 | private: | 271 | private: |
| 285 | /// Offset in TSC memory from which to read the sampler object, as specified by the sampling | 272 | u32 index{}; ///< Emulated index given for the this sampler. |
| 286 | /// instruction. | 273 | u32 offset{}; ///< Offset in the const buffer from where the sampler is being read. |
| 287 | std::size_t offset{}; | 274 | u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers). |
| 288 | std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. | 275 | |
| 289 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | 276 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) |
| 290 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. | 277 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. |
| 291 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. | 278 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. |
| @@ -294,18 +281,13 @@ private: | |||
| 294 | 281 | ||
| 295 | class Image final { | 282 | class Image final { |
| 296 | public: | 283 | public: |
| 297 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type) | 284 | /// This constructor is for bound images |
| 298 | : offset{offset}, index{index}, type{type}, is_bindless{false} {} | 285 | constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type) |
| 299 | 286 | : index{index}, offset{offset}, type{type} {} | |
| 300 | constexpr explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index, | ||
| 301 | Tegra::Shader::ImageType type) | ||
| 302 | : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, | ||
| 303 | is_bindless{true} {} | ||
| 304 | 287 | ||
| 305 | constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, | 288 | /// This constructor is for bindless samplers |
| 306 | bool is_bindless, bool is_written, bool is_read, bool is_atomic) | 289 | constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type) |
| 307 | : offset{offset}, index{index}, type{type}, is_bindless{is_bindless}, | 290 | : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {} |
| 308 | is_written{is_written}, is_read{is_read}, is_atomic{is_atomic} {} | ||
| 309 | 291 | ||
| 310 | void MarkWrite() { | 292 | void MarkWrite() { |
| 311 | is_written = true; | 293 | is_written = true; |
| @@ -321,12 +303,16 @@ public: | |||
| 321 | is_atomic = true; | 303 | is_atomic = true; |
| 322 | } | 304 | } |
| 323 | 305 | ||
| 324 | constexpr std::size_t GetOffset() const { | 306 | constexpr u32 GetIndex() const { |
| 307 | return index; | ||
| 308 | } | ||
| 309 | |||
| 310 | constexpr u32 GetOffset() const { | ||
| 325 | return offset; | 311 | return offset; |
| 326 | } | 312 | } |
| 327 | 313 | ||
| 328 | constexpr std::size_t GetIndex() const { | 314 | constexpr u32 GetBuffer() const { |
| 329 | return index; | 315 | return buffer; |
| 330 | } | 316 | } |
| 331 | 317 | ||
| 332 | constexpr Tegra::Shader::ImageType GetType() const { | 318 | constexpr Tegra::Shader::ImageType GetType() const { |
| @@ -349,18 +335,11 @@ public: | |||
| 349 | return is_atomic; | 335 | return is_atomic; |
| 350 | } | 336 | } |
| 351 | 337 | ||
| 352 | constexpr std::pair<u32, u32> GetBindlessCBuf() const { | ||
| 353 | return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)}; | ||
| 354 | } | ||
| 355 | |||
| 356 | constexpr bool operator<(const Image& rhs) const { | ||
| 357 | return std::tie(offset, index, type, is_bindless) < | ||
| 358 | std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless); | ||
| 359 | } | ||
| 360 | |||
| 361 | private: | 338 | private: |
| 362 | u64 offset{}; | 339 | u32 index{}; |
| 363 | std::size_t index{}; | 340 | u32 offset{}; |
| 341 | u32 buffer{}; | ||
| 342 | |||
| 364 | Tegra::Shader::ImageType type{}; | 343 | Tegra::Shader::ImageType type{}; |
| 365 | bool is_bindless{}; | 344 | bool is_bindless{}; |
| 366 | bool is_written{}; | 345 | bool is_written{}; |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index b5567f54e..26c8fde22 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <list> | ||
| 8 | #include <map> | 9 | #include <map> |
| 9 | #include <optional> | 10 | #include <optional> |
| 10 | #include <set> | 11 | #include <set> |
| @@ -95,11 +96,11 @@ public: | |||
| 95 | return used_cbufs; | 96 | return used_cbufs; |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | const std::set<Sampler>& GetSamplers() const { | 99 | const std::list<Sampler>& GetSamplers() const { |
| 99 | return used_samplers; | 100 | return used_samplers; |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | const std::map<u64, Image>& GetImages() const { | 103 | const std::list<Image>& GetImages() const { |
| 103 | return used_images; | 104 | return used_images; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| @@ -316,9 +317,6 @@ private: | |||
| 316 | /// Access a bindless image sampler. | 317 | /// Access a bindless image sampler. |
| 317 | Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); | 318 | Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); |
| 318 | 319 | ||
| 319 | /// Tries to access an existing image, updating it's state as needed | ||
| 320 | Image* TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type); | ||
| 321 | |||
| 322 | /// Extracts a sequence of bits from a node | 320 | /// Extracts a sequence of bits from a node |
| 323 | Node BitfieldExtract(Node value, u32 offset, u32 bits); | 321 | Node BitfieldExtract(Node value, u32 offset, u32 bits); |
| 324 | 322 | ||
| @@ -402,8 +400,8 @@ private: | |||
| 402 | std::set<Tegra::Shader::Attribute::Index> used_input_attributes; | 400 | std::set<Tegra::Shader::Attribute::Index> used_input_attributes; |
| 403 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; | 401 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; |
| 404 | std::map<u32, ConstBuffer> used_cbufs; | 402 | std::map<u32, ConstBuffer> used_cbufs; |
| 405 | std::set<Sampler> used_samplers; | 403 | std::list<Sampler> used_samplers; |
| 406 | std::map<u64, Image> used_images; | 404 | std::list<Image> used_images; |
| 407 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | 405 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; |
| 408 | std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; | 406 | std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; |
| 409 | bool uses_layer{}; | 407 | bool uses_layer{}; |
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 0429af9c1..27c8ce975 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h | |||
| @@ -132,6 +132,8 @@ enum class SwizzleSource : u32 { | |||
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | union TextureHandle { | 134 | union TextureHandle { |
| 135 | TextureHandle(u32 raw) : raw{raw} {} | ||
| 136 | |||
| 135 | u32 raw; | 137 | u32 raw; |
| 136 | BitField<0, 20, u32> tic_id; | 138 | BitField<0, 20, u32> tic_id; |
| 137 | BitField<20, 12, u32> tsc_id; | 139 | BitField<20, 12, u32> tsc_id; |