Merge pull request #3313 from ReinUsesLisp/vk-rasterizer
vk_rasterizer: Implement Vulkan's rasterizer
This commit is contained in:
		
						commit
						41373d212e
					
				@ -153,6 +153,7 @@ if (ENABLE_VULKAN)
 | 
			
		||||
        renderer_vulkan/fixed_pipeline_state.h
 | 
			
		||||
        renderer_vulkan/maxwell_to_vk.cpp
 | 
			
		||||
        renderer_vulkan/maxwell_to_vk.h
 | 
			
		||||
        renderer_vulkan/renderer_vulkan.h
 | 
			
		||||
        renderer_vulkan/vk_buffer_cache.cpp
 | 
			
		||||
        renderer_vulkan/vk_buffer_cache.h
 | 
			
		||||
        renderer_vulkan/vk_compute_pass.cpp
 | 
			
		||||
@ -171,6 +172,7 @@ if (ENABLE_VULKAN)
 | 
			
		||||
        renderer_vulkan/vk_memory_manager.h
 | 
			
		||||
        renderer_vulkan/vk_pipeline_cache.cpp
 | 
			
		||||
        renderer_vulkan/vk_pipeline_cache.h
 | 
			
		||||
        renderer_vulkan/vk_rasterizer.cpp
 | 
			
		||||
        renderer_vulkan/vk_rasterizer.h
 | 
			
		||||
        renderer_vulkan/vk_renderpass_cache.cpp
 | 
			
		||||
        renderer_vulkan/vk_renderpass_cache.h
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								src/video_core/renderer_vulkan/renderer_vulkan.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/video_core/renderer_vulkan/renderer_vulkan.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
// Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "video_core/renderer_base.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/declarations.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
class VKBlitScreen;
 | 
			
		||||
class VKDevice;
 | 
			
		||||
class VKFence;
 | 
			
		||||
class VKMemoryManager;
 | 
			
		||||
class VKResourceManager;
 | 
			
		||||
class VKSwapchain;
 | 
			
		||||
class VKScheduler;
 | 
			
		||||
class VKImage;
 | 
			
		||||
 | 
			
		||||
struct VKScreenInfo {
 | 
			
		||||
    VKImage* image{};
 | 
			
		||||
    u32 width{};
 | 
			
		||||
    u32 height{};
 | 
			
		||||
    bool is_srgb{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class RendererVulkan final : public VideoCore::RendererBase {
 | 
			
		||||
public:
 | 
			
		||||
    explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system);
 | 
			
		||||
    ~RendererVulkan() override;
 | 
			
		||||
 | 
			
		||||
    /// Swap buffers (render frame)
 | 
			
		||||
    void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
 | 
			
		||||
 | 
			
		||||
    /// Initialize the renderer
 | 
			
		||||
    bool Init() override;
 | 
			
		||||
 | 
			
		||||
    /// Shutdown the renderer
 | 
			
		||||
    void ShutDown() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
 | 
			
		||||
        const vk::DispatchLoaderDynamic& dldi);
 | 
			
		||||
 | 
			
		||||
    bool PickDevices(const vk::DispatchLoaderDynamic& dldi);
 | 
			
		||||
 | 
			
		||||
    void Report() const;
 | 
			
		||||
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
 | 
			
		||||
    vk::Instance instance;
 | 
			
		||||
    vk::SurfaceKHR surface;
 | 
			
		||||
 | 
			
		||||
    VKScreenInfo screen_info;
 | 
			
		||||
 | 
			
		||||
    UniqueDebugUtilsMessengerEXT debug_callback;
 | 
			
		||||
    std::unique_ptr<VKDevice> device;
 | 
			
		||||
    std::unique_ptr<VKSwapchain> swapchain;
 | 
			
		||||
    std::unique_ptr<VKMemoryManager> memory_manager;
 | 
			
		||||
    std::unique_ptr<VKResourceManager> resource_manager;
 | 
			
		||||
    std::unique_ptr<VKScheduler> scheduler;
 | 
			
		||||
    std::unique_ptr<VKBlitScreen> blit_screen;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
							
								
								
									
										1141
									
								
								src/video_core/renderer_vulkan/vk_rasterizer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1141
									
								
								src/video_core/renderer_vulkan/vk_rasterizer.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -4,10 +4,260 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <bitset>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <boost/container/static_vector.hpp>
 | 
			
		||||
#include <boost/functional/hash.hpp>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "video_core/memory_manager.h"
 | 
			
		||||
#include "video_core/rasterizer_accelerated.h"
 | 
			
		||||
#include "video_core/rasterizer_interface.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/declarations.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_compute_pass.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_memory_manager.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_resource_manager.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_sampler_cache.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Core::Frontend {
 | 
			
		||||
class EmuWindow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Tegra::Engines {
 | 
			
		||||
class Maxwell3D;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
class RasterizerVulkan : public VideoCore::RasterizerInterface {};
 | 
			
		||||
struct VKScreenInfo;
 | 
			
		||||
 | 
			
		||||
using ImageViewsPack =
 | 
			
		||||
    boost::container::static_vector<vk::ImageView, Maxwell::NumRenderTargets + 1>;
 | 
			
		||||
 | 
			
		||||
struct FramebufferCacheKey {
 | 
			
		||||
    vk::RenderPass renderpass{};
 | 
			
		||||
    u32 width = 0;
 | 
			
		||||
    u32 height = 0;
 | 
			
		||||
    ImageViewsPack views;
 | 
			
		||||
 | 
			
		||||
    std::size_t Hash() const noexcept {
 | 
			
		||||
        std::size_t hash = 0;
 | 
			
		||||
        boost::hash_combine(hash, static_cast<VkRenderPass>(renderpass));
 | 
			
		||||
        for (const auto& view : views) {
 | 
			
		||||
            boost::hash_combine(hash, static_cast<VkImageView>(view));
 | 
			
		||||
        }
 | 
			
		||||
        boost::hash_combine(hash, width);
 | 
			
		||||
        boost::hash_combine(hash, height);
 | 
			
		||||
        return hash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator==(const FramebufferCacheKey& rhs) const noexcept {
 | 
			
		||||
        return std::tie(renderpass, views, width, height) ==
 | 
			
		||||
               std::tie(rhs.renderpass, rhs.views, rhs.width, rhs.height);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
 | 
			
		||||
namespace std {
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct hash<Vulkan::FramebufferCacheKey> {
 | 
			
		||||
    std::size_t operator()(const Vulkan::FramebufferCacheKey& k) const noexcept {
 | 
			
		||||
        return k.Hash();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace std
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
class BufferBindings;
 | 
			
		||||
 | 
			
		||||
struct ImageView {
 | 
			
		||||
    View view;
 | 
			
		||||
    vk::ImageLayout* layout = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class RasterizerVulkan : public VideoCore::RasterizerAccelerated {
 | 
			
		||||
public:
 | 
			
		||||
    explicit RasterizerVulkan(Core::System& system, Core::Frontend::EmuWindow& render_window,
 | 
			
		||||
                              VKScreenInfo& screen_info, const VKDevice& device,
 | 
			
		||||
                              VKResourceManager& resource_manager, VKMemoryManager& memory_manager,
 | 
			
		||||
                              VKScheduler& scheduler);
 | 
			
		||||
    ~RasterizerVulkan() override;
 | 
			
		||||
 | 
			
		||||
    bool DrawBatch(bool is_indexed) override;
 | 
			
		||||
    bool DrawMultiBatch(bool is_indexed) override;
 | 
			
		||||
    void Clear() override;
 | 
			
		||||
    void DispatchCompute(GPUVAddr code_addr) override;
 | 
			
		||||
    void FlushAll() override;
 | 
			
		||||
    void FlushRegion(CacheAddr addr, u64 size) override;
 | 
			
		||||
    void InvalidateRegion(CacheAddr addr, u64 size) override;
 | 
			
		||||
    void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override;
 | 
			
		||||
    void FlushCommands() override;
 | 
			
		||||
    void TickFrame() override;
 | 
			
		||||
    bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
 | 
			
		||||
                               const Tegra::Engines::Fermi2D::Regs::Surface& dst,
 | 
			
		||||
                               const Tegra::Engines::Fermi2D::Config& copy_config) override;
 | 
			
		||||
    bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
 | 
			
		||||
                           u32 pixel_stride) override;
 | 
			
		||||
 | 
			
		||||
    /// Maximum supported size that a constbuffer can have in bytes.
 | 
			
		||||
    static constexpr std::size_t MaxConstbufferSize = 0x10000;
 | 
			
		||||
    static_assert(MaxConstbufferSize % (4 * sizeof(float)) == 0,
 | 
			
		||||
                  "The maximum size of a constbuffer must be a multiple of the size of GLvec4");
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    struct DrawParameters {
 | 
			
		||||
        void Draw(vk::CommandBuffer cmdbuf, const vk::DispatchLoaderDynamic& dld) const;
 | 
			
		||||
 | 
			
		||||
        u32 base_instance = 0;
 | 
			
		||||
        u32 num_instances = 0;
 | 
			
		||||
        u32 base_vertex = 0;
 | 
			
		||||
        u32 num_vertices = 0;
 | 
			
		||||
        bool is_indexed = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    using Texceptions = std::bitset<Maxwell::NumRenderTargets + 1>;
 | 
			
		||||
 | 
			
		||||
    static constexpr std::size_t ZETA_TEXCEPTION_INDEX = 8;
 | 
			
		||||
 | 
			
		||||
    void Draw(bool is_indexed, bool is_instanced);
 | 
			
		||||
 | 
			
		||||
    void FlushWork();
 | 
			
		||||
 | 
			
		||||
    Texceptions UpdateAttachments();
 | 
			
		||||
 | 
			
		||||
    std::tuple<vk::Framebuffer, vk::Extent2D> ConfigureFramebuffers(vk::RenderPass renderpass);
 | 
			
		||||
 | 
			
		||||
    /// Setups geometry buffers and state.
 | 
			
		||||
    DrawParameters SetupGeometry(FixedPipelineState& fixed_state, BufferBindings& buffer_bindings,
 | 
			
		||||
                                 bool is_indexed, bool is_instanced);
 | 
			
		||||
 | 
			
		||||
    /// Setup descriptors in the graphics pipeline.
 | 
			
		||||
    void SetupShaderDescriptors(const std::array<Shader, Maxwell::MaxShaderProgram>& shaders);
 | 
			
		||||
 | 
			
		||||
    void SetupImageTransitions(Texceptions texceptions,
 | 
			
		||||
                               const std::array<View, Maxwell::NumRenderTargets>& color_attachments,
 | 
			
		||||
                               const View& zeta_attachment);
 | 
			
		||||
 | 
			
		||||
    void UpdateDynamicStates();
 | 
			
		||||
 | 
			
		||||
    bool WalkAttachmentOverlaps(const CachedSurfaceView& attachment);
 | 
			
		||||
 | 
			
		||||
    void SetupVertexArrays(FixedPipelineState::VertexInput& vertex_input,
 | 
			
		||||
                           BufferBindings& buffer_bindings);
 | 
			
		||||
 | 
			
		||||
    void SetupIndexBuffer(BufferBindings& buffer_bindings, DrawParameters& params, bool is_indexed);
 | 
			
		||||
 | 
			
		||||
    /// Setup constant buffers in the graphics pipeline.
 | 
			
		||||
    void SetupGraphicsConstBuffers(const ShaderEntries& entries, std::size_t stage);
 | 
			
		||||
 | 
			
		||||
    /// Setup global buffers in the graphics pipeline.
 | 
			
		||||
    void SetupGraphicsGlobalBuffers(const ShaderEntries& entries, std::size_t stage);
 | 
			
		||||
 | 
			
		||||
    /// Setup texel buffers in the graphics pipeline.
 | 
			
		||||
    void SetupGraphicsTexelBuffers(const ShaderEntries& entries, std::size_t stage);
 | 
			
		||||
 | 
			
		||||
    /// Setup textures in the graphics pipeline.
 | 
			
		||||
    void SetupGraphicsTextures(const ShaderEntries& entries, std::size_t stage);
 | 
			
		||||
 | 
			
		||||
    /// Setup images in the graphics pipeline.
 | 
			
		||||
    void SetupGraphicsImages(const ShaderEntries& entries, std::size_t stage);
 | 
			
		||||
 | 
			
		||||
    /// Setup constant buffers in the compute pipeline.
 | 
			
		||||
    void SetupComputeConstBuffers(const ShaderEntries& entries);
 | 
			
		||||
 | 
			
		||||
    /// Setup global buffers in the compute pipeline.
 | 
			
		||||
    void SetupComputeGlobalBuffers(const ShaderEntries& entries);
 | 
			
		||||
 | 
			
		||||
    /// Setup texel buffers in the compute pipeline.
 | 
			
		||||
    void SetupComputeTexelBuffers(const ShaderEntries& entries);
 | 
			
		||||
 | 
			
		||||
    /// Setup textures in the compute pipeline.
 | 
			
		||||
    void SetupComputeTextures(const ShaderEntries& entries);
 | 
			
		||||
 | 
			
		||||
    /// Setup images in the compute pipeline.
 | 
			
		||||
    void SetupComputeImages(const ShaderEntries& entries);
 | 
			
		||||
 | 
			
		||||
    void SetupConstBuffer(const ConstBufferEntry& entry,
 | 
			
		||||
                          const Tegra::Engines::ConstBufferInfo& buffer);
 | 
			
		||||
 | 
			
		||||
    void SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address);
 | 
			
		||||
 | 
			
		||||
    void SetupTexelBuffer(const Tegra::Texture::TICEntry& image, const TexelBufferEntry& entry);
 | 
			
		||||
 | 
			
		||||
    void SetupTexture(const Tegra::Texture::FullTextureInfo& texture, const SamplerEntry& entry);
 | 
			
		||||
 | 
			
		||||
    void SetupImage(const Tegra::Texture::TICEntry& tic, const ImageEntry& entry);
 | 
			
		||||
 | 
			
		||||
    void UpdateViewportsState(Tegra::Engines::Maxwell3D& gpu);
 | 
			
		||||
    void UpdateScissorsState(Tegra::Engines::Maxwell3D& gpu);
 | 
			
		||||
    void UpdateDepthBias(Tegra::Engines::Maxwell3D& gpu);
 | 
			
		||||
    void UpdateBlendConstants(Tegra::Engines::Maxwell3D& gpu);
 | 
			
		||||
    void UpdateDepthBounds(Tegra::Engines::Maxwell3D& gpu);
 | 
			
		||||
    void UpdateStencilFaces(Tegra::Engines::Maxwell3D& gpu);
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateGraphicsStreamBufferSize(bool is_indexed) const;
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateComputeStreamBufferSize() const;
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateVertexArraysSize() const;
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateIndexBufferSize() const;
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateConstBufferSize(const ConstBufferEntry& entry,
 | 
			
		||||
                                         const Tegra::Engines::ConstBufferInfo& buffer) const;
 | 
			
		||||
 | 
			
		||||
    RenderPassParams GetRenderPassParams(Texceptions texceptions) const;
 | 
			
		||||
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
    Core::Frontend::EmuWindow& render_window;
 | 
			
		||||
    VKScreenInfo& screen_info;
 | 
			
		||||
    const VKDevice& device;
 | 
			
		||||
    VKResourceManager& resource_manager;
 | 
			
		||||
    VKMemoryManager& memory_manager;
 | 
			
		||||
    VKScheduler& scheduler;
 | 
			
		||||
 | 
			
		||||
    VKStagingBufferPool staging_pool;
 | 
			
		||||
    VKDescriptorPool descriptor_pool;
 | 
			
		||||
    VKUpdateDescriptorQueue update_descriptor_queue;
 | 
			
		||||
    QuadArrayPass quad_array_pass;
 | 
			
		||||
    Uint8Pass uint8_pass;
 | 
			
		||||
 | 
			
		||||
    VKTextureCache texture_cache;
 | 
			
		||||
    VKPipelineCache pipeline_cache;
 | 
			
		||||
    VKBufferCache buffer_cache;
 | 
			
		||||
    VKSamplerCache sampler_cache;
 | 
			
		||||
 | 
			
		||||
    std::array<View, Maxwell::NumRenderTargets> color_attachments;
 | 
			
		||||
    View zeta_attachment;
 | 
			
		||||
 | 
			
		||||
    std::vector<ImageView> sampled_views;
 | 
			
		||||
    std::vector<ImageView> image_views;
 | 
			
		||||
 | 
			
		||||
    u32 draw_counter = 0;
 | 
			
		||||
 | 
			
		||||
    // TODO(Rodrigo): Invalidate on image destruction
 | 
			
		||||
    std::unordered_map<FramebufferCacheKey, UniqueFramebuffer> framebuffer_cache;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user