diff options
Diffstat (limited to 'src')
17 files changed, 333 insertions, 148 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index d01633628..b738e00cc 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -130,8 +130,8 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin | |||
| 130 | DefineSharedMemory(program); | 130 | DefineSharedMemory(program); |
| 131 | DefineConstantBuffers(program.info, binding); | 131 | DefineConstantBuffers(program.info, binding); |
| 132 | DefineStorageBuffers(program.info, binding); | 132 | DefineStorageBuffers(program.info, binding); |
| 133 | DefineTextures(program.info, binding); | ||
| 134 | DefineTextureBuffers(program.info, binding); | 133 | DefineTextureBuffers(program.info, binding); |
| 134 | DefineTextures(program.info, binding); | ||
| 135 | DefineAttributeMemAccess(program.info); | 135 | DefineAttributeMemAccess(program.info); |
| 136 | DefineLabels(program); | 136 | DefineLabels(program); |
| 137 | } | 137 | } |
| @@ -516,6 +516,32 @@ void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { | |||
| 516 | } | 516 | } |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { | ||
| 520 | if (info.texture_buffer_descriptors.empty()) { | ||
| 521 | return; | ||
| 522 | } | ||
| 523 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | ||
| 524 | image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); | ||
| 525 | sampled_texture_buffer_type = TypeSampledImage(image_buffer_type); | ||
| 526 | |||
| 527 | const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)}; | ||
| 528 | texture_buffers.reserve(info.texture_buffer_descriptors.size()); | ||
| 529 | for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { | ||
| 530 | if (desc.count != 1) { | ||
| 531 | throw NotImplementedException("Array of texture buffers"); | ||
| 532 | } | ||
| 533 | const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; | ||
| 534 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 535 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 536 | Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 537 | texture_buffers.insert(texture_buffers.end(), desc.count, id); | ||
| 538 | if (profile.supported_spirv >= 0x00010400) { | ||
| 539 | interfaces.push_back(id); | ||
| 540 | } | ||
| 541 | binding += desc.count; | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 519 | void EmitContext::DefineTextures(const Info& info, u32& binding) { | 545 | void EmitContext::DefineTextures(const Info& info, u32& binding) { |
| 520 | textures.reserve(info.texture_descriptors.size()); | 546 | textures.reserve(info.texture_descriptors.size()); |
| 521 | for (const TextureDescriptor& desc : info.texture_descriptors) { | 547 | for (const TextureDescriptor& desc : info.texture_descriptors) { |
| @@ -544,32 +570,6 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) { | |||
| 544 | } | 570 | } |
| 545 | } | 571 | } |
| 546 | 572 | ||
| 547 | void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { | ||
| 548 | if (info.texture_buffer_descriptors.empty()) { | ||
| 549 | return; | ||
| 550 | } | ||
| 551 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | ||
| 552 | image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); | ||
| 553 | sampled_texture_buffer_type = TypeSampledImage(image_buffer_type); | ||
| 554 | |||
| 555 | const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)}; | ||
| 556 | texture_buffers.reserve(info.texture_buffer_descriptors.size()); | ||
| 557 | for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { | ||
| 558 | if (desc.count != 1) { | ||
| 559 | throw NotImplementedException("Array of texture buffers"); | ||
| 560 | } | ||
| 561 | const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; | ||
| 562 | Decorate(id, spv::Decoration::Binding, binding); | ||
| 563 | Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||
| 564 | Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset)); | ||
| 565 | texture_buffers.insert(texture_buffers.end(), desc.count, id); | ||
| 566 | if (profile.supported_spirv >= 0x00010400) { | ||
| 567 | interfaces.push_back(id); | ||
| 568 | } | ||
| 569 | binding += desc.count; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | void EmitContext::DefineLabels(IR::Program& program) { | 573 | void EmitContext::DefineLabels(IR::Program& program) { |
| 574 | for (IR::Block* const block : program.blocks) { | 574 | for (IR::Block* const block : program.blocks) { |
| 575 | block->SetDefinition(OpLabel()); | 575 | block->SetDefinition(OpLabel()); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 2a10e94e5..f1ac4430c 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -154,8 +154,8 @@ private: | |||
| 154 | void DefineSharedMemory(const IR::Program& program); | 154 | void DefineSharedMemory(const IR::Program& program); |
| 155 | void DefineConstantBuffers(const Info& info, u32& binding); | 155 | void DefineConstantBuffers(const Info& info, u32& binding); |
| 156 | void DefineStorageBuffers(const Info& info, u32& binding); | 156 | void DefineStorageBuffers(const Info& info, u32& binding); |
| 157 | void DefineTextures(const Info& info, u32& binding); | ||
| 158 | void DefineTextureBuffers(const Info& info, u32& binding); | 157 | void DefineTextureBuffers(const Info& info, u32& binding); |
| 158 | void DefineTextures(const Info& info, u32& binding); | ||
| 159 | void DefineAttributeMemAccess(const Info& info); | 159 | void DefineAttributeMemAccess(const Info& info); |
| 160 | void DefineLabels(IR::Program& program); | 160 | void DefineLabels(IR::Program& program); |
| 161 | 161 | ||
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index e6f0de8d8..4cc731198 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -119,8 +119,8 @@ struct Info { | |||
| 119 | boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS> | 119 | boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS> |
| 120 | constant_buffer_descriptors; | 120 | constant_buffer_descriptors; |
| 121 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; | 121 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; |
| 122 | TextureDescriptors texture_descriptors; | ||
| 123 | TextureBufferDescriptors texture_buffer_descriptors; | 122 | TextureBufferDescriptors texture_buffer_descriptors; |
| 123 | TextureDescriptors texture_descriptors; | ||
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | } // namespace Shader | 126 | } // namespace Shader |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 7373cb62d..6701aab82 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "video_core/engines/maxwell_3d.h" | 31 | #include "video_core/engines/maxwell_3d.h" |
| 32 | #include "video_core/memory_manager.h" | 32 | #include "video_core/memory_manager.h" |
| 33 | #include "video_core/rasterizer_interface.h" | 33 | #include "video_core/rasterizer_interface.h" |
| 34 | #include "video_core/surface.h" | ||
| 34 | #include "video_core/texture_cache/slot_vector.h" | 35 | #include "video_core/texture_cache/slot_vector.h" |
| 35 | #include "video_core/texture_cache/types.h" | 36 | #include "video_core/texture_cache/types.h" |
| 36 | 37 | ||
| @@ -42,11 +43,14 @@ MICROPROFILE_DECLARE(GPU_DownloadMemory); | |||
| 42 | 43 | ||
| 43 | using BufferId = SlotId; | 44 | using BufferId = SlotId; |
| 44 | 45 | ||
| 46 | using VideoCore::Surface::PixelFormat; | ||
| 47 | |||
| 45 | constexpr u32 NUM_VERTEX_BUFFERS = 32; | 48 | constexpr u32 NUM_VERTEX_BUFFERS = 32; |
| 46 | constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4; | 49 | constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4; |
| 47 | constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; | 50 | constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; |
| 48 | constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; | 51 | constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; |
| 49 | constexpr u32 NUM_STORAGE_BUFFERS = 16; | 52 | constexpr u32 NUM_STORAGE_BUFFERS = 16; |
| 53 | constexpr u32 NUM_TEXTURE_BUFFERS = 16; | ||
| 50 | constexpr u32 NUM_STAGES = 5; | 54 | constexpr u32 NUM_STAGES = 5; |
| 51 | 55 | ||
| 52 | using namespace Common::Literals; | 56 | using namespace Common::Literals; |
| @@ -66,6 +70,7 @@ class BufferCache { | |||
| 66 | P::HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT; | 70 | P::HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT; |
| 67 | static constexpr bool NEEDS_BIND_UNIFORM_INDEX = P::NEEDS_BIND_UNIFORM_INDEX; | 71 | static constexpr bool NEEDS_BIND_UNIFORM_INDEX = P::NEEDS_BIND_UNIFORM_INDEX; |
| 68 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = P::NEEDS_BIND_STORAGE_INDEX; | 72 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = P::NEEDS_BIND_STORAGE_INDEX; |
| 73 | static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = P::NEEDS_BIND_TEXTURE_BUFFER_INDEX; | ||
| 69 | static constexpr bool USE_MEMORY_MAPS = P::USE_MEMORY_MAPS; | 74 | static constexpr bool USE_MEMORY_MAPS = P::USE_MEMORY_MAPS; |
| 70 | 75 | ||
| 71 | static constexpr BufferId NULL_BUFFER_ID{0}; | 76 | static constexpr BufferId NULL_BUFFER_ID{0}; |
| @@ -96,6 +101,10 @@ class BufferCache { | |||
| 96 | BufferId buffer_id; | 101 | BufferId buffer_id; |
| 97 | }; | 102 | }; |
| 98 | 103 | ||
| 104 | struct TextureBufferBinding : Binding { | ||
| 105 | PixelFormat format; | ||
| 106 | }; | ||
| 107 | |||
| 99 | static constexpr Binding NULL_BINDING{ | 108 | static constexpr Binding NULL_BINDING{ |
| 100 | .cpu_addr = 0, | 109 | .cpu_addr = 0, |
| 101 | .size = 0, | 110 | .size = 0, |
| @@ -142,11 +151,21 @@ public: | |||
| 142 | void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, | 151 | void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, |
| 143 | bool is_written); | 152 | bool is_written); |
| 144 | 153 | ||
| 154 | void UnbindGraphicsTextureBuffers(size_t stage); | ||
| 155 | |||
| 156 | void BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, u32 size, | ||
| 157 | PixelFormat format); | ||
| 158 | |||
| 145 | void UnbindComputeStorageBuffers(); | 159 | void UnbindComputeStorageBuffers(); |
| 146 | 160 | ||
| 147 | void BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, | 161 | void BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, |
| 148 | bool is_written); | 162 | bool is_written); |
| 149 | 163 | ||
| 164 | void UnbindComputeTextureBuffers(); | ||
| 165 | |||
| 166 | void BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, | ||
| 167 | PixelFormat format); | ||
| 168 | |||
| 150 | void FlushCachedWrites(); | 169 | void FlushCachedWrites(); |
| 151 | 170 | ||
| 152 | /// Return true when there are uncommitted buffers to be downloaded | 171 | /// Return true when there are uncommitted buffers to be downloaded |
| @@ -254,12 +273,16 @@ private: | |||
| 254 | 273 | ||
| 255 | void BindHostGraphicsStorageBuffers(size_t stage); | 274 | void BindHostGraphicsStorageBuffers(size_t stage); |
| 256 | 275 | ||
| 276 | void BindHostGraphicsTextureBuffers(size_t stage); | ||
| 277 | |||
| 257 | void BindHostTransformFeedbackBuffers(); | 278 | void BindHostTransformFeedbackBuffers(); |
| 258 | 279 | ||
| 259 | void BindHostComputeUniformBuffers(); | 280 | void BindHostComputeUniformBuffers(); |
| 260 | 281 | ||
| 261 | void BindHostComputeStorageBuffers(); | 282 | void BindHostComputeStorageBuffers(); |
| 262 | 283 | ||
| 284 | void BindHostComputeTextureBuffers(); | ||
| 285 | |||
| 263 | void DoUpdateGraphicsBuffers(bool is_indexed); | 286 | void DoUpdateGraphicsBuffers(bool is_indexed); |
| 264 | 287 | ||
| 265 | void DoUpdateComputeBuffers(); | 288 | void DoUpdateComputeBuffers(); |
| @@ -274,6 +297,8 @@ private: | |||
| 274 | 297 | ||
| 275 | void UpdateStorageBuffers(size_t stage); | 298 | void UpdateStorageBuffers(size_t stage); |
| 276 | 299 | ||
| 300 | void UpdateTextureBuffers(size_t stage); | ||
| 301 | |||
| 277 | void UpdateTransformFeedbackBuffers(); | 302 | void UpdateTransformFeedbackBuffers(); |
| 278 | 303 | ||
| 279 | void UpdateTransformFeedbackBuffer(u32 index); | 304 | void UpdateTransformFeedbackBuffer(u32 index); |
| @@ -282,6 +307,8 @@ private: | |||
| 282 | 307 | ||
| 283 | void UpdateComputeStorageBuffers(); | 308 | void UpdateComputeStorageBuffers(); |
| 284 | 309 | ||
| 310 | void UpdateComputeTextureBuffers(); | ||
| 311 | |||
| 285 | void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size); | 312 | void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size); |
| 286 | 313 | ||
| 287 | [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); | 314 | [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); |
| @@ -323,6 +350,9 @@ private: | |||
| 323 | 350 | ||
| 324 | [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const; | 351 | [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const; |
| 325 | 352 | ||
| 353 | [[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, | ||
| 354 | PixelFormat format); | ||
| 355 | |||
| 326 | [[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size); | 356 | [[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size); |
| 327 | 357 | ||
| 328 | [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity); | 358 | [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity); |
| @@ -347,10 +377,12 @@ private: | |||
| 347 | std::array<Binding, NUM_VERTEX_BUFFERS> vertex_buffers; | 377 | std::array<Binding, NUM_VERTEX_BUFFERS> vertex_buffers; |
| 348 | std::array<std::array<Binding, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES> uniform_buffers; | 378 | std::array<std::array<Binding, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES> uniform_buffers; |
| 349 | std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers; | 379 | std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers; |
| 380 | std::array<std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS>, NUM_STAGES> texture_buffers; | ||
| 350 | std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers; | 381 | std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers; |
| 351 | 382 | ||
| 352 | std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers; | 383 | std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers; |
| 353 | std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers; | 384 | std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers; |
| 385 | std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS> compute_texture_buffers; | ||
| 354 | 386 | ||
| 355 | std::array<u32, NUM_STAGES> enabled_uniform_buffers{}; | 387 | std::array<u32, NUM_STAGES> enabled_uniform_buffers{}; |
| 356 | u32 enabled_compute_uniform_buffers = 0; | 388 | u32 enabled_compute_uniform_buffers = 0; |
| @@ -360,6 +392,9 @@ private: | |||
| 360 | u32 enabled_compute_storage_buffers = 0; | 392 | u32 enabled_compute_storage_buffers = 0; |
| 361 | u32 written_compute_storage_buffers = 0; | 393 | u32 written_compute_storage_buffers = 0; |
| 362 | 394 | ||
| 395 | std::array<u32, NUM_STAGES> enabled_texture_buffers{}; | ||
| 396 | u32 enabled_compute_texture_buffers = 0; | ||
| 397 | |||
| 363 | std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{}; | 398 | std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{}; |
| 364 | 399 | ||
| 365 | std::array<u32, 16> uniform_cache_hits{}; | 400 | std::array<u32, 16> uniform_cache_hits{}; |
| @@ -619,6 +654,7 @@ void BufferCache<P>::BindHostStageBuffers(size_t stage) { | |||
| 619 | MICROPROFILE_SCOPE(GPU_BindUploadBuffers); | 654 | MICROPROFILE_SCOPE(GPU_BindUploadBuffers); |
| 620 | BindHostGraphicsUniformBuffers(stage); | 655 | BindHostGraphicsUniformBuffers(stage); |
| 621 | BindHostGraphicsStorageBuffers(stage); | 656 | BindHostGraphicsStorageBuffers(stage); |
| 657 | BindHostGraphicsTextureBuffers(stage); | ||
| 622 | } | 658 | } |
| 623 | 659 | ||
| 624 | template <class P> | 660 | template <class P> |
| @@ -626,6 +662,7 @@ void BufferCache<P>::BindHostComputeBuffers() { | |||
| 626 | MICROPROFILE_SCOPE(GPU_BindUploadBuffers); | 662 | MICROPROFILE_SCOPE(GPU_BindUploadBuffers); |
| 627 | BindHostComputeUniformBuffers(); | 663 | BindHostComputeUniformBuffers(); |
| 628 | BindHostComputeStorageBuffers(); | 664 | BindHostComputeStorageBuffers(); |
| 665 | BindHostComputeTextureBuffers(); | ||
| 629 | } | 666 | } |
| 630 | 667 | ||
| 631 | template <class P> | 668 | template <class P> |
| @@ -661,6 +698,18 @@ void BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, | |||
| 661 | } | 698 | } |
| 662 | 699 | ||
| 663 | template <class P> | 700 | template <class P> |
| 701 | void BufferCache<P>::UnbindGraphicsTextureBuffers(size_t stage) { | ||
| 702 | enabled_texture_buffers[stage] = 0; | ||
| 703 | } | ||
| 704 | |||
| 705 | template <class P> | ||
| 706 | void BufferCache<P>::BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, | ||
| 707 | u32 size, PixelFormat format) { | ||
| 708 | enabled_texture_buffers[stage] |= 1U << tbo_index; | ||
| 709 | texture_buffers[stage][tbo_index] = GetTextureBufferBinding(gpu_addr, size, format); | ||
| 710 | } | ||
| 711 | |||
| 712 | template <class P> | ||
| 664 | void BufferCache<P>::UnbindComputeStorageBuffers() { | 713 | void BufferCache<P>::UnbindComputeStorageBuffers() { |
| 665 | enabled_compute_storage_buffers = 0; | 714 | enabled_compute_storage_buffers = 0; |
| 666 | written_compute_storage_buffers = 0; | 715 | written_compute_storage_buffers = 0; |
| @@ -681,6 +730,18 @@ void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, | |||
| 681 | } | 730 | } |
| 682 | 731 | ||
| 683 | template <class P> | 732 | template <class P> |
| 733 | void BufferCache<P>::UnbindComputeTextureBuffers() { | ||
| 734 | enabled_compute_texture_buffers = 0; | ||
| 735 | } | ||
| 736 | |||
| 737 | template <class P> | ||
| 738 | void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, | ||
| 739 | PixelFormat format) { | ||
| 740 | enabled_compute_texture_buffers |= 1U << tbo_index; | ||
| 741 | compute_texture_buffers[tbo_index] = GetTextureBufferBinding(gpu_addr, size, format); | ||
| 742 | } | ||
| 743 | |||
| 744 | template <class P> | ||
| 684 | void BufferCache<P>::FlushCachedWrites() { | 745 | void BufferCache<P>::FlushCachedWrites() { |
| 685 | for (const BufferId buffer_id : cached_write_buffer_ids) { | 746 | for (const BufferId buffer_id : cached_write_buffer_ids) { |
| 686 | slot_buffers[buffer_id].FlushCachedWrites(); | 747 | slot_buffers[buffer_id].FlushCachedWrites(); |
| @@ -989,6 +1050,26 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) { | |||
| 989 | } | 1050 | } |
| 990 | 1051 | ||
| 991 | template <class P> | 1052 | template <class P> |
| 1053 | void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) { | ||
| 1054 | u32 binding_index = 0; | ||
| 1055 | ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) { | ||
| 1056 | const TextureBufferBinding& binding = texture_buffers[stage][index]; | ||
| 1057 | Buffer& buffer = slot_buffers[binding.buffer_id]; | ||
| 1058 | const u32 size = binding.size; | ||
| 1059 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | ||
| 1060 | |||
| 1061 | const u32 offset = buffer.Offset(binding.cpu_addr); | ||
| 1062 | const PixelFormat format = binding.format; | ||
| 1063 | if constexpr (NEEDS_BIND_TEXTURE_BUFFER_INDEX) { | ||
| 1064 | runtime.BindTextureBuffer(binding_index, buffer, offset, size, format); | ||
| 1065 | ++binding_index; | ||
| 1066 | } else { | ||
| 1067 | runtime.BindTextureBuffer(buffer, offset, size, format); | ||
| 1068 | } | ||
| 1069 | }); | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | template <class P> | ||
| 992 | void BufferCache<P>::BindHostTransformFeedbackBuffers() { | 1073 | void BufferCache<P>::BindHostTransformFeedbackBuffers() { |
| 993 | if (maxwell3d.regs.tfb_enabled == 0) { | 1074 | if (maxwell3d.regs.tfb_enabled == 0) { |
| 994 | return; | 1075 | return; |
| @@ -1051,6 +1132,26 @@ void BufferCache<P>::BindHostComputeStorageBuffers() { | |||
| 1051 | } | 1132 | } |
| 1052 | 1133 | ||
| 1053 | template <class P> | 1134 | template <class P> |
| 1135 | void BufferCache<P>::BindHostComputeTextureBuffers() { | ||
| 1136 | u32 binding_index = 0; | ||
| 1137 | ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) { | ||
| 1138 | const TextureBufferBinding& binding = compute_texture_buffers[index]; | ||
| 1139 | Buffer& buffer = slot_buffers[binding.buffer_id]; | ||
| 1140 | const u32 size = binding.size; | ||
| 1141 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | ||
| 1142 | |||
| 1143 | const u32 offset = buffer.Offset(binding.cpu_addr); | ||
| 1144 | const PixelFormat format = binding.format; | ||
| 1145 | if constexpr (NEEDS_BIND_TEXTURE_BUFFER_INDEX) { | ||
| 1146 | runtime.BindTextureBuffer(binding_index, buffer, offset, size, format); | ||
| 1147 | ++binding_index; | ||
| 1148 | } else { | ||
| 1149 | runtime.BindTextureBuffer(buffer, offset, size, format); | ||
| 1150 | } | ||
| 1151 | }); | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | template <class P> | ||
| 1054 | void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { | 1155 | void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { |
| 1055 | if (is_indexed) { | 1156 | if (is_indexed) { |
| 1056 | UpdateIndexBuffer(); | 1157 | UpdateIndexBuffer(); |
| @@ -1060,6 +1161,7 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { | |||
| 1060 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { | 1161 | for (size_t stage = 0; stage < NUM_STAGES; ++stage) { |
| 1061 | UpdateUniformBuffers(stage); | 1162 | UpdateUniformBuffers(stage); |
| 1062 | UpdateStorageBuffers(stage); | 1163 | UpdateStorageBuffers(stage); |
| 1164 | UpdateTextureBuffers(stage); | ||
| 1063 | } | 1165 | } |
| 1064 | } | 1166 | } |
| 1065 | 1167 | ||
| @@ -1067,6 +1169,7 @@ template <class P> | |||
| 1067 | void BufferCache<P>::DoUpdateComputeBuffers() { | 1169 | void BufferCache<P>::DoUpdateComputeBuffers() { |
| 1068 | UpdateComputeUniformBuffers(); | 1170 | UpdateComputeUniformBuffers(); |
| 1069 | UpdateComputeStorageBuffers(); | 1171 | UpdateComputeStorageBuffers(); |
| 1172 | UpdateComputeTextureBuffers(); | ||
| 1070 | } | 1173 | } |
| 1071 | 1174 | ||
| 1072 | template <class P> | 1175 | template <class P> |
| @@ -1167,6 +1270,14 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) { | |||
| 1167 | } | 1270 | } |
| 1168 | 1271 | ||
| 1169 | template <class P> | 1272 | template <class P> |
| 1273 | void BufferCache<P>::UpdateTextureBuffers(size_t stage) { | ||
| 1274 | ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) { | ||
| 1275 | Binding& binding = texture_buffers[stage][index]; | ||
| 1276 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | ||
| 1277 | }); | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | template <class P> | ||
| 1170 | void BufferCache<P>::UpdateTransformFeedbackBuffers() { | 1281 | void BufferCache<P>::UpdateTransformFeedbackBuffers() { |
| 1171 | if (maxwell3d.regs.tfb_enabled == 0) { | 1282 | if (maxwell3d.regs.tfb_enabled == 0) { |
| 1172 | return; | 1283 | return; |
| @@ -1228,6 +1339,14 @@ void BufferCache<P>::UpdateComputeStorageBuffers() { | |||
| 1228 | } | 1339 | } |
| 1229 | 1340 | ||
| 1230 | template <class P> | 1341 | template <class P> |
| 1342 | void BufferCache<P>::UpdateComputeTextureBuffers() { | ||
| 1343 | ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) { | ||
| 1344 | Binding& binding = compute_texture_buffers[index]; | ||
| 1345 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | ||
| 1346 | }); | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | template <class P> | ||
| 1231 | void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) { | 1350 | void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) { |
| 1232 | Buffer& buffer = slot_buffers[buffer_id]; | 1351 | Buffer& buffer = slot_buffers[buffer_id]; |
| 1233 | buffer.MarkRegionAsGpuModified(cpu_addr, size); | 1352 | buffer.MarkRegionAsGpuModified(cpu_addr, size); |
| @@ -1582,6 +1701,25 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s | |||
| 1582 | } | 1701 | } |
| 1583 | 1702 | ||
| 1584 | template <class P> | 1703 | template <class P> |
| 1704 | typename BufferCache<P>::TextureBufferBinding BufferCache<P>::GetTextureBufferBinding( | ||
| 1705 | GPUVAddr gpu_addr, u32 size, PixelFormat format) { | ||
| 1706 | const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); | ||
| 1707 | TextureBufferBinding binding; | ||
| 1708 | if (!cpu_addr || size == 0) { | ||
| 1709 | binding.cpu_addr = 0; | ||
| 1710 | binding.size = 0; | ||
| 1711 | binding.buffer_id = NULL_BUFFER_ID; | ||
| 1712 | binding.format = PixelFormat::Invalid; | ||
| 1713 | } else { | ||
| 1714 | binding.cpu_addr = *cpu_addr; | ||
| 1715 | binding.size = size; | ||
| 1716 | binding.buffer_id = BufferId{}; | ||
| 1717 | binding.format = format; | ||
| 1718 | } | ||
| 1719 | return binding; | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | template <class P> | ||
| 1585 | std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) { | 1723 | std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) { |
| 1586 | u8* const base_pointer = cpu_memory.GetPointer(cpu_addr); | 1724 | u8* const base_pointer = cpu_memory.GetPointer(cpu_addr); |
| 1587 | if (IsRangeGranular(cpu_addr, size) || | 1725 | if (IsRangeGranular(cpu_addr, size) || |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index fe91aa452..ddcce5e97 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -155,6 +155,7 @@ struct BufferCacheParams { | |||
| 155 | static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true; | 155 | static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true; |
| 156 | static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true; | 156 | static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true; |
| 157 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = true; | 157 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = true; |
| 158 | static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = true; | ||
| 158 | static constexpr bool USE_MEMORY_MAPS = false; | 159 | static constexpr bool USE_MEMORY_MAPS = false; |
| 159 | }; | 160 | }; |
| 160 | 161 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index ff0f03e99..a8bf84218 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -1016,6 +1016,10 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 1016 | default_handle = Handle(info.type); | 1016 | default_handle = Handle(info.type); |
| 1017 | } | 1017 | } |
| 1018 | 1018 | ||
| 1019 | ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||
| 1020 | const VideoCommon::ImageViewInfo& view_info) | ||
| 1021 | : VideoCommon::ImageViewBase{info, view_info} {} | ||
| 1022 | |||
| 1019 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) | 1023 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) |
| 1020 | : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} | 1024 | : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} |
| 1021 | 1025 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index cf3b789e3..817b0e650 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -182,6 +182,8 @@ class ImageView : public VideoCommon::ImageViewBase { | |||
| 182 | 182 | ||
| 183 | public: | 183 | public: |
| 184 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); | 184 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); |
| 185 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||
| 186 | const VideoCommon::ImageViewInfo& view_info); | ||
| 185 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); | 187 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); |
| 186 | 188 | ||
| 187 | [[nodiscard]] GLuint Handle(ImageViewType query_type) const noexcept { | 189 | [[nodiscard]] GLuint Handle(ImageViewType query_type) const noexcept { |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index decf0d32c..cff93cc60 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -24,7 +24,8 @@ struct TextureHandle { | |||
| 24 | [[likely]] if (via_header_index) { | 24 | [[likely]] if (via_header_index) { |
| 25 | image = data; | 25 | image = data; |
| 26 | sampler = data; | 26 | sampler = data; |
| 27 | } else { | 27 | } |
| 28 | else { | ||
| 28 | const Tegra::Texture::TextureHandle handle{data}; | 29 | const Tegra::Texture::TextureHandle handle{data}; |
| 29 | image = handle.tic_id; | 30 | image = handle.tic_id; |
| 30 | sampler = via_header_index ? image : handle.tsc_id.Value(); | 31 | sampler = via_header_index ? image : handle.tsc_id.Value(); |
| @@ -90,12 +91,12 @@ public: | |||
| 90 | for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { | 91 | for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { |
| 91 | Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage); | 92 | Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage); |
| 92 | } | 93 | } |
| 94 | for ([[maybe_unused]] const auto& desc : info.texture_buffer_descriptors) { | ||
| 95 | Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage); | ||
| 96 | } | ||
| 93 | for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { | 97 | for ([[maybe_unused]] const auto& desc : info.texture_descriptors) { |
| 94 | Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); | 98 | Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage); |
| 95 | } | 99 | } |
| 96 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 97 | Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage); | ||
| 98 | } | ||
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | private: | 102 | private: |
| @@ -156,20 +157,15 @@ inline VideoCommon::ImageViewType CastType(Shader::TextureType type) { | |||
| 156 | return {}; | 157 | return {}; |
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | inline void PushImageDescriptors(const Shader::Info& info, const VkSampler* samplers, | 160 | inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers, |
| 160 | const ImageId* image_view_ids, TextureCache& texture_cache, | 161 | const ImageId*& image_view_ids, TextureCache& texture_cache, |
| 161 | VKUpdateDescriptorQueue& update_descriptor_queue, size_t& index) { | 162 | VKUpdateDescriptorQueue& update_descriptor_queue) { |
| 163 | image_view_ids += info.texture_buffer_descriptors.size(); | ||
| 162 | for (const auto& desc : info.texture_descriptors) { | 164 | for (const auto& desc : info.texture_descriptors) { |
| 163 | const VkSampler sampler{samplers[index]}; | 165 | const VkSampler sampler{*(samplers++)}; |
| 164 | ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; | 166 | ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))}; |
| 165 | const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))}; | 167 | const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))}; |
| 166 | update_descriptor_queue.AddSampledImage(vk_image_view, sampler); | 168 | update_descriptor_queue.AddSampledImage(vk_image_view, sampler); |
| 167 | ++index; | ||
| 168 | } | ||
| 169 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 170 | ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])}; | ||
| 171 | update_descriptor_queue.AddTexelBuffer(image_view.BufferView()); | ||
| 172 | ++index; | ||
| 173 | } | 169 | } |
| 174 | } | 170 | } |
| 175 | 171 | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 0def1e769..cdda56ab1 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -67,25 +67,50 @@ Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params) | |||
| 67 | 67 | ||
| 68 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, | 68 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, |
| 69 | VAddr cpu_addr_, u64 size_bytes_) | 69 | VAddr cpu_addr_, u64 size_bytes_) |
| 70 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) { | 70 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_), |
| 71 | buffer = runtime.device.GetLogical().CreateBuffer(VkBufferCreateInfo{ | 71 | device{&runtime.device}, |
| 72 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 72 | buffer{device->GetLogical().CreateBuffer({ |
| 73 | .pNext = nullptr, | 73 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 74 | .flags = 0, | 74 | .pNext = nullptr, |
| 75 | .size = SizeBytes(), | 75 | .flags = 0, |
| 76 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | 76 | .size = SizeBytes(), |
| 77 | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | | 77 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | |
| 78 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | | 78 | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | |
| 79 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | | 79 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | |
| 80 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, | 80 | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | |
| 81 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 81 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, |
| 82 | .queueFamilyIndexCount = 0, | 82 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 83 | .pQueueFamilyIndices = nullptr, | 83 | .queueFamilyIndexCount = 0, |
| 84 | }); | 84 | .pQueueFamilyIndices = nullptr, |
| 85 | })}, | ||
| 86 | commit{runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal)} { | ||
| 85 | if (runtime.device.HasDebuggingToolAttached()) { | 87 | if (runtime.device.HasDebuggingToolAttached()) { |
| 86 | buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); | 88 | buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); |
| 87 | } | 89 | } |
| 88 | commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); | 90 | } |
| 91 | |||
| 92 | VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format) { | ||
| 93 | const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) { | ||
| 94 | return offset == view.offset && size == view.size && format == view.format; | ||
| 95 | })}; | ||
| 96 | if (it != views.end()) { | ||
| 97 | return *it->handle; | ||
| 98 | } | ||
| 99 | views.push_back({ | ||
| 100 | .offset = offset, | ||
| 101 | .size = size, | ||
| 102 | .format = format, | ||
| 103 | .handle = device->GetLogical().CreateBufferView({ | ||
| 104 | .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, | ||
| 105 | .pNext = nullptr, | ||
| 106 | .flags = 0, | ||
| 107 | .buffer = *buffer, | ||
| 108 | .format = MaxwellToVK::SurfaceFormat(*device, FormatType::Buffer, false, format).format, | ||
| 109 | .offset = offset, | ||
| 110 | .range = size, | ||
| 111 | }), | ||
| 112 | }); | ||
| 113 | return *views.back().handle; | ||
| 89 | } | 114 | } |
| 90 | 115 | ||
| 91 | BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, | 116 | BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 3bb81d5b3..ea17406dc 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "video_core/renderer_vulkan/vk_compute_pass.h" | 9 | #include "video_core/renderer_vulkan/vk_compute_pass.h" |
| 10 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 10 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| 11 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 11 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 12 | #include "video_core/surface.h" | ||
| 12 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 13 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 14 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 14 | 15 | ||
| @@ -26,6 +27,8 @@ public: | |||
| 26 | explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, | 27 | explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, |
| 27 | VAddr cpu_addr_, u64 size_bytes_); | 28 | VAddr cpu_addr_, u64 size_bytes_); |
| 28 | 29 | ||
| 30 | [[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format); | ||
| 31 | |||
| 29 | [[nodiscard]] VkBuffer Handle() const noexcept { | 32 | [[nodiscard]] VkBuffer Handle() const noexcept { |
| 30 | return *buffer; | 33 | return *buffer; |
| 31 | } | 34 | } |
| @@ -35,8 +38,17 @@ public: | |||
| 35 | } | 38 | } |
| 36 | 39 | ||
| 37 | private: | 40 | private: |
| 41 | struct BufferView { | ||
| 42 | u32 offset; | ||
| 43 | u32 size; | ||
| 44 | VideoCore::Surface::PixelFormat format; | ||
| 45 | vk::BufferView handle; | ||
| 46 | }; | ||
| 47 | |||
| 48 | const Device* device{}; | ||
| 38 | vk::Buffer buffer; | 49 | vk::Buffer buffer; |
| 39 | MemoryCommit commit; | 50 | MemoryCommit commit; |
| 51 | std::vector<BufferView> views; | ||
| 40 | }; | 52 | }; |
| 41 | 53 | ||
| 42 | class BufferCacheRuntime { | 54 | class BufferCacheRuntime { |
| @@ -87,6 +99,11 @@ public: | |||
| 87 | BindBuffer(buffer, offset, size); | 99 | BindBuffer(buffer, offset, size); |
| 88 | } | 100 | } |
| 89 | 101 | ||
| 102 | void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, | ||
| 103 | VideoCore::Surface::PixelFormat format) { | ||
| 104 | update_descriptor_queue.AddTexelBuffer(buffer.View(offset, size, format)); | ||
| 105 | } | ||
| 106 | |||
| 90 | private: | 107 | private: |
| 91 | void BindBuffer(VkBuffer buffer, u32 offset, u32 size) { | 108 | void BindBuffer(VkBuffer buffer, u32 offset, u32 size) { |
| 92 | update_descriptor_queue.AddBuffer(buffer, offset, size); | 109 | update_descriptor_queue.AddBuffer(buffer, offset, size); |
| @@ -123,6 +140,7 @@ struct BufferCacheParams { | |||
| 123 | static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false; | 140 | static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false; |
| 124 | static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false; | 141 | static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false; |
| 125 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = false; | 142 | static constexpr bool NEEDS_BIND_STORAGE_INDEX = false; |
| 143 | static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = false; | ||
| 126 | static constexpr bool USE_MEMORY_MAPS = true; | 144 | static constexpr bool USE_MEMORY_MAPS = true; |
| 127 | }; | 145 | }; |
| 128 | 146 | ||
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 9922cbd0f..ac47b1f3c 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -80,8 +80,6 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 80 | desc.is_written); | 80 | desc.is_written); |
| 81 | ++ssbo_index; | 81 | ++ssbo_index; |
| 82 | } | 82 | } |
| 83 | buffer_cache.UpdateComputeBuffers(); | ||
| 84 | buffer_cache.BindHostComputeBuffers(); | ||
| 85 | 83 | ||
| 86 | texture_cache.SynchronizeComputeDescriptors(); | 84 | texture_cache.SynchronizeComputeDescriptors(); |
| 87 | 85 | ||
| @@ -99,6 +97,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 99 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; | 97 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; |
| 100 | return TextureHandle(raw_handle, via_header_index); | 98 | return TextureHandle(raw_handle, via_header_index); |
| 101 | }}; | 99 | }}; |
| 100 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 101 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 102 | image_view_indices.push_back(handle.image); | ||
| 103 | } | ||
| 102 | for (const auto& desc : info.texture_descriptors) { | 104 | for (const auto& desc : info.texture_descriptors) { |
| 103 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | 105 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; |
| 104 | image_view_indices.push_back(handle.image); | 106 | image_view_indices.push_back(handle.image); |
| @@ -106,16 +108,26 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 106 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); | 108 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler); |
| 107 | samplers.push_back(sampler->Handle()); | 109 | samplers.push_back(sampler->Handle()); |
| 108 | } | 110 | } |
| 109 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 110 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 111 | image_view_indices.push_back(handle.image); | ||
| 112 | } | ||
| 113 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | 111 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); |
| 114 | texture_cache.FillComputeImageViews(indices_span, image_view_ids); | 112 | texture_cache.FillComputeImageViews(indices_span, image_view_ids); |
| 115 | 113 | ||
| 116 | size_t image_index{}; | 114 | buffer_cache.UnbindComputeTextureBuffers(); |
| 117 | PushImageDescriptors(info, samplers.data(), image_view_ids.data(), texture_cache, | 115 | ImageId* texture_buffer_ids{image_view_ids.data()}; |
| 118 | update_descriptor_queue, image_index); | 116 | size_t index{}; |
| 117 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 118 | ASSERT(desc.count == 1); | ||
| 119 | ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids); | ||
| 120 | buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), image_view.BufferSize(), | ||
| 121 | image_view.format); | ||
| 122 | ++texture_buffer_ids; | ||
| 123 | ++index; | ||
| 124 | } | ||
| 125 | buffer_cache.UpdateComputeBuffers(); | ||
| 126 | buffer_cache.BindHostComputeBuffers(); | ||
| 127 | |||
| 128 | const VkSampler* samplers_it{samplers.data()}; | ||
| 129 | const ImageId* views_it{image_view_ids.data()}; | ||
| 130 | PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue); | ||
| 119 | 131 | ||
| 120 | if (!is_built.load(std::memory_order::relaxed)) { | 132 | if (!is_built.load(std::memory_order::relaxed)) { |
| 121 | // Wait for the pipeline to be built | 133 | // Wait for the pipeline to be built |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index afdd8b371..893258b4a 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -175,6 +175,10 @@ void GraphicsPipeline::Configure(bool is_indexed) { | |||
| 175 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; | 175 | const u32 raw_handle{gpu_memory.Read<u32>(addr)}; |
| 176 | return TextureHandle(raw_handle, via_header_index); | 176 | return TextureHandle(raw_handle, via_header_index); |
| 177 | }}; | 177 | }}; |
| 178 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 179 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | ||
| 180 | image_view_indices.push_back(handle.image); | ||
| 181 | } | ||
| 178 | for (const auto& desc : info.texture_descriptors) { | 182 | for (const auto& desc : info.texture_descriptors) { |
| 179 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | 183 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; |
| 180 | image_view_indices.push_back(handle.image); | 184 | image_view_indices.push_back(handle.image); |
| @@ -182,24 +186,37 @@ void GraphicsPipeline::Configure(bool is_indexed) { | |||
| 182 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; | 186 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)}; |
| 183 | samplers.push_back(sampler->Handle()); | 187 | samplers.push_back(sampler->Handle()); |
| 184 | } | 188 | } |
| 189 | } | ||
| 190 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | ||
| 191 | texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); | ||
| 192 | |||
| 193 | ImageId* texture_buffer_index{image_view_ids.data()}; | ||
| 194 | for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { | ||
| 195 | const Shader::Info& info{stage_infos[stage]}; | ||
| 196 | buffer_cache.UnbindGraphicsTextureBuffers(stage); | ||
| 197 | size_t index{}; | ||
| 185 | for (const auto& desc : info.texture_buffer_descriptors) { | 198 | for (const auto& desc : info.texture_buffer_descriptors) { |
| 186 | const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)}; | 199 | ASSERT(desc.count == 1); |
| 187 | image_view_indices.push_back(handle.image); | 200 | ImageView& image_view = texture_cache.GetImageView(*texture_buffer_index); |
| 201 | buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(), | ||
| 202 | image_view.BufferSize(), image_view.format); | ||
| 203 | ++index; | ||
| 204 | ++texture_buffer_index; | ||
| 188 | } | 205 | } |
| 206 | texture_buffer_index += info.texture_descriptors.size(); | ||
| 189 | } | 207 | } |
| 190 | const std::span indices_span(image_view_indices.data(), image_view_indices.size()); | ||
| 191 | buffer_cache.UpdateGraphicsBuffers(is_indexed); | 208 | buffer_cache.UpdateGraphicsBuffers(is_indexed); |
| 192 | texture_cache.FillGraphicsImageViews(indices_span, image_view_ids); | ||
| 193 | 209 | ||
| 194 | buffer_cache.BindHostGeometryBuffers(is_indexed); | 210 | buffer_cache.BindHostGeometryBuffers(is_indexed); |
| 195 | 211 | ||
| 196 | update_descriptor_queue.Acquire(); | 212 | update_descriptor_queue.Acquire(); |
| 197 | 213 | ||
| 198 | size_t index{}; | 214 | const VkSampler* samplers_it{samplers.data()}; |
| 215 | const ImageId* views_it{image_view_ids.data()}; | ||
| 199 | for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { | 216 | for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { |
| 200 | buffer_cache.BindHostStageBuffers(stage); | 217 | buffer_cache.BindHostStageBuffers(stage); |
| 201 | PushImageDescriptors(stage_infos[stage], samplers.data(), image_view_ids.data(), | 218 | PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache, |
| 202 | texture_cache, update_descriptor_queue, index); | 219 | update_descriptor_queue); |
| 203 | } | 220 | } |
| 204 | texture_cache.UpdateRenderTargets(false); | 221 | texture_cache.UpdateRenderTargets(false); |
| 205 | scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); | 222 | scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 1bbc542a1..e42b091c5 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -15,10 +15,10 @@ | |||
| 15 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 15 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| 16 | #include "video_core/renderer_vulkan/vk_compute_pass.h" | 16 | #include "video_core/renderer_vulkan/vk_compute_pass.h" |
| 17 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | 17 | #include "video_core/renderer_vulkan/vk_rasterizer.h" |
| 18 | #include "video_core/renderer_vulkan/vk_render_pass_cache.h" | ||
| 18 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 19 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 19 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 20 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| 20 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 21 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 21 | #include "video_core/renderer_vulkan/vk_render_pass_cache.h" | ||
| 22 | #include "video_core/vulkan_common/vulkan_device.h" | 22 | #include "video_core/vulkan_common/vulkan_device.h" |
| 23 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 23 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 24 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 24 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| @@ -162,25 +162,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 162 | return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info)); | 162 | return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info)); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | [[nodiscard]] vk::Buffer MakeBuffer(const Device& device, const ImageInfo& info) { | ||
| 166 | if (info.type != ImageType::Buffer) { | ||
| 167 | return vk::Buffer{}; | ||
| 168 | } | ||
| 169 | const size_t bytes_per_block = VideoCore::Surface::BytesPerBlock(info.format); | ||
| 170 | return device.GetLogical().CreateBuffer(VkBufferCreateInfo{ | ||
| 171 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
| 172 | .pNext = nullptr, | ||
| 173 | .flags = 0, | ||
| 174 | .size = info.size.width * bytes_per_block, | ||
| 175 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | ||
| 176 | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | | ||
| 177 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, | ||
| 178 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 179 | .queueFamilyIndexCount = 0, | ||
| 180 | .pQueueFamilyIndices = nullptr, | ||
| 181 | }); | ||
| 182 | } | ||
| 183 | |||
| 184 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { | 165 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { |
| 185 | switch (VideoCore::Surface::GetFormatType(format)) { | 166 | switch (VideoCore::Surface::GetFormatType(format)) { |
| 186 | case VideoCore::Surface::SurfaceType::ColorTexture: | 167 | case VideoCore::Surface::SurfaceType::ColorTexture: |
| @@ -813,13 +794,9 @@ u64 TextureCacheRuntime::GetDeviceLocalMemory() const { | |||
| 813 | Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_, | 794 | Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_, |
| 814 | VAddr cpu_addr_) | 795 | VAddr cpu_addr_) |
| 815 | : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler}, | 796 | : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler}, |
| 816 | image(MakeImage(runtime.device, info)), buffer(MakeBuffer(runtime.device, info)), | 797 | image(MakeImage(runtime.device, info)), |
| 798 | commit(runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal)), | ||
| 817 | aspect_mask(ImageAspectMask(info.format)) { | 799 | aspect_mask(ImageAspectMask(info.format)) { |
| 818 | if (image) { | ||
| 819 | commit = runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal); | ||
| 820 | } else { | ||
| 821 | commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); | ||
| 822 | } | ||
| 823 | if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { | 800 | if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) { |
| 824 | if (Settings::values.accelerate_astc.GetValue()) { | 801 | if (Settings::values.accelerate_astc.GetValue()) { |
| 825 | flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; | 802 | flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; |
| @@ -828,11 +805,7 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_ | |||
| 828 | } | 805 | } |
| 829 | } | 806 | } |
| 830 | if (runtime.device.HasDebuggingToolAttached()) { | 807 | if (runtime.device.HasDebuggingToolAttached()) { |
| 831 | if (image) { | 808 | image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); |
| 832 | image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); | ||
| 833 | } else { | ||
| 834 | buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); | ||
| 835 | } | ||
| 836 | } | 809 | } |
| 837 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ | 810 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ |
| 838 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | 811 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, |
| @@ -884,19 +857,6 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag | |||
| 884 | }); | 857 | }); |
| 885 | } | 858 | } |
| 886 | 859 | ||
| 887 | void Image::UploadMemory(const StagingBufferRef& map, | ||
| 888 | std::span<const VideoCommon::BufferCopy> copies) { | ||
| 889 | // TODO: Move this to another API | ||
| 890 | scheduler->RequestOutsideRenderPassOperationContext(); | ||
| 891 | std::vector vk_copies = TransformBufferCopies(copies, map.offset); | ||
| 892 | const VkBuffer src_buffer = map.buffer; | ||
| 893 | const VkBuffer dst_buffer = *buffer; | ||
| 894 | scheduler->Record([src_buffer, dst_buffer, vk_copies](vk::CommandBuffer cmdbuf) { | ||
| 895 | // TODO: Barriers | ||
| 896 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies); | ||
| 897 | }); | ||
| 898 | } | ||
| 899 | |||
| 900 | void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { | 860 | void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) { |
| 901 | std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); | 861 | std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask); |
| 902 | scheduler->RequestOutsideRenderPassOperationContext(); | 862 | scheduler->RequestOutsideRenderPassOperationContext(); |
| @@ -1032,19 +992,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 1032 | UNIMPLEMENTED(); | 992 | UNIMPLEMENTED(); |
| 1033 | break; | 993 | break; |
| 1034 | case VideoCommon::ImageViewType::Buffer: | 994 | case VideoCommon::ImageViewType::Buffer: |
| 1035 | buffer_view = device->GetLogical().CreateBufferView(VkBufferViewCreateInfo{ | 995 | UNREACHABLE(); |
| 1036 | .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, | ||
| 1037 | .pNext = nullptr, | ||
| 1038 | .flags = 0, | ||
| 1039 | .buffer = image.Buffer(), | ||
| 1040 | .format = format_info.format, | ||
| 1041 | .offset = 0, // TODO: Redesign buffer cache to support this | ||
| 1042 | .range = image.guest_size_bytes, | ||
| 1043 | }); | ||
| 1044 | break; | 996 | break; |
| 1045 | } | 997 | } |
| 1046 | } | 998 | } |
| 1047 | 999 | ||
| 1000 | ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | ||
| 1001 | const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_) | ||
| 1002 | : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_}, | ||
| 1003 | buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {} | ||
| 1004 | |||
| 1048 | ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params) | 1005 | ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params) |
| 1049 | : VideoCommon::ImageViewBase{params} {} | 1006 | : VideoCommon::ImageViewBase{params} {} |
| 1050 | 1007 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 189ee5a68..498e76a1c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -41,9 +41,9 @@ struct TextureCacheRuntime { | |||
| 41 | 41 | ||
| 42 | void Finish(); | 42 | void Finish(); |
| 43 | 43 | ||
| 44 | [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size); | 44 | StagingBufferRef UploadStagingBuffer(size_t size); |
| 45 | 45 | ||
| 46 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); | 46 | StagingBufferRef DownloadStagingBuffer(size_t size); |
| 47 | 47 | ||
| 48 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 48 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 49 | const Region2D& dst_region, const Region2D& src_region, | 49 | const Region2D& dst_region, const Region2D& src_region, |
| @@ -54,7 +54,7 @@ struct TextureCacheRuntime { | |||
| 54 | 54 | ||
| 55 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view); | 55 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view); |
| 56 | 56 | ||
| 57 | [[nodiscard]] bool CanAccelerateImageUpload(Image&) const noexcept { | 57 | bool CanAccelerateImageUpload(Image&) const noexcept { |
| 58 | return false; | 58 | return false; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| @@ -92,8 +92,6 @@ public: | |||
| 92 | void UploadMemory(const StagingBufferRef& map, | 92 | void UploadMemory(const StagingBufferRef& map, |
| 93 | std::span<const VideoCommon::BufferImageCopy> copies); | 93 | std::span<const VideoCommon::BufferImageCopy> copies); |
| 94 | 94 | ||
| 95 | void UploadMemory(const StagingBufferRef& map, std::span<const VideoCommon::BufferCopy> copies); | ||
| 96 | |||
| 97 | void DownloadMemory(const StagingBufferRef& map, | 95 | void DownloadMemory(const StagingBufferRef& map, |
| 98 | std::span<const VideoCommon::BufferImageCopy> copies); | 96 | std::span<const VideoCommon::BufferImageCopy> copies); |
| 99 | 97 | ||
| @@ -101,10 +99,6 @@ public: | |||
| 101 | return *image; | 99 | return *image; |
| 102 | } | 100 | } |
| 103 | 101 | ||
| 104 | [[nodiscard]] VkBuffer Buffer() const noexcept { | ||
| 105 | return *buffer; | ||
| 106 | } | ||
| 107 | |||
| 108 | [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept { | 102 | [[nodiscard]] VkImageAspectFlags AspectMask() const noexcept { |
| 109 | return aspect_mask; | 103 | return aspect_mask; |
| 110 | } | 104 | } |
| @@ -121,7 +115,6 @@ public: | |||
| 121 | private: | 115 | private: |
| 122 | VKScheduler* scheduler; | 116 | VKScheduler* scheduler; |
| 123 | vk::Image image; | 117 | vk::Image image; |
| 124 | vk::Buffer buffer; | ||
| 125 | MemoryCommit commit; | 118 | MemoryCommit commit; |
| 126 | vk::ImageView image_view; | 119 | vk::ImageView image_view; |
| 127 | std::vector<vk::ImageView> storage_image_views; | 120 | std::vector<vk::ImageView> storage_image_views; |
| @@ -132,6 +125,8 @@ private: | |||
| 132 | class ImageView : public VideoCommon::ImageViewBase { | 125 | class ImageView : public VideoCommon::ImageViewBase { |
| 133 | public: | 126 | public: |
| 134 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); | 127 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); |
| 128 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, | ||
| 129 | const VideoCommon::ImageViewInfo&, GPUVAddr); | ||
| 135 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); | 130 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); |
| 136 | 131 | ||
| 137 | [[nodiscard]] VkImageView DepthView(); | 132 | [[nodiscard]] VkImageView DepthView(); |
| @@ -142,10 +137,6 @@ public: | |||
| 142 | return *image_views[static_cast<size_t>(query_type)]; | 137 | return *image_views[static_cast<size_t>(query_type)]; |
| 143 | } | 138 | } |
| 144 | 139 | ||
| 145 | [[nodiscard]] VkBufferView BufferView() const noexcept { | ||
| 146 | return *buffer_view; | ||
| 147 | } | ||
| 148 | |||
| 149 | [[nodiscard]] VkImage ImageHandle() const noexcept { | 140 | [[nodiscard]] VkImage ImageHandle() const noexcept { |
| 150 | return image_handle; | 141 | return image_handle; |
| 151 | } | 142 | } |
| @@ -162,6 +153,14 @@ public: | |||
| 162 | return samples; | 153 | return samples; |
| 163 | } | 154 | } |
| 164 | 155 | ||
| 156 | [[nodiscard]] GPUVAddr GpuAddr() const noexcept { | ||
| 157 | return gpu_addr; | ||
| 158 | } | ||
| 159 | |||
| 160 | [[nodiscard]] u32 BufferSize() const noexcept { | ||
| 161 | return buffer_size; | ||
| 162 | } | ||
| 163 | |||
| 165 | private: | 164 | private: |
| 166 | [[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask); | 165 | [[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask); |
| 167 | 166 | ||
| @@ -169,11 +168,12 @@ private: | |||
| 169 | std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views; | 168 | std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views; |
| 170 | vk::ImageView depth_view; | 169 | vk::ImageView depth_view; |
| 171 | vk::ImageView stencil_view; | 170 | vk::ImageView stencil_view; |
| 172 | vk::BufferView buffer_view; | ||
| 173 | VkImage image_handle = VK_NULL_HANDLE; | 171 | VkImage image_handle = VK_NULL_HANDLE; |
| 174 | VkImageView render_target = VK_NULL_HANDLE; | 172 | VkImageView render_target = VK_NULL_HANDLE; |
| 175 | PixelFormat image_format = PixelFormat::Invalid; | 173 | PixelFormat image_format = PixelFormat::Invalid; |
| 176 | VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; | 174 | VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; |
| 175 | GPUVAddr gpu_addr = 0; | ||
| 176 | u32 buffer_size = 0; | ||
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | class ImageAlloc : public VideoCommon::ImageAllocBase {}; | 179 | class ImageAlloc : public VideoCommon::ImageAllocBase {}; |
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index e8d632f9e..450becbeb 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp | |||
| @@ -36,6 +36,15 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i | |||
| 36 | } | 36 | } |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info) | ||
| 40 | : format{info.format}, type{ImageViewType::Buffer}, size{ | ||
| 41 | .width = info.size.width, | ||
| 42 | .height = 1, | ||
| 43 | .depth = 1, | ||
| 44 | } { | ||
| 45 | ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer"); | ||
| 46 | } | ||
| 47 | |||
| 39 | ImageViewBase::ImageViewBase(const NullImageParams&) {} | 48 | ImageViewBase::ImageViewBase(const NullImageParams&) {} |
| 40 | 49 | ||
| 41 | } // namespace VideoCommon | 50 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/image_view_base.h b/src/video_core/texture_cache/image_view_base.h index 73954167e..903f715c5 100644 --- a/src/video_core/texture_cache/image_view_base.h +++ b/src/video_core/texture_cache/image_view_base.h | |||
| @@ -27,6 +27,7 @@ DECLARE_ENUM_FLAG_OPERATORS(ImageViewFlagBits) | |||
| 27 | struct ImageViewBase { | 27 | struct ImageViewBase { |
| 28 | explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info, | 28 | explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info, |
| 29 | ImageId image_id); | 29 | ImageId image_id); |
| 30 | explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info); | ||
| 30 | explicit ImageViewBase(const NullImageParams&); | 31 | explicit ImageViewBase(const NullImageParams&); |
| 31 | 32 | ||
| 32 | [[nodiscard]] bool IsBuffer() const noexcept { | 33 | [[nodiscard]] bool IsBuffer() const noexcept { |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 85ce06d56..5e8d99482 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -968,9 +968,6 @@ void TextureCache<P>::UploadImageContents(Image& image, StagingBuffer& staging) | |||
| 968 | auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, unswizzled_data); | 968 | auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, unswizzled_data); |
| 969 | ConvertImage(unswizzled_data, image.info, mapped_span, copies); | 969 | ConvertImage(unswizzled_data, image.info, mapped_span, copies); |
| 970 | image.UploadMemory(staging, copies); | 970 | image.UploadMemory(staging, copies); |
| 971 | } else if (image.info.type == ImageType::Buffer) { | ||
| 972 | const std::array copies{UploadBufferCopy(gpu_memory, gpu_addr, image, mapped_span)}; | ||
| 973 | image.UploadMemory(staging, copies); | ||
| 974 | } else { | 971 | } else { |
| 975 | const auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, mapped_span); | 972 | const auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, mapped_span); |
| 976 | image.UploadMemory(staging, copies); | 973 | image.UploadMemory(staging, copies); |
| @@ -993,7 +990,12 @@ ImageViewId TextureCache<P>::FindImageView(const TICEntry& config) { | |||
| 993 | template <class P> | 990 | template <class P> |
| 994 | ImageViewId TextureCache<P>::CreateImageView(const TICEntry& config) { | 991 | ImageViewId TextureCache<P>::CreateImageView(const TICEntry& config) { |
| 995 | const ImageInfo info(config); | 992 | const ImageInfo info(config); |
| 996 | const GPUVAddr image_gpu_addr = config.Address() - config.BaseLayer() * info.layer_stride; | 993 | if (info.type == ImageType::Buffer) { |
| 994 | const ImageViewInfo view_info(config, 0); | ||
| 995 | return slot_image_views.insert(runtime, info, view_info, config.Address()); | ||
| 996 | } | ||
| 997 | const u32 layer_offset = config.BaseLayer() * info.layer_stride; | ||
| 998 | const GPUVAddr image_gpu_addr = config.Address() - layer_offset; | ||
| 997 | const ImageId image_id = FindOrInsertImage(info, image_gpu_addr); | 999 | const ImageId image_id = FindOrInsertImage(info, image_gpu_addr); |
| 998 | if (!image_id) { | 1000 | if (!image_id) { |
| 999 | return NULL_IMAGE_VIEW_ID; | 1001 | return NULL_IMAGE_VIEW_ID; |
| @@ -1801,6 +1803,9 @@ void TextureCache<P>::PrepareImageView(ImageViewId image_view_id, bool is_modifi | |||
| 1801 | return; | 1803 | return; |
| 1802 | } | 1804 | } |
| 1803 | const ImageViewBase& image_view = slot_image_views[image_view_id]; | 1805 | const ImageViewBase& image_view = slot_image_views[image_view_id]; |
| 1806 | if (image_view.IsBuffer()) { | ||
| 1807 | return; | ||
| 1808 | } | ||
| 1804 | PrepareImage(image_view.image_id, is_modification, invalidate); | 1809 | PrepareImage(image_view.image_id, is_modification, invalidate); |
| 1805 | } | 1810 | } |
| 1806 | 1811 | ||