2022-11-27 10:22:37 +01:00
# pragma once
# include "Common/Common.h"
# include "Common/GPU/Vulkan/VulkanContext.h"
class VKRRenderPass ;
2023-05-31 14:10:36 +02:00
class VulkanBarrierBatch ;
2022-11-27 10:22:37 +01:00
// Pipelines need to be created for the right type of render pass.
// TODO: Rename to RenderPassFlags?
// When you add more flags, don't forget to update rpTypeDebugNames[].
enum class RenderPassType {
DEFAULT = 0 ,
// These eight are organized so that bit 0 is DEPTH and bit 1 is INPUT and bit 2 is MULTIVIEW, so
// they can be OR-ed together in MergeRPTypes.
HAS_DEPTH = 1 ,
2023-06-13 20:46:27 +02:00
MULTIVIEW = 2 ,
MULTISAMPLE = 4 ,
2022-11-27 10:22:37 +01:00
// This is the odd one out, and gets special handling in MergeRPTypes.
// If this flag is set, none of the other flags can be set.
// For the backbuffer we can always use CLEAR/DONT_CARE, so bandwidth cost for a depth channel is negligible
// so we don't bother with a non-depth version.
2023-06-13 20:46:27 +02:00
BACKBUFFER = 8 ,
2022-11-27 10:22:37 +01:00
TYPE_COUNT = BACKBUFFER + 1 ,
} ;
ENUM_CLASS_BITOPS ( RenderPassType ) ;
// Simple independent framebuffer image.
struct VKRImage {
// These four are "immutable".
VkImage image ;
VkImageView rtView ; // Used for rendering to, and readbacks of stencil. 2D if single layer, 2D_ARRAY if multiple. Includes both depth and stencil if depth/stencil.
// This is for texturing all layers at once. If aspect is depth/stencil, does not include stencil.
VkImageView texAllLayersView ;
// If it's a layered image (for stereo), this is two 2D views of it, to make it compatible with shaders that don't yet support stereo.
// If there's only one layer, layerViews[0] only is initialized.
VkImageView texLayerViews [ 2 ] { } ;
VmaAllocation alloc ;
VkFormat format ;
2022-11-28 11:50:28 +01:00
VkSampleCountFlagBits sampleCount ;
2022-11-27 10:22:37 +01:00
// This one is used by QueueRunner's Perform functions to keep track. CANNOT be used anywhere else due to sync issues.
VkImageLayout layout ;
int numLayers ;
// For debugging.
std : : string tag ;
2022-11-28 11:50:28 +01:00
void Delete ( VulkanContext * vulkan ) ;
2022-11-27 10:22:37 +01:00
} ;
class VKRFramebuffer {
public :
2024-10-10 10:24:40 +02:00
VKRFramebuffer ( VulkanContext * vk , VulkanBarrierBatch * barriers , int _width , int _height , int _numLayers , int _multiSampleLevel , bool createDepthStencilBuffer , const char * tag ) ;
2022-11-27 10:22:37 +01:00
~ VKRFramebuffer ( ) ;
VkFramebuffer Get ( VKRRenderPass * compatibleRenderPass , RenderPassType rpType ) ;
int width = 0 ;
int height = 0 ;
int numLayers = 0 ;
2022-11-27 11:39:44 +01:00
VkSampleCountFlagBits sampleCount ;
2022-11-27 10:22:37 +01:00
VKRImage color { } ; // color.image is always there.
VKRImage depth { } ; // depth.image is allowed to be VK_NULL_HANDLE.
2022-11-27 11:39:44 +01:00
// These are only initialized and used if numSamples > 1.
VKRImage msaaColor { } ;
VKRImage msaaDepth { } ;
2022-11-27 10:22:37 +01:00
const char * Tag ( ) const {
return tag_ . c_str ( ) ;
}
void UpdateTag ( const char * newTag ) ;
bool HasDepth ( ) const {
return depth . image ! = VK_NULL_HANDLE ;
}
2022-11-28 11:50:28 +01:00
VkImageView GetRTView ( ) {
if ( sampleCount = = VK_SAMPLE_COUNT_1_BIT ) {
return color . rtView ;
} else {
return msaaColor . rtView ;
}
}
2022-11-27 11:39:44 +01:00
VulkanContext * Vulkan ( ) const { return vulkan_ ; }
2022-11-27 10:22:37 +01:00
private :
2024-10-10 10:24:40 +02:00
static void CreateImage ( VulkanContext * vulkan , VulkanBarrierBatch * barriers , VKRImage & img , int width , int height , int numLayers , VkSampleCountFlagBits sampleCount , VkFormat format , VkImageLayout initialLayout , bool color , const char * tag ) ;
2022-11-27 10:22:37 +01:00
VkFramebuffer framebuf [ ( size_t ) RenderPassType : : TYPE_COUNT ] { } ;
2022-11-27 11:39:44 +01:00
VulkanContext * vulkan_ ;
2022-11-27 10:22:37 +01:00
std : : string tag_ ;
} ;
inline bool RenderPassTypeHasDepth ( RenderPassType type ) {
return ( type & RenderPassType : : HAS_DEPTH ) | | type = = RenderPassType : : BACKBUFFER ;
}
inline bool RenderPassTypeHasMultiView ( RenderPassType type ) {
return ( type & RenderPassType : : MULTIVIEW ) ! = 0 ;
}
2022-11-28 11:50:28 +01:00
inline bool RenderPassTypeHasMultisample ( RenderPassType type ) {
return ( type & RenderPassType : : MULTISAMPLE ) ! = 0 ;
}
VkSampleCountFlagBits MultiSampleLevelToFlagBits ( int count ) ;
2022-11-27 11:39:44 +01:00
2022-11-27 10:22:37 +01:00
// Must be the same order as Draw::RPAction
enum class VKRRenderPassLoadAction : uint8_t {
KEEP , // default. avoid when possible.
CLEAR ,
DONT_CARE ,
} ;
enum class VKRRenderPassStoreAction : uint8_t {
STORE , // default. avoid when possible.
DONT_CARE ,
} ;
struct RPKey {
// Only render-pass-compatibility-volatile things can be here.
VKRRenderPassLoadAction colorLoadAction ;
VKRRenderPassLoadAction depthLoadAction ;
VKRRenderPassLoadAction stencilLoadAction ;
VKRRenderPassStoreAction colorStoreAction ;
VKRRenderPassStoreAction depthStoreAction ;
VKRRenderPassStoreAction stencilStoreAction ;
} ;
class VKRRenderPass {
public :
2024-10-10 11:55:07 +02:00
explicit VKRRenderPass ( const RPKey & key ) : key_ ( key ) { }
2022-11-27 10:22:37 +01:00
2022-11-27 11:39:44 +01:00
VkRenderPass Get ( VulkanContext * vulkan , RenderPassType rpType , VkSampleCountFlagBits sampleCount ) ;
2022-11-27 10:22:37 +01:00
void Destroy ( VulkanContext * vulkan ) {
for ( size_t i = 0 ; i < ( size_t ) RenderPassType : : TYPE_COUNT ; i + + ) {
if ( pass [ i ] ) {
vulkan - > Delete ( ) . QueueDeleteRenderPass ( pass [ i ] ) ;
}
}
}
private :
// TODO: Might be better off with a hashmap once the render pass type count grows really large..
VkRenderPass pass [ ( size_t ) RenderPassType : : TYPE_COUNT ] { } ;
2024-01-17 21:41:04 +01:00
VkSampleCountFlagBits sampleCounts [ ( size_t ) RenderPassType : : TYPE_COUNT ] { } ;
2022-11-27 10:22:37 +01:00
RPKey key_ ;
} ;
2023-09-19 11:17:25 +02:00
const char * GetRPTypeName ( RenderPassType rpType ) ;