Engine
Frameworkcreatedbymeusableforthecreationofsimplegames.CurrentlysupportsOpenGL(Verysimple)andVulkan.
VulkanSkeletalMeshRenderer.cpp
Go to the documentation of this file.
2 #ifdef USING_VULKAN
4 #include "Engine/engine.hpp"
6 
7 namespace Engine {
8 
9  VulkanSkeletalMeshRenderer::VulkanSkeletalMeshRenderer(VulkanRenderer* renderer, VulkanLogicalDevice* device, VulkanDescriptorPool* descriptorPool)
10  {
11  this->renderer_ = renderer;
12  this->device_ = device;
13  this->descriptorPool_ = descriptorPool;
14  this->commandPool_ = renderer->GetGraphicsCommandPool();
15  this->allocator_ = renderer->GetVmaAllocator();
16 
17  skeletalMeshPipeline_ = eastl::unique_ptr<VulkanPipeline>(new VulkanPipeline(device, renderer));
18 
19  skeletalMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER, "SkeletonMesh.vert.spv");
20  //skeletalMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::GEOMETRY_SHADER, "Mesh.geom.spv");
21  skeletalMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER, "Mesh.frag.spv");
22 
23  skeletalMeshPipeline_->AddVertexInputBindingDescription(0, static_cast<uint32_t>(sizeof(Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
24  skeletalMeshPipeline_->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position));
25  skeletalMeshPipeline_->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal));
26  skeletalMeshPipeline_->AddVertexInputAttributeDescription(2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoords));
27  skeletalMeshPipeline_->AddVertexInputAttributeDescription(3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, boneWeights));
28  skeletalMeshPipeline_->AddVertexInputAttributeDescription(4, 0, VK_FORMAT_R32G32B32A32_SINT, offsetof(Vertex, boneIds));
29 
30 
31  skeletalMeshPipeline_->CreateDescriptorSet();
32  skeletalMeshPipeline_->AddDescriptorSetLayout(VulkanMaterial::CreateMaterialDescriptorSetLayout(device));
33  skeletalMeshPipeline_->AddDescriptorSetLayout(renderer_->CreateLightDescriptorSetLayout());
34  skeletalMeshPipeline_->CreateDescriptorSet();
35  skeletalMeshPipeline_->CreateDescriptorSet();
36 
37  skeletalMeshPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, nullptr);
38  skeletalMeshPipeline_->AddDescriptorSetBinding(3, 0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr);
39  skeletalMeshPipeline_->AddDescriptorSetBinding(4, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr);
40 
41  skeletalMeshPipeline_->AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, static_cast<uint32_t>(sizeof(PushConstants_t)));
42 
43  skeletalMeshPipeline_->SetRenderPassInfo(renderer->GetGBufferRenderPass(), static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
44 
45  skeletalMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
46  skeletalMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
47  skeletalMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
48 
49  skeletalMeshPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false);
50 
51  skeletalMeshPipeline_->SetRasterizerSettings();
52 
53  skeletalMeshPipeline_->Compile();
54 
55  shadowPipeline_ = eastl::unique_ptr<VulkanPipeline>(new VulkanPipeline(device_, renderer_));
56 
57  shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER, "SkeletonShadow.vert.spv");
58  shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::GEOMETRY_SHADER, "ShadowVolume.geom.spv");
59  shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER, "ShadowVolume.frag.spv");
60 
61  shadowPipeline_->AddVertexInputBindingDescription(0,
62  static_cast<uint32_t>(sizeof(Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
63 
64  shadowPipeline_->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position));
65  shadowPipeline_->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal));
66  shadowPipeline_->AddVertexInputAttributeDescription(2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoords));
67  shadowPipeline_->AddVertexInputAttributeDescription(3, 0, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, boneWeights));
68  shadowPipeline_->AddVertexInputAttributeDescription(4, 0, VK_FORMAT_R32G32B32A32_SINT, offsetof(Vertex, boneIds));
69 
70  shadowPipeline_->CreateDescriptorSet();
71  shadowPipeline_->AddDescriptorSetLayout(renderer_->CreateLightDescriptorSetLayout());
72  shadowPipeline_->CreateDescriptorSet();
73  shadowPipeline_->CreateDescriptorSet();
74  shadowPipeline_->CreateDescriptorSet();
75 
76  shadowPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, nullptr);
77  shadowPipeline_->AddDescriptorSetBinding(3, 0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr);
78  shadowPipeline_->AddDescriptorSetBinding(4, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr);
79 
80  shadowPipeline_->AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
81  0, static_cast<uint32_t>(sizeof(PushConstants_t)));
82 
83  shadowPipeline_->SetRenderPassInfo(renderer->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
84 
85  shadowPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, false);
86 
87  shadowPipeline_->SetRasterizerSettings(VK_TRUE, VK_FALSE,
88  VK_POLYGON_MODE_FILL, 1.f, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, VK_FALSE, 0.0, 0.f, 0.f);
89 
90  VkStencilOpState front = {};
91  front.failOp = VK_STENCIL_OP_KEEP;
92  front.passOp = VK_STENCIL_OP_KEEP;
93  front.depthFailOp = VK_STENCIL_OP_DECREMENT_AND_WRAP;
94  front.compareOp = VK_COMPARE_OP_ALWAYS;
95  front.reference = 0;
96  front.writeMask = 0xff;
97  front.compareMask = 0xff;
98 
99  VkStencilOpState back = {};
100  back.failOp = VK_STENCIL_OP_KEEP;
101  back.passOp = VK_STENCIL_OP_KEEP;
102  back.depthFailOp = VK_STENCIL_OP_INCREMENT_AND_WRAP;
103  back.compareOp = VK_COMPARE_OP_ALWAYS;
104  back.reference = 0;
105  back.writeMask = 0xff;
106  back.compareMask = 0xff;
107 
108  shadowPipeline_->SetDepthStencilState(VK_TRUE, VK_FALSE, VK_COMPARE_OP_LESS, VK_TRUE, 0.f, 1.f, VK_TRUE, front, back);
109 
110  shadowPipeline_->CreateColorBlendAttachment(VK_TRUE, 0U);
111 
112  shadowPipeline_->Compile();
113 
114  ubo_ = { glm::mat4(), glm::mat4() };
115 
116  uniformBuffer_ = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, renderer->GetVmaAllocator(),
117  static_cast<uint32_t>(sizeof(ubo_)), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, false, renderer->GetGraphicsCommandPool()));
118 
119  uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(sizeof(ubo_)));
120 
121  uboDescriptors_.resize(renderer_->GetThreadCount());
122 
123  for (size_t i = 0, size = uboDescriptors_.size(); i < size; ++i) {
124 
125  VkDescriptorSetLayout layouts[] = { skeletalMeshPipeline_->GetDescriptorSetLayout(0) };
126  renderer_->GetDescriptorPool(i)->AllocateDescriptorSet(1, layouts, &uboDescriptors_[i]);
127 
128  renderer_->GetDescriptorPool(i)->DescriptorSetBindToBuffer(uboDescriptors_[i], uniformBuffer_->GetBuffer(),
129  0, static_cast<VkDeviceSize>(sizeof(ubo_)), 0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
130  }
131 
132  Engine::GetEngine().lock()->GetResourceManager().lock()->CreateTexture("default.png");
133  defaultTexture_ = eastl::dynamic_pointer_cast<VulkanTexture, Texture>(
134  Engine::GetEngine().lock()->GetResourceManager().lock()->GetTexture("default.png").lock());
135  }
136 
137 
138  VulkanSkeletalMeshRenderer::~VulkanSkeletalMeshRenderer()
139  {
140  uniformBuffer_.reset();
141 
142  skeletalMeshPipeline_.reset();
143  }
144 
145  void VulkanSkeletalMeshRenderer::StartRender(glm::mat4 view, glm::mat4 projection) {
146  if (ubo_.view != view || ubo_.proj != projection) {
147  ubo_.view = view;
148  ubo_.proj = projection;
149 
150  uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(sizeof(ubo_)));
151  }
152 
153  meshes.clear();
154  }
155 
156  void VulkanSkeletalMeshRenderer::RenderMesh(const glm::mat4x4& modelMatrix, VulkanMesh* mesh,
157  VulkanMaterial* material, Skeleton* skeleton, size_t animation,
158  float time, float ticksPerSecond, float duration, bool looping, const glm::vec4 & mainColor)
159  {
160  MeshData data = {};
161  data.animation = animation;
162  data.skeleton = skeleton;
163  data.transform = modelMatrix;
164  data.material = material;
165  data.color = mainColor;
166  data.mesh = mesh;
167  data.time = time;
168  data.ticksPerSecond = ticksPerSecond;
169  data.duration = duration;
170  data.looping = looping;
171  data.boneData = static_cast<VulkanTexture*>(skeleton->GetAnimationData(animation));
172 
173  meshes.push_back(data);
174  }
175 
176  void VulkanSkeletalMeshRenderer::FinishRender(size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer)
177  {
178  /*VkCommandBufferAllocateInfo allocInfo = {};
179  allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
180  allocInfo.commandBufferCount = 1;
181  allocInfo.commandPool = commandPool;
182  allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
183 */
184  VkCommandBuffer commandBuffer = buffer;
185 /*
186  vkAllocateCommandBuffers(device->GetDevice(), &allocInfo, &commandBuffer);*/
187 
188  renderer_->StartSecondaryCommandBufferRecording(commandBuffer,
189  VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
190  renderer_->GetGBufferRenderPass(), static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS), VK_NULL_HANDLE);
191 
192 
193  VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
194 
195  vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
196 
197  vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipeline());
198 
199  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
200  skeletalMeshPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0, nullptr);
201 
202  for (size_t i = 0, size = meshes.size(); i<size; ++i) {
203 
204  VulkanMesh* mesh = meshes[i].mesh;
205 
206  PushConstants_t constants = {};
207  constants.model = meshes[i].transform;
208  constants.color = meshes[i].color;
209  constants.duration = meshes[i].duration;
210  constants.looping = meshes[i].looping;
211  constants.ticksPerSecond = meshes[i].ticksPerSecond;
212  constants.time = meshes[i].time;
213 
214 
215  vkCmdPushConstants(commandBuffer, skeletalMeshPipeline_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0,
216  static_cast<uint32_t>(sizeof(PushConstants_t)), &constants);
217 
218  VkBuffer buffers[] = { mesh->GetVertexBuffer() };
219  VkDeviceSize offsets[] = { 0 };
220  vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
221 
222  vkCmdBindIndexBuffer(commandBuffer, mesh->GetIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
223 
224  VkDescriptorSet materialDescriptor;
225 
226  materialDescriptor = meshes[i].material->GetMaterialDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(), 1);
227  if (materialDescriptor == VK_NULL_HANDLE)
228  materialDescriptor = meshes[i].material->CreateMaterialDescriptorSet(
229  threadID, skeletalMeshPipeline_->GetPipelineId(),
230  1, skeletalMeshPipeline_->GetDescriptorSetLayout(1));
231 
232  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipelineLayout(),
233  1, 1, &(materialDescriptor), 0, nullptr);
234 
235  VkDescriptorSet boneOffsets = mesh->GetBoneOffsetDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(), 4);
236 
237  if (boneOffsets == VK_NULL_HANDLE)
238  boneOffsets = mesh->CreateBoneOffsetDescriptorSet(
239  threadID, skeletalMeshPipeline_->GetPipelineId(),
240  4, skeletalMeshPipeline_->GetDescriptorSetLayout(4));
241 
242  VkDescriptorSet boneDescriptor = meshes[i].boneData->GetDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(), 3);
243  if (boneDescriptor == VK_NULL_HANDLE)
244  boneDescriptor = meshes[i].boneData->CreateDescriptorSet(threadID, skeletalMeshPipeline_->GetPipelineId(),
245  3, skeletalMeshPipeline_->GetDescriptorSetLayout(3));
246 
247  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipelineLayout(),
248  3, 1, &(boneDescriptor), 0, nullptr);
249 
250  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, skeletalMeshPipeline_->GetPipelineLayout(), 4, 1, &boneOffsets, 0, nullptr);
251 
252  vkCmdDrawIndexed(commandBuffer, mesh->GetIndexCount(), 1, 0, 0, 0);
253  }
254 
255  renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
256 
257  }
258 
259  void VulkanSkeletalMeshRenderer::RenderShadows(size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer, uint32_t lightOffset)
260  {/*
261  VkCommandBufferAllocateInfo allocInfo = {};
262  allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
263  allocInfo.commandBufferCount = 1;
264  allocInfo.commandPool = commandPool;
265  allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;*/
266 
267  VkCommandBuffer commandBuffer = buffer;
268 /*
269  vkAllocateCommandBuffers(device->GetDevice(), &allocInfo, &commandBuffer);*/
270 
271  renderer_->StartSecondaryCommandBufferRecording(commandBuffer,
272  VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
273  renderer_->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS), renderer_->GetFrameBuffer());
274 
275  VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
276 
277  vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
278 
279  vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipeline());
280 
281  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
282  shadowPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0, nullptr);
283 
284  VkDescriptorSet lightDescriptor = renderer_->GetLightDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 1);
285  if (lightDescriptor == VK_NULL_HANDLE)
286  lightDescriptor = renderer_->CreateLightDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 1, shadowPipeline_->GetDescriptorSetLayout(1));
287 
288  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
289  shadowPipeline_->GetPipelineLayout(), 1, 1, &lightDescriptor, 1, &lightOffset);
290 
291  for (size_t i = 0, size = meshes.size(); i < size; ++i) {
292 
293  VulkanMesh* mesh = meshes[i].mesh;
294 
295  PushConstants_t constants = {};
296  constants.model = meshes[i].transform;
297  constants.color = meshes[i].color;
298  constants.duration = meshes[i].duration;
299  constants.looping = meshes[i].looping;
300  constants.ticksPerSecond = meshes[i].ticksPerSecond;
301  constants.time = meshes[i].time;
302 
303 
304  vkCmdPushConstants(commandBuffer, shadowPipeline_->GetPipelineLayout(),
305  VK_SHADER_STAGE_VERTEX_BIT |VK_SHADER_STAGE_GEOMETRY_BIT, 0,
306  static_cast<uint32_t>(sizeof(PushConstants_t)), &constants);
307 
308  VkBuffer buffers[] = { mesh->GetVertexBuffer() };
309  VkDeviceSize offsets[] = { 0 };
310  vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
311 
312  vkCmdBindIndexBuffer(commandBuffer, mesh->GetShadowIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
313 
314  VkDescriptorSet boneOffsets = mesh->GetBoneOffsetDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 4);
315 
316  if (boneOffsets == VK_NULL_HANDLE)
317  boneOffsets = mesh->CreateBoneOffsetDescriptorSet(
318  threadID, shadowPipeline_->GetPipelineId(),
319  4, shadowPipeline_->GetDescriptorSetLayout(4));
320 
321  VkDescriptorSet boneDescriptor = meshes[i].boneData->GetDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 3);
322  if (boneDescriptor == VK_NULL_HANDLE)
323  boneDescriptor = meshes[i].boneData->CreateDescriptorSet(threadID, shadowPipeline_->GetPipelineId(),
324  3, shadowPipeline_->GetDescriptorSetLayout(3));
325 
326  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipelineLayout(),
327  3, 1, &(boneDescriptor), 0, nullptr);
328 
329  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipelineLayout(), 4, 1, &boneOffsets, 0, nullptr);
330 
331  vkCmdDrawIndexed(commandBuffer, mesh->GetShadowIndexCount(), 1, 0, 0, 0);
332  }
333 
334  renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
335 
336  }
337 
338  void VulkanSkeletalMeshRenderer::Clean() const
339  {
340  skeletalMeshPipeline_->Clean();
341  shadowPipeline_->Clean();
342  }
343 
344  void VulkanSkeletalMeshRenderer::Recreate() {
345  skeletalMeshPipeline_->SetRenderPassInfo(renderer_->GetGBufferRenderPass(), static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
346  skeletalMeshPipeline_->Recreate();
347 
348  shadowPipeline_->SetRenderPassInfo(renderer_->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
349  shadowPipeline_->Recreate();
350  }
351 }
352 
353 #endif // USING_VULKAN
This object is used to store general data for a vertex.
Definition: Vertex.hpp:6