diff options
Diffstat (limited to 'src/video_core/renderer_vulkan')
22 files changed, 541 insertions, 429 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 568744e3c..424278816 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -71,8 +71,7 @@ void FixedPipelineState::Rasterizer::Fill(const Maxwell& regs) noexcept { | |||
| 71 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); | 71 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); |
| 72 | 72 | ||
| 73 | u32 packed_front_face = PackFrontFace(regs.front_face); | 73 | u32 packed_front_face = PackFrontFace(regs.front_face); |
| 74 | if (regs.screen_y_control.triangle_rast_flip != 0 && | 74 | if (regs.screen_y_control.triangle_rast_flip != 0) { |
| 75 | regs.viewport_transform[0].scale_y > 0.0f) { | ||
| 76 | // Flip front face | 75 | // Flip front face |
| 77 | packed_front_face = 1 - packed_front_face; | 76 | packed_front_face = 1 - packed_front_face; |
| 78 | } | 77 | } |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 2871035f5..1f2b6734b 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -21,29 +21,29 @@ namespace Sampler { | |||
| 21 | 21 | ||
| 22 | VkFilter Filter(Tegra::Texture::TextureFilter filter) { | 22 | VkFilter Filter(Tegra::Texture::TextureFilter filter) { |
| 23 | switch (filter) { | 23 | switch (filter) { |
| 24 | case Tegra::Texture::TextureFilter::Linear: | ||
| 25 | return VK_FILTER_LINEAR; | ||
| 26 | case Tegra::Texture::TextureFilter::Nearest: | 24 | case Tegra::Texture::TextureFilter::Nearest: |
| 27 | return VK_FILTER_NEAREST; | 25 | return VK_FILTER_NEAREST; |
| 26 | case Tegra::Texture::TextureFilter::Linear: | ||
| 27 | return VK_FILTER_LINEAR; | ||
| 28 | } | 28 | } |
| 29 | UNIMPLEMENTED_MSG("Unimplemented sampler filter={}", static_cast<u32>(filter)); | 29 | UNREACHABLE_MSG("Invalid sampler filter={}", static_cast<u32>(filter)); |
| 30 | return {}; | 30 | return {}; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | VkSamplerMipmapMode MipmapMode(Tegra::Texture::TextureMipmapFilter mipmap_filter) { | 33 | VkSamplerMipmapMode MipmapMode(Tegra::Texture::TextureMipmapFilter mipmap_filter) { |
| 34 | switch (mipmap_filter) { | 34 | switch (mipmap_filter) { |
| 35 | case Tegra::Texture::TextureMipmapFilter::None: | 35 | case Tegra::Texture::TextureMipmapFilter::None: |
| 36 | // TODO(Rodrigo): None seems to be mapped to OpenGL's mag and min filters without mipmapping | 36 | // There are no Vulkan filter modes that directly correspond to OpenGL minification filters |
| 37 | // (e.g. GL_NEAREST and GL_LINEAR). Vulkan doesn't have such a thing, find out if we have to | 37 | // of GL_LINEAR or GL_NEAREST, but they can be emulated using |
| 38 | // use an image view with a single mipmap level to emulate this. | 38 | // VK_SAMPLER_MIPMAP_MODE_NEAREST, minLod = 0, and maxLod = 0.25, and using minFilter = |
| 39 | return VK_SAMPLER_MIPMAP_MODE_LINEAR; | 39 | // VK_FILTER_LINEAR or minFilter = VK_FILTER_NEAREST, respectively. |
| 40 | ; | 40 | return VK_SAMPLER_MIPMAP_MODE_NEAREST; |
| 41 | case Tegra::Texture::TextureMipmapFilter::Linear: | ||
| 42 | return VK_SAMPLER_MIPMAP_MODE_LINEAR; | ||
| 43 | case Tegra::Texture::TextureMipmapFilter::Nearest: | 41 | case Tegra::Texture::TextureMipmapFilter::Nearest: |
| 44 | return VK_SAMPLER_MIPMAP_MODE_NEAREST; | 42 | return VK_SAMPLER_MIPMAP_MODE_NEAREST; |
| 43 | case Tegra::Texture::TextureMipmapFilter::Linear: | ||
| 44 | return VK_SAMPLER_MIPMAP_MODE_LINEAR; | ||
| 45 | } | 45 | } |
| 46 | UNIMPLEMENTED_MSG("Unimplemented sampler mipmap mode={}", static_cast<u32>(mipmap_filter)); | 46 | UNREACHABLE_MSG("Invalid sampler mipmap mode={}", static_cast<u32>(mipmap_filter)); |
| 47 | return {}; | 47 | return {}; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| @@ -78,10 +78,9 @@ VkSamplerAddressMode WrapMode(const VKDevice& device, Tegra::Texture::WrapMode w | |||
| 78 | case Tegra::Texture::WrapMode::MirrorOnceBorder: | 78 | case Tegra::Texture::WrapMode::MirrorOnceBorder: |
| 79 | UNIMPLEMENTED(); | 79 | UNIMPLEMENTED(); |
| 80 | return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; | 80 | return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; |
| 81 | default: | ||
| 82 | UNIMPLEMENTED_MSG("Unimplemented wrap mode={}", static_cast<u32>(wrap_mode)); | ||
| 83 | return {}; | ||
| 84 | } | 81 | } |
| 82 | UNIMPLEMENTED_MSG("Unimplemented wrap mode={}", static_cast<u32>(wrap_mode)); | ||
| 83 | return {}; | ||
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | VkCompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compare_func) { | 86 | VkCompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compare_func) { |
| @@ -149,7 +148,7 @@ struct FormatTuple { | |||
| 149 | {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16F | 148 | {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16F |
| 150 | {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16U | 149 | {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16U |
| 151 | {VK_FORMAT_UNDEFINED}, // R16S | 150 | {VK_FORMAT_UNDEFINED}, // R16S |
| 152 | {VK_FORMAT_UNDEFINED}, // R16UI | 151 | {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16UI |
| 153 | {VK_FORMAT_UNDEFINED}, // R16I | 152 | {VK_FORMAT_UNDEFINED}, // R16I |
| 154 | {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // RG16 | 153 | {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // RG16 |
| 155 | {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // RG16F | 154 | {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // RG16F |
| @@ -288,10 +287,9 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const VKDevice& device, | |||
| 288 | return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; | 287 | return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; |
| 289 | case Maxwell::PrimitiveTopology::Patches: | 288 | case Maxwell::PrimitiveTopology::Patches: |
| 290 | return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; | 289 | return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; |
| 291 | default: | ||
| 292 | UNIMPLEMENTED_MSG("Unimplemented topology={}", static_cast<u32>(topology)); | ||
| 293 | return {}; | ||
| 294 | } | 290 | } |
| 291 | UNIMPLEMENTED_MSG("Unimplemented topology={}", static_cast<u32>(topology)); | ||
| 292 | return {}; | ||
| 295 | } | 293 | } |
| 296 | 294 | ||
| 297 | VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttribute::Size size) { | 295 | VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttribute::Size size) { |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 59b441943..cd9673d1f 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| 14 | 14 | ||
| 15 | #include "common/dynamic_library.h" | 15 | #include "common/dynamic_library.h" |
| 16 | #include "common/file_util.h" | ||
| 16 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 17 | #include "common/telemetry.h" | 18 | #include "common/telemetry.h" |
| 18 | #include "core/core.h" | 19 | #include "core/core.h" |
| @@ -76,7 +77,8 @@ Common::DynamicLibrary OpenVulkanLibrary() { | |||
| 76 | char* libvulkan_env = getenv("LIBVULKAN_PATH"); | 77 | char* libvulkan_env = getenv("LIBVULKAN_PATH"); |
| 77 | if (!libvulkan_env || !library.Open(libvulkan_env)) { | 78 | if (!libvulkan_env || !library.Open(libvulkan_env)) { |
| 78 | // Use the libvulkan.dylib from the application bundle. | 79 | // Use the libvulkan.dylib from the application bundle. |
| 79 | std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; | 80 | const std::string filename = |
| 81 | FileUtil::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; | ||
| 80 | library.Open(filename.c_str()); | 82 | library.Open(filename.c_str()); |
| 81 | } | 83 | } |
| 82 | #else | 84 | #else |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 5f33d9e40..f10f96cd8 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -37,9 +37,9 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch | |||
| 37 | 37 | ||
| 38 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 39 | 39 | ||
| 40 | CachedBufferBlock::CachedBufferBlock(const VKDevice& device, VKMemoryManager& memory_manager, | 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, |
| 41 | VAddr cpu_addr, std::size_t size) | 41 | VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) |
| 42 | : VideoCommon::BufferBlock{cpu_addr, size} { | 42 | : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { |
| 43 | VkBufferCreateInfo ci; | 43 | VkBufferCreateInfo ci; |
| 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| 45 | ci.pNext = nullptr; | 45 | ci.pNext = nullptr; |
| @@ -54,46 +54,17 @@ CachedBufferBlock::CachedBufferBlock(const VKDevice& device, VKMemoryManager& me | |||
| 54 | buffer.commit = memory_manager.Commit(buffer.handle, false); | 54 | buffer.commit = memory_manager.Commit(buffer.handle, false); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | CachedBufferBlock::~CachedBufferBlock() = default; | 57 | Buffer::~Buffer() = default; |
| 58 | 58 | ||
| 59 | VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | 59 | void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { |
| 60 | const VKDevice& device, VKMemoryManager& memory_manager, | ||
| 61 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||
| 62 | : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||
| 63 | CreateStreamBuffer(device, | ||
| 64 | scheduler)}, | ||
| 65 | device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||
| 66 | staging_pool} {} | ||
| 67 | |||
| 68 | VKBufferCache::~VKBufferCache() = default; | ||
| 69 | |||
| 70 | Buffer VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||
| 71 | return std::make_shared<CachedBufferBlock>(device, memory_manager, cpu_addr, size); | ||
| 72 | } | ||
| 73 | |||
| 74 | VkBuffer VKBufferCache::ToHandle(const Buffer& buffer) { | ||
| 75 | return buffer->GetHandle(); | ||
| 76 | } | ||
| 77 | |||
| 78 | VkBuffer VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||
| 79 | size = std::max(size, std::size_t(4)); | ||
| 80 | const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||
| 81 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 82 | scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||
| 83 | cmdbuf.FillBuffer(buffer, 0, size, 0); | ||
| 84 | }); | ||
| 85 | return *empty.handle; | ||
| 86 | } | ||
| 87 | |||
| 88 | void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 89 | const u8* data) { | ||
| 90 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); | 60 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); |
| 91 | std::memcpy(staging.commit->Map(size), data, size); | 61 | std::memcpy(staging.commit->Map(size), data, size); |
| 92 | 62 | ||
| 93 | scheduler.RequestOutsideRenderPassOperationContext(); | 63 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 94 | scheduler.Record([staging = *staging.handle, buffer = buffer->GetHandle(), offset, | 64 | |
| 95 | size](vk::CommandBuffer cmdbuf) { | 65 | const VkBuffer handle = Handle(); |
| 96 | cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); | 66 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { |
| 67 | cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); | ||
| 97 | 68 | ||
| 98 | VkBufferMemoryBarrier barrier; | 69 | VkBufferMemoryBarrier barrier; |
| 99 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 70 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| @@ -102,7 +73,7 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | |||
| 102 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; | 73 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; |
| 103 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 74 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 104 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 75 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 105 | barrier.buffer = buffer; | 76 | barrier.buffer = handle; |
| 106 | barrier.offset = offset; | 77 | barrier.offset = offset; |
| 107 | barrier.size = size; | 78 | barrier.size = size; |
| 108 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, | 79 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, |
| @@ -110,12 +81,12 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | |||
| 110 | }); | 81 | }); |
| 111 | } | 82 | } |
| 112 | 83 | ||
| 113 | void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | 84 | void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { |
| 114 | u8* data) { | ||
| 115 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); | 85 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); |
| 116 | scheduler.RequestOutsideRenderPassOperationContext(); | 86 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 117 | scheduler.Record([staging = *staging.handle, buffer = buffer->GetHandle(), offset, | 87 | |
| 118 | size](vk::CommandBuffer cmdbuf) { | 88 | const VkBuffer handle = Handle(); |
| 89 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | ||
| 119 | VkBufferMemoryBarrier barrier; | 90 | VkBufferMemoryBarrier barrier; |
| 120 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 91 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| 121 | barrier.pNext = nullptr; | 92 | barrier.pNext = nullptr; |
| @@ -123,7 +94,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | |||
| 123 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; | 94 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| 124 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 95 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 125 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 96 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 126 | barrier.buffer = buffer; | 97 | barrier.buffer = handle; |
| 127 | barrier.offset = offset; | 98 | barrier.offset = offset; |
| 128 | barrier.size = size; | 99 | barrier.size = size; |
| 129 | 100 | ||
| @@ -131,18 +102,20 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | |||
| 131 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | | 102 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | |
| 132 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | 103 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
| 133 | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); | 104 | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); |
| 134 | cmdbuf.CopyBuffer(buffer, staging, VkBufferCopy{offset, 0, size}); | 105 | cmdbuf.CopyBuffer(handle, staging, VkBufferCopy{offset, 0, size}); |
| 135 | }); | 106 | }); |
| 136 | scheduler.Finish(); | 107 | scheduler.Finish(); |
| 137 | 108 | ||
| 138 | std::memcpy(data, staging.commit->Map(size), size); | 109 | std::memcpy(data, staging.commit->Map(size), size); |
| 139 | } | 110 | } |
| 140 | 111 | ||
| 141 | void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | 112 | void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, |
| 142 | std::size_t dst_offset, std::size_t size) { | 113 | std::size_t size) const { |
| 143 | scheduler.RequestOutsideRenderPassOperationContext(); | 114 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 144 | scheduler.Record([src_buffer = src->GetHandle(), dst_buffer = dst->GetHandle(), src_offset, | 115 | |
| 145 | dst_offset, size](vk::CommandBuffer cmdbuf) { | 116 | const VkBuffer dst_buffer = Handle(); |
| 117 | scheduler.Record([src_buffer = src.Handle(), dst_buffer, src_offset, dst_offset, | ||
| 118 | size](vk::CommandBuffer cmdbuf) { | ||
| 146 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); | 119 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); |
| 147 | 120 | ||
| 148 | std::array<VkBufferMemoryBarrier, 2> barriers; | 121 | std::array<VkBufferMemoryBarrier, 2> barriers; |
| @@ -169,4 +142,30 @@ void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t | |||
| 169 | }); | 142 | }); |
| 170 | } | 143 | } |
| 171 | 144 | ||
| 145 | VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | ||
| 146 | const VKDevice& device, VKMemoryManager& memory_manager, | ||
| 147 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||
| 148 | : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||
| 149 | CreateStreamBuffer(device, | ||
| 150 | scheduler)}, | ||
| 151 | device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||
| 152 | staging_pool} {} | ||
| 153 | |||
| 154 | VKBufferCache::~VKBufferCache() = default; | ||
| 155 | |||
| 156 | std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||
| 157 | return std::make_shared<Buffer>(device, memory_manager, scheduler, staging_pool, cpu_addr, | ||
| 158 | size); | ||
| 159 | } | ||
| 160 | |||
| 161 | VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||
| 162 | size = std::max(size, std::size_t(4)); | ||
| 163 | const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||
| 164 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 165 | scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||
| 166 | cmdbuf.FillBuffer(buffer, 0, size, 0); | ||
| 167 | }); | ||
| 168 | return {*empty.handle, 0, 0}; | ||
| 169 | } | ||
| 170 | |||
| 172 | } // namespace Vulkan | 171 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index a54583e7d..3630aca77 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "video_core/buffer_cache/buffer_cache.h" | 10 | #include "video_core/buffer_cache/buffer_cache.h" |
| 11 | #include "video_core/rasterizer_cache.h" | ||
| 12 | #include "video_core/renderer_vulkan/vk_memory_manager.h" | 11 | #include "video_core/renderer_vulkan/vk_memory_manager.h" |
| 13 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" | 12 | #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" |
| 14 | #include "video_core/renderer_vulkan/vk_stream_buffer.h" | 13 | #include "video_core/renderer_vulkan/vk_stream_buffer.h" |
| @@ -24,22 +23,34 @@ class VKDevice; | |||
| 24 | class VKMemoryManager; | 23 | class VKMemoryManager; |
| 25 | class VKScheduler; | 24 | class VKScheduler; |
| 26 | 25 | ||
| 27 | class CachedBufferBlock final : public VideoCommon::BufferBlock { | 26 | class Buffer final : public VideoCommon::BufferBlock { |
| 28 | public: | 27 | public: |
| 29 | explicit CachedBufferBlock(const VKDevice& device, VKMemoryManager& memory_manager, | 28 | explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler, |
| 30 | VAddr cpu_addr, std::size_t size); | 29 | VKStagingBufferPool& staging_pool, VAddr cpu_addr, std::size_t size); |
| 31 | ~CachedBufferBlock(); | 30 | ~Buffer(); |
| 32 | 31 | ||
| 33 | VkBuffer GetHandle() const { | 32 | void Upload(std::size_t offset, std::size_t size, const u8* data) const; |
| 33 | |||
| 34 | void Download(std::size_t offset, std::size_t size, u8* data) const; | ||
| 35 | |||
| 36 | void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 37 | std::size_t size) const; | ||
| 38 | |||
| 39 | VkBuffer Handle() const { | ||
| 34 | return *buffer.handle; | 40 | return *buffer.handle; |
| 35 | } | 41 | } |
| 36 | 42 | ||
| 43 | u64 Address() const { | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 37 | private: | 47 | private: |
| 48 | VKScheduler& scheduler; | ||
| 49 | VKStagingBufferPool& staging_pool; | ||
| 50 | |||
| 38 | VKBuffer buffer; | 51 | VKBuffer buffer; |
| 39 | }; | 52 | }; |
| 40 | 53 | ||
| 41 | using Buffer = std::shared_ptr<CachedBufferBlock>; | ||
| 42 | |||
| 43 | class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> { | 54 | class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> { |
| 44 | public: | 55 | public: |
| 45 | explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | 56 | explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, |
| @@ -47,21 +58,10 @@ public: | |||
| 47 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool); | 58 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool); |
| 48 | ~VKBufferCache(); | 59 | ~VKBufferCache(); |
| 49 | 60 | ||
| 50 | VkBuffer GetEmptyBuffer(std::size_t size) override; | 61 | BufferInfo GetEmptyBuffer(std::size_t size) override; |
| 51 | 62 | ||
| 52 | protected: | 63 | protected: |
| 53 | VkBuffer ToHandle(const Buffer& buffer) override; | 64 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; |
| 54 | |||
| 55 | Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override; | ||
| 56 | |||
| 57 | void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 58 | const u8* data) override; | ||
| 59 | |||
| 60 | void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 61 | u8* data) override; | ||
| 62 | |||
| 63 | void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 64 | std::size_t dst_offset, std::size_t size) override; | ||
| 65 | 65 | ||
| 66 | private: | 66 | private: |
| 67 | const VKDevice& device; | 67 | const VKDevice& device; |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 8e1b46277..281bf9ac3 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -53,8 +53,9 @@ vk::DescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const { | |||
| 53 | }; | 53 | }; |
| 54 | add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size()); | 54 | add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, entries.const_buffers.size()); |
| 55 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, entries.global_buffers.size()); | 55 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, entries.global_buffers.size()); |
| 56 | add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, entries.texel_buffers.size()); | 56 | add_bindings(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, entries.uniform_texels.size()); |
| 57 | add_bindings(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, entries.samplers.size()); | 57 | add_bindings(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, entries.samplers.size()); |
| 58 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, entries.storage_texels.size()); | ||
| 58 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size()); | 59 | add_bindings(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, entries.images.size()); |
| 59 | 60 | ||
| 60 | VkDescriptorSetLayoutCreateInfo ci; | 61 | VkDescriptorSetLayoutCreateInfo ci; |
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 890fd52cf..9259b618d 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp | |||
| @@ -42,6 +42,7 @@ vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() { | |||
| 42 | {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_sets * 60}, | 42 | {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_sets * 60}, |
| 43 | {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, | 43 | {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, |
| 44 | {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, | 44 | {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, |
| 45 | {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64}, | ||
| 45 | {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}}; | 46 | {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}}; |
| 46 | 47 | ||
| 47 | VkDescriptorPoolCreateInfo ci; | 48 | VkDescriptorPoolCreateInfo ci; |
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp index 750e5a0ca..9fd8ac3f6 100644 --- a/src/video_core/renderer_vulkan/vk_device.cpp +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -73,76 +73,79 @@ VkFormatFeatureFlags GetFormatFeatures(VkFormatProperties properties, FormatType | |||
| 73 | 73 | ||
| 74 | std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties( | 74 | std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties( |
| 75 | vk::PhysicalDevice physical, const vk::InstanceDispatch& dld) { | 75 | vk::PhysicalDevice physical, const vk::InstanceDispatch& dld) { |
| 76 | static constexpr std::array formats{VK_FORMAT_A8B8G8R8_UNORM_PACK32, | 76 | static constexpr std::array formats{ |
| 77 | VK_FORMAT_A8B8G8R8_UINT_PACK32, | 77 | VK_FORMAT_A8B8G8R8_UNORM_PACK32, |
| 78 | VK_FORMAT_A8B8G8R8_SNORM_PACK32, | 78 | VK_FORMAT_A8B8G8R8_UINT_PACK32, |
| 79 | VK_FORMAT_A8B8G8R8_SRGB_PACK32, | 79 | VK_FORMAT_A8B8G8R8_SNORM_PACK32, |
| 80 | VK_FORMAT_B5G6R5_UNORM_PACK16, | 80 | VK_FORMAT_A8B8G8R8_SRGB_PACK32, |
| 81 | VK_FORMAT_A2B10G10R10_UNORM_PACK32, | 81 | VK_FORMAT_B5G6R5_UNORM_PACK16, |
| 82 | VK_FORMAT_A1R5G5B5_UNORM_PACK16, | 82 | VK_FORMAT_A2B10G10R10_UNORM_PACK32, |
| 83 | VK_FORMAT_R32G32B32A32_SFLOAT, | 83 | VK_FORMAT_A1R5G5B5_UNORM_PACK16, |
| 84 | VK_FORMAT_R32G32B32A32_UINT, | 84 | VK_FORMAT_R32G32B32A32_SFLOAT, |
| 85 | VK_FORMAT_R32G32_SFLOAT, | 85 | VK_FORMAT_R32G32B32A32_UINT, |
| 86 | VK_FORMAT_R32G32_UINT, | 86 | VK_FORMAT_R32G32_SFLOAT, |
| 87 | VK_FORMAT_R16G16B16A16_UINT, | 87 | VK_FORMAT_R32G32_UINT, |
| 88 | VK_FORMAT_R16G16B16A16_SNORM, | 88 | VK_FORMAT_R16G16B16A16_UINT, |
| 89 | VK_FORMAT_R16G16B16A16_UNORM, | 89 | VK_FORMAT_R16G16B16A16_SNORM, |
| 90 | VK_FORMAT_R16G16_UNORM, | 90 | VK_FORMAT_R16G16B16A16_UNORM, |
| 91 | VK_FORMAT_R16G16_SNORM, | 91 | VK_FORMAT_R16G16_UNORM, |
| 92 | VK_FORMAT_R16G16_SFLOAT, | 92 | VK_FORMAT_R16G16_SNORM, |
| 93 | VK_FORMAT_R16_UNORM, | 93 | VK_FORMAT_R16G16_SFLOAT, |
| 94 | VK_FORMAT_R8G8B8A8_SRGB, | 94 | VK_FORMAT_R16_UNORM, |
| 95 | VK_FORMAT_R8G8_UNORM, | 95 | VK_FORMAT_R16_UINT, |
| 96 | VK_FORMAT_R8G8_SNORM, | 96 | VK_FORMAT_R8G8B8A8_SRGB, |
| 97 | VK_FORMAT_R8G8_UINT, | 97 | VK_FORMAT_R8G8_UNORM, |
| 98 | VK_FORMAT_R8_UNORM, | 98 | VK_FORMAT_R8G8_SNORM, |
| 99 | VK_FORMAT_R8_UINT, | 99 | VK_FORMAT_R8G8_UINT, |
| 100 | VK_FORMAT_B10G11R11_UFLOAT_PACK32, | 100 | VK_FORMAT_R8_UNORM, |
| 101 | VK_FORMAT_R32_SFLOAT, | 101 | VK_FORMAT_R8_UINT, |
| 102 | VK_FORMAT_R32_UINT, | 102 | VK_FORMAT_B10G11R11_UFLOAT_PACK32, |
| 103 | VK_FORMAT_R32_SINT, | 103 | VK_FORMAT_R32_SFLOAT, |
| 104 | VK_FORMAT_R16_SFLOAT, | 104 | VK_FORMAT_R32_UINT, |
| 105 | VK_FORMAT_R16G16B16A16_SFLOAT, | 105 | VK_FORMAT_R32_SINT, |
| 106 | VK_FORMAT_B8G8R8A8_UNORM, | 106 | VK_FORMAT_R16_SFLOAT, |
| 107 | VK_FORMAT_B8G8R8A8_SRGB, | 107 | VK_FORMAT_R16G16B16A16_SFLOAT, |
| 108 | VK_FORMAT_R4G4B4A4_UNORM_PACK16, | 108 | VK_FORMAT_B8G8R8A8_UNORM, |
| 109 | VK_FORMAT_D32_SFLOAT, | 109 | VK_FORMAT_B8G8R8A8_SRGB, |
| 110 | VK_FORMAT_D16_UNORM, | 110 | VK_FORMAT_R4G4B4A4_UNORM_PACK16, |
| 111 | VK_FORMAT_D16_UNORM_S8_UINT, | 111 | VK_FORMAT_D32_SFLOAT, |
| 112 | VK_FORMAT_D24_UNORM_S8_UINT, | 112 | VK_FORMAT_D16_UNORM, |
| 113 | VK_FORMAT_D32_SFLOAT_S8_UINT, | 113 | VK_FORMAT_D16_UNORM_S8_UINT, |
| 114 | VK_FORMAT_BC1_RGBA_UNORM_BLOCK, | 114 | VK_FORMAT_D24_UNORM_S8_UINT, |
| 115 | VK_FORMAT_BC2_UNORM_BLOCK, | 115 | VK_FORMAT_D32_SFLOAT_S8_UINT, |
| 116 | VK_FORMAT_BC3_UNORM_BLOCK, | 116 | VK_FORMAT_BC1_RGBA_UNORM_BLOCK, |
| 117 | VK_FORMAT_BC4_UNORM_BLOCK, | 117 | VK_FORMAT_BC2_UNORM_BLOCK, |
| 118 | VK_FORMAT_BC5_UNORM_BLOCK, | 118 | VK_FORMAT_BC3_UNORM_BLOCK, |
| 119 | VK_FORMAT_BC5_SNORM_BLOCK, | 119 | VK_FORMAT_BC4_UNORM_BLOCK, |
| 120 | VK_FORMAT_BC7_UNORM_BLOCK, | 120 | VK_FORMAT_BC5_UNORM_BLOCK, |
| 121 | VK_FORMAT_BC6H_UFLOAT_BLOCK, | 121 | VK_FORMAT_BC5_SNORM_BLOCK, |
| 122 | VK_FORMAT_BC6H_SFLOAT_BLOCK, | 122 | VK_FORMAT_BC7_UNORM_BLOCK, |
| 123 | VK_FORMAT_BC1_RGBA_SRGB_BLOCK, | 123 | VK_FORMAT_BC6H_UFLOAT_BLOCK, |
| 124 | VK_FORMAT_BC2_SRGB_BLOCK, | 124 | VK_FORMAT_BC6H_SFLOAT_BLOCK, |
| 125 | VK_FORMAT_BC3_SRGB_BLOCK, | 125 | VK_FORMAT_BC1_RGBA_SRGB_BLOCK, |
| 126 | VK_FORMAT_BC7_SRGB_BLOCK, | 126 | VK_FORMAT_BC2_SRGB_BLOCK, |
| 127 | VK_FORMAT_ASTC_4x4_SRGB_BLOCK, | 127 | VK_FORMAT_BC3_SRGB_BLOCK, |
| 128 | VK_FORMAT_ASTC_8x8_SRGB_BLOCK, | 128 | VK_FORMAT_BC7_SRGB_BLOCK, |
| 129 | VK_FORMAT_ASTC_8x5_SRGB_BLOCK, | 129 | VK_FORMAT_ASTC_4x4_SRGB_BLOCK, |
| 130 | VK_FORMAT_ASTC_5x4_SRGB_BLOCK, | 130 | VK_FORMAT_ASTC_8x8_SRGB_BLOCK, |
| 131 | VK_FORMAT_ASTC_5x5_UNORM_BLOCK, | 131 | VK_FORMAT_ASTC_8x5_SRGB_BLOCK, |
| 132 | VK_FORMAT_ASTC_5x5_SRGB_BLOCK, | 132 | VK_FORMAT_ASTC_5x4_SRGB_BLOCK, |
| 133 | VK_FORMAT_ASTC_10x8_UNORM_BLOCK, | 133 | VK_FORMAT_ASTC_5x5_UNORM_BLOCK, |
| 134 | VK_FORMAT_ASTC_10x8_SRGB_BLOCK, | 134 | VK_FORMAT_ASTC_5x5_SRGB_BLOCK, |
| 135 | VK_FORMAT_ASTC_6x6_UNORM_BLOCK, | 135 | VK_FORMAT_ASTC_10x8_UNORM_BLOCK, |
| 136 | VK_FORMAT_ASTC_6x6_SRGB_BLOCK, | 136 | VK_FORMAT_ASTC_10x8_SRGB_BLOCK, |
| 137 | VK_FORMAT_ASTC_10x10_UNORM_BLOCK, | 137 | VK_FORMAT_ASTC_6x6_UNORM_BLOCK, |
| 138 | VK_FORMAT_ASTC_10x10_SRGB_BLOCK, | 138 | VK_FORMAT_ASTC_6x6_SRGB_BLOCK, |
| 139 | VK_FORMAT_ASTC_12x12_UNORM_BLOCK, | 139 | VK_FORMAT_ASTC_10x10_UNORM_BLOCK, |
| 140 | VK_FORMAT_ASTC_12x12_SRGB_BLOCK, | 140 | VK_FORMAT_ASTC_10x10_SRGB_BLOCK, |
| 141 | VK_FORMAT_ASTC_8x6_UNORM_BLOCK, | 141 | VK_FORMAT_ASTC_12x12_UNORM_BLOCK, |
| 142 | VK_FORMAT_ASTC_8x6_SRGB_BLOCK, | 142 | VK_FORMAT_ASTC_12x12_SRGB_BLOCK, |
| 143 | VK_FORMAT_ASTC_6x5_UNORM_BLOCK, | 143 | VK_FORMAT_ASTC_8x6_UNORM_BLOCK, |
| 144 | VK_FORMAT_ASTC_6x5_SRGB_BLOCK, | 144 | VK_FORMAT_ASTC_8x6_SRGB_BLOCK, |
| 145 | VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}; | 145 | VK_FORMAT_ASTC_6x5_UNORM_BLOCK, |
| 146 | VK_FORMAT_ASTC_6x5_SRGB_BLOCK, | ||
| 147 | VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, | ||
| 148 | }; | ||
| 146 | std::unordered_map<VkFormat, VkFormatProperties> format_properties; | 149 | std::unordered_map<VkFormat, VkFormatProperties> format_properties; |
| 147 | for (const auto format : formats) { | 150 | for (const auto format : formats) { |
| 148 | format_properties.emplace(format, physical.GetFormatProperties(format)); | 151 | format_properties.emplace(format, physical.GetFormatProperties(format)); |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index a5c7b7945..ea66e621e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "video_core/renderer_vulkan/wrapper.h" | 27 | #include "video_core/renderer_vulkan/wrapper.h" |
| 28 | #include "video_core/shader/compiler_settings.h" | 28 | #include "video_core/shader/compiler_settings.h" |
| 29 | #include "video_core/shader/memory_util.h" | 29 | #include "video_core/shader/memory_util.h" |
| 30 | #include "video_core/shader_cache.h" | ||
| 30 | 31 | ||
| 31 | namespace Vulkan { | 32 | namespace Vulkan { |
| 32 | 33 | ||
| @@ -45,6 +46,7 @@ constexpr VkDescriptorType UNIFORM_BUFFER = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; | |||
| 45 | constexpr VkDescriptorType STORAGE_BUFFER = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; | 46 | constexpr VkDescriptorType STORAGE_BUFFER = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
| 46 | constexpr VkDescriptorType UNIFORM_TEXEL_BUFFER = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; | 47 | constexpr VkDescriptorType UNIFORM_TEXEL_BUFFER = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; |
| 47 | constexpr VkDescriptorType COMBINED_IMAGE_SAMPLER = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | 48 | constexpr VkDescriptorType COMBINED_IMAGE_SAMPLER = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; |
| 49 | constexpr VkDescriptorType STORAGE_TEXEL_BUFFER = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; | ||
| 48 | constexpr VkDescriptorType STORAGE_IMAGE = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; | 50 | constexpr VkDescriptorType STORAGE_IMAGE = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; |
| 49 | 51 | ||
| 50 | constexpr VideoCommon::Shader::CompilerSettings compiler_settings{ | 52 | constexpr VideoCommon::Shader::CompilerSettings compiler_settings{ |
| @@ -104,8 +106,9 @@ u32 FillDescriptorLayout(const ShaderEntries& entries, | |||
| 104 | u32 binding = base_binding; | 106 | u32 binding = base_binding; |
| 105 | AddBindings<UNIFORM_BUFFER>(bindings, binding, flags, entries.const_buffers); | 107 | AddBindings<UNIFORM_BUFFER>(bindings, binding, flags, entries.const_buffers); |
| 106 | AddBindings<STORAGE_BUFFER>(bindings, binding, flags, entries.global_buffers); | 108 | AddBindings<STORAGE_BUFFER>(bindings, binding, flags, entries.global_buffers); |
| 107 | AddBindings<UNIFORM_TEXEL_BUFFER>(bindings, binding, flags, entries.texel_buffers); | 109 | AddBindings<UNIFORM_TEXEL_BUFFER>(bindings, binding, flags, entries.uniform_texels); |
| 108 | AddBindings<COMBINED_IMAGE_SAMPLER>(bindings, binding, flags, entries.samplers); | 110 | AddBindings<COMBINED_IMAGE_SAMPLER>(bindings, binding, flags, entries.samplers); |
| 111 | AddBindings<STORAGE_TEXEL_BUFFER>(bindings, binding, flags, entries.storage_texels); | ||
| 109 | AddBindings<STORAGE_IMAGE>(bindings, binding, flags, entries.images); | 112 | AddBindings<STORAGE_IMAGE>(bindings, binding, flags, entries.images); |
| 110 | return binding; | 113 | return binding; |
| 111 | } | 114 | } |
| @@ -130,19 +133,18 @@ bool ComputePipelineCacheKey::operator==(const ComputePipelineCacheKey& rhs) con | |||
| 130 | return std::memcmp(&rhs, this, sizeof *this) == 0; | 133 | return std::memcmp(&rhs, this, sizeof *this) == 0; |
| 131 | } | 134 | } |
| 132 | 135 | ||
| 133 | CachedShader::CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, | 136 | Shader::Shader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr, |
| 134 | GPUVAddr gpu_addr, VAddr cpu_addr, ProgramCode program_code, | 137 | VideoCommon::Shader::ProgramCode program_code, u32 main_offset) |
| 135 | u32 main_offset) | 138 | : gpu_addr{gpu_addr}, program_code{std::move(program_code)}, |
| 136 | : RasterizerCacheObject{cpu_addr}, gpu_addr{gpu_addr}, program_code{std::move(program_code)}, | ||
| 137 | registry{stage, GetEngine(system, stage)}, shader_ir{this->program_code, main_offset, | 139 | registry{stage, GetEngine(system, stage)}, shader_ir{this->program_code, main_offset, |
| 138 | compiler_settings, registry}, | 140 | compiler_settings, registry}, |
| 139 | entries{GenerateShaderEntries(shader_ir)} {} | 141 | entries{GenerateShaderEntries(shader_ir)} {} |
| 140 | 142 | ||
| 141 | CachedShader::~CachedShader() = default; | 143 | Shader::~Shader() = default; |
| 142 | 144 | ||
| 143 | Tegra::Engines::ConstBufferEngineInterface& CachedShader::GetEngine( | 145 | Tegra::Engines::ConstBufferEngineInterface& Shader::GetEngine(Core::System& system, |
| 144 | Core::System& system, Tegra::Engines::ShaderType stage) { | 146 | Tegra::Engines::ShaderType stage) { |
| 145 | if (stage == Tegra::Engines::ShaderType::Compute) { | 147 | if (stage == ShaderType::Compute) { |
| 146 | return system.GPU().KeplerCompute(); | 148 | return system.GPU().KeplerCompute(); |
| 147 | } else { | 149 | } else { |
| 148 | return system.GPU().Maxwell3D(); | 150 | return system.GPU().Maxwell3D(); |
| @@ -154,16 +156,16 @@ VKPipelineCache::VKPipelineCache(Core::System& system, RasterizerVulkan& rasteri | |||
| 154 | VKDescriptorPool& descriptor_pool, | 156 | VKDescriptorPool& descriptor_pool, |
| 155 | VKUpdateDescriptorQueue& update_descriptor_queue, | 157 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 156 | VKRenderPassCache& renderpass_cache) | 158 | VKRenderPassCache& renderpass_cache) |
| 157 | : RasterizerCache{rasterizer}, system{system}, device{device}, scheduler{scheduler}, | 159 | : VideoCommon::ShaderCache<Shader>{rasterizer}, system{system}, device{device}, |
| 158 | descriptor_pool{descriptor_pool}, update_descriptor_queue{update_descriptor_queue}, | 160 | scheduler{scheduler}, descriptor_pool{descriptor_pool}, |
| 159 | renderpass_cache{renderpass_cache} {} | 161 | update_descriptor_queue{update_descriptor_queue}, renderpass_cache{renderpass_cache} {} |
| 160 | 162 | ||
| 161 | VKPipelineCache::~VKPipelineCache() = default; | 163 | VKPipelineCache::~VKPipelineCache() = default; |
| 162 | 164 | ||
| 163 | std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { | 165 | std::array<Shader*, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { |
| 164 | const auto& gpu = system.GPU().Maxwell3D(); | 166 | const auto& gpu = system.GPU().Maxwell3D(); |
| 165 | 167 | ||
| 166 | std::array<Shader, Maxwell::MaxShaderProgram> shaders; | 168 | std::array<Shader*, Maxwell::MaxShaderProgram> shaders{}; |
| 167 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 169 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 168 | const auto program{static_cast<Maxwell::ShaderProgram>(index)}; | 170 | const auto program{static_cast<Maxwell::ShaderProgram>(index)}; |
| 169 | 171 | ||
| @@ -176,24 +178,28 @@ std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() { | |||
| 176 | const GPUVAddr program_addr{GetShaderAddress(system, program)}; | 178 | const GPUVAddr program_addr{GetShaderAddress(system, program)}; |
| 177 | const std::optional cpu_addr = memory_manager.GpuToCpuAddress(program_addr); | 179 | const std::optional cpu_addr = memory_manager.GpuToCpuAddress(program_addr); |
| 178 | ASSERT(cpu_addr); | 180 | ASSERT(cpu_addr); |
| 179 | auto shader = cpu_addr ? TryGet(*cpu_addr) : null_shader; | 181 | |
| 180 | if (!shader) { | 182 | Shader* result = cpu_addr ? TryGet(*cpu_addr) : null_shader.get(); |
| 183 | if (!result) { | ||
| 181 | const auto host_ptr{memory_manager.GetPointer(program_addr)}; | 184 | const auto host_ptr{memory_manager.GetPointer(program_addr)}; |
| 182 | 185 | ||
| 183 | // No shader found - create a new one | 186 | // No shader found - create a new one |
| 184 | constexpr u32 stage_offset = STAGE_MAIN_OFFSET; | 187 | constexpr u32 stage_offset = STAGE_MAIN_OFFSET; |
| 185 | const auto stage = static_cast<Tegra::Engines::ShaderType>(index == 0 ? 0 : index - 1); | 188 | const auto stage = static_cast<ShaderType>(index == 0 ? 0 : index - 1); |
| 186 | ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, false); | 189 | ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, false); |
| 190 | const std::size_t size_in_bytes = code.size() * sizeof(u64); | ||
| 191 | |||
| 192 | auto shader = std::make_unique<Shader>(system, stage, program_addr, std::move(code), | ||
| 193 | stage_offset); | ||
| 194 | result = shader.get(); | ||
| 187 | 195 | ||
| 188 | shader = std::make_shared<CachedShader>(system, stage, program_addr, *cpu_addr, | ||
| 189 | std::move(code), stage_offset); | ||
| 190 | if (cpu_addr) { | 196 | if (cpu_addr) { |
| 191 | Register(shader); | 197 | Register(std::move(shader), *cpu_addr, size_in_bytes); |
| 192 | } else { | 198 | } else { |
| 193 | null_shader = shader; | 199 | null_shader = std::move(shader); |
| 194 | } | 200 | } |
| 195 | } | 201 | } |
| 196 | shaders[index] = std::move(shader); | 202 | shaders[index] = result; |
| 197 | } | 203 | } |
| 198 | return last_shaders = shaders; | 204 | return last_shaders = shaders; |
| 199 | } | 205 | } |
| @@ -234,19 +240,22 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach | |||
| 234 | const auto cpu_addr = memory_manager.GpuToCpuAddress(program_addr); | 240 | const auto cpu_addr = memory_manager.GpuToCpuAddress(program_addr); |
| 235 | ASSERT(cpu_addr); | 241 | ASSERT(cpu_addr); |
| 236 | 242 | ||
| 237 | auto shader = cpu_addr ? TryGet(*cpu_addr) : null_kernel; | 243 | Shader* shader = cpu_addr ? TryGet(*cpu_addr) : null_kernel.get(); |
| 238 | if (!shader) { | 244 | if (!shader) { |
| 239 | // No shader found - create a new one | 245 | // No shader found - create a new one |
| 240 | const auto host_ptr = memory_manager.GetPointer(program_addr); | 246 | const auto host_ptr = memory_manager.GetPointer(program_addr); |
| 241 | 247 | ||
| 242 | ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, true); | 248 | ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, true); |
| 243 | shader = std::make_shared<CachedShader>(system, Tegra::Engines::ShaderType::Compute, | 249 | const std::size_t size_in_bytes = code.size() * sizeof(u64); |
| 244 | program_addr, *cpu_addr, std::move(code), | 250 | |
| 245 | KERNEL_MAIN_OFFSET); | 251 | auto shader_info = std::make_unique<Shader>(system, ShaderType::Compute, program_addr, |
| 252 | std::move(code), KERNEL_MAIN_OFFSET); | ||
| 253 | shader = shader_info.get(); | ||
| 254 | |||
| 246 | if (cpu_addr) { | 255 | if (cpu_addr) { |
| 247 | Register(shader); | 256 | Register(std::move(shader_info), *cpu_addr, size_in_bytes); |
| 248 | } else { | 257 | } else { |
| 249 | null_kernel = shader; | 258 | null_kernel = std::move(shader_info); |
| 250 | } | 259 | } |
| 251 | } | 260 | } |
| 252 | 261 | ||
| @@ -262,7 +271,7 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach | |||
| 262 | return *entry; | 271 | return *entry; |
| 263 | } | 272 | } |
| 264 | 273 | ||
| 265 | void VKPipelineCache::Unregister(const Shader& shader) { | 274 | void VKPipelineCache::OnShaderRemoval(Shader* shader) { |
| 266 | bool finished = false; | 275 | bool finished = false; |
| 267 | const auto Finish = [&] { | 276 | const auto Finish = [&] { |
| 268 | // TODO(Rodrigo): Instead of finishing here, wait for the fences that use this pipeline and | 277 | // TODO(Rodrigo): Instead of finishing here, wait for the fences that use this pipeline and |
| @@ -294,8 +303,6 @@ void VKPipelineCache::Unregister(const Shader& shader) { | |||
| 294 | Finish(); | 303 | Finish(); |
| 295 | it = compute_cache.erase(it); | 304 | it = compute_cache.erase(it); |
| 296 | } | 305 | } |
| 297 | |||
| 298 | RasterizerCache::Unregister(shader); | ||
| 299 | } | 306 | } |
| 300 | 307 | ||
| 301 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> | 308 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> |
| @@ -312,7 +319,9 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) { | |||
| 312 | ASSERT(point_size != 0.0f); | 319 | ASSERT(point_size != 0.0f); |
| 313 | } | 320 | } |
| 314 | for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) { | 321 | for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) { |
| 315 | specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].Type(); | 322 | const auto& attribute = fixed_state.vertex_input.attributes[i]; |
| 323 | specialization.enabled_attributes[i] = attribute.enabled.Value() != 0; | ||
| 324 | specialization.attribute_types[i] = attribute.Type(); | ||
| 316 | } | 325 | } |
| 317 | specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one; | 326 | specialization.ndc_minus_one_to_one = fixed_state.rasterizer.ndc_minus_one_to_one; |
| 318 | 327 | ||
| @@ -328,12 +337,11 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) { | |||
| 328 | } | 337 | } |
| 329 | 338 | ||
| 330 | const GPUVAddr gpu_addr = GetShaderAddress(system, program_enum); | 339 | const GPUVAddr gpu_addr = GetShaderAddress(system, program_enum); |
| 331 | const auto cpu_addr = memory_manager.GpuToCpuAddress(gpu_addr); | 340 | const std::optional<VAddr> cpu_addr = memory_manager.GpuToCpuAddress(gpu_addr); |
| 332 | const auto shader = cpu_addr ? TryGet(*cpu_addr) : null_shader; | 341 | Shader* const shader = cpu_addr ? TryGet(*cpu_addr) : null_shader.get(); |
| 333 | ASSERT(shader); | ||
| 334 | 342 | ||
| 335 | const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5 | 343 | const std::size_t stage = index == 0 ? 0 : index - 1; // Stage indices are 0 - 5 |
| 336 | const auto program_type = GetShaderType(program_enum); | 344 | const ShaderType program_type = GetShaderType(program_enum); |
| 337 | const auto& entries = shader->GetEntries(); | 345 | const auto& entries = shader->GetEntries(); |
| 338 | program[stage] = { | 346 | program[stage] = { |
| 339 | Decompile(device, shader->GetIR(), program_type, shader->GetRegistry(), specialization), | 347 | Decompile(device, shader->GetIR(), program_type, shader->GetRegistry(), specialization), |
| @@ -375,16 +383,17 @@ void AddEntry(std::vector<VkDescriptorUpdateTemplateEntry>& template_entries, u3 | |||
| 375 | return; | 383 | return; |
| 376 | } | 384 | } |
| 377 | 385 | ||
| 378 | if constexpr (descriptor_type == UNIFORM_TEXEL_BUFFER) { | 386 | if constexpr (descriptor_type == UNIFORM_TEXEL_BUFFER || |
| 379 | // Nvidia has a bug where updating multiple uniform texels at once causes the driver to | 387 | descriptor_type == STORAGE_TEXEL_BUFFER) { |
| 380 | // crash. | 388 | // Nvidia has a bug where updating multiple texels at once causes the driver to crash. |
| 389 | // Note: Fixed in driver Windows 443.24, Linux 440.66.15 | ||
| 381 | for (u32 i = 0; i < count; ++i) { | 390 | for (u32 i = 0; i < count; ++i) { |
| 382 | VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); | 391 | VkDescriptorUpdateTemplateEntry& entry = template_entries.emplace_back(); |
| 383 | entry.dstBinding = binding + i; | 392 | entry.dstBinding = binding + i; |
| 384 | entry.dstArrayElement = 0; | 393 | entry.dstArrayElement = 0; |
| 385 | entry.descriptorCount = 1; | 394 | entry.descriptorCount = 1; |
| 386 | entry.descriptorType = descriptor_type; | 395 | entry.descriptorType = descriptor_type; |
| 387 | entry.offset = offset + i * entry_size; | 396 | entry.offset = static_cast<std::size_t>(offset + i * entry_size); |
| 388 | entry.stride = entry_size; | 397 | entry.stride = entry_size; |
| 389 | } | 398 | } |
| 390 | } else if (count > 0) { | 399 | } else if (count > 0) { |
| @@ -405,8 +414,9 @@ void FillDescriptorUpdateTemplateEntries( | |||
| 405 | std::vector<VkDescriptorUpdateTemplateEntryKHR>& template_entries) { | 414 | std::vector<VkDescriptorUpdateTemplateEntryKHR>& template_entries) { |
| 406 | AddEntry<UNIFORM_BUFFER>(template_entries, offset, binding, entries.const_buffers); | 415 | AddEntry<UNIFORM_BUFFER>(template_entries, offset, binding, entries.const_buffers); |
| 407 | AddEntry<STORAGE_BUFFER>(template_entries, offset, binding, entries.global_buffers); | 416 | AddEntry<STORAGE_BUFFER>(template_entries, offset, binding, entries.global_buffers); |
| 408 | AddEntry<UNIFORM_TEXEL_BUFFER>(template_entries, offset, binding, entries.texel_buffers); | 417 | AddEntry<UNIFORM_TEXEL_BUFFER>(template_entries, offset, binding, entries.uniform_texels); |
| 409 | AddEntry<COMBINED_IMAGE_SAMPLER>(template_entries, offset, binding, entries.samplers); | 418 | AddEntry<COMBINED_IMAGE_SAMPLER>(template_entries, offset, binding, entries.samplers); |
| 419 | AddEntry<STORAGE_TEXEL_BUFFER>(template_entries, offset, binding, entries.storage_texels); | ||
| 410 | AddEntry<STORAGE_IMAGE>(template_entries, offset, binding, entries.images); | 420 | AddEntry<STORAGE_IMAGE>(template_entries, offset, binding, entries.images); |
| 411 | } | 421 | } |
| 412 | 422 | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 0b5796fef..0a36e5112 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "video_core/engines/const_buffer_engine_interface.h" | 18 | #include "video_core/engines/const_buffer_engine_interface.h" |
| 19 | #include "video_core/engines/maxwell_3d.h" | 19 | #include "video_core/engines/maxwell_3d.h" |
| 20 | #include "video_core/rasterizer_cache.h" | ||
| 21 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 20 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 22 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" | 21 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" |
| 23 | #include "video_core/renderer_vulkan/vk_renderpass_cache.h" | 22 | #include "video_core/renderer_vulkan/vk_renderpass_cache.h" |
| @@ -26,6 +25,7 @@ | |||
| 26 | #include "video_core/shader/memory_util.h" | 25 | #include "video_core/shader/memory_util.h" |
| 27 | #include "video_core/shader/registry.h" | 26 | #include "video_core/shader/registry.h" |
| 28 | #include "video_core/shader/shader_ir.h" | 27 | #include "video_core/shader/shader_ir.h" |
| 28 | #include "video_core/shader_cache.h" | ||
| 29 | 29 | ||
| 30 | namespace Core { | 30 | namespace Core { |
| 31 | class System; | 31 | class System; |
| @@ -41,8 +41,6 @@ class VKFence; | |||
| 41 | class VKScheduler; | 41 | class VKScheduler; |
| 42 | class VKUpdateDescriptorQueue; | 42 | class VKUpdateDescriptorQueue; |
| 43 | 43 | ||
| 44 | class CachedShader; | ||
| 45 | using Shader = std::shared_ptr<CachedShader>; | ||
| 46 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 44 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 47 | 45 | ||
| 48 | struct GraphicsPipelineCacheKey { | 46 | struct GraphicsPipelineCacheKey { |
| @@ -102,21 +100,16 @@ struct hash<Vulkan::ComputePipelineCacheKey> { | |||
| 102 | 100 | ||
| 103 | namespace Vulkan { | 101 | namespace Vulkan { |
| 104 | 102 | ||
| 105 | class CachedShader final : public RasterizerCacheObject { | 103 | class Shader { |
| 106 | public: | 104 | public: |
| 107 | explicit CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr, | 105 | explicit Shader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr, |
| 108 | VAddr cpu_addr, VideoCommon::Shader::ProgramCode program_code, | 106 | VideoCommon::Shader::ProgramCode program_code, u32 main_offset); |
| 109 | u32 main_offset); | 107 | ~Shader(); |
| 110 | ~CachedShader(); | ||
| 111 | 108 | ||
| 112 | GPUVAddr GetGpuAddr() const { | 109 | GPUVAddr GetGpuAddr() const { |
| 113 | return gpu_addr; | 110 | return gpu_addr; |
| 114 | } | 111 | } |
| 115 | 112 | ||
| 116 | std::size_t GetSizeInBytes() const override { | ||
| 117 | return program_code.size() * sizeof(u64); | ||
| 118 | } | ||
| 119 | |||
| 120 | VideoCommon::Shader::ShaderIR& GetIR() { | 113 | VideoCommon::Shader::ShaderIR& GetIR() { |
| 121 | return shader_ir; | 114 | return shader_ir; |
| 122 | } | 115 | } |
| @@ -144,25 +137,23 @@ private: | |||
| 144 | ShaderEntries entries; | 137 | ShaderEntries entries; |
| 145 | }; | 138 | }; |
| 146 | 139 | ||
| 147 | class VKPipelineCache final : public RasterizerCache<Shader> { | 140 | class VKPipelineCache final : public VideoCommon::ShaderCache<Shader> { |
| 148 | public: | 141 | public: |
| 149 | explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer, | 142 | explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer, |
| 150 | const VKDevice& device, VKScheduler& scheduler, | 143 | const VKDevice& device, VKScheduler& scheduler, |
| 151 | VKDescriptorPool& descriptor_pool, | 144 | VKDescriptorPool& descriptor_pool, |
| 152 | VKUpdateDescriptorQueue& update_descriptor_queue, | 145 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 153 | VKRenderPassCache& renderpass_cache); | 146 | VKRenderPassCache& renderpass_cache); |
| 154 | ~VKPipelineCache(); | 147 | ~VKPipelineCache() override; |
| 155 | 148 | ||
| 156 | std::array<Shader, Maxwell::MaxShaderProgram> GetShaders(); | 149 | std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders(); |
| 157 | 150 | ||
| 158 | VKGraphicsPipeline& GetGraphicsPipeline(const GraphicsPipelineCacheKey& key); | 151 | VKGraphicsPipeline& GetGraphicsPipeline(const GraphicsPipelineCacheKey& key); |
| 159 | 152 | ||
| 160 | VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); | 153 | VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); |
| 161 | 154 | ||
| 162 | protected: | 155 | protected: |
| 163 | void Unregister(const Shader& shader) override; | 156 | void OnShaderRemoval(Shader* shader) final; |
| 164 | |||
| 165 | void FlushObjectInner(const Shader& object) override {} | ||
| 166 | 157 | ||
| 167 | private: | 158 | private: |
| 168 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders( | 159 | std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders( |
| @@ -175,10 +166,10 @@ private: | |||
| 175 | VKUpdateDescriptorQueue& update_descriptor_queue; | 166 | VKUpdateDescriptorQueue& update_descriptor_queue; |
| 176 | VKRenderPassCache& renderpass_cache; | 167 | VKRenderPassCache& renderpass_cache; |
| 177 | 168 | ||
| 178 | Shader null_shader{}; | 169 | std::unique_ptr<Shader> null_shader; |
| 179 | Shader null_kernel{}; | 170 | std::unique_ptr<Shader> null_kernel; |
| 180 | 171 | ||
| 181 | std::array<Shader, Maxwell::MaxShaderProgram> last_shaders; | 172 | std::array<Shader*, Maxwell::MaxShaderProgram> last_shaders{}; |
| 182 | 173 | ||
| 183 | GraphicsPipelineCacheKey last_graphics_key; | 174 | GraphicsPipelineCacheKey last_graphics_key; |
| 184 | VKGraphicsPipeline* last_graphics_pipeline = nullptr; | 175 | VKGraphicsPipeline* last_graphics_pipeline = nullptr; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index be5b77fae..e3714ee6d 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 38 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 39 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 39 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 40 | #include "video_core/renderer_vulkan/wrapper.h" | 40 | #include "video_core/renderer_vulkan/wrapper.h" |
| 41 | #include "video_core/shader_cache.h" | ||
| 41 | 42 | ||
| 42 | namespace Vulkan { | 43 | namespace Vulkan { |
| 43 | 44 | ||
| @@ -98,7 +99,7 @@ VkRect2D GetScissorState(const Maxwell& regs, std::size_t index) { | |||
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> GetShaderAddresses( | 101 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> GetShaderAddresses( |
| 101 | const std::array<Shader, Maxwell::MaxShaderProgram>& shaders) { | 102 | const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders) { |
| 102 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> addresses; | 103 | std::array<GPUVAddr, Maxwell::MaxShaderProgram> addresses; |
| 103 | for (std::size_t i = 0; i < std::size(addresses); ++i) { | 104 | for (std::size_t i = 0; i < std::size(addresses); ++i) { |
| 104 | addresses[i] = shaders[i] ? shaders[i]->GetGpuAddr() : 0; | 105 | addresses[i] = shaders[i] ? shaders[i]->GetGpuAddr() : 0; |
| @@ -117,6 +118,17 @@ template <typename Engine, typename Entry> | |||
| 117 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, | 118 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, |
| 118 | std::size_t stage, std::size_t index = 0) { | 119 | std::size_t stage, std::size_t index = 0) { |
| 119 | const auto stage_type = static_cast<Tegra::Engines::ShaderType>(stage); | 120 | const auto stage_type = static_cast<Tegra::Engines::ShaderType>(stage); |
| 121 | if constexpr (std::is_same_v<Entry, SamplerEntry>) { | ||
| 122 | if (entry.is_separated) { | ||
| 123 | const u32 buffer_1 = entry.buffer; | ||
| 124 | const u32 buffer_2 = entry.secondary_buffer; | ||
| 125 | const u32 offset_1 = entry.offset; | ||
| 126 | const u32 offset_2 = entry.secondary_offset; | ||
| 127 | const u32 handle_1 = engine.AccessConstBuffer32(stage_type, buffer_1, offset_1); | ||
| 128 | const u32 handle_2 = engine.AccessConstBuffer32(stage_type, buffer_2, offset_2); | ||
| 129 | return engine.GetTextureInfo(handle_1 | handle_2); | ||
| 130 | } | ||
| 131 | } | ||
| 120 | if (entry.is_bindless) { | 132 | if (entry.is_bindless) { |
| 121 | const auto tex_handle = engine.AccessConstBuffer32(stage_type, entry.buffer, entry.offset); | 133 | const auto tex_handle = engine.AccessConstBuffer32(stage_type, entry.buffer, entry.offset); |
| 122 | return engine.GetTextureInfo(tex_handle); | 134 | return engine.GetTextureInfo(tex_handle); |
| @@ -468,8 +480,9 @@ void RasterizerVulkan::DispatchCompute(GPUVAddr code_addr) { | |||
| 468 | const auto& entries = pipeline.GetEntries(); | 480 | const auto& entries = pipeline.GetEntries(); |
| 469 | SetupComputeConstBuffers(entries); | 481 | SetupComputeConstBuffers(entries); |
| 470 | SetupComputeGlobalBuffers(entries); | 482 | SetupComputeGlobalBuffers(entries); |
| 471 | SetupComputeTexelBuffers(entries); | 483 | SetupComputeUniformTexels(entries); |
| 472 | SetupComputeTextures(entries); | 484 | SetupComputeTextures(entries); |
| 485 | SetupComputeStorageTexels(entries); | ||
| 473 | SetupComputeImages(entries); | 486 | SetupComputeImages(entries); |
| 474 | 487 | ||
| 475 | buffer_cache.Unmap(); | 488 | buffer_cache.Unmap(); |
| @@ -715,7 +728,7 @@ std::tuple<VkFramebuffer, VkExtent2D> RasterizerVulkan::ConfigureFramebuffers( | |||
| 715 | if (!view) { | 728 | if (!view) { |
| 716 | return false; | 729 | return false; |
| 717 | } | 730 | } |
| 718 | key.views.push_back(view->GetHandle()); | 731 | key.views.push_back(view->GetAttachment()); |
| 719 | key.width = std::min(key.width, view->GetWidth()); | 732 | key.width = std::min(key.width, view->GetWidth()); |
| 720 | key.height = std::min(key.height, view->GetHeight()); | 733 | key.height = std::min(key.height, view->GetHeight()); |
| 721 | key.layers = std::min(key.layers, view->GetNumLayers()); | 734 | key.layers = std::min(key.layers, view->GetNumLayers()); |
| @@ -775,20 +788,21 @@ RasterizerVulkan::DrawParameters RasterizerVulkan::SetupGeometry(FixedPipelineSt | |||
| 775 | } | 788 | } |
| 776 | 789 | ||
| 777 | void RasterizerVulkan::SetupShaderDescriptors( | 790 | void RasterizerVulkan::SetupShaderDescriptors( |
| 778 | const std::array<Shader, Maxwell::MaxShaderProgram>& shaders) { | 791 | const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders) { |
| 779 | texture_cache.GuardSamplers(true); | 792 | texture_cache.GuardSamplers(true); |
| 780 | 793 | ||
| 781 | for (std::size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { | 794 | for (std::size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) { |
| 782 | // Skip VertexA stage | 795 | // Skip VertexA stage |
| 783 | const auto& shader = shaders[stage + 1]; | 796 | Shader* const shader = shaders[stage + 1]; |
| 784 | if (!shader) { | 797 | if (!shader) { |
| 785 | continue; | 798 | continue; |
| 786 | } | 799 | } |
| 787 | const auto& entries = shader->GetEntries(); | 800 | const auto& entries = shader->GetEntries(); |
| 788 | SetupGraphicsConstBuffers(entries, stage); | 801 | SetupGraphicsConstBuffers(entries, stage); |
| 789 | SetupGraphicsGlobalBuffers(entries, stage); | 802 | SetupGraphicsGlobalBuffers(entries, stage); |
| 790 | SetupGraphicsTexelBuffers(entries, stage); | 803 | SetupGraphicsUniformTexels(entries, stage); |
| 791 | SetupGraphicsTextures(entries, stage); | 804 | SetupGraphicsTextures(entries, stage); |
| 805 | SetupGraphicsStorageTexels(entries, stage); | ||
| 792 | SetupGraphicsImages(entries, stage); | 806 | SetupGraphicsImages(entries, stage); |
| 793 | } | 807 | } |
| 794 | texture_cache.GuardSamplers(false); | 808 | texture_cache.GuardSamplers(false); |
| @@ -838,6 +852,10 @@ void RasterizerVulkan::BeginTransformFeedback() { | |||
| 838 | if (regs.tfb_enabled == 0) { | 852 | if (regs.tfb_enabled == 0) { |
| 839 | return; | 853 | return; |
| 840 | } | 854 | } |
| 855 | if (!device.IsExtTransformFeedbackSupported()) { | ||
| 856 | LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported"); | ||
| 857 | return; | ||
| 858 | } | ||
| 841 | 859 | ||
| 842 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || | 860 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || |
| 843 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || | 861 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || |
| @@ -852,10 +870,10 @@ void RasterizerVulkan::BeginTransformFeedback() { | |||
| 852 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); | 870 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); |
| 853 | 871 | ||
| 854 | const GPUVAddr gpu_addr = binding.Address(); | 872 | const GPUVAddr gpu_addr = binding.Address(); |
| 855 | const std::size_t size = binding.buffer_size; | 873 | const VkDeviceSize size = static_cast<VkDeviceSize>(binding.buffer_size); |
| 856 | const auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); | 874 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, 4, true); |
| 857 | 875 | ||
| 858 | scheduler.Record([buffer = buffer, offset = offset, size](vk::CommandBuffer cmdbuf) { | 876 | scheduler.Record([buffer = info.handle, offset = info.offset, size](vk::CommandBuffer cmdbuf) { |
| 859 | cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); | 877 | cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); |
| 860 | cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); | 878 | cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); |
| 861 | }); | 879 | }); |
| @@ -866,6 +884,9 @@ void RasterizerVulkan::EndTransformFeedback() { | |||
| 866 | if (regs.tfb_enabled == 0) { | 884 | if (regs.tfb_enabled == 0) { |
| 867 | return; | 885 | return; |
| 868 | } | 886 | } |
| 887 | if (!device.IsExtTransformFeedbackSupported()) { | ||
| 888 | return; | ||
| 889 | } | ||
| 869 | 890 | ||
| 870 | scheduler.Record( | 891 | scheduler.Record( |
| 871 | [](vk::CommandBuffer cmdbuf) { cmdbuf.EndTransformFeedbackEXT(0, 0, nullptr, nullptr); }); | 892 | [](vk::CommandBuffer cmdbuf) { cmdbuf.EndTransformFeedbackEXT(0, 0, nullptr, nullptr); }); |
| @@ -877,14 +898,10 @@ void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex | |||
| 877 | 898 | ||
| 878 | for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { | 899 | for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
| 879 | const auto& attrib = regs.vertex_attrib_format[index]; | 900 | const auto& attrib = regs.vertex_attrib_format[index]; |
| 880 | if (!attrib.IsValid()) { | 901 | if (attrib.IsConstant()) { |
| 881 | vertex_input.SetAttribute(index, false, 0, 0, {}, {}); | 902 | vertex_input.SetAttribute(index, false, 0, 0, {}, {}); |
| 882 | continue; | 903 | continue; |
| 883 | } | 904 | } |
| 884 | |||
| 885 | [[maybe_unused]] const auto& buffer = regs.vertex_array[attrib.buffer]; | ||
| 886 | ASSERT(buffer.IsEnabled()); | ||
| 887 | |||
| 888 | vertex_input.SetAttribute(index, true, attrib.buffer, attrib.offset, attrib.type.Value(), | 905 | vertex_input.SetAttribute(index, true, attrib.buffer, attrib.offset, attrib.type.Value(), |
| 889 | attrib.size.Value()); | 906 | attrib.size.Value()); |
| 890 | } | 907 | } |
| @@ -908,8 +925,8 @@ void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex | |||
| 908 | buffer_bindings.AddVertexBinding(DefaultBuffer(), 0); | 925 | buffer_bindings.AddVertexBinding(DefaultBuffer(), 0); |
| 909 | continue; | 926 | continue; |
| 910 | } | 927 | } |
| 911 | const auto [buffer, offset] = buffer_cache.UploadMemory(start, size); | 928 | const auto info = buffer_cache.UploadMemory(start, size); |
| 912 | buffer_bindings.AddVertexBinding(buffer, offset); | 929 | buffer_bindings.AddVertexBinding(info.handle, info.offset); |
| 913 | } | 930 | } |
| 914 | } | 931 | } |
| 915 | 932 | ||
| @@ -931,7 +948,9 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar | |||
| 931 | break; | 948 | break; |
| 932 | } | 949 | } |
| 933 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); | 950 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); |
| 934 | auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); | 951 | const auto info = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); |
| 952 | VkBuffer buffer = info.handle; | ||
| 953 | u64 offset = info.offset; | ||
| 935 | std::tie(buffer, offset) = quad_indexed_pass.Assemble( | 954 | std::tie(buffer, offset) = quad_indexed_pass.Assemble( |
| 936 | regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset); | 955 | regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset); |
| 937 | 956 | ||
| @@ -945,7 +964,9 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar | |||
| 945 | break; | 964 | break; |
| 946 | } | 965 | } |
| 947 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); | 966 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); |
| 948 | auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); | 967 | const auto info = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); |
| 968 | VkBuffer buffer = info.handle; | ||
| 969 | u64 offset = info.offset; | ||
| 949 | 970 | ||
| 950 | auto format = regs.index_array.format; | 971 | auto format = regs.index_array.format; |
| 951 | const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; | 972 | const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; |
| @@ -980,12 +1001,12 @@ void RasterizerVulkan::SetupGraphicsGlobalBuffers(const ShaderEntries& entries, | |||
| 980 | } | 1001 | } |
| 981 | } | 1002 | } |
| 982 | 1003 | ||
| 983 | void RasterizerVulkan::SetupGraphicsTexelBuffers(const ShaderEntries& entries, std::size_t stage) { | 1004 | void RasterizerVulkan::SetupGraphicsUniformTexels(const ShaderEntries& entries, std::size_t stage) { |
| 984 | MICROPROFILE_SCOPE(Vulkan_Textures); | 1005 | MICROPROFILE_SCOPE(Vulkan_Textures); |
| 985 | const auto& gpu = system.GPU().Maxwell3D(); | 1006 | const auto& gpu = system.GPU().Maxwell3D(); |
| 986 | for (const auto& entry : entries.texel_buffers) { | 1007 | for (const auto& entry : entries.uniform_texels) { |
| 987 | const auto image = GetTextureInfo(gpu, entry, stage).tic; | 1008 | const auto image = GetTextureInfo(gpu, entry, stage).tic; |
| 988 | SetupTexelBuffer(image, entry); | 1009 | SetupUniformTexels(image, entry); |
| 989 | } | 1010 | } |
| 990 | } | 1011 | } |
| 991 | 1012 | ||
| @@ -1000,6 +1021,15 @@ void RasterizerVulkan::SetupGraphicsTextures(const ShaderEntries& entries, std:: | |||
| 1000 | } | 1021 | } |
| 1001 | } | 1022 | } |
| 1002 | 1023 | ||
| 1024 | void RasterizerVulkan::SetupGraphicsStorageTexels(const ShaderEntries& entries, std::size_t stage) { | ||
| 1025 | MICROPROFILE_SCOPE(Vulkan_Textures); | ||
| 1026 | const auto& gpu = system.GPU().Maxwell3D(); | ||
| 1027 | for (const auto& entry : entries.storage_texels) { | ||
| 1028 | const auto image = GetTextureInfo(gpu, entry, stage).tic; | ||
| 1029 | SetupStorageTexel(image, entry); | ||
| 1030 | } | ||
| 1031 | } | ||
| 1032 | |||
| 1003 | void RasterizerVulkan::SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage) { | 1033 | void RasterizerVulkan::SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage) { |
| 1004 | MICROPROFILE_SCOPE(Vulkan_Images); | 1034 | MICROPROFILE_SCOPE(Vulkan_Images); |
| 1005 | const auto& gpu = system.GPU().Maxwell3D(); | 1035 | const auto& gpu = system.GPU().Maxwell3D(); |
| @@ -1032,12 +1062,12 @@ void RasterizerVulkan::SetupComputeGlobalBuffers(const ShaderEntries& entries) { | |||
| 1032 | } | 1062 | } |
| 1033 | } | 1063 | } |
| 1034 | 1064 | ||
| 1035 | void RasterizerVulkan::SetupComputeTexelBuffers(const ShaderEntries& entries) { | 1065 | void RasterizerVulkan::SetupComputeUniformTexels(const ShaderEntries& entries) { |
| 1036 | MICROPROFILE_SCOPE(Vulkan_Textures); | 1066 | MICROPROFILE_SCOPE(Vulkan_Textures); |
| 1037 | const auto& gpu = system.GPU().KeplerCompute(); | 1067 | const auto& gpu = system.GPU().KeplerCompute(); |
| 1038 | for (const auto& entry : entries.texel_buffers) { | 1068 | for (const auto& entry : entries.uniform_texels) { |
| 1039 | const auto image = GetTextureInfo(gpu, entry, ComputeShaderIndex).tic; | 1069 | const auto image = GetTextureInfo(gpu, entry, ComputeShaderIndex).tic; |
| 1040 | SetupTexelBuffer(image, entry); | 1070 | SetupUniformTexels(image, entry); |
| 1041 | } | 1071 | } |
| 1042 | } | 1072 | } |
| 1043 | 1073 | ||
| @@ -1052,6 +1082,15 @@ void RasterizerVulkan::SetupComputeTextures(const ShaderEntries& entries) { | |||
| 1052 | } | 1082 | } |
| 1053 | } | 1083 | } |
| 1054 | 1084 | ||
| 1085 | void RasterizerVulkan::SetupComputeStorageTexels(const ShaderEntries& entries) { | ||
| 1086 | MICROPROFILE_SCOPE(Vulkan_Textures); | ||
| 1087 | const auto& gpu = system.GPU().KeplerCompute(); | ||
| 1088 | for (const auto& entry : entries.storage_texels) { | ||
| 1089 | const auto image = GetTextureInfo(gpu, entry, ComputeShaderIndex).tic; | ||
| 1090 | SetupStorageTexel(image, entry); | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | |||
| 1055 | void RasterizerVulkan::SetupComputeImages(const ShaderEntries& entries) { | 1094 | void RasterizerVulkan::SetupComputeImages(const ShaderEntries& entries) { |
| 1056 | MICROPROFILE_SCOPE(Vulkan_Images); | 1095 | MICROPROFILE_SCOPE(Vulkan_Images); |
| 1057 | const auto& gpu = system.GPU().KeplerCompute(); | 1096 | const auto& gpu = system.GPU().KeplerCompute(); |
| @@ -1074,10 +1113,9 @@ void RasterizerVulkan::SetupConstBuffer(const ConstBufferEntry& entry, | |||
| 1074 | Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); | 1113 | Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); |
| 1075 | ASSERT(size <= MaxConstbufferSize); | 1114 | ASSERT(size <= MaxConstbufferSize); |
| 1076 | 1115 | ||
| 1077 | const auto [buffer_handle, offset] = | 1116 | const auto info = |
| 1078 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); | 1117 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); |
| 1079 | 1118 | update_descriptor_queue.AddBuffer(info.handle, info.offset, size); | |
| 1080 | update_descriptor_queue.AddBuffer(buffer_handle, offset, size); | ||
| 1081 | } | 1119 | } |
| 1082 | 1120 | ||
| 1083 | void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address) { | 1121 | void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address) { |
| @@ -1091,18 +1129,18 @@ void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAdd | |||
| 1091 | // Note: Do *not* use DefaultBuffer() here, storage buffers can be written breaking the | 1129 | // Note: Do *not* use DefaultBuffer() here, storage buffers can be written breaking the |
| 1092 | // default buffer. | 1130 | // default buffer. |
| 1093 | static constexpr std::size_t dummy_size = 4; | 1131 | static constexpr std::size_t dummy_size = 4; |
| 1094 | const auto buffer = buffer_cache.GetEmptyBuffer(dummy_size); | 1132 | const auto info = buffer_cache.GetEmptyBuffer(dummy_size); |
| 1095 | update_descriptor_queue.AddBuffer(buffer, 0, dummy_size); | 1133 | update_descriptor_queue.AddBuffer(info.handle, info.offset, dummy_size); |
| 1096 | return; | 1134 | return; |
| 1097 | } | 1135 | } |
| 1098 | 1136 | ||
| 1099 | const auto [buffer, offset] = buffer_cache.UploadMemory( | 1137 | const auto info = buffer_cache.UploadMemory( |
| 1100 | actual_addr, size, device.GetStorageBufferAlignment(), entry.IsWritten()); | 1138 | actual_addr, size, device.GetStorageBufferAlignment(), entry.IsWritten()); |
| 1101 | update_descriptor_queue.AddBuffer(buffer, offset, size); | 1139 | update_descriptor_queue.AddBuffer(info.handle, info.offset, size); |
| 1102 | } | 1140 | } |
| 1103 | 1141 | ||
| 1104 | void RasterizerVulkan::SetupTexelBuffer(const Tegra::Texture::TICEntry& tic, | 1142 | void RasterizerVulkan::SetupUniformTexels(const Tegra::Texture::TICEntry& tic, |
| 1105 | const TexelBufferEntry& entry) { | 1143 | const UniformTexelEntry& entry) { |
| 1106 | const auto view = texture_cache.GetTextureSurface(tic, entry); | 1144 | const auto view = texture_cache.GetTextureSurface(tic, entry); |
| 1107 | ASSERT(view->IsBufferView()); | 1145 | ASSERT(view->IsBufferView()); |
| 1108 | 1146 | ||
| @@ -1114,16 +1152,24 @@ void RasterizerVulkan::SetupTexture(const Tegra::Texture::FullTextureInfo& textu | |||
| 1114 | auto view = texture_cache.GetTextureSurface(texture.tic, entry); | 1152 | auto view = texture_cache.GetTextureSurface(texture.tic, entry); |
| 1115 | ASSERT(!view->IsBufferView()); | 1153 | ASSERT(!view->IsBufferView()); |
| 1116 | 1154 | ||
| 1117 | const auto image_view = view->GetHandle(texture.tic.x_source, texture.tic.y_source, | 1155 | const VkImageView image_view = view->GetImageView(texture.tic.x_source, texture.tic.y_source, |
| 1118 | texture.tic.z_source, texture.tic.w_source); | 1156 | texture.tic.z_source, texture.tic.w_source); |
| 1119 | const auto sampler = sampler_cache.GetSampler(texture.tsc); | 1157 | const auto sampler = sampler_cache.GetSampler(texture.tsc); |
| 1120 | update_descriptor_queue.AddSampledImage(sampler, image_view); | 1158 | update_descriptor_queue.AddSampledImage(sampler, image_view); |
| 1121 | 1159 | ||
| 1122 | const auto image_layout = update_descriptor_queue.GetLastImageLayout(); | 1160 | VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout(); |
| 1123 | *image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; | 1161 | *image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; |
| 1124 | sampled_views.push_back(ImageView{std::move(view), image_layout}); | 1162 | sampled_views.push_back(ImageView{std::move(view), image_layout}); |
| 1125 | } | 1163 | } |
| 1126 | 1164 | ||
| 1165 | void RasterizerVulkan::SetupStorageTexel(const Tegra::Texture::TICEntry& tic, | ||
| 1166 | const StorageTexelEntry& entry) { | ||
| 1167 | const auto view = texture_cache.GetImageSurface(tic, entry); | ||
| 1168 | ASSERT(view->IsBufferView()); | ||
| 1169 | |||
| 1170 | update_descriptor_queue.AddTexelBuffer(view->GetBufferView()); | ||
| 1171 | } | ||
| 1172 | |||
| 1127 | void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry) { | 1173 | void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry) { |
| 1128 | auto view = texture_cache.GetImageSurface(tic, entry); | 1174 | auto view = texture_cache.GetImageSurface(tic, entry); |
| 1129 | 1175 | ||
| @@ -1133,10 +1179,11 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima | |||
| 1133 | 1179 | ||
| 1134 | UNIMPLEMENTED_IF(tic.IsBuffer()); | 1180 | UNIMPLEMENTED_IF(tic.IsBuffer()); |
| 1135 | 1181 | ||
| 1136 | const auto image_view = view->GetHandle(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | 1182 | const VkImageView image_view = |
| 1183 | view->GetImageView(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | ||
| 1137 | update_descriptor_queue.AddImage(image_view); | 1184 | update_descriptor_queue.AddImage(image_view); |
| 1138 | 1185 | ||
| 1139 | const auto image_layout = update_descriptor_queue.GetLastImageLayout(); | 1186 | VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout(); |
| 1140 | *image_layout = VK_IMAGE_LAYOUT_GENERAL; | 1187 | *image_layout = VK_IMAGE_LAYOUT_GENERAL; |
| 1141 | image_views.push_back(ImageView{std::move(view), image_layout}); | 1188 | image_views.push_back(ImageView{std::move(view), image_layout}); |
| 1142 | } | 1189 | } |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 0ed0e48c6..c8c187606 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -168,7 +168,7 @@ private: | |||
| 168 | bool is_indexed, bool is_instanced); | 168 | bool is_indexed, bool is_instanced); |
| 169 | 169 | ||
| 170 | /// Setup descriptors in the graphics pipeline. | 170 | /// Setup descriptors in the graphics pipeline. |
| 171 | void SetupShaderDescriptors(const std::array<Shader, Maxwell::MaxShaderProgram>& shaders); | 171 | void SetupShaderDescriptors(const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders); |
| 172 | 172 | ||
| 173 | void SetupImageTransitions(Texceptions texceptions, | 173 | void SetupImageTransitions(Texceptions texceptions, |
| 174 | const std::array<View, Maxwell::NumRenderTargets>& color_attachments, | 174 | const std::array<View, Maxwell::NumRenderTargets>& color_attachments, |
| @@ -193,12 +193,15 @@ private: | |||
| 193 | /// Setup global buffers in the graphics pipeline. | 193 | /// Setup global buffers in the graphics pipeline. |
| 194 | void SetupGraphicsGlobalBuffers(const ShaderEntries& entries, std::size_t stage); | 194 | void SetupGraphicsGlobalBuffers(const ShaderEntries& entries, std::size_t stage); |
| 195 | 195 | ||
| 196 | /// Setup texel buffers in the graphics pipeline. | 196 | /// Setup uniform texels in the graphics pipeline. |
| 197 | void SetupGraphicsTexelBuffers(const ShaderEntries& entries, std::size_t stage); | 197 | void SetupGraphicsUniformTexels(const ShaderEntries& entries, std::size_t stage); |
| 198 | 198 | ||
| 199 | /// Setup textures in the graphics pipeline. | 199 | /// Setup textures in the graphics pipeline. |
| 200 | void SetupGraphicsTextures(const ShaderEntries& entries, std::size_t stage); | 200 | void SetupGraphicsTextures(const ShaderEntries& entries, std::size_t stage); |
| 201 | 201 | ||
| 202 | /// Setup storage texels in the graphics pipeline. | ||
| 203 | void SetupGraphicsStorageTexels(const ShaderEntries& entries, std::size_t stage); | ||
| 204 | |||
| 202 | /// Setup images in the graphics pipeline. | 205 | /// Setup images in the graphics pipeline. |
| 203 | void SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage); | 206 | void SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage); |
| 204 | 207 | ||
| @@ -209,11 +212,14 @@ private: | |||
| 209 | void SetupComputeGlobalBuffers(const ShaderEntries& entries); | 212 | void SetupComputeGlobalBuffers(const ShaderEntries& entries); |
| 210 | 213 | ||
| 211 | /// Setup texel buffers in the compute pipeline. | 214 | /// Setup texel buffers in the compute pipeline. |
| 212 | void SetupComputeTexelBuffers(const ShaderEntries& entries); | 215 | void SetupComputeUniformTexels(const ShaderEntries& entries); |
| 213 | 216 | ||
| 214 | /// Setup textures in the compute pipeline. | 217 | /// Setup textures in the compute pipeline. |
| 215 | void SetupComputeTextures(const ShaderEntries& entries); | 218 | void SetupComputeTextures(const ShaderEntries& entries); |
| 216 | 219 | ||
| 220 | /// Setup storage texels in the compute pipeline. | ||
| 221 | void SetupComputeStorageTexels(const ShaderEntries& entries); | ||
| 222 | |||
| 217 | /// Setup images in the compute pipeline. | 223 | /// Setup images in the compute pipeline. |
| 218 | void SetupComputeImages(const ShaderEntries& entries); | 224 | void SetupComputeImages(const ShaderEntries& entries); |
| 219 | 225 | ||
| @@ -222,10 +228,12 @@ private: | |||
| 222 | 228 | ||
| 223 | void SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address); | 229 | void SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address); |
| 224 | 230 | ||
| 225 | void SetupTexelBuffer(const Tegra::Texture::TICEntry& image, const TexelBufferEntry& entry); | 231 | void SetupUniformTexels(const Tegra::Texture::TICEntry& image, const UniformTexelEntry& entry); |
| 226 | 232 | ||
| 227 | void SetupTexture(const Tegra::Texture::FullTextureInfo& texture, const SamplerEntry& entry); | 233 | void SetupTexture(const Tegra::Texture::FullTextureInfo& texture, const SamplerEntry& entry); |
| 228 | 234 | ||
| 235 | void SetupStorageTexel(const Tegra::Texture::TICEntry& tic, const StorageTexelEntry& entry); | ||
| 236 | |||
| 229 | void SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry); | 237 | void SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry); |
| 230 | 238 | ||
| 231 | void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs); | 239 | void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs); |
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp index e6f2fa553..616eacc36 100644 --- a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include "video_core/renderer_vulkan/wrapper.h" | 9 | #include "video_core/renderer_vulkan/wrapper.h" |
| 10 | #include "video_core/textures/texture.h" | 10 | #include "video_core/textures/texture.h" |
| 11 | 11 | ||
| 12 | using Tegra::Texture::TextureMipmapFilter; | ||
| 13 | |||
| 12 | namespace Vulkan { | 14 | namespace Vulkan { |
| 13 | 15 | ||
| 14 | namespace { | 16 | namespace { |
| @@ -63,8 +65,8 @@ vk::Sampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) c | |||
| 63 | ci.maxAnisotropy = tsc.GetMaxAnisotropy(); | 65 | ci.maxAnisotropy = tsc.GetMaxAnisotropy(); |
| 64 | ci.compareEnable = tsc.depth_compare_enabled; | 66 | ci.compareEnable = tsc.depth_compare_enabled; |
| 65 | ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); | 67 | ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); |
| 66 | ci.minLod = tsc.GetMinLod(); | 68 | ci.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(); |
| 67 | ci.maxLod = tsc.GetMaxLod(); | 69 | ci.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(); |
| 68 | ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); | 70 | ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); |
| 69 | ci.unnormalizedCoordinates = VK_FALSE; | 71 | ci.unnormalizedCoordinates = VK_FALSE; |
| 70 | return device.GetLogical().CreateSampler(ci); | 72 | return device.GetLogical().CreateSampler(ci); |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 6f6dedd82..97429cc59 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -400,8 +400,9 @@ private: | |||
| 400 | u32 binding = specialization.base_binding; | 400 | u32 binding = specialization.base_binding; |
| 401 | binding = DeclareConstantBuffers(binding); | 401 | binding = DeclareConstantBuffers(binding); |
| 402 | binding = DeclareGlobalBuffers(binding); | 402 | binding = DeclareGlobalBuffers(binding); |
| 403 | binding = DeclareTexelBuffers(binding); | 403 | binding = DeclareUniformTexels(binding); |
| 404 | binding = DeclareSamplers(binding); | 404 | binding = DeclareSamplers(binding); |
| 405 | binding = DeclareStorageTexels(binding); | ||
| 405 | binding = DeclareImages(binding); | 406 | binding = DeclareImages(binding); |
| 406 | 407 | ||
| 407 | const Id main = OpFunction(t_void, {}, TypeFunction(t_void)); | 408 | const Id main = OpFunction(t_void, {}, TypeFunction(t_void)); |
| @@ -741,8 +742,10 @@ private: | |||
| 741 | if (!IsGenericAttribute(index)) { | 742 | if (!IsGenericAttribute(index)) { |
| 742 | continue; | 743 | continue; |
| 743 | } | 744 | } |
| 744 | |||
| 745 | const u32 location = GetGenericAttributeLocation(index); | 745 | const u32 location = GetGenericAttributeLocation(index); |
| 746 | if (!IsAttributeEnabled(location)) { | ||
| 747 | continue; | ||
| 748 | } | ||
| 746 | const auto type_descriptor = GetAttributeType(location); | 749 | const auto type_descriptor = GetAttributeType(location); |
| 747 | Id type; | 750 | Id type; |
| 748 | if (IsInputAttributeArray()) { | 751 | if (IsInputAttributeArray()) { |
| @@ -887,7 +890,7 @@ private: | |||
| 887 | return binding; | 890 | return binding; |
| 888 | } | 891 | } |
| 889 | 892 | ||
| 890 | u32 DeclareTexelBuffers(u32 binding) { | 893 | u32 DeclareUniformTexels(u32 binding) { |
| 891 | for (const auto& sampler : ir.GetSamplers()) { | 894 | for (const auto& sampler : ir.GetSamplers()) { |
| 892 | if (!sampler.is_buffer) { | 895 | if (!sampler.is_buffer) { |
| 893 | continue; | 896 | continue; |
| @@ -908,7 +911,7 @@ private: | |||
| 908 | Decorate(id, spv::Decoration::Binding, binding++); | 911 | Decorate(id, spv::Decoration::Binding, binding++); |
| 909 | Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); | 912 | Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); |
| 910 | 913 | ||
| 911 | texel_buffers.emplace(sampler.index, TexelBuffer{image_type, id}); | 914 | uniform_texels.emplace(sampler.index, TexelBuffer{image_type, id}); |
| 912 | } | 915 | } |
| 913 | return binding; | 916 | return binding; |
| 914 | } | 917 | } |
| @@ -943,31 +946,48 @@ private: | |||
| 943 | return binding; | 946 | return binding; |
| 944 | } | 947 | } |
| 945 | 948 | ||
| 946 | u32 DeclareImages(u32 binding) { | 949 | u32 DeclareStorageTexels(u32 binding) { |
| 947 | for (const auto& image : ir.GetImages()) { | 950 | for (const auto& image : ir.GetImages()) { |
| 948 | const auto [dim, arrayed] = GetImageDim(image); | 951 | if (image.type != Tegra::Shader::ImageType::TextureBuffer) { |
| 949 | constexpr int depth = 0; | 952 | continue; |
| 950 | constexpr bool ms = false; | ||
| 951 | constexpr int sampled = 2; // This won't be accessed with a sampler | ||
| 952 | constexpr auto format = spv::ImageFormat::Unknown; | ||
| 953 | const Id image_type = TypeImage(t_uint, dim, depth, arrayed, ms, sampled, format, {}); | ||
| 954 | const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type); | ||
| 955 | const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); | ||
| 956 | AddGlobalVariable(Name(id, fmt::format("image_{}", image.index))); | ||
| 957 | |||
| 958 | Decorate(id, spv::Decoration::Binding, binding++); | ||
| 959 | Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); | ||
| 960 | if (image.is_read && !image.is_written) { | ||
| 961 | Decorate(id, spv::Decoration::NonWritable); | ||
| 962 | } else if (image.is_written && !image.is_read) { | ||
| 963 | Decorate(id, spv::Decoration::NonReadable); | ||
| 964 | } | 953 | } |
| 954 | DeclareImage(image, binding); | ||
| 955 | } | ||
| 956 | return binding; | ||
| 957 | } | ||
| 965 | 958 | ||
| 966 | images.emplace(image.index, StorageImage{image_type, id}); | 959 | u32 DeclareImages(u32 binding) { |
| 960 | for (const auto& image : ir.GetImages()) { | ||
| 961 | if (image.type == Tegra::Shader::ImageType::TextureBuffer) { | ||
| 962 | continue; | ||
| 963 | } | ||
| 964 | DeclareImage(image, binding); | ||
| 967 | } | 965 | } |
| 968 | return binding; | 966 | return binding; |
| 969 | } | 967 | } |
| 970 | 968 | ||
| 969 | void DeclareImage(const Image& image, u32& binding) { | ||
| 970 | const auto [dim, arrayed] = GetImageDim(image); | ||
| 971 | constexpr int depth = 0; | ||
| 972 | constexpr bool ms = false; | ||
| 973 | constexpr int sampled = 2; // This won't be accessed with a sampler | ||
| 974 | const auto format = image.is_atomic ? spv::ImageFormat::R32ui : spv::ImageFormat::Unknown; | ||
| 975 | const Id image_type = TypeImage(t_uint, dim, depth, arrayed, ms, sampled, format, {}); | ||
| 976 | const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type); | ||
| 977 | const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); | ||
| 978 | AddGlobalVariable(Name(id, fmt::format("image_{}", image.index))); | ||
| 979 | |||
| 980 | Decorate(id, spv::Decoration::Binding, binding++); | ||
| 981 | Decorate(id, spv::Decoration::DescriptorSet, DESCRIPTOR_SET); | ||
| 982 | if (image.is_read && !image.is_written) { | ||
| 983 | Decorate(id, spv::Decoration::NonWritable); | ||
| 984 | } else if (image.is_written && !image.is_read) { | ||
| 985 | Decorate(id, spv::Decoration::NonReadable); | ||
| 986 | } | ||
| 987 | |||
| 988 | images.emplace(image.index, StorageImage{image_type, id}); | ||
| 989 | } | ||
| 990 | |||
| 971 | bool IsRenderTargetEnabled(u32 rt) const { | 991 | bool IsRenderTargetEnabled(u32 rt) const { |
| 972 | for (u32 component = 0; component < 4; ++component) { | 992 | for (u32 component = 0; component < 4; ++component) { |
| 973 | if (header.ps.IsColorComponentOutputEnabled(rt, component)) { | 993 | if (header.ps.IsColorComponentOutputEnabled(rt, component)) { |
| @@ -986,6 +1006,10 @@ private: | |||
| 986 | return stage == ShaderType::TesselationControl; | 1006 | return stage == ShaderType::TesselationControl; |
| 987 | } | 1007 | } |
| 988 | 1008 | ||
| 1009 | bool IsAttributeEnabled(u32 location) const { | ||
| 1010 | return stage != ShaderType::Vertex || specialization.enabled_attributes[location]; | ||
| 1011 | } | ||
| 1012 | |||
| 989 | u32 GetNumInputVertices() const { | 1013 | u32 GetNumInputVertices() const { |
| 990 | switch (stage) { | 1014 | switch (stage) { |
| 991 | case ShaderType::Geometry: | 1015 | case ShaderType::Geometry: |
| @@ -1201,16 +1225,20 @@ private: | |||
| 1201 | UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element); | 1225 | UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element); |
| 1202 | return {v_float_zero, Type::Float}; | 1226 | return {v_float_zero, Type::Float}; |
| 1203 | default: | 1227 | default: |
| 1204 | if (IsGenericAttribute(attribute)) { | 1228 | if (!IsGenericAttribute(attribute)) { |
| 1205 | const u32 location = GetGenericAttributeLocation(attribute); | 1229 | break; |
| 1206 | const auto type_descriptor = GetAttributeType(location); | ||
| 1207 | const Type type = type_descriptor.type; | ||
| 1208 | const Id attribute_id = input_attributes.at(attribute); | ||
| 1209 | const std::vector elements = {element}; | ||
| 1210 | const Id pointer = ArrayPass(type_descriptor.scalar, attribute_id, elements); | ||
| 1211 | return {OpLoad(GetTypeDefinition(type), pointer), type}; | ||
| 1212 | } | 1230 | } |
| 1213 | break; | 1231 | const u32 location = GetGenericAttributeLocation(attribute); |
| 1232 | if (!IsAttributeEnabled(location)) { | ||
| 1233 | // Disabled attributes (also known as constant attributes) always return zero. | ||
| 1234 | return {v_float_zero, Type::Float}; | ||
| 1235 | } | ||
| 1236 | const auto type_descriptor = GetAttributeType(location); | ||
| 1237 | const Type type = type_descriptor.type; | ||
| 1238 | const Id attribute_id = input_attributes.at(attribute); | ||
| 1239 | const std::vector elements = {element}; | ||
| 1240 | const Id pointer = ArrayPass(type_descriptor.scalar, attribute_id, elements); | ||
| 1241 | return {OpLoad(GetTypeDefinition(type), pointer), type}; | ||
| 1214 | } | 1242 | } |
| 1215 | UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); | 1243 | UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); |
| 1216 | return {v_float_zero, Type::Float}; | 1244 | return {v_float_zero, Type::Float}; |
| @@ -1246,7 +1274,7 @@ private: | |||
| 1246 | } else { | 1274 | } else { |
| 1247 | UNREACHABLE_MSG("Unmanaged offset node type"); | 1275 | UNREACHABLE_MSG("Unmanaged offset node type"); |
| 1248 | } | 1276 | } |
| 1249 | pointer = OpAccessChain(t_cbuf_float, buffer_id, Constant(t_uint, 0), buffer_index, | 1277 | pointer = OpAccessChain(t_cbuf_float, buffer_id, v_uint_zero, buffer_index, |
| 1250 | buffer_element); | 1278 | buffer_element); |
| 1251 | } | 1279 | } |
| 1252 | return {OpLoad(t_float, pointer), Type::Float}; | 1280 | return {OpLoad(t_float, pointer), Type::Float}; |
| @@ -1601,7 +1629,7 @@ private: | |||
| 1601 | 1629 | ||
| 1602 | const Id result = OpIAddCarry(TypeStruct({t_uint, t_uint}), op_a, op_b); | 1630 | const Id result = OpIAddCarry(TypeStruct({t_uint, t_uint}), op_a, op_b); |
| 1603 | const Id carry = OpCompositeExtract(t_uint, result, 1); | 1631 | const Id carry = OpCompositeExtract(t_uint, result, 1); |
| 1604 | return {OpINotEqual(t_bool, carry, Constant(t_uint, 0)), Type::Bool}; | 1632 | return {OpINotEqual(t_bool, carry, v_uint_zero), Type::Bool}; |
| 1605 | } | 1633 | } |
| 1606 | 1634 | ||
| 1607 | Expression LogicalAssign(Operation operation) { | 1635 | Expression LogicalAssign(Operation operation) { |
| @@ -1664,7 +1692,7 @@ private: | |||
| 1664 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); | 1692 | const auto& meta = std::get<MetaTexture>(operation.GetMeta()); |
| 1665 | const u32 index = meta.sampler.index; | 1693 | const u32 index = meta.sampler.index; |
| 1666 | if (meta.sampler.is_buffer) { | 1694 | if (meta.sampler.is_buffer) { |
| 1667 | const auto& entry = texel_buffers.at(index); | 1695 | const auto& entry = uniform_texels.at(index); |
| 1668 | return OpLoad(entry.image_type, entry.image); | 1696 | return OpLoad(entry.image_type, entry.image); |
| 1669 | } else { | 1697 | } else { |
| 1670 | const auto& entry = sampled_images.at(index); | 1698 | const auto& entry = sampled_images.at(index); |
| @@ -1941,39 +1969,20 @@ private: | |||
| 1941 | return {}; | 1969 | return {}; |
| 1942 | } | 1970 | } |
| 1943 | 1971 | ||
| 1944 | Expression AtomicImageAdd(Operation operation) { | 1972 | template <Id (Module::*func)(Id, Id, Id, Id, Id)> |
| 1945 | UNIMPLEMENTED(); | 1973 | Expression AtomicImage(Operation operation) { |
| 1946 | return {}; | 1974 | const auto& meta{std::get<MetaImage>(operation.GetMeta())}; |
| 1947 | } | 1975 | ASSERT(meta.values.size() == 1); |
| 1948 | |||
| 1949 | Expression AtomicImageMin(Operation operation) { | ||
| 1950 | UNIMPLEMENTED(); | ||
| 1951 | return {}; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | Expression AtomicImageMax(Operation operation) { | ||
| 1955 | UNIMPLEMENTED(); | ||
| 1956 | return {}; | ||
| 1957 | } | ||
| 1958 | |||
| 1959 | Expression AtomicImageAnd(Operation operation) { | ||
| 1960 | UNIMPLEMENTED(); | ||
| 1961 | return {}; | ||
| 1962 | } | ||
| 1963 | |||
| 1964 | Expression AtomicImageOr(Operation operation) { | ||
| 1965 | UNIMPLEMENTED(); | ||
| 1966 | return {}; | ||
| 1967 | } | ||
| 1968 | 1976 | ||
| 1969 | Expression AtomicImageXor(Operation operation) { | 1977 | const Id coordinate = GetCoordinates(operation, Type::Int); |
| 1970 | UNIMPLEMENTED(); | 1978 | const Id image = images.at(meta.image.index).image; |
| 1971 | return {}; | 1979 | const Id sample = v_uint_zero; |
| 1972 | } | 1980 | const Id pointer = OpImageTexelPointer(t_image_uint, image, coordinate, sample); |
| 1973 | 1981 | ||
| 1974 | Expression AtomicImageExchange(Operation operation) { | 1982 | const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); |
| 1975 | UNIMPLEMENTED(); | 1983 | const Id semantics = v_uint_zero; |
| 1976 | return {}; | 1984 | const Id value = AsUint(Visit(meta.values[0])); |
| 1985 | return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint}; | ||
| 1977 | } | 1986 | } |
| 1978 | 1987 | ||
| 1979 | template <Id (Module::*func)(Id, Id, Id, Id, Id)> | 1988 | template <Id (Module::*func)(Id, Id, Id, Id, Id)> |
| @@ -1988,7 +1997,7 @@ private: | |||
| 1988 | return {v_float_zero, Type::Float}; | 1997 | return {v_float_zero, Type::Float}; |
| 1989 | } | 1998 | } |
| 1990 | const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); | 1999 | const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); |
| 1991 | const Id semantics = Constant(t_uint, 0); | 2000 | const Id semantics = v_uint_zero; |
| 1992 | const Id value = AsUint(Visit(operation[1])); | 2001 | const Id value = AsUint(Visit(operation[1])); |
| 1993 | 2002 | ||
| 1994 | return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint}; | 2003 | return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint}; |
| @@ -2612,11 +2621,11 @@ private: | |||
| 2612 | 2621 | ||
| 2613 | &SPIRVDecompiler::ImageLoad, | 2622 | &SPIRVDecompiler::ImageLoad, |
| 2614 | &SPIRVDecompiler::ImageStore, | 2623 | &SPIRVDecompiler::ImageStore, |
| 2615 | &SPIRVDecompiler::AtomicImageAdd, | 2624 | &SPIRVDecompiler::AtomicImage<&Module::OpAtomicIAdd>, |
| 2616 | &SPIRVDecompiler::AtomicImageAnd, | 2625 | &SPIRVDecompiler::AtomicImage<&Module::OpAtomicAnd>, |
| 2617 | &SPIRVDecompiler::AtomicImageOr, | 2626 | &SPIRVDecompiler::AtomicImage<&Module::OpAtomicOr>, |
| 2618 | &SPIRVDecompiler::AtomicImageXor, | 2627 | &SPIRVDecompiler::AtomicImage<&Module::OpAtomicXor>, |
| 2619 | &SPIRVDecompiler::AtomicImageExchange, | 2628 | &SPIRVDecompiler::AtomicImage<&Module::OpAtomicExchange>, |
| 2620 | 2629 | ||
| 2621 | &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>, | 2630 | &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>, |
| 2622 | &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>, | 2631 | &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>, |
| @@ -2758,8 +2767,11 @@ private: | |||
| 2758 | Decorate(TypeStruct(t_gmem_array), spv::Decoration::Block), 0, spv::Decoration::Offset, 0); | 2767 | Decorate(TypeStruct(t_gmem_array), spv::Decoration::Block), 0, spv::Decoration::Offset, 0); |
| 2759 | const Id t_gmem_ssbo = TypePointer(spv::StorageClass::StorageBuffer, t_gmem_struct); | 2768 | const Id t_gmem_ssbo = TypePointer(spv::StorageClass::StorageBuffer, t_gmem_struct); |
| 2760 | 2769 | ||
| 2770 | const Id t_image_uint = TypePointer(spv::StorageClass::Image, t_uint); | ||
| 2771 | |||
| 2761 | const Id v_float_zero = Constant(t_float, 0.0f); | 2772 | const Id v_float_zero = Constant(t_float, 0.0f); |
| 2762 | const Id v_float_one = Constant(t_float, 1.0f); | 2773 | const Id v_float_one = Constant(t_float, 1.0f); |
| 2774 | const Id v_uint_zero = Constant(t_uint, 0); | ||
| 2763 | 2775 | ||
| 2764 | // Nvidia uses these defaults for varyings (e.g. position and generic attributes) | 2776 | // Nvidia uses these defaults for varyings (e.g. position and generic attributes) |
| 2765 | const Id v_varying_default = | 2777 | const Id v_varying_default = |
| @@ -2784,15 +2796,16 @@ private: | |||
| 2784 | std::unordered_map<u8, GenericVaryingDescription> output_attributes; | 2796 | std::unordered_map<u8, GenericVaryingDescription> output_attributes; |
| 2785 | std::map<u32, Id> constant_buffers; | 2797 | std::map<u32, Id> constant_buffers; |
| 2786 | std::map<GlobalMemoryBase, Id> global_buffers; | 2798 | std::map<GlobalMemoryBase, Id> global_buffers; |
| 2787 | std::map<u32, TexelBuffer> texel_buffers; | 2799 | std::map<u32, TexelBuffer> uniform_texels; |
| 2788 | std::map<u32, SampledImage> sampled_images; | 2800 | std::map<u32, SampledImage> sampled_images; |
| 2801 | std::map<u32, TexelBuffer> storage_texels; | ||
| 2789 | std::map<u32, StorageImage> images; | 2802 | std::map<u32, StorageImage> images; |
| 2790 | 2803 | ||
| 2804 | std::array<Id, Maxwell::NumRenderTargets> frag_colors{}; | ||
| 2791 | Id instance_index{}; | 2805 | Id instance_index{}; |
| 2792 | Id vertex_index{}; | 2806 | Id vertex_index{}; |
| 2793 | Id base_instance{}; | 2807 | Id base_instance{}; |
| 2794 | Id base_vertex{}; | 2808 | Id base_vertex{}; |
| 2795 | std::array<Id, Maxwell::NumRenderTargets> frag_colors{}; | ||
| 2796 | Id frag_depth{}; | 2809 | Id frag_depth{}; |
| 2797 | Id frag_coord{}; | 2810 | Id frag_coord{}; |
| 2798 | Id front_facing{}; | 2811 | Id front_facing{}; |
| @@ -3048,13 +3061,17 @@ ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir) { | |||
| 3048 | } | 3061 | } |
| 3049 | for (const auto& sampler : ir.GetSamplers()) { | 3062 | for (const auto& sampler : ir.GetSamplers()) { |
| 3050 | if (sampler.is_buffer) { | 3063 | if (sampler.is_buffer) { |
| 3051 | entries.texel_buffers.emplace_back(sampler); | 3064 | entries.uniform_texels.emplace_back(sampler); |
| 3052 | } else { | 3065 | } else { |
| 3053 | entries.samplers.emplace_back(sampler); | 3066 | entries.samplers.emplace_back(sampler); |
| 3054 | } | 3067 | } |
| 3055 | } | 3068 | } |
| 3056 | for (const auto& image : ir.GetImages()) { | 3069 | for (const auto& image : ir.GetImages()) { |
| 3057 | entries.images.emplace_back(image); | 3070 | if (image.type == Tegra::Shader::ImageType::TextureBuffer) { |
| 3071 | entries.storage_texels.emplace_back(image); | ||
| 3072 | } else { | ||
| 3073 | entries.images.emplace_back(image); | ||
| 3074 | } | ||
| 3058 | } | 3075 | } |
| 3059 | for (const auto& attribute : ir.GetInputAttributes()) { | 3076 | for (const auto& attribute : ir.GetInputAttributes()) { |
| 3060 | if (IsGenericAttribute(attribute)) { | 3077 | if (IsGenericAttribute(attribute)) { |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h index f4c05ac3c..2b0e90396 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h | |||
| @@ -21,8 +21,9 @@ class VKDevice; | |||
| 21 | namespace Vulkan { | 21 | namespace Vulkan { |
| 22 | 22 | ||
| 23 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 23 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 24 | using TexelBufferEntry = VideoCommon::Shader::Sampler; | 24 | using UniformTexelEntry = VideoCommon::Shader::Sampler; |
| 25 | using SamplerEntry = VideoCommon::Shader::Sampler; | 25 | using SamplerEntry = VideoCommon::Shader::Sampler; |
| 26 | using StorageTexelEntry = VideoCommon::Shader::Image; | ||
| 26 | using ImageEntry = VideoCommon::Shader::Image; | 27 | using ImageEntry = VideoCommon::Shader::Image; |
| 27 | 28 | ||
| 28 | constexpr u32 DESCRIPTOR_SET = 0; | 29 | constexpr u32 DESCRIPTOR_SET = 0; |
| @@ -66,13 +67,15 @@ private: | |||
| 66 | struct ShaderEntries { | 67 | struct ShaderEntries { |
| 67 | u32 NumBindings() const { | 68 | u32 NumBindings() const { |
| 68 | return static_cast<u32>(const_buffers.size() + global_buffers.size() + | 69 | return static_cast<u32>(const_buffers.size() + global_buffers.size() + |
| 69 | texel_buffers.size() + samplers.size() + images.size()); | 70 | uniform_texels.size() + samplers.size() + storage_texels.size() + |
| 71 | images.size()); | ||
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | std::vector<ConstBufferEntry> const_buffers; | 74 | std::vector<ConstBufferEntry> const_buffers; |
| 73 | std::vector<GlobalBufferEntry> global_buffers; | 75 | std::vector<GlobalBufferEntry> global_buffers; |
| 74 | std::vector<TexelBufferEntry> texel_buffers; | 76 | std::vector<UniformTexelEntry> uniform_texels; |
| 75 | std::vector<SamplerEntry> samplers; | 77 | std::vector<SamplerEntry> samplers; |
| 78 | std::vector<StorageTexelEntry> storage_texels; | ||
| 76 | std::vector<ImageEntry> images; | 79 | std::vector<ImageEntry> images; |
| 77 | std::set<u32> attributes; | 80 | std::set<u32> attributes; |
| 78 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | 81 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; |
| @@ -88,7 +91,8 @@ struct Specialization final { | |||
| 88 | u32 shared_memory_size{}; | 91 | u32 shared_memory_size{}; |
| 89 | 92 | ||
| 90 | // Graphics specific | 93 | // Graphics specific |
| 91 | std::optional<float> point_size{}; | 94 | std::optional<float> point_size; |
| 95 | std::bitset<Maxwell::NumVertexAttributes> enabled_attributes; | ||
| 92 | std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; | 96 | std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; |
| 93 | bool ndc_minus_one_to_one{}; | 97 | bool ndc_minus_one_to_one{}; |
| 94 | }; | 98 | }; |
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h index dfddf7ad6..689f0d276 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.h +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.h | |||
| @@ -35,10 +35,14 @@ public: | |||
| 35 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. | 35 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. |
| 36 | void Unmap(u64 size); | 36 | void Unmap(u64 size); |
| 37 | 37 | ||
| 38 | VkBuffer GetHandle() const { | 38 | VkBuffer Handle() const noexcept { |
| 39 | return *buffer; | 39 | return *buffer; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | u64 Address() const noexcept { | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 42 | private: | 46 | private: |
| 43 | struct Watch final { | 47 | struct Watch final { |
| 44 | VKFenceWatch fence; | 48 | VKFenceWatch fence; |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 2f1d5021d..430031665 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -100,8 +100,8 @@ vk::Buffer CreateBuffer(const VKDevice& device, const SurfaceParams& params, | |||
| 100 | ci.pNext = nullptr; | 100 | ci.pNext = nullptr; |
| 101 | ci.flags = 0; | 101 | ci.flags = 0; |
| 102 | ci.size = static_cast<VkDeviceSize>(host_memory_size); | 102 | ci.size = static_cast<VkDeviceSize>(host_memory_size); |
| 103 | ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | | 103 | ci.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | |
| 104 | VK_BUFFER_USAGE_TRANSFER_DST_BIT; | 104 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| 105 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | 105 | ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| 106 | ci.queueFamilyIndexCount = 0; | 106 | ci.queueFamilyIndexCount = 0; |
| 107 | ci.pQueueFamilyIndices = nullptr; | 107 | ci.pQueueFamilyIndices = nullptr; |
| @@ -167,6 +167,7 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP | |||
| 167 | ci.extent = {params.width, params.height, 1}; | 167 | ci.extent = {params.width, params.height, 1}; |
| 168 | break; | 168 | break; |
| 169 | case SurfaceTarget::Texture3D: | 169 | case SurfaceTarget::Texture3D: |
| 170 | ci.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; | ||
| 170 | ci.extent = {params.width, params.height, params.depth}; | 171 | ci.extent = {params.width, params.height, params.depth}; |
| 171 | break; | 172 | break; |
| 172 | case SurfaceTarget::TextureBuffer: | 173 | case SurfaceTarget::TextureBuffer: |
| @@ -176,6 +177,12 @@ VkImageCreateInfo GenerateImageCreateInfo(const VKDevice& device, const SurfaceP | |||
| 176 | return ci; | 177 | return ci; |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 180 | u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, Tegra::Texture::SwizzleSource y_source, | ||
| 181 | Tegra::Texture::SwizzleSource z_source, Tegra::Texture::SwizzleSource w_source) { | ||
| 182 | return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) | | ||
| 183 | (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source); | ||
| 184 | } | ||
| 185 | |||
| 179 | } // Anonymous namespace | 186 | } // Anonymous namespace |
| 180 | 187 | ||
| 181 | CachedSurface::CachedSurface(Core::System& system, const VKDevice& device, | 188 | CachedSurface::CachedSurface(Core::System& system, const VKDevice& device, |
| @@ -203,9 +210,11 @@ CachedSurface::CachedSurface(Core::System& system, const VKDevice& device, | |||
| 203 | } | 210 | } |
| 204 | 211 | ||
| 205 | // TODO(Rodrigo): Move this to a virtual function. | 212 | // TODO(Rodrigo): Move this to a virtual function. |
| 206 | main_view = CreateViewInner( | 213 | u32 num_layers = 1; |
| 207 | ViewParams(params.target, 0, static_cast<u32>(params.GetNumLayers()), 0, params.num_levels), | 214 | if (params.is_layered || params.target == SurfaceTarget::Texture3D) { |
| 208 | true); | 215 | num_layers = params.depth; |
| 216 | } | ||
| 217 | main_view = CreateView(ViewParams(params.target, 0, num_layers, 0, params.num_levels)); | ||
| 209 | } | 218 | } |
| 210 | 219 | ||
| 211 | CachedSurface::~CachedSurface() = default; | 220 | CachedSurface::~CachedSurface() = default; |
| @@ -253,12 +262,8 @@ void CachedSurface::DecorateSurfaceName() { | |||
| 253 | } | 262 | } |
| 254 | 263 | ||
| 255 | View CachedSurface::CreateView(const ViewParams& params) { | 264 | View CachedSurface::CreateView(const ViewParams& params) { |
| 256 | return CreateViewInner(params, false); | ||
| 257 | } | ||
| 258 | |||
| 259 | View CachedSurface::CreateViewInner(const ViewParams& params, bool is_proxy) { | ||
| 260 | // TODO(Rodrigo): Add name decorations | 265 | // TODO(Rodrigo): Add name decorations |
| 261 | return views[params] = std::make_shared<CachedSurfaceView>(device, *this, params, is_proxy); | 266 | return views[params] = std::make_shared<CachedSurfaceView>(device, *this, params); |
| 262 | } | 267 | } |
| 263 | 268 | ||
| 264 | void CachedSurface::UploadBuffer(const std::vector<u8>& staging_buffer) { | 269 | void CachedSurface::UploadBuffer(const std::vector<u8>& staging_buffer) { |
| @@ -342,18 +347,27 @@ VkImageSubresourceRange CachedSurface::GetImageSubresourceRange() const { | |||
| 342 | } | 347 | } |
| 343 | 348 | ||
| 344 | CachedSurfaceView::CachedSurfaceView(const VKDevice& device, CachedSurface& surface, | 349 | CachedSurfaceView::CachedSurfaceView(const VKDevice& device, CachedSurface& surface, |
| 345 | const ViewParams& params, bool is_proxy) | 350 | const ViewParams& params) |
| 346 | : VideoCommon::ViewBase{params}, params{surface.GetSurfaceParams()}, | 351 | : VideoCommon::ViewBase{params}, params{surface.GetSurfaceParams()}, |
| 347 | image{surface.GetImageHandle()}, buffer_view{surface.GetBufferViewHandle()}, | 352 | image{surface.GetImageHandle()}, buffer_view{surface.GetBufferViewHandle()}, |
| 348 | aspect_mask{surface.GetAspectMask()}, device{device}, surface{surface}, | 353 | aspect_mask{surface.GetAspectMask()}, device{device}, surface{surface}, |
| 349 | base_layer{params.base_layer}, num_layers{params.num_layers}, base_level{params.base_level}, | 354 | base_level{params.base_level}, num_levels{params.num_levels}, |
| 350 | num_levels{params.num_levels}, image_view_type{image ? GetImageViewType(params.target) | 355 | image_view_type{image ? GetImageViewType(params.target) : VK_IMAGE_VIEW_TYPE_1D} { |
| 351 | : VK_IMAGE_VIEW_TYPE_1D} {} | 356 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { |
| 357 | base_layer = 0; | ||
| 358 | num_layers = 1; | ||
| 359 | base_slice = params.base_layer; | ||
| 360 | num_slices = params.num_layers; | ||
| 361 | } else { | ||
| 362 | base_layer = params.base_layer; | ||
| 363 | num_layers = params.num_layers; | ||
| 364 | } | ||
| 365 | } | ||
| 352 | 366 | ||
| 353 | CachedSurfaceView::~CachedSurfaceView() = default; | 367 | CachedSurfaceView::~CachedSurfaceView() = default; |
| 354 | 368 | ||
| 355 | VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source, | 369 | VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSource y_source, |
| 356 | SwizzleSource z_source, SwizzleSource w_source) { | 370 | SwizzleSource z_source, SwizzleSource w_source) { |
| 357 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); | 371 | const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); |
| 358 | if (last_image_view && last_swizzle == new_swizzle) { | 372 | if (last_image_view && last_swizzle == new_swizzle) { |
| 359 | return last_image_view; | 373 | return last_image_view; |
| @@ -399,6 +413,11 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y | |||
| 399 | }); | 413 | }); |
| 400 | } | 414 | } |
| 401 | 415 | ||
| 416 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { | ||
| 417 | ASSERT(base_slice == 0); | ||
| 418 | ASSERT(num_slices == params.depth); | ||
| 419 | } | ||
| 420 | |||
| 402 | VkImageViewCreateInfo ci; | 421 | VkImageViewCreateInfo ci; |
| 403 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | 422 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; |
| 404 | ci.pNext = nullptr; | 423 | ci.pNext = nullptr; |
| @@ -417,6 +436,35 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y | |||
| 417 | return last_image_view = *image_view; | 436 | return last_image_view = *image_view; |
| 418 | } | 437 | } |
| 419 | 438 | ||
| 439 | VkImageView CachedSurfaceView::GetAttachment() { | ||
| 440 | if (render_target) { | ||
| 441 | return *render_target; | ||
| 442 | } | ||
| 443 | |||
| 444 | VkImageViewCreateInfo ci; | ||
| 445 | ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | ||
| 446 | ci.pNext = nullptr; | ||
| 447 | ci.flags = 0; | ||
| 448 | ci.image = surface.GetImageHandle(); | ||
| 449 | ci.format = surface.GetImage().GetFormat(); | ||
| 450 | ci.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 451 | VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; | ||
| 452 | ci.subresourceRange.aspectMask = aspect_mask; | ||
| 453 | ci.subresourceRange.baseMipLevel = base_level; | ||
| 454 | ci.subresourceRange.levelCount = num_levels; | ||
| 455 | if (image_view_type == VK_IMAGE_VIEW_TYPE_3D) { | ||
| 456 | ci.viewType = num_slices > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; | ||
| 457 | ci.subresourceRange.baseArrayLayer = base_slice; | ||
| 458 | ci.subresourceRange.layerCount = num_slices; | ||
| 459 | } else { | ||
| 460 | ci.viewType = image_view_type; | ||
| 461 | ci.subresourceRange.baseArrayLayer = base_layer; | ||
| 462 | ci.subresourceRange.layerCount = num_layers; | ||
| 463 | } | ||
| 464 | render_target = device.GetLogical().CreateImageView(ci); | ||
| 465 | return *render_target; | ||
| 466 | } | ||
| 467 | |||
| 420 | VKTextureCache::VKTextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer, | 468 | VKTextureCache::VKTextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer, |
| 421 | const VKDevice& device, VKResourceManager& resource_manager, | 469 | const VKDevice& device, VKResourceManager& resource_manager, |
| 422 | VKMemoryManager& memory_manager, VKScheduler& scheduler, | 470 | VKMemoryManager& memory_manager, VKScheduler& scheduler, |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index f211ccb1e..807e26c8a 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -91,7 +91,6 @@ protected: | |||
| 91 | void DecorateSurfaceName(); | 91 | void DecorateSurfaceName(); |
| 92 | 92 | ||
| 93 | View CreateView(const ViewParams& params) override; | 93 | View CreateView(const ViewParams& params) override; |
| 94 | View CreateViewInner(const ViewParams& params, bool is_proxy); | ||
| 95 | 94 | ||
| 96 | private: | 95 | private: |
| 97 | void UploadBuffer(const std::vector<u8>& staging_buffer); | 96 | void UploadBuffer(const std::vector<u8>& staging_buffer); |
| @@ -120,23 +119,20 @@ private: | |||
| 120 | class CachedSurfaceView final : public VideoCommon::ViewBase { | 119 | class CachedSurfaceView final : public VideoCommon::ViewBase { |
| 121 | public: | 120 | public: |
| 122 | explicit CachedSurfaceView(const VKDevice& device, CachedSurface& surface, | 121 | explicit CachedSurfaceView(const VKDevice& device, CachedSurface& surface, |
| 123 | const ViewParams& params, bool is_proxy); | 122 | const ViewParams& params); |
| 124 | ~CachedSurfaceView(); | 123 | ~CachedSurfaceView(); |
| 125 | 124 | ||
| 126 | VkImageView GetHandle(Tegra::Texture::SwizzleSource x_source, | 125 | VkImageView GetImageView(Tegra::Texture::SwizzleSource x_source, |
| 127 | Tegra::Texture::SwizzleSource y_source, | 126 | Tegra::Texture::SwizzleSource y_source, |
| 128 | Tegra::Texture::SwizzleSource z_source, | 127 | Tegra::Texture::SwizzleSource z_source, |
| 129 | Tegra::Texture::SwizzleSource w_source); | 128 | Tegra::Texture::SwizzleSource w_source); |
| 129 | |||
| 130 | VkImageView GetAttachment(); | ||
| 130 | 131 | ||
| 131 | bool IsSameSurface(const CachedSurfaceView& rhs) const { | 132 | bool IsSameSurface(const CachedSurfaceView& rhs) const { |
| 132 | return &surface == &rhs.surface; | 133 | return &surface == &rhs.surface; |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | VkImageView GetHandle() { | ||
| 136 | return GetHandle(Tegra::Texture::SwizzleSource::R, Tegra::Texture::SwizzleSource::G, | ||
| 137 | Tegra::Texture::SwizzleSource::B, Tegra::Texture::SwizzleSource::A); | ||
| 138 | } | ||
| 139 | |||
| 140 | u32 GetWidth() const { | 136 | u32 GetWidth() const { |
| 141 | return params.GetMipWidth(base_level); | 137 | return params.GetMipWidth(base_level); |
| 142 | } | 138 | } |
| @@ -180,14 +176,6 @@ public: | |||
| 180 | } | 176 | } |
| 181 | 177 | ||
| 182 | private: | 178 | private: |
| 183 | static u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source, | ||
| 184 | Tegra::Texture::SwizzleSource y_source, | ||
| 185 | Tegra::Texture::SwizzleSource z_source, | ||
| 186 | Tegra::Texture::SwizzleSource w_source) { | ||
| 187 | return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) | | ||
| 188 | (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source); | ||
| 189 | } | ||
| 190 | |||
| 191 | // Store a copy of these values to avoid double dereference when reading them | 179 | // Store a copy of these values to avoid double dereference when reading them |
| 192 | const SurfaceParams params; | 180 | const SurfaceParams params; |
| 193 | const VkImage image; | 181 | const VkImage image; |
| @@ -196,15 +184,18 @@ private: | |||
| 196 | 184 | ||
| 197 | const VKDevice& device; | 185 | const VKDevice& device; |
| 198 | CachedSurface& surface; | 186 | CachedSurface& surface; |
| 199 | const u32 base_layer; | ||
| 200 | const u32 num_layers; | ||
| 201 | const u32 base_level; | 187 | const u32 base_level; |
| 202 | const u32 num_levels; | 188 | const u32 num_levels; |
| 203 | const VkImageViewType image_view_type; | 189 | const VkImageViewType image_view_type; |
| 190 | u32 base_layer = 0; | ||
| 191 | u32 num_layers = 0; | ||
| 192 | u32 base_slice = 0; | ||
| 193 | u32 num_slices = 0; | ||
| 204 | 194 | ||
| 205 | VkImageView last_image_view = nullptr; | 195 | VkImageView last_image_view = nullptr; |
| 206 | u32 last_swizzle = 0; | 196 | u32 last_swizzle = 0; |
| 207 | 197 | ||
| 198 | vk::ImageView render_target; | ||
| 208 | std::unordered_map<u32, vk::ImageView> view_cache; | 199 | std::unordered_map<u32, vk::ImageView> view_cache; |
| 209 | }; | 200 | }; |
| 210 | 201 | ||
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp index 681ecde98..351c048d2 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp | |||
| @@ -24,35 +24,25 @@ void VKUpdateDescriptorQueue::TickFrame() { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | void VKUpdateDescriptorQueue::Acquire() { | 26 | void VKUpdateDescriptorQueue::Acquire() { |
| 27 | entries.clear(); | 27 | // Minimum number of entries required. |
| 28 | } | 28 | // This is the maximum number of entries a single draw call migth use. |
| 29 | static constexpr std::size_t MIN_ENTRIES = 0x400; | ||
| 29 | 30 | ||
| 30 | void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template, | 31 | if (payload.size() + MIN_ENTRIES >= payload.max_size()) { |
| 31 | VkDescriptorSet set) { | ||
| 32 | if (payload.size() + entries.size() >= payload.max_size()) { | ||
| 33 | LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread"); | 32 | LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread"); |
| 34 | scheduler.WaitWorker(); | 33 | scheduler.WaitWorker(); |
| 35 | payload.clear(); | 34 | payload.clear(); |
| 36 | } | 35 | } |
| 36 | upload_start = &*payload.end(); | ||
| 37 | } | ||
| 37 | 38 | ||
| 38 | // TODO(Rodrigo): Rework to write the payload directly | 39 | void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template, |
| 39 | const auto payload_start = payload.data() + payload.size(); | 40 | VkDescriptorSet set) { |
| 40 | for (const auto& entry : entries) { | 41 | const void* const data = upload_start; |
| 41 | if (const auto image = std::get_if<VkDescriptorImageInfo>(&entry)) { | 42 | const vk::Device* const logical = &device.GetLogical(); |
| 42 | payload.push_back(*image); | 43 | scheduler.Record([data, logical, set, update_template](vk::CommandBuffer) { |
| 43 | } else if (const auto buffer = std::get_if<VkDescriptorBufferInfo>(&entry)) { | 44 | logical->UpdateDescriptorSet(set, update_template, data); |
| 44 | payload.push_back(*buffer); | 45 | }); |
| 45 | } else if (const auto texel = std::get_if<VkBufferView>(&entry)) { | ||
| 46 | payload.push_back(*texel); | ||
| 47 | } else { | ||
| 48 | UNREACHABLE(); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | scheduler.Record( | ||
| 53 | [payload_start, set, update_template, logical = &device.GetLogical()](vk::CommandBuffer) { | ||
| 54 | logical->UpdateDescriptorSet(set, update_template, payload_start); | ||
| 55 | }); | ||
| 56 | } | 46 | } |
| 57 | 47 | ||
| 58 | } // namespace Vulkan | 48 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h index cc7e3dff4..945320c72 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.h +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h | |||
| @@ -15,17 +15,13 @@ namespace Vulkan { | |||
| 15 | class VKDevice; | 15 | class VKDevice; |
| 16 | class VKScheduler; | 16 | class VKScheduler; |
| 17 | 17 | ||
| 18 | class DescriptorUpdateEntry { | 18 | struct DescriptorUpdateEntry { |
| 19 | public: | 19 | DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {} |
| 20 | explicit DescriptorUpdateEntry() {} | ||
| 21 | |||
| 22 | DescriptorUpdateEntry(VkDescriptorImageInfo image) : image{image} {} | ||
| 23 | 20 | ||
| 24 | DescriptorUpdateEntry(VkDescriptorBufferInfo buffer) : buffer{buffer} {} | 21 | DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {} |
| 25 | 22 | ||
| 26 | DescriptorUpdateEntry(VkBufferView texel_buffer) : texel_buffer{texel_buffer} {} | 23 | DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {} |
| 27 | 24 | ||
| 28 | private: | ||
| 29 | union { | 25 | union { |
| 30 | VkDescriptorImageInfo image; | 26 | VkDescriptorImageInfo image; |
| 31 | VkDescriptorBufferInfo buffer; | 27 | VkDescriptorBufferInfo buffer; |
| @@ -45,32 +41,34 @@ public: | |||
| 45 | void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set); | 41 | void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set); |
| 46 | 42 | ||
| 47 | void AddSampledImage(VkSampler sampler, VkImageView image_view) { | 43 | void AddSampledImage(VkSampler sampler, VkImageView image_view) { |
| 48 | entries.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}}); | 44 | payload.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}}); |
| 49 | } | 45 | } |
| 50 | 46 | ||
| 51 | void AddImage(VkImageView image_view) { | 47 | void AddImage(VkImageView image_view) { |
| 52 | entries.emplace_back(VkDescriptorImageInfo{{}, image_view, {}}); | 48 | payload.emplace_back(VkDescriptorImageInfo{{}, image_view, {}}); |
| 53 | } | 49 | } |
| 54 | 50 | ||
| 55 | void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) { | 51 | void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) { |
| 56 | entries.emplace_back(VkDescriptorBufferInfo{buffer, offset, size}); | 52 | payload.emplace_back(VkDescriptorBufferInfo{buffer, offset, size}); |
| 57 | } | 53 | } |
| 58 | 54 | ||
| 59 | void AddTexelBuffer(VkBufferView texel_buffer) { | 55 | void AddTexelBuffer(VkBufferView texel_buffer) { |
| 60 | entries.emplace_back(texel_buffer); | 56 | payload.emplace_back(texel_buffer); |
| 61 | } | 57 | } |
| 62 | 58 | ||
| 63 | VkImageLayout* GetLastImageLayout() { | 59 | VkImageLayout* LastImageLayout() { |
| 64 | return &std::get<VkDescriptorImageInfo>(entries.back()).imageLayout; | 60 | return &payload.back().image.imageLayout; |
| 65 | } | 61 | } |
| 66 | 62 | ||
| 67 | private: | 63 | const VkImageLayout* LastImageLayout() const { |
| 68 | using Variant = std::variant<VkDescriptorImageInfo, VkDescriptorBufferInfo, VkBufferView>; | 64 | return &payload.back().image.imageLayout; |
| 65 | } | ||
| 69 | 66 | ||
| 67 | private: | ||
| 70 | const VKDevice& device; | 68 | const VKDevice& device; |
| 71 | VKScheduler& scheduler; | 69 | VKScheduler& scheduler; |
| 72 | 70 | ||
| 73 | boost::container::static_vector<Variant, 0x400> entries; | 71 | const DescriptorUpdateEntry* upload_start = nullptr; |
| 74 | boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload; | 72 | boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload; |
| 75 | }; | 73 | }; |
| 76 | 74 | ||
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp index 2ce9b0626..42eff85d3 100644 --- a/src/video_core/renderer_vulkan/wrapper.cpp +++ b/src/video_core/renderer_vulkan/wrapper.cpp | |||
| @@ -725,8 +725,7 @@ bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR s | |||
| 725 | return supported == VK_TRUE; | 725 | return supported == VK_TRUE; |
| 726 | } | 726 | } |
| 727 | 727 | ||
| 728 | VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const | 728 | VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const { |
| 729 | noexcept { | ||
| 730 | VkSurfaceCapabilitiesKHR capabilities; | 729 | VkSurfaceCapabilitiesKHR capabilities; |
| 731 | Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities)); | 730 | Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities)); |
| 732 | return capabilities; | 731 | return capabilities; |
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h index 98937a77a..da42ca88e 100644 --- a/src/video_core/renderer_vulkan/wrapper.h +++ b/src/video_core/renderer_vulkan/wrapper.h | |||
| @@ -779,7 +779,7 @@ public: | |||
| 779 | 779 | ||
| 780 | bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const; | 780 | bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const; |
| 781 | 781 | ||
| 782 | VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const noexcept; | 782 | VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const; |
| 783 | 783 | ||
| 784 | std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const; | 784 | std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const; |
| 785 | 785 | ||