Engine
Frameworkcreatedbymeusableforthecreationofsimplegames.CurrentlysupportsOpenGL(Verysimple)andVulkan.
VulkanSpriteRenderer.cpp
Go to the documentation of this file.
2 #ifdef USING_VULKAN
4 
5 namespace Engine {
6 
7  VulkanSpriteRenderer::VulkanSpriteRenderer(VulkanRenderer * renderer, VulkanLogicalDevice * device, VulkanDescriptorPool * descriptorPool)
8  {
9  this->renderer = renderer;
10  this->device = device;
11  this->descriptorPool = descriptorPool;
12 
13  renderPassPipeline = eastl::unique_ptr<VulkanPipeline>(new VulkanPipeline(device, renderer));
14 
15  renderPassPipeline->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER, "Sprite.vert.spv");
16  renderPassPipeline->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER, "Sprite.frag.spv");
17 
18  renderPassPipeline->AddVertexInputBindingDescription(0, static_cast<uint32_t>(sizeof(VertexInfo_t)), VK_VERTEX_INPUT_RATE_VERTEX);
19  renderPassPipeline->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
20  renderPassPipeline->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexInfo_t, texCoord));
21 
22  renderPassPipeline->CreateDescriptorSet();
23  renderPassPipeline->CreateDescriptorSet();
24 
25  renderPassPipeline->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr);
26 
27  renderPassPipeline->AddDescriptorSetBinding(1, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
28 
29  renderPassPipeline->AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, static_cast<uint32_t>(sizeof(PushConstants_t)));
30 
31  renderPassPipeline->SetRenderPassInfo(renderer->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
32 
33  renderPassPipeline->CreateColorBlendAttachment(VK_TRUE, VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
34  VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
35 
36  renderPassPipeline->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false);
37 
38  renderPassPipeline->SetRasterizerSettings(0U, 0U, VK_POLYGON_MODE_FILL, 1.f, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE);
39 
40  renderPassPipeline->Compile();
41 
42 
43 
44  vertexBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, renderer->GetVmaAllocator(),
45  static_cast<uint32_t>(sizeof(VertexInfo_t))*4, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
46  true, renderer->GetGraphicsCommandPool()));
47 
48  indexBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, renderer->GetVmaAllocator(),
49  static_cast<uint32_t>(sizeof(uint32_t)) * 6, VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
50  true, renderer->GetGraphicsCommandPool()));
51 
52  uboBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, renderer->GetVmaAllocator(),
53  static_cast<uint32_t>(sizeof(Ubo_t)), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
54  false, renderer->GetGraphicsCommandPool()));
55 
56  ubo.proj = glm::mat4();
57  ubo.view = glm::scale(glm::mat4(),glm::vec3(0.f,0.f,0.f));
58 
59  eastl::vector<VertexInfo_t> vertexData = {
60  {glm::vec3(-0.5f,0.5f,0.0f),glm::vec2(0.f,1.f)},
61  {glm::vec3(-0.5f,-0.5f,0.0f),glm::vec2(0.f,0.f)},
62  {glm::vec3(0.5f,-0.5f,0.0f),glm::vec2(1.f,0.f)},
63  {glm::vec3(0.5f,0.5f,0.0f),glm::vec2(1.f,1.f)}
64  };
65 
66  indices = { 0,1,2,2,3,0 };
67 
68  vertexBuffer->UpdateBuffer(vertexData.data(), 0, static_cast<uint32_t>(sizeof(VertexInfo_t)*vertexData.size()));
69  indexBuffer->UpdateBuffer(indices.data(), 0, static_cast<uint32_t>(sizeof(uint32_t)*indices.size()));
70  uboBuffer->UpdateBuffer(&ubo, 0, static_cast<uint32_t>(sizeof(Ubo_t)));
71 
72  VkDescriptorSetLayout renderLayouts[] = { renderPassPipeline->GetDescriptorSetLayout(0) };
73 
74  descriptorPool->AllocateDescriptorSet(1, renderLayouts, &renderUboDescriptorSet);
75  descriptorPool->DescriptorSetBindToBuffer(renderUboDescriptorSet, uboBuffer->GetBuffer(),
76  0, static_cast<VkDeviceSize>(sizeof(Ubo_t)),
77  0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
78  }
79 
80  VulkanSpriteRenderer::~VulkanSpriteRenderer()
81  {
82  vertexBuffer.reset();
83  indexBuffer.reset();
84  uboBuffer.reset();
85 
86  renderPassPipeline.reset();
87  }
88 
89  void VulkanSpriteRenderer::StartRender(VkCommandBuffer renderPassBuffer, glm::mat4 viewMatrix, glm::mat4 projectionMatrix)
90  {
91  this->renderCommandBuffer = renderPassBuffer;
92 
93  if (ubo.view != viewMatrix || ubo.proj != projectionMatrix) {
94  ubo.view = viewMatrix;
95  ubo.proj = projectionMatrix;
96 
97  uboBuffer->UpdateBuffer(&ubo, 0, static_cast<uint32_t>(sizeof(Ubo_t)));
98  }
99 
100  VkRect2D scissor = { 0,0,renderer->GetSwapChainExtent() };
101 
102  VkBuffer vertexBuffers[] = { (vertexBuffer->GetBuffer()) };
103  VkDeviceSize offsets[] = { 0 };
104 
105  renderer->StartSecondaryCommandBufferRecording(renderCommandBuffer,
106  VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
107  renderer->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS), renderer->GetFrameBuffer());
108 
109  vkCmdSetScissor(renderCommandBuffer, 0, 1, &scissor);
110 
111  vkCmdBindPipeline(renderCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, renderPassPipeline->GetPipeline());
112 
113  vkCmdBindDescriptorSets(renderCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, renderPassPipeline->GetPipelineLayout(), 0, 1, &renderUboDescriptorSet, 0, nullptr);
114 
115  vkCmdBindVertexBuffers(renderCommandBuffer, 0, 1, vertexBuffers, offsets);
116 
117  vkCmdBindIndexBuffer(renderCommandBuffer, indexBuffer->GetBuffer(), 0, VK_INDEX_TYPE_UINT32);
118  }
119 
120  void VulkanSpriteRenderer::RenderSprite(eastl::weak_ptr<VulkanTexture> texture, glm::mat4 modelMatrix)
121  {
122  PushConstants_t constants = { modelMatrix };
123 
124  vkCmdPushConstants(renderCommandBuffer, renderPassPipeline->GetPipelineLayout(),
125  VK_SHADER_STAGE_VERTEX_BIT, 0, static_cast<uint32_t>(sizeof(PushConstants_t)), &constants);
126 
127  if (texture.lock()->GetDescriptorSet(0, renderPassPipeline->GetPipelineId(), 1) == VK_NULL_HANDLE) {
128  texture.lock()->CreateDescriptorSet(0, renderPassPipeline->GetPipelineId(), 1, renderPassPipeline->GetDescriptorSetLayout(1));
129  }
130 
131  VkDescriptorSet sets[] = { texture.lock()->GetDescriptorSet(0, renderPassPipeline->GetPipelineId(),1) };
132  vkCmdBindDescriptorSets(renderCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
133  renderPassPipeline->GetPipelineLayout(), 1, 1, sets, 0, nullptr);
134 
135  vkCmdDrawIndexed(renderCommandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
136  }
137 
138  void VulkanSpriteRenderer::FinishRender()
139  {
140  renderer->EndSecondaryCommandBufferRecording(renderCommandBuffer);
141  }
142 
143  void VulkanSpriteRenderer::Clean() const
144  {
145  renderPassPipeline->Clean();
146  }
147 
148  void VulkanSpriteRenderer::Recreate()
149  {
150  renderPassPipeline->SetRenderPassInfo(renderer->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
151  renderPassPipeline->Recreate();
152  }
153 
154 }
155 
156 #endif // USING_VULKAN