Rendering Engine 0.2.0
Modular Graphics Rendering Engine | v0.2.0
Loading...
Searching...
No Matches
rendering_engine::VulkanRenderResources Class Reference

Vulkan implementation of IRenderResources for the Rendering Engine. More...

#include <vulkan_render_resources.hpp>

Inherits rendering_engine::IRenderResources, and rendering_engine::IRendererObserver.

Public Member Functions

 VulkanRenderResources (VulkanRenderer *renderer)
 Constructor.
 ~VulkanRenderResources ()
 Destructor.
void Initialize (Material *material, MeshDataGpu *meshData, TextureCache *textureCache) override
 Initializes GPU-side resources using provided material, mesh, and texture cache.
void SubmitResources (Transformations2D &transformations, const PackedMaterialData &materialParameters) override
 Updates GPU resources and issues a draw call for a 2D object.
void SubmitResources (Transformations3D &transformations, const PackedMaterialData &materialParameters) override
 Updates GPU resources and issues a draw call for a 3D object.
void Shutdown () override
 Releases all allocated GPU resources for this object.
Public Member Functions inherited from rendering_engine::IRenderResources
virtual ~IRenderResources ()=default
 Virtual destructor.
Public Member Functions inherited from rendering_engine::IRendererObserver
virtual ~IRendererObserver ()=default
 Virtual destructor.

Protected Member Functions

void OnRenderResourcesRelease () override
 Renderer callback: release all GPU resources (used during device loss/reset).
void OnRenderResourcesRebuild () override
 Renderer callback: re-upload or recreate all GPU resources (used after device reset/rebuild).
void AcquireResources ()
 Allocates and initializes all GPU buffers, descriptor sets, and pipelines for this drawable.
void CreateUniformBuffers ()
void CreateDescriptorPool ()
void CreateDescriptorSet ()
void UpdateTransformations (Transformations2D &transformations)
void UpdateTransformations (Transformations3D &transformations)
void UpdateMaterialParameters (const PackedMaterialData &materialParameters)
void DrawIndexed ()
 Issues a Vulkan draw command for the currently bound indexed mesh.

Detailed Description

Vulkan implementation of IRenderResources for the Rendering Engine.

Aggregates and manages Vulkan GPU-side resources (buffers, descriptor sets, pipelines) required to render a drawable object. Responds to renderer events (release/rebuild) and can be safely reused with shared caches for materials, meshes, and textures.

Definition at line 28 of file vulkan_render_resources.hpp.

Constructor & Destructor Documentation

◆ VulkanRenderResources()

rendering_engine::VulkanRenderResources::VulkanRenderResources ( VulkanRenderer * renderer)

Constructor.

Parameters
rendererPointer to the owning VulkanRenderer instance.

Registers itself as an observer for resource (re)creation events.

Definition at line 16 of file vulkan_render_resources.cpp.

17 :
18 mRenderer(renderer),
19 bHasCustomMaterialVariables(false)
20{
21 mRenderer->RegisterObserver(this);
22}

◆ ~VulkanRenderResources()

rendering_engine::VulkanRenderResources::~VulkanRenderResources ( )

Destructor.

Unregisters from the renderer and calls Shutdown() to release all resources.

Definition at line 24 of file vulkan_render_resources.cpp.

25{
26 mRenderer->UnregisterObserver(this);
27}

Member Function Documentation

◆ AcquireResources()

void rendering_engine::VulkanRenderResources::AcquireResources ( )
protected

Allocates and initializes all GPU buffers, descriptor sets, and pipelines for this drawable.

Definition at line 81 of file vulkan_render_resources.cpp.

82{
83 if (!mMaterial)
84 {
85 // Log error message, as without initialized material rendering is not possible.
86 return;
87 }
88 VulkanMaterialResources* materialResources = static_cast<VulkanMaterialResources*>(mMaterial->GetMaterialRenderResources());
89 mGraphicsPipeline = materialResources->GetPipeline();
90 mPipelineLayout = materialResources->GetPipelineLayout();
91
92 VulkanMeshResources* meshResources = static_cast<VulkanMeshResources*>(mMeshData->GetMeshRenderResources());
93 mVertexBuffer = meshResources->GetVertexBuffer();
94 mIndexBuffer = meshResources->GetIndexBuffer();
95
99}

◆ CreateDescriptorPool()

void rendering_engine::VulkanRenderResources::CreateDescriptorPool ( )
protected

Definition at line 141 of file vulkan_render_resources.cpp.

142{
143 const uint32_t maxFramesInFlight = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
144 std::vector<VkDescriptorPoolSize> poolSizes;
145
146 VkDescriptorPoolSize tranformationPool;
147 tranformationPool.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
148 tranformationPool.descriptorCount = maxFramesInFlight;
149
150 poolSizes.push_back(tranformationPool);
151
152 auto materialParameters = mMaterial->PackMaterialParameters();
153 if (!materialParameters.buffer.empty())
154 {
155 VkDescriptorPoolSize materialParameterPool;
156 materialParameterPool.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
157 materialParameterPool.descriptorCount = maxFramesInFlight;
158
159 poolSizes.push_back(materialParameterPool);
160 }
161
162 for (const auto& texture : mMaterial->GetTextures())
163 {
164 (void)texture;
165 VkDescriptorPoolSize textureSamplerPool;
166 textureSamplerPool.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
167 textureSamplerPool.descriptorCount = maxFramesInFlight;
168
169 poolSizes.push_back(textureSamplerPool);
170 }
171
172 VkDescriptorPoolCreateInfo poolInfo{};
173 poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
174 poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
175 poolInfo.pPoolSizes = poolSizes.data();
176 poolInfo.maxSets = maxFramesInFlight;
177
178 if (vkCreateDescriptorPool(mRenderer->GetLogicalDevice(), &poolInfo, nullptr, &mDescriptorPool) != VK_SUCCESS)
179 {
180 throw std::runtime_error("failed to create descriptor pool!");
181 }
182}
const int MAX_FRAMES_IN_FLIGHT
Number of frames that can be processed simultaneously (double buffering).

◆ CreateDescriptorSet()

void rendering_engine::VulkanRenderResources::CreateDescriptorSet ( )
protected

Definition at line 184 of file vulkan_render_resources.cpp.

185{
186 // By local convention of this engine, bindings will be numbered:
187 // Bindings i = 0, i < n, there n - total number of bindings
188 // Binding i - transformations matrices of types according to material domain (2D or 3D)
189 // Binding i++ - cunstom parameter variable of material, if any. All variables will be
190 // serialized and packed in a single binding
191 // Binding i++ - textures sampler, if any. One texture per binding.
192
193 const uint32_t maxFramesInFlight = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
194
195 VulkanMaterialResources* materialResources = static_cast<VulkanMaterialResources*>(mMaterial->GetMaterialRenderResources());
196 auto descriptorSetLayout = materialResources->GetDescriptorSetLayout();
197 std::vector<VkDescriptorSetLayout> layouts(maxFramesInFlight, descriptorSetLayout);
198 VkDescriptorSetAllocateInfo allocInfo{};
199 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
200 allocInfo.descriptorPool = mDescriptorPool;
201 allocInfo.descriptorSetCount = maxFramesInFlight;
202 allocInfo.pSetLayouts = layouts.data();
203
204 mDescriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
205 VkResult result = vkAllocateDescriptorSets(mRenderer->GetLogicalDevice(), &allocInfo, mDescriptorSets.data());
206 if (result != VK_SUCCESS)
207 {
208 throw std::runtime_error("failed to allocate descriptor sets! Error: " + std::to_string(result));
209 }
210
211 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
212 {
213 unsigned int dstBinding = 0;
214 std::vector<VkWriteDescriptorSet> descriptorWrites;
215
216 // Transfotmations descriptor set
217 VkDescriptorBufferInfo transformationBufferInfo{};
218 transformationBufferInfo.buffer = mTransformationBuffers[i];
219 transformationBufferInfo.offset = 0;
220 if (mMaterial->GetMaterialSettings().materialDomain == MaterialDomain::Sprite2D)
221 {
222 transformationBufferInfo.range = sizeof(Transformations2D);
223 }
224 if (mMaterial->GetMaterialSettings().materialDomain == MaterialDomain::Surface3D)
225 {
226 transformationBufferInfo.range = sizeof(Transformations3D);
227 }
228 VkWriteDescriptorSet transformationsDescSet;
229 transformationsDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
230 transformationsDescSet.pNext = nullptr;
231 transformationsDescSet.dstSet = mDescriptorSets[i];
232 transformationsDescSet.dstBinding = dstBinding;
233 transformationsDescSet.dstArrayElement = 0;
234 transformationsDescSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
235 transformationsDescSet.descriptorCount = 1;
236 transformationsDescSet.pBufferInfo = &transformationBufferInfo;
237 descriptorWrites.push_back(transformationsDescSet);
238
239 // Custom material parameters descriptor set
240 auto materialParameters = mMaterial->PackMaterialParameters();
241 if (!materialParameters.buffer.empty())
242 {
243 ++dstBinding;
244 VkDescriptorBufferInfo matVarBufferInfo{};
245 matVarBufferInfo.buffer = mMaterialParametersBuffers[i];
246 matVarBufferInfo.offset = 0;
247 matVarBufferInfo.range = materialParameters.buffer.size();
248
249 VkWriteDescriptorSet matVarDescSet;
250 matVarDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
251 matVarDescSet.pNext = nullptr;
252 matVarDescSet.dstSet = mDescriptorSets[i];
253 matVarDescSet.dstBinding = dstBinding;
254 matVarDescSet.dstArrayElement = 0;
255 matVarDescSet.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
256 matVarDescSet.descriptorCount = 1;
257 matVarDescSet.pBufferInfo = &matVarBufferInfo;
258 descriptorWrites.push_back(matVarDescSet);
259 }
260
261 // Custom texture image data descriptor set
262 for (const auto& texture : mMaterial->GetTextures())
263 {
264 ++dstBinding;
265 auto imageData = mTextureCache->GetTextureResources(texture);
266 VulkanTextureResources* textureResources = static_cast<VulkanTextureResources*>(imageData->GetTextureRenderResources());
267 VkDescriptorImageInfo imageInfo{};
268 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
269 imageInfo.imageView = textureResources->GetVkImageView();
270 imageInfo.sampler = textureResources->GetVkSampler();
271
272 VkWriteDescriptorSet imageDescSet;
273 imageDescSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
274 imageDescSet.pNext = nullptr;
275 imageDescSet.dstSet = mDescriptorSets[i];
276 imageDescSet.dstBinding = dstBinding;
277 imageDescSet.dstArrayElement = 0;
278 imageDescSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
279 imageDescSet.descriptorCount = 1;
280 imageDescSet.pImageInfo = &imageInfo;
281
282 descriptorWrites.push_back(imageDescSet);
283 }
284
285 vkUpdateDescriptorSets(mRenderer->GetLogicalDevice(), static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
286 }
287}

◆ CreateUniformBuffers()

void rendering_engine::VulkanRenderResources::CreateUniformBuffers ( )
protected

Definition at line 101 of file vulkan_render_resources.cpp.

102{
103 VkDeviceSize transformationBufferSize;
104 if (mMaterial->GetMaterialSettings().materialDomain == MaterialDomain::Sprite2D)
105 {
106 transformationBufferSize = sizeof(Transformations2D);
107 }
108 if (mMaterial->GetMaterialSettings().materialDomain == MaterialDomain::Surface3D)
109 {
110 transformationBufferSize = sizeof(Transformations3D);
111 }
112
113 mTransformationBuffers.resize(MAX_FRAMES_IN_FLIGHT);
114 mTransformationBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
115
116 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
117 {
118 mRenderer->CreateBuffer(transformationBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
119 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
120 mTransformationBuffers[i], mTransformationBuffersMemory[i]);
121 }
122
123 auto materialParameters = mMaterial->PackMaterialParameters();
124 if (materialParameters.buffer.empty())
125 {
126 return;
127 }
128
129 VkDeviceSize matVarBufferSize = materialParameters.buffer.size();
130 mMaterialParametersBuffers.resize(MAX_FRAMES_IN_FLIGHT);
131 mMaterialParametersMemory.resize(MAX_FRAMES_IN_FLIGHT);
132
133 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
134 {
135 mRenderer->CreateBuffer(matVarBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
136 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
137 mMaterialParametersBuffers[i], mMaterialParametersMemory[i]);
138 }
139}

◆ DrawIndexed()

void rendering_engine::VulkanRenderResources::DrawIndexed ( )
protected

Issues a Vulkan draw command for the currently bound indexed mesh.

Definition at line 330 of file vulkan_render_resources.cpp.

331{
332 auto commandBuffers = mRenderer->GetComandBuffers();
333 auto frame = mRenderer->GetCurrentFrame();
334
335 VkBuffer vertexBuffer[] = { mVertexBuffer };
336 VkDeviceSize offsets[] = { 0 };
337
338 vkCmdBindPipeline(commandBuffers[frame], VK_PIPELINE_BIND_POINT_GRAPHICS, mGraphicsPipeline);
339
340 /*If dynamicState in pipeline is used then vkCmdSetViewport and vkCmdSetScissor per draw call*/
341 //VkViewport viewport{};
342 //viewport.x = 0.0f;
343 //viewport.y = 0.0f;
344 //viewport.width = static_cast<float>(mRenderer->GetSwapChainExtent().width);
345 //viewport.height = static_cast<float>(mRenderer->GetSwapChainExtent().height);
346 //viewport.minDepth = 0.0f;
347 //viewport.maxDepth = 1.0f;
348 //vkCmdSetViewport(commandBuffers[frame], 0, 1, &viewport);
349
350 //VkRect2D scissor{};
351 //scissor.offset = { 0, 0 };
352 //scissor.extent = mRenderer->GetSwapChainExtent();
353 //vkCmdSetScissor(commandBuffers[frame], 0, 1, &scissor);
354
355 vkCmdBindVertexBuffers(commandBuffers[frame], 0, 1, vertexBuffer, offsets);
356 vkCmdBindIndexBuffer(commandBuffers[frame], mIndexBuffer, 0, VK_INDEX_TYPE_UINT32);
357 vkCmdBindDescriptorSets(commandBuffers[frame], VK_PIPELINE_BIND_POINT_GRAPHICS,
358 mPipelineLayout, 0, 1, &mDescriptorSets[frame], 0, nullptr);
359 vkCmdDrawIndexed(commandBuffers[frame], static_cast<uint32_t>(mMeshData->GetIndices().size()), 1, 0, 0, 0);
360}

◆ Initialize()

void rendering_engine::VulkanRenderResources::Initialize ( Material * material,
MeshDataGpu * meshData,
TextureCache * textureCache )
overridevirtual

Initializes GPU-side resources using provided material, mesh, and texture cache.

Parameters
materialPointer to the Material describing the shader and its parameters.
meshDataPointer to MeshDataGpu containing vertex and index buffers.
textureCachePointer to the TextureCache containing all loaded textures.
Note
Ownership of parameters is not transferred; caller must ensure they remain valid.

Implements rendering_engine::IRenderResources.

Definition at line 29 of file vulkan_render_resources.cpp.

30{
31 mMaterial = material;
32 mMeshData = meshData;
33 mTextureCache = textureCache;
34
36}
void AcquireResources()
Allocates and initializes all GPU buffers, descriptor sets, and pipelines for this drawable.

◆ OnRenderResourcesRebuild()

void rendering_engine::VulkanRenderResources::OnRenderResourcesRebuild ( )
overrideprotectedvirtual

Renderer callback: re-upload or recreate all GPU resources (used after device reset/rebuild).

This method will be called after the device or swapchain is recreated, allowing the observer to re-upload or recreate all necessary resources for rendering.

Implements rendering_engine::IRendererObserver.

Definition at line 76 of file vulkan_render_resources.cpp.

77{
79}

◆ OnRenderResourcesRelease()

void rendering_engine::VulkanRenderResources::OnRenderResourcesRelease ( )
overrideprotectedvirtual

Renderer callback: release all GPU resources (used during device loss/reset).

This method will be called before any device or swapchain is destroyed, allowing the observer to safely release all handles and deallocate any GPU memory.

Implements rendering_engine::IRendererObserver.

Definition at line 71 of file vulkan_render_resources.cpp.

72{
73 Shutdown();
74}
void Shutdown() override
Releases all allocated GPU resources for this object.

◆ Shutdown()

void rendering_engine::VulkanRenderResources::Shutdown ( )
overridevirtual

Releases all allocated GPU resources for this object.

Implements rendering_engine::IRenderResources.

Definition at line 52 of file vulkan_render_resources.cpp.

53{
54 auto logicalDevice = mRenderer->GetLogicalDevice();
55
56 vkDestroyDescriptorPool(logicalDevice, mDescriptorPool, nullptr);
57
58 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
59 {
60 vkDestroyBuffer(logicalDevice, mTransformationBuffers[i], nullptr);
61 vkFreeMemory(logicalDevice, mTransformationBuffersMemory[i], nullptr);
62
63 if (!mMaterialParametersBuffers.empty())
64 {
65 vkDestroyBuffer(logicalDevice, mMaterialParametersBuffers[i], nullptr);
66 vkFreeMemory(logicalDevice, mMaterialParametersMemory[i], nullptr);
67 }
68 }
69}

◆ SubmitResources() [1/2]

void rendering_engine::VulkanRenderResources::SubmitResources ( Transformations2D & transformations,
const PackedMaterialData & materialParameters )
overridevirtual

Updates GPU resources and issues a draw call for a 2D object.

Parameters
transformationsTransformation data (2D).
materialParametersPacked structure with material parameters for the draw call.

Implements rendering_engine::IRenderResources.

Definition at line 38 of file vulkan_render_resources.cpp.

39{
40 UpdateTransformations(transformations);
41 UpdateMaterialParameters(materialParameters);
43}
void DrawIndexed()
Issues a Vulkan draw command for the currently bound indexed mesh.
void UpdateTransformations(Transformations2D &transformations)
void UpdateMaterialParameters(const PackedMaterialData &materialParameters)

◆ SubmitResources() [2/2]

void rendering_engine::VulkanRenderResources::SubmitResources ( Transformations3D & transformations,
const PackedMaterialData & materialParameters )
overridevirtual

Updates GPU resources and issues a draw call for a 3D object.

Parameters
transformationsTransformation data (3D).
materialParametersPacked structure with material parameters for the draw call.

Implements rendering_engine::IRenderResources.

Definition at line 45 of file vulkan_render_resources.cpp.

46{
47 UpdateTransformations(transformations);
48 UpdateMaterialParameters(materialParameters);
50}

◆ UpdateMaterialParameters()

void rendering_engine::VulkanRenderResources::UpdateMaterialParameters ( const PackedMaterialData & materialParameters)
protected

Definition at line 315 of file vulkan_render_resources.cpp.

316{
317 auto device = mRenderer->GetLogicalDevice();
318 auto frame = mRenderer->GetCurrentFrame();
319
320 // Update custom variables
321 if (!materialParameters.buffer.empty())
322 {
323 void* dataCustom;
324 vkMapMemory(device, mMaterialParametersMemory[frame], 0, materialParameters.buffer.size(), 0, &dataCustom);
325 memcpy(dataCustom, materialParameters.buffer.data(), materialParameters.buffer.size());
326 vkUnmapMemory(device, mMaterialParametersMemory[frame]);
327 }
328}

◆ UpdateTransformations() [1/2]

void rendering_engine::VulkanRenderResources::UpdateTransformations ( Transformations2D & transformations)
protected

Definition at line 289 of file vulkan_render_resources.cpp.

290{
291 auto device = mRenderer->GetLogicalDevice();
292 auto frame = mRenderer->GetCurrentFrame();
293
294 // Update transformations
295 void* dataTransform;
296 vkMapMemory(device, mTransformationBuffersMemory[frame], 0, sizeof(Transformations2D), 0, &dataTransform);
297 memcpy(dataTransform, &transformations, sizeof(transformations));
298 vkUnmapMemory(device, mTransformationBuffersMemory[frame]);
299}

◆ UpdateTransformations() [2/2]

void rendering_engine::VulkanRenderResources::UpdateTransformations ( Transformations3D & transformations)
protected

Definition at line 301 of file vulkan_render_resources.cpp.

302{
303 auto device = mRenderer->GetLogicalDevice();
304 auto frame = mRenderer->GetCurrentFrame();
305
306 // Flip Y-axis for Vulkan clip space
307 transformations.proj[1][1] *= -1;
308 // Update transformations
309 void* dataTransform;
310 vkMapMemory(device, mTransformationBuffersMemory[frame], 0, sizeof(Transformations3D), 0, &dataTransform);
311 memcpy(dataTransform, &transformations, sizeof(transformations));
312 vkUnmapMemory(device, mTransformationBuffersMemory[frame]);
313}

The documentation for this class was generated from the following files: