mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
Merge pull request #3313 from ReinUsesLisp/vk-rasterizer
vk_rasterizer: Implement Vulkan's rasterizer
This commit is contained in:
commit
41373d212e
4 changed files with 1466 additions and 1 deletions
|
@ -153,6 +153,7 @@ if (ENABLE_VULKAN)
|
||||||
renderer_vulkan/fixed_pipeline_state.h
|
renderer_vulkan/fixed_pipeline_state.h
|
||||||
renderer_vulkan/maxwell_to_vk.cpp
|
renderer_vulkan/maxwell_to_vk.cpp
|
||||||
renderer_vulkan/maxwell_to_vk.h
|
renderer_vulkan/maxwell_to_vk.h
|
||||||
|
renderer_vulkan/renderer_vulkan.h
|
||||||
renderer_vulkan/vk_buffer_cache.cpp
|
renderer_vulkan/vk_buffer_cache.cpp
|
||||||
renderer_vulkan/vk_buffer_cache.h
|
renderer_vulkan/vk_buffer_cache.h
|
||||||
renderer_vulkan/vk_compute_pass.cpp
|
renderer_vulkan/vk_compute_pass.cpp
|
||||||
|
@ -171,6 +172,7 @@ if (ENABLE_VULKAN)
|
||||||
renderer_vulkan/vk_memory_manager.h
|
renderer_vulkan/vk_memory_manager.h
|
||||||
renderer_vulkan/vk_pipeline_cache.cpp
|
renderer_vulkan/vk_pipeline_cache.cpp
|
||||||
renderer_vulkan/vk_pipeline_cache.h
|
renderer_vulkan/vk_pipeline_cache.h
|
||||||
|
renderer_vulkan/vk_rasterizer.cpp
|
||||||
renderer_vulkan/vk_rasterizer.h
|
renderer_vulkan/vk_rasterizer.h
|
||||||
renderer_vulkan/vk_renderpass_cache.cpp
|
renderer_vulkan/vk_renderpass_cache.cpp
|
||||||
renderer_vulkan/vk_renderpass_cache.h
|
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
|
#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/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 {
|
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
|
} // namespace Vulkan
|
||||||
|
|
Loading…
Reference in a new issue