1 #pragma once
2 
3 #include <memory>
4 #include "GSH_VulkanContext.h"
5 #include "GSH_VulkanFrameCommandBuffer.h"
6 #include "GSH_VulkanPipelineCache.h"
7 #include "vulkan/ShaderModule.h"
8 #include "vulkan/Buffer.h"
9 #include "vulkan/Image.h"
10 #include "Convertible.h"
11 
12 namespace GSH_Vulkan
13 {
14 	class CDraw : public IFrameCommandBufferWriter
15 	{
16 	public:
17 		enum
18 		{
19 			MAX_FRAMES = CFrameCommandBuffer::MAX_FRAMES,
20 		};
21 
22 		typedef uint64 PipelineCapsInt;
23 
24 		enum PIPELINE_PRIMITIVE_TYPE
25 		{
26 			PIPELINE_PRIMITIVE_TRIANGLE = 0,
27 			PIPELINE_PRIMITIVE_LINE = 1,
28 		};
29 
30 		struct PIPELINE_CAPS : public convertible<PipelineCapsInt>
31 		{
32 			uint32 primitiveType : 2;
33 
34 			uint32 hasTexture : 1;
35 			uint32 textureHasAlpha : 1;
36 			uint32 textureBlackIsTransparent : 1;
37 			uint32 textureFunction : 2;
38 			uint32 textureUseLinearFiltering : 1;
39 			uint32 texClampU : 2;
40 			uint32 texClampV : 2;
41 
42 			uint32 hasFog : 1;
43 
44 			uint32 maskColor : 1;
45 			uint32 writeDepth : 1;
46 
47 			uint32 hasAlphaBlending : 1;
48 			uint32 alphaA : 2;
49 			uint32 alphaB : 2;
50 			uint32 alphaC : 2;
51 			uint32 alphaD : 2;
52 
53 			uint32 depthTestFunction : 2;
54 			uint32 alphaTestFunction : 3;
55 			uint32 alphaTestFailAction : 2;
56 
57 			uint32 hasDstAlphaTest : 1;
58 			uint32 dstAlphaTestRef : 1;
59 
60 			uint32 textureFormat : 6;
61 			uint32 clutFormat : 6;
62 			uint32 framebufferFormat : 6;
63 			uint32 depthbufferFormat : 6;
64 		};
65 		static_assert(sizeof(PIPELINE_CAPS) <= sizeof(PipelineCapsInt), "PIPELINE_CAPS too big for PipelineCapsInt");
66 
67 		struct PRIM_VERTEX
68 		{
69 			float x, y;
70 			uint32 z;
71 			uint32 color;
72 			float s, t, q;
73 			float f;
74 		};
75 
76 		CDraw(const ContextPtr&, const FrameCommandBufferPtr&);
77 		virtual ~CDraw();
78 
79 		void SetPipelineCaps(const PIPELINE_CAPS&);
80 		void SetFramebufferParams(uint32, uint32, uint32);
81 		void SetDepthbufferParams(uint32, uint32);
82 		void SetTextureParams(uint32, uint32, uint32, uint32, uint32);
83 		void SetClutBufferOffset(uint32);
84 		void SetTextureAlphaParams(uint32, uint32);
85 		void SetTextureClampParams(uint32, uint32, uint32, uint32);
86 		void SetFogParams(float, float, float);
87 		void SetAlphaBlendingParams(uint32);
88 		void SetAlphaTestParams(uint32);
89 		void SetScissor(uint32, uint32, uint32, uint32);
90 
91 		void AddVertices(const PRIM_VERTEX*, const PRIM_VERTEX*);
92 		void FlushVertices();
93 		void FlushRenderPass();
94 
95 		void PreFlushFrameCommandBuffer() override;
96 		void PostFlushFrameCommandBuffer() override;
97 
98 	private:
99 		struct FRAMECONTEXT
100 		{
101 			Framework::Vulkan::CBuffer vertexBuffer;
102 			PRIM_VERTEX* vertexBufferPtr = nullptr;
103 		};
104 
105 		typedef uint32 DescriptorSetCapsInt;
106 
107 		struct DESCRIPTORSET_CAPS : public convertible<DescriptorSetCapsInt>
108 		{
109 			uint32 hasTexture : 1;
110 			uint32 textureFormat : 6;
111 			uint32 framebufferFormat : 6;
112 			uint32 depthbufferFormat : 6;
113 		};
114 		static_assert(sizeof(DESCRIPTORSET_CAPS) == sizeof(DescriptorSetCapsInt));
115 		typedef std::unordered_map<DescriptorSetCapsInt, VkDescriptorSet> DescriptorSetCache;
116 
117 		typedef CPipelineCache<PipelineCapsInt> PipelineCache;
118 
119 		struct DRAW_PIPELINE_PUSHCONSTANTS
120 		{
121 			//fbDepthParams
122 			uint32 fbBufAddr = 0;
123 			uint32 fbBufWidth = 0;
124 			uint32 depthBufAddr = 0;
125 			uint32 depthBufWidth = 0;
126 
127 			//texParams0
128 			uint32 texBufAddr = 0;
129 			uint32 texBufWidth = 0;
130 			uint32 texWidth = 0;
131 			uint32 texHeight = 0;
132 
133 			//texParams1
134 			uint32 texCsa = 0;
135 			uint32 texA0 = 0;
136 			uint32 texA1 = 0;
137 			uint32 texParams1Reserved = 0;
138 
139 			//texParams2
140 			uint32 clampMin[2];
141 			uint32 clampMax[2];
142 
143 			//alphaFbParams
144 			uint32 fbWriteMask = 0;
145 			uint32 alphaFix = 0;
146 			uint32 alphaRef = 0;
147 			uint32 alphaFbParamsReserved = 0;
148 
149 			//fogColor
150 			float fogColor[4];
151 		};
152 		static_assert(sizeof(DRAW_PIPELINE_PUSHCONSTANTS) <= 128, "Push constants size can't exceed 128 bytes.");
153 
154 		VkDescriptorSet PrepareDescriptorSet(VkDescriptorSetLayout, const DESCRIPTORSET_CAPS&);
155 
156 		void CreateFramebuffer();
157 		void CreateRenderPass();
158 		void CreateDrawImage();
159 
160 		PIPELINE CreateDrawPipeline(const PIPELINE_CAPS&);
161 		Framework::Vulkan::CShaderModule CreateVertexShader();
162 		Framework::Vulkan::CShaderModule CreateFragmentShader(const PIPELINE_CAPS&);
163 
164 		ContextPtr m_context;
165 		FrameCommandBufferPtr m_frameCommandBuffer;
166 		PipelineCache m_pipelineCache;
167 		DescriptorSetCache m_descriptorSetCache;
168 
169 		VkRenderPass m_renderPass = VK_NULL_HANDLE;
170 		VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
171 
172 		FRAMECONTEXT m_frames[MAX_FRAMES];
173 
174 		Framework::Vulkan::CImage m_drawImage;
175 		VkImageView m_drawImageView = VK_NULL_HANDLE;
176 
177 		uint32 m_passVertexStart = 0;
178 		uint32 m_passVertexEnd = 0;
179 		bool m_renderPassBegun = false;
180 
181 		PIPELINE_CAPS m_pipelineCaps;
182 		DRAW_PIPELINE_PUSHCONSTANTS m_pushConstants;
183 		uint32 m_scissorX = 0;
184 		uint32 m_scissorY = 0;
185 		uint32 m_scissorWidth = 0;
186 		uint32 m_scissorHeight = 0;
187 		uint32 m_clutBufferOffset = 0;
188 	};
189 
190 	typedef std::shared_ptr<CDraw> DrawPtr;
191 }
192