From a38155a1166cf6353ccf9f15297a88a703a7daa9 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Sat, 17 Dec 2022 17:36:09 +0100 Subject: [PATCH] early-access version 3225 --- README.md | 2 +- src/input_common/drivers/camera.cpp | 2 +- src/input_common/drivers/camera.h | 4 +- src/video_core/buffer_cache/buffer_cache.h | 7 +- .../host_shaders/vulkan_quad_indexed.comp | 5 +- .../renderer_vulkan/maxwell_to_vk.cpp | 21 +- .../renderer_vulkan/vk_buffer_cache.cpp | 297 ++++++++++++------ .../renderer_vulkan/vk_buffer_cache.h | 13 +- .../renderer_vulkan/vk_compute_pass.cpp | 10 +- .../renderer_vulkan/vk_compute_pass.h | 2 +- .../renderer_vulkan/vk_rasterizer.cpp | 11 +- src/yuzu/bootmanager.cpp | 12 +- src/yuzu/bootmanager.h | 3 + 13 files changed, 254 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index 100322ad4..1225c3fbd 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3224. +This is the source code for early-access 3225. ## Legal Notice diff --git a/src/input_common/drivers/camera.cpp b/src/input_common/drivers/camera.cpp index d4d5ef619..ba611fbfd 100755 --- a/src/input_common/drivers/camera.cpp +++ b/src/input_common/drivers/camera.cpp @@ -17,7 +17,7 @@ Camera::Camera(std::string input_engine_) : InputEngine(std::move(input_engine_) PreSetController(identifier); } -void Camera::SetCameraData(std::size_t width, std::size_t height, std::vector data) { +void Camera::SetCameraData(std::size_t width, std::size_t height, std::span data) { const std::size_t desired_width = getImageWidth(); const std::size_t desired_height = getImageHeight(); status.data.resize(desired_width * desired_height); diff --git a/src/input_common/drivers/camera.h b/src/input_common/drivers/camera.h index 68a600ee6..257cdc7c2 100755 --- a/src/input_common/drivers/camera.h +++ b/src/input_common/drivers/camera.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "input_common/input_engine.h" namespace InputCommon { @@ -15,7 +17,7 @@ class Camera final : public InputEngine { public: explicit Camera(std::string input_engine_); - void SetCameraData(std::size_t width, std::size_t height, std::vector data); + void SetCameraData(std::size_t width, std::size_t height, std::span data); std::size_t getImageWidth() const; std::size_t getImageHeight() const; diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index cc55e89ab..1ea87d824 100755 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -666,9 +666,10 @@ void BufferCache

::BindHostGeometryBuffers(bool is_indexed) { BindHostIndexBuffer(); } else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); - if (draw_state.topology == Maxwell::PrimitiveTopology::Quads) { - runtime.BindQuadArrayIndexBuffer(draw_state.vertex_buffer.first, - draw_state.vertex_buffer.count); + if (draw_state.topology == Maxwell::PrimitiveTopology::Quads || + draw_state.topology == Maxwell::PrimitiveTopology::QuadStrip) { + runtime.BindQuadIndexBuffer(draw_state.topology, draw_state.vertex_buffer.first, + draw_state.vertex_buffer.count); } } BindHostVertexBuffers(); diff --git a/src/video_core/host_shaders/vulkan_quad_indexed.comp b/src/video_core/host_shaders/vulkan_quad_indexed.comp index d45e71197..53f116b58 100755 --- a/src/video_core/host_shaders/vulkan_quad_indexed.comp +++ b/src/video_core/host_shaders/vulkan_quad_indexed.comp @@ -16,6 +16,7 @@ layout (std430, set = 0, binding = 1) writeonly buffer OutputBuffer { layout (push_constant) uniform PushConstants { uint base_vertex; int index_shift; // 0: uint8, 1: uint16, 2: uint32 + int is_strip; // 0: quads 1: quadstrip }; void main() { @@ -28,9 +29,9 @@ void main() { int flipped_shift = 2 - index_shift; int mask = (1 << flipped_shift) - 1; - const int quad_swizzle[6] = int[](0, 1, 2, 0, 2, 3); + const int quad_swizzle[6] = (is_strip == 0 ? int[](0, 1, 2, 0, 2, 3) : int[](0, 3, 1, 0, 2, 3)); for (uint vertex = 0; vertex < 6; ++vertex) { - int offset = primitive * 4 + quad_swizzle[vertex]; + int offset = quad_swizzle[vertex] + (is_strip == 0 ? primitive * 4 : primitive * 2); int int_offset = offset >> flipped_shift; int bit_offset = (offset & mask) * index_size; uint packed_input = input_indexes[int_offset]; diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index fea9d06e0..e35eb7c26 100755 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -301,6 +301,8 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const Device& device, return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; case Maxwell::PrimitiveTopology::Lines: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + case Maxwell::PrimitiveTopology::LineLoop: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; case Maxwell::PrimitiveTopology::LineStrip: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; case Maxwell::PrimitiveTopology::Triangles: @@ -309,15 +311,26 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const Device& device, return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; case Maxwell::PrimitiveTopology::TriangleFan: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; + case Maxwell::PrimitiveTopology::LinesAdjacency: + return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; + case Maxwell::PrimitiveTopology::LineStripAdjacency: + return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; + case Maxwell::PrimitiveTopology::TrianglesAdjacency: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; + case Maxwell::PrimitiveTopology::TriangleStripAdjacency: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; case Maxwell::PrimitiveTopology::Quads: - // TODO(Rodrigo): Use VK_PRIMITIVE_TOPOLOGY_QUAD_LIST_EXT whenever it releases + case Maxwell::PrimitiveTopology::QuadStrip: + // TODO: Use VK_PRIMITIVE_TOPOLOGY_QUAD_LIST_EXT/VK_PRIMITIVE_TOPOLOGY_QUAD_STRIP_EXT + // whenever it releases return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; case Maxwell::PrimitiveTopology::Patches: return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; - default: - UNIMPLEMENTED_MSG("Unimplemented topology={}", topology); - return {}; + case Maxwell::PrimitiveTopology::Polygon: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; } + UNIMPLEMENTED_MSG("Unimplemented topology={}", topology); + return {}; } VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 66ffb64ff..0ddedb777 100755 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -51,15 +51,6 @@ size_t BytesPerIndex(VkIndexType index_type) { } } -template -std::array MakeQuadIndices(u32 quad, u32 first) { - std::array indices{0, 1, 2, 0, 2, 3}; - for (T& index : indices) { - index = static_cast(first + index + quad * 4); - } - return indices; -} - vk::Buffer CreateBuffer(const Device& device, u64 size) { VkBufferUsageFlags flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | @@ -123,6 +114,187 @@ VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat return *views.back().handle; } +class QuadIndexBuffer { +public: + QuadIndexBuffer(const Device& device_, MemoryAllocator& memory_allocator_, + Scheduler& scheduler_, StagingBufferPool& staging_pool_) + : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, + staging_pool{staging_pool_} {} + + virtual ~QuadIndexBuffer() = default; + + void UpdateBuffer(u32 num_indices_) { + if (num_indices_ <= num_indices) { + return; + } + + scheduler.Finish(); + + num_indices = num_indices_; + index_type = IndexTypeFromNumElements(device, num_indices); + + const u32 num_quads = GetQuadsNum(num_indices); + const u32 num_triangle_indices = num_quads * 6; + const u32 num_first_offset_copies = 4; + const size_t bytes_per_index = BytesPerIndex(index_type); + const size_t size_bytes = num_triangle_indices * bytes_per_index * num_first_offset_copies; + buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = size_bytes, + .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + }); + if (device.HasDebuggingToolAttached()) { + buffer.SetObjectNameEXT("Quad LUT"); + } + memory_commit = memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal); + + const StagingBufferRef staging = staging_pool.Request(size_bytes, MemoryUsage::Upload); + u8* staging_data = staging.mapped_span.data(); + const size_t quad_size = bytes_per_index * 6; + + for (u32 first = 0; first < num_first_offset_copies; ++first) { + for (u32 quad = 0; quad < num_quads; ++quad) { + MakeAndUpdateIndices(staging_data, quad_size, quad, first); + staging_data += quad_size; + } + } + + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset, + dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) { + const VkBufferCopy copy{ + .srcOffset = src_offset, + .dstOffset = 0, + .size = size_bytes, + }; + const VkBufferMemoryBarrier write_barrier{ + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_INDEX_READ_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = dst_buffer, + .offset = 0, + .size = size_bytes, + }; + cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy); + cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, write_barrier); + }); + } + + void BindBuffer(u32 first) { + const VkIndexType index_type_ = index_type; + const size_t sub_first_offset = static_cast(first % 4) * GetQuadsNum(num_indices); + const size_t offset = + (sub_first_offset + GetQuadsNum(first)) * 6ULL * BytesPerIndex(index_type); + scheduler.Record([buffer = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) { + cmdbuf.BindIndexBuffer(buffer, offset, index_type_); + }); + } + +protected: + virtual u32 GetQuadsNum(u32 num_indices) const = 0; + + virtual void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) = 0; + + const Device& device; + MemoryAllocator& memory_allocator; + Scheduler& scheduler; + StagingBufferPool& staging_pool; + + vk::Buffer buffer{}; + MemoryCommit memory_commit{}; + VkIndexType index_type{}; + u32 num_indices = 0; +}; + +class QuadArrayIndexBuffer : public QuadIndexBuffer { +public: + QuadArrayIndexBuffer(const Device& device_, MemoryAllocator& memory_allocator_, + Scheduler& scheduler_, StagingBufferPool& staging_pool_) + : QuadIndexBuffer(device_, memory_allocator_, scheduler_, staging_pool_) {} + + ~QuadArrayIndexBuffer() = default; + +private: + u32 GetQuadsNum(u32 num_indices_) const override { + return num_indices_ / 4; + } + + template + static std::array MakeIndices(u32 quad, u32 first) { + std::array indices{0, 1, 2, 0, 2, 3}; + for (T& index : indices) { + index = static_cast(first + index + quad * 4); + } + return indices; + } + + void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) { + switch (index_type) { + case VK_INDEX_TYPE_UINT8_EXT: + std::memcpy(staging_data, MakeIndices(quad, first).data(), quad_size); + break; + case VK_INDEX_TYPE_UINT16: + std::memcpy(staging_data, MakeIndices(quad, first).data(), quad_size); + break; + case VK_INDEX_TYPE_UINT32: + std::memcpy(staging_data, MakeIndices(quad, first).data(), quad_size); + break; + default: + ASSERT(false); + break; + } + } +}; + +class QuadStripIndexBuffer : public QuadIndexBuffer { +public: + QuadStripIndexBuffer(const Device& device_, MemoryAllocator& memory_allocator_, + Scheduler& scheduler_, StagingBufferPool& staging_pool_) + : QuadIndexBuffer(device_, memory_allocator_, scheduler_, staging_pool_) {} + + ~QuadStripIndexBuffer() = default; + +private: + u32 GetQuadsNum(u32 num_indices_) const override { + return num_indices_ >= 4 ? (num_indices_ - 2) / 2 : 0; + } + + template + static std::array MakeIndices(u32 quad, u32 first) { + std::array indices{0, 3, 1, 0, 2, 3}; + for (T& index : indices) { + index = static_cast(first + index + quad * 2); + } + return indices; + } + + void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) { + switch (index_type) { + case VK_INDEX_TYPE_UINT8_EXT: + std::memcpy(staging_data, MakeIndices(quad, first).data(), quad_size); + break; + case VK_INDEX_TYPE_UINT16: + std::memcpy(staging_data, MakeIndices(quad, first).data(), quad_size); + break; + case VK_INDEX_TYPE_UINT32: + std::memcpy(staging_data, MakeIndices(quad, first).data(), quad_size); + break; + default: + ASSERT(false); + break; + } + } +}; + BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, UpdateDescriptorQueue& update_descriptor_queue_, @@ -130,7 +302,12 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_}, uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), - quad_index_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue) {} + quad_index_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue) { + quad_array_index_buffer = std::make_shared(device_, memory_allocator_, + scheduler_, staging_pool_); + quad_strip_index_buffer = std::make_shared(device_, memory_allocator_, + scheduler_, staging_pool_); +} StagingBufferRef BufferCacheRuntime::UploadStagingBuffer(size_t size) { return staging_pool.Request(size, MemoryUsage::Upload); @@ -245,10 +422,11 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat VkIndexType vk_index_type = MaxwellToVK::IndexFormat(index_format); VkDeviceSize vk_offset = offset; VkBuffer vk_buffer = buffer; - if (topology == PrimitiveTopology::Quads) { + if (topology == PrimitiveTopology::Quads || topology == PrimitiveTopology::QuadStrip) { vk_index_type = VK_INDEX_TYPE_UINT32; std::tie(vk_buffer, vk_offset) = - quad_index_pass.Assemble(index_format, num_indices, base_vertex, buffer, offset); + quad_index_pass.Assemble(index_format, num_indices, base_vertex, buffer, offset, + topology == PrimitiveTopology::QuadStrip); } else if (vk_index_type == VK_INDEX_TYPE_UINT8_EXT && !device.IsExtIndexTypeUint8Supported()) { vk_index_type = VK_INDEX_TYPE_UINT16; std::tie(vk_buffer, vk_offset) = uint8_pass.Assemble(num_indices, buffer, offset); @@ -263,7 +441,7 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat }); } -void BufferCacheRuntime::BindQuadArrayIndexBuffer(u32 first, u32 count) { +void BufferCacheRuntime::BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count) { if (count == 0) { ReserveNullBuffer(); scheduler.Record([this](vk::CommandBuffer cmdbuf) { @@ -271,16 +449,14 @@ void BufferCacheRuntime::BindQuadArrayIndexBuffer(u32 first, u32 count) { }); return; } - ReserveQuadArrayLUT(first + count, true); - // The LUT has the indices 0, 1, 2, and 3 copied as an array - // To apply these 'first' offsets we can apply an offset based on the modulus. - const VkIndexType index_type = quad_array_lut_index_type; - const size_t sub_first_offset = static_cast(first % 4) * (current_num_indices / 4); - const size_t offset = (sub_first_offset + first / 4) * 6ULL * BytesPerIndex(index_type); - scheduler.Record([buffer = *quad_array_lut, index_type, offset](vk::CommandBuffer cmdbuf) { - cmdbuf.BindIndexBuffer(buffer, offset, index_type); - }); + if (topology == PrimitiveTopology::Quads) { + quad_array_index_buffer->UpdateBuffer(first + count); + quad_array_index_buffer->BindBuffer(first); + } else if (topology == PrimitiveTopology::QuadStrip) { + quad_strip_index_buffer->UpdateBuffer(first + count); + quad_strip_index_buffer->BindBuffer(first); + } } void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, @@ -323,83 +499,6 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, }); } -void BufferCacheRuntime::ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle) { - if (num_indices <= current_num_indices) { - return; - } - if (wait_for_idle) { - scheduler.Finish(); - } - current_num_indices = num_indices; - quad_array_lut_index_type = IndexTypeFromNumElements(device, num_indices); - - const u32 num_quads = num_indices / 4; - const u32 num_triangle_indices = num_quads * 6; - const u32 num_first_offset_copies = 4; - const size_t bytes_per_index = BytesPerIndex(quad_array_lut_index_type); - const size_t size_bytes = num_triangle_indices * bytes_per_index * num_first_offset_copies; - quad_array_lut = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = size_bytes, - .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - }); - if (device.HasDebuggingToolAttached()) { - quad_array_lut.SetObjectNameEXT("Quad LUT"); - } - quad_array_lut_commit = memory_allocator.Commit(quad_array_lut, MemoryUsage::DeviceLocal); - - const StagingBufferRef staging = staging_pool.Request(size_bytes, MemoryUsage::Upload); - u8* staging_data = staging.mapped_span.data(); - const size_t quad_size = bytes_per_index * 6; - for (u32 first = 0; first < num_first_offset_copies; ++first) { - for (u32 quad = 0; quad < num_quads; ++quad) { - switch (quad_array_lut_index_type) { - case VK_INDEX_TYPE_UINT8_EXT: - std::memcpy(staging_data, MakeQuadIndices(quad, first).data(), quad_size); - break; - case VK_INDEX_TYPE_UINT16: - std::memcpy(staging_data, MakeQuadIndices(quad, first).data(), quad_size); - break; - case VK_INDEX_TYPE_UINT32: - std::memcpy(staging_data, MakeQuadIndices(quad, first).data(), quad_size); - break; - default: - ASSERT(false); - break; - } - staging_data += quad_size; - } - } - scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset, - dst_buffer = *quad_array_lut, size_bytes](vk::CommandBuffer cmdbuf) { - const VkBufferCopy copy{ - .srcOffset = src_offset, - .dstOffset = 0, - .size = size_bytes, - }; - const VkBufferMemoryBarrier write_barrier{ - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_INDEX_READ_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = dst_buffer, - .offset = 0, - .size = size_bytes, - }; - cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, write_barrier); - }); -} - void BufferCacheRuntime::ReserveNullBuffer() { if (null_buffer) { return; diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 6025b8066..7e3d03bc0 100755 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -50,6 +50,9 @@ private: std::vector views; }; +class QuadArrayIndexBuffer; +class QuadStripIndexBuffer; + class BufferCacheRuntime { friend Buffer; @@ -86,7 +89,7 @@ public: void BindIndexBuffer(PrimitiveTopology topology, IndexFormat index_format, u32 num_indices, u32 base_vertex, VkBuffer buffer, u32 offset, u32 size); - void BindQuadArrayIndexBuffer(u32 first, u32 count); + void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count); void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride); @@ -118,8 +121,6 @@ private: update_descriptor_queue.AddBuffer(buffer, offset, size); } - void ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle); - void ReserveNullBuffer(); const Device& device; @@ -128,10 +129,8 @@ private: StagingBufferPool& staging_pool; UpdateDescriptorQueue& update_descriptor_queue; - vk::Buffer quad_array_lut; - MemoryCommit quad_array_lut_commit; - VkIndexType quad_array_lut_index_type{}; - u32 current_num_indices = 0; + std::shared_ptr quad_array_index_buffer; + std::shared_ptr quad_strip_index_buffer; vk::Buffer null_buffer; MemoryCommit null_buffer_commit; diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 53d11790a..43bfd889f 100755 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -253,7 +253,7 @@ QuadIndexedPass::~QuadIndexedPass() = default; std::pair QuadIndexedPass::Assemble( Tegra::Engines::Maxwell3D::Regs::IndexFormat index_format, u32 num_vertices, u32 base_vertex, - VkBuffer src_buffer, u32 src_offset) { + VkBuffer src_buffer, u32 src_offset, bool is_strip) { const u32 index_shift = [index_format] { switch (index_format) { case Tegra::Engines::Maxwell3D::Regs::IndexFormat::UnsignedByte: @@ -267,7 +267,7 @@ std::pair QuadIndexedPass::Assemble( return 2; }(); const u32 input_size = num_vertices << index_shift; - const u32 num_tri_vertices = (num_vertices / 4) * 6; + const u32 num_tri_vertices = (is_strip ? (num_vertices - 2) / 2 : num_vertices / 4) * 6; const std::size_t staging_size = num_tri_vertices * sizeof(u32); const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal); @@ -278,8 +278,8 @@ std::pair QuadIndexedPass::Assemble( const void* const descriptor_data{update_descriptor_queue.UpdateData()}; scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([this, descriptor_data, num_tri_vertices, base_vertex, - index_shift](vk::CommandBuffer cmdbuf) { + scheduler.Record([this, descriptor_data, num_tri_vertices, base_vertex, index_shift, + is_strip](vk::CommandBuffer cmdbuf) { static constexpr u32 DISPATCH_SIZE = 1024; static constexpr VkMemoryBarrier WRITE_BARRIER{ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, @@ -287,7 +287,7 @@ std::pair QuadIndexedPass::Assemble( .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .dstAccessMask = VK_ACCESS_INDEX_READ_BIT, }; - const std::array push_constants{base_vertex, index_shift}; + const std::array push_constants{base_vertex, index_shift, is_strip ? 1u : 0u}; const VkDescriptorSet set = descriptor_allocator.Commit(); device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index ac872b312..fe1ea521d 100755 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -74,7 +74,7 @@ public: std::pair Assemble( Tegra::Engines::Maxwell3D::Regs::IndexFormat index_format, u32 num_vertices, - u32 base_vertex, VkBuffer src_buffer, u32 src_offset); + u32 base_vertex, VkBuffer src_buffer, u32 src_offset, bool is_strip); private: Scheduler& scheduler; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index b579cb74b..b5c9873eb 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -138,12 +138,16 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, .first_index = is_indexed ? draw_state.index_buffer.first : 0, .is_indexed = is_indexed, }; + // 6 triangle vertices per quad, base vertex is part of the index + // See BindQuadIndexBuffer for more details if (draw_state.topology == Maxwell::PrimitiveTopology::Quads) { - // 6 triangle vertices per quad, base vertex is part of the index - // See BindQuadArrayIndexBuffer for more details params.num_vertices = (params.num_vertices / 4) * 6; params.base_vertex = 0; params.is_indexed = true; + } else if (draw_state.topology == Maxwell::PrimitiveTopology::QuadStrip) { + params.num_vertices = (params.num_vertices - 2) / 2 * 6; + params.base_vertex = 0; + params.is_indexed = true; } return params; } @@ -658,8 +662,7 @@ void RasterizerVulkan::BeginTransformFeedback() { return; } UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) || - regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation) || - regs.IsShaderConfigEnabled(Maxwell::ShaderType::Geometry)); + regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation)); scheduler.Record( [](vk::CommandBuffer cmdbuf) { cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); }); } diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 33aa66b33..2695b89d5 100755 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -760,6 +760,7 @@ void GRenderWindow::InitializeCamera() { return; } + camera_data.resize(CAMERA_WIDTH * CAMERA_HEIGHT); camera_capture->setCaptureDestination(QCameraImageCapture::CaptureDestination::CaptureToBuffer); connect(camera_capture.get(), &QCameraImageCapture::imageCaptured, this, &GRenderWindow::OnCameraCapture); @@ -815,16 +816,13 @@ void GRenderWindow::RequestCameraCapture() { } void GRenderWindow::OnCameraCapture(int requestId, const QImage& img) { - constexpr std::size_t camera_width = 320; - constexpr std::size_t camera_height = 240; + // TODO: Capture directly in the format and resolution needed const auto converted = - img.scaled(camera_width, camera_height, Qt::AspectRatioMode::IgnoreAspectRatio, + img.scaled(CAMERA_WIDTH, CAMERA_HEIGHT, Qt::AspectRatioMode::IgnoreAspectRatio, Qt::TransformationMode::SmoothTransformation) .mirrored(false, true); - std::vector camera_data{}; - camera_data.resize(camera_width * camera_height); - std::memcpy(camera_data.data(), converted.bits(), camera_width * camera_height * sizeof(u32)); - input_subsystem->GetCamera()->SetCameraData(camera_width, camera_height, camera_data); + std::memcpy(camera_data.data(), converted.bits(), CAMERA_WIDTH * CAMERA_HEIGHT * sizeof(u32)); + input_subsystem->GetCamera()->SetCameraData(CAMERA_WIDTH, CAMERA_HEIGHT, camera_data); pending_camera_snapshots = 0; } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index e8af41ab4..478d324c5 100755 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -247,6 +247,9 @@ private: #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA std::unique_ptr camera; std::unique_ptr camera_capture; + static constexpr std::size_t CAMERA_WIDTH = 320; + static constexpr std::size_t CAMERA_HEIGHT = 240; + std::vector camera_data; #endif std::unique_ptr camera_timer;