summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-10-28 02:31:05 -0300
committerGravatar ReinUsesLisp2019-10-29 20:53:48 -0300
commita993df1ee294b861eef4f35fccabeecd05754f2a (patch)
tree04150cb66c138c75f6a4fc47218bb2255af7e234
parentMerge pull request #3004 from ReinUsesLisp/maxwell3d-cleanup (diff)
downloadyuzu-a993df1ee294b861eef4f35fccabeecd05754f2a.tar.gz
yuzu-a993df1ee294b861eef4f35fccabeecd05754f2a.tar.xz
yuzu-a993df1ee294b861eef4f35fccabeecd05754f2a.zip
shader/node: Unpack bindless texture encoding
Bindless textures were using u64 to pack the buffer and offset from where they come from. Drop this in favor of separated entries in the struct. Remove the usage of std::set in favor of std::list (it's not std::vector to avoid reference invalidations) for samplers and images.
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp19
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp12
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h3
-rw-r--r--src/video_core/shader/decode/image.cpp50
-rw-r--r--src/video_core/shader/decode/texture.cpp59
-rw-r--r--src/video_core/shader/node.h101
-rw-r--r--src/video_core/shader/shader_ir.h12
-rw-r--r--src/video_core/textures/texture.h2
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 43032e9a7..35fc094a8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -973,10 +973,9 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
973 if (!entry.IsBindless()) { 973 if (!entry.IsBindless()) {
974 return maxwell3d.GetStageTexture(stage, entry.GetOffset()); 974 return maxwell3d.GetStageTexture(stage, entry.GetOffset());
975 } 975 }
976 const auto cbuf = entry.GetBindlessCBuf(); 976 const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
977 Tegra::Texture::TextureHandle tex_handle; 977 const Tegra::Texture::TextureHandle tex_handle =
978 Tegra::Engines::ShaderType shader_type = static_cast<Tegra::Engines::ShaderType>(stage); 978 maxwell3d.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset());
979 tex_handle.raw = maxwell3d.AccessConstBuffer32(shader_type, cbuf.first, cbuf.second);
980 return maxwell3d.GetTextureInfo(tex_handle); 979 return maxwell3d.GetTextureInfo(tex_handle);
981 }(); 980 }();
982 981
@@ -1004,10 +1003,8 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel)
1004 if (!entry.IsBindless()) { 1003 if (!entry.IsBindless()) {
1005 return compute.GetTexture(entry.GetOffset()); 1004 return compute.GetTexture(entry.GetOffset());
1006 } 1005 }
1007 const auto cbuf = entry.GetBindlessCBuf(); 1006 const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32(
1008 Tegra::Texture::TextureHandle tex_handle; 1007 Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset());
1009 tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute,
1010 cbuf.first, cbuf.second);
1011 return compute.GetTextureInfo(tex_handle); 1008 return compute.GetTextureInfo(tex_handle);
1012 }(); 1009 }();
1013 1010
@@ -1050,10 +1047,8 @@ void RasterizerOpenGL::SetupComputeImages(const Shader& shader) {
1050 if (!entry.IsBindless()) { 1047 if (!entry.IsBindless()) {
1051 return compute.GetTexture(entry.GetOffset()).tic; 1048 return compute.GetTexture(entry.GetOffset()).tic;
1052 } 1049 }
1053 const auto cbuf = entry.GetBindlessCBuf(); 1050 const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32(
1054 Tegra::Texture::TextureHandle tex_handle; 1051 Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset());
1055 tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute,
1056 cbuf.first, cbuf.second);
1057 return compute.GetTextureInfo(tex_handle).tic; 1052 return compute.GetTextureInfo(tex_handle).tic;
1058 }(); 1053 }();
1059 SetupImage(bindpoint, tic, entry); 1054 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
83struct ShaderEntries { 83struct 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
145Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { 145Image& 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
155Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { 160Image& 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
170Image* 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 &image; 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 d61e656b7..8d3d962c7 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -255,7 +255,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
255 break; 255 break;
256 } 256 }
257 case OpCode::Id::TLDS: { 257 case OpCode::Id::TLDS: {
258 const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; 258 const TextureType texture_type{instr.tlds.GetTextureType()};
259 const bool is_array{instr.tlds.IsArrayTexture()}; 259 const bool is_array{instr.tlds.IsArrayTexture()};
260 260
261 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), 261 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI),
@@ -286,77 +286,80 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
286 std::optional<SamplerInfo> sampler_info) { 286 std::optional<SamplerInfo> sampler_info) {
287 const auto offset = static_cast<u32>(sampler.index.Value()); 287 const auto offset = static_cast<u32>(sampler.index.Value());
288 288
289 Tegra::Shader::TextureType type; 289 TextureType type;
290 bool is_array; 290 bool is_array;
291 bool is_shadow; 291 bool is_shadow;
292 if (sampler_info) { 292 if (sampler_info) {
293 type = sampler_info->type; 293 type = sampler_info->type;
294 is_array = sampler_info->is_array; 294 is_array = sampler_info->is_array;
295 is_shadow = sampler_info->is_shadow; 295 is_shadow = sampler_info->is_shadow;
296 } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) { 296 } else if (const auto sampler = locker.ObtainBoundSampler(offset)) {
297 type = sampler->texture_type.Value(); 297 type = sampler->texture_type.Value();
298 is_array = sampler->is_array.Value() != 0; 298 is_array = sampler->is_array.Value() != 0;
299 is_shadow = sampler->is_shadow.Value() != 0; 299 is_shadow = sampler->is_shadow.Value() != 0;
300 } else { 300 } else {
301 type = Tegra::Shader::TextureType::Texture2D; 301 LOG_WARNING(HW_GPU, "Unknown sampler info");
302 type = TextureType::Texture2D;
302 is_array = false; 303 is_array = false;
303 is_shadow = false; 304 is_shadow = false;
304 } 305 }
305 306
306 // If this sampler has already been used, return the existing mapping. 307 // If this sampler has already been used, return the existing mapping.
307 const auto itr = 308 const auto it =
308 std::find_if(used_samplers.begin(), used_samplers.end(), 309 std::find_if(used_samplers.begin(), used_samplers.end(),
309 [&](const Sampler& entry) { return entry.GetOffset() == offset; }); 310 [offset](const Sampler& entry) { return entry.GetOffset() == offset; });
310 if (itr != used_samplers.end()) { 311 if (it != used_samplers.end()) {
311 ASSERT(itr->GetType() == type && itr->IsArray() == is_array && 312 ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
312 itr->IsShadow() == is_shadow); 313 it->IsShadow() == is_shadow);
313 return *itr; 314 return *it;
314 } 315 }
315 316
316 // Otherwise create a new mapping for this sampler 317 // Otherwise create a new mapping for this sampler
317 const std::size_t next_index = used_samplers.size(); 318 const auto next_index = static_cast<u32>(used_samplers.size());
318 const Sampler entry{offset, next_index, type, is_array, is_shadow}; 319 return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow));
319 return *used_samplers.emplace(entry).first; 320}
320} // namespace VideoCommon::Shader
321 321
322const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, 322const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
323 std::optional<SamplerInfo> sampler_info) { 323 std::optional<SamplerInfo> sampler_info) {
324 const Node sampler_register = GetRegister(reg); 324 const Node sampler_register = GetRegister(reg);
325 const auto [base_sampler, cbuf_index, cbuf_offset] = 325 const auto [base_sampler, buffer, offset] =
326 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 326 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
327 ASSERT(base_sampler != nullptr); 327 ASSERT(base_sampler != nullptr);
328 const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); 328
329 Tegra::Shader::TextureType type; 329 TextureType type;
330 bool is_array; 330 bool is_array;
331 bool is_shadow; 331 bool is_shadow;
332 if (sampler_info) { 332 if (sampler_info) {
333 type = sampler_info->type; 333 type = sampler_info->type;
334 is_array = sampler_info->is_array; 334 is_array = sampler_info->is_array;
335 is_shadow = sampler_info->is_shadow; 335 is_shadow = sampler_info->is_shadow;
336 } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) { 336 } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) {
337 type = sampler->texture_type.Value(); 337 type = sampler->texture_type.Value();
338 is_array = sampler->is_array.Value() != 0; 338 is_array = sampler->is_array.Value() != 0;
339 is_shadow = sampler->is_shadow.Value() != 0; 339 is_shadow = sampler->is_shadow.Value() != 0;
340 } else { 340 } else {
341 type = Tegra::Shader::TextureType::Texture2D; 341 LOG_WARNING(HW_GPU, "Unknown sampler info");
342 type = TextureType::Texture2D;
342 is_array = false; 343 is_array = false;
343 is_shadow = false; 344 is_shadow = false;
344 } 345 }
345 346
346 // If this sampler has already been used, return the existing mapping. 347 // If this sampler has already been used, return the existing mapping.
347 const auto itr = 348 const auto it =
348 std::find_if(used_samplers.begin(), used_samplers.end(), 349 std::find_if(used_samplers.begin(), used_samplers.end(),
349 [&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; }); 350 [buffer = buffer, offset = offset](const Sampler& entry) {
350 if (itr != used_samplers.end()) { 351 return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
351 ASSERT(itr->GetType() == type && itr->IsArray() == is_array && 352 });
352 itr->IsShadow() == is_shadow); 353 if (it != used_samplers.end()) {
353 return *itr; 354 ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
355 it->IsShadow() == is_shadow);
356 return *it;
354 } 357 }
355 358
356 // Otherwise create a new mapping for this sampler 359 // Otherwise create a new mapping for this sampler
357 const std::size_t next_index = used_samplers.size(); 360 const auto next_index = static_cast<u32>(used_samplers.size());
358 const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow}; 361 return used_samplers.emplace_back(
359 return *used_samplers.emplace(entry).first; 362 Sampler(next_index, offset, buffer, type, is_array, is_shadow));
360} 363}
361 364
362void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { 365void 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>;
230class Sampler { 230class Sampler {
231public: 231public:
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
284private: 271private:
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
295class Image final { 282class Image final {
296public: 283public:
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
361private: 338private:
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 1fd44bde1..5243644e8 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
134union TextureHandle { 134union 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;