CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/GPU/Vulkan/DrawEngineVulkan.h
Views: 1401
// Copyright (c) 2015- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819// The Descriptor Set used for the majority of PSP rendering looks like this:20//21// * binding 0: Texture/Sampler (the PSP texture)22// * binding 1: Secondary texture sampler for shader blending23// * binding 2: Depal palette24// * binding 3: Base Uniform Buffer (includes fragment state)25// * binding 4: Light uniform buffer26// * binding 5: Bone uniform buffer27// * binding 6: Tess data storage buffer28//29// All shaders conform to this layout, so they are all compatible with the same descriptor set.30// The format of the various uniform buffers may vary though - vertex shaders that don't skin31// won't get any bone data, etc.3233#include "Common/Data/Collections/Hashmaps.h"3435#include "GPU/Vulkan/VulkanUtil.h"3637#include "GPU/GPUState.h"38#include "GPU/Common/GPUDebugInterface.h"39#include "GPU/Common/IndexGenerator.h"40#include "GPU/Common/VertexDecoderCommon.h"41#include "GPU/Common/DrawEngineCommon.h"42#include "GPU/Common/GPUStateUtils.h"43#include "GPU/Vulkan/StateMappingVulkan.h"44#include "GPU/Vulkan/VulkanRenderManager.h"454647// TODO: Move to some appropriate header.48#ifdef _MSC_VER49#define NO_INLINE __declspec(noinline)50#else51#define NO_INLINE __attribute__((noinline))52#endif5354struct DecVtxFormat;55struct UVScale;5657class ShaderManagerVulkan;58class PipelineManagerVulkan;59class TextureCacheVulkan;60class FramebufferManagerVulkan;6162class VulkanContext;63class VulkanPushPool;64struct VulkanPipeline;6566struct DrawEngineVulkanStats {67int pushVertexSpaceUsed;68int pushIndexSpaceUsed;69};7071class VulkanRenderManager;7273class TessellationDataTransferVulkan : public TessellationDataTransfer {74public:75TessellationDataTransferVulkan(VulkanContext *vulkan) : vulkan_(vulkan) {}7677void SetPushPool(VulkanPushPool *push) { push_ = push; }78// Send spline/bezier's control points and weights to vertex shader through structured shader buffer.79void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override;80const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; }81private:82VulkanContext *vulkan_;83VulkanPushPool *push_; // Updated each frame.84VkDescriptorBufferInfo bufInfo_[3]{};85};8687enum {88DRAW_BINDING_TEXTURE = 0,89DRAW_BINDING_2ND_TEXTURE = 1,90DRAW_BINDING_DEPAL_TEXTURE = 2,91DRAW_BINDING_DYNUBO_BASE = 3,92DRAW_BINDING_DYNUBO_LIGHT = 4,93DRAW_BINDING_DYNUBO_BONE = 5,94DRAW_BINDING_TESS_STORAGE_BUF = 6,95DRAW_BINDING_TESS_STORAGE_BUF_WU = 7,96DRAW_BINDING_TESS_STORAGE_BUF_WV = 8,97DRAW_BINDING_COUNT = 9,98};99100// Handles transform, lighting and drawing.101class DrawEngineVulkan : public DrawEngineCommon {102public:103DrawEngineVulkan(Draw::DrawContext *draw);104~DrawEngineVulkan();105106// We reference feature flags, so this is called after construction.107void InitDeviceObjects();108109void SetShaderManager(ShaderManagerVulkan *shaderManager) {110shaderManager_ = shaderManager;111}112void SetPipelineManager(PipelineManagerVulkan *pipelineManager) {113pipelineManager_ = pipelineManager;114}115void SetTextureCache(TextureCacheVulkan *textureCache) {116textureCache_ = textureCache;117}118void SetFramebufferManager(FramebufferManagerVulkan *fbManager) {119framebufferManager_ = fbManager;120}121122void DeviceLost() override;123void DeviceRestore(Draw::DrawContext *draw) override;124125// So that this can be inlined126void Flush() {127if (!numDrawInds_)128return;129DoFlush();130}131132void FinishDeferred() {133if (!numDrawInds_)134return;135// Decode any pending vertices. And also flush while we're at it, for simplicity.136// It might be possible to only decode like in the other backends, but meh, it can't matter.137// Issue #10095 has a nice example of where this is required.138DoFlush();139}140141void DispatchFlush() override {142if (!numDrawInds_)143return;144DoFlush();145}146147VKRPipelineLayout *GetPipelineLayout() const {148return pipelineLayout_;149}150151void BeginFrame();152void EndFrame();153154void DirtyAllUBOs();155156void DirtyPipeline() {157lastPipeline_ = nullptr;158}159160VulkanPushPool *GetPushBufferForTextureData() {161return pushUBO_;162}163164const DrawEngineVulkanStats &GetStats() const {165return stats_;166}167168void SetDepalTexture(VkImageView depal, bool smooth) {169if (boundDepal_ != depal) {170boundDepal_ = depal;171boundDepalSmoothed_ = smooth;172gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);173}174}175176private:177void Invalidate(InvalidationCallbackFlags flags);178179void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant);180void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerVulkan *shaderManager, int prim, VulkanPipelineRasterStateKey &key, VulkanDynamicState &dynState);181void BindShaderBlendTex();182183void DestroyDeviceObjects();184185void DoFlush();186void UpdateUBOs();187188NO_INLINE void ResetAfterDraw();189190Draw::DrawContext *draw_;191192// We use a shared descriptor set layouts for all PSP draws.193VKRPipelineLayout *pipelineLayout_ = nullptr;194VulkanPipeline *lastPipeline_ = nullptr;195VkDescriptorSet lastDs_ = VK_NULL_HANDLE;196197// Secondary texture for shader blending198VkImageView boundSecondary_ = VK_NULL_HANDLE;199200// CLUT texture for shader depal201VkImageView boundDepal_ = VK_NULL_HANDLE;202bool boundDepalSmoothed_ = false;203VkSampler samplerSecondaryLinear_ = VK_NULL_HANDLE;204VkSampler samplerSecondaryNearest_ = VK_NULL_HANDLE;205206struct DescriptorSetKey {207VkImageView imageView_;208VkImageView secondaryImageView_;209VkImageView depalImageView_;210VkSampler sampler_;211VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical212// for all draws in a frame, except when the buffer has to grow.213};214215GEPrimitiveType lastPrim_ = GE_PRIM_INVALID;216217// This one's not accurately named, it's used for all kinds of stuff that's not vertices or indices.218VulkanPushPool *pushUBO_ = nullptr;219220VulkanPushPool *pushVertex_ = nullptr;221VulkanPushPool *pushIndex_ = nullptr;222223// Other224ShaderManagerVulkan *shaderManager_ = nullptr;225PipelineManagerVulkan *pipelineManager_ = nullptr;226TextureCacheVulkan *textureCache_ = nullptr;227FramebufferManagerVulkan *framebufferManager_ = nullptr;228229// State cache230uint64_t dirtyUniforms_ = 0;231uint32_t baseUBOOffset = 0;232uint32_t lightUBOOffset = 0;233uint32_t boneUBOOffset = 0;234VkBuffer baseBuf = VK_NULL_HANDLE;235VkBuffer lightBuf = VK_NULL_HANDLE;236VkBuffer boneBuf = VK_NULL_HANDLE;237VkImageView imageView = VK_NULL_HANDLE;238VkSampler sampler = VK_NULL_HANDLE;239240// For null texture241VkSampler nullSampler_ = VK_NULL_HANDLE;242243DrawEngineVulkanStats stats_{};244245VulkanPipelineRasterStateKey pipelineKey_{};246VulkanDynamicState dynState_{};247248int tessOffset_ = 0;249FBOTexState fboTexBindState_ = FBO_TEX_NONE;250251// Hardware tessellation252TessellationDataTransferVulkan *tessDataTransferVulkan;253};254255256