Cogs.Core
ContextVK.cpp
1#include "ContextVK.h"
2
3#include "GraphicsDeviceVK.h"
4
5#include "BuffersVK.h"
6#include "EffectsVK.h"
7
8#include "Foundation/HashFunctions.h"
9
10namespace
11{
12 Cogs::Logging::Log logger = Cogs::Logging::getLogger("ContextVK");
13}
14
15void Cogs::ContextVK::initialize(GraphicsDeviceVK * graphicsDevice)
16{
17 this->graphicsDevice = graphicsDevice;
18 device = graphicsDevice->device;
19
20 effects = &graphicsDevice->effects;
21 buffers = &graphicsDevice->buffers;
22 textures = &graphicsDevice->textures;
23 renderTargets = &graphicsDevice->renderTargets;
24
25 for (auto & frameResource : frameResources) {
26 const VkCommandPoolCreateInfo commandPoolInfo = {
27 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
28 nullptr,
29 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
30 0,
31 };
32
33 auto result = vkCreateCommandPool(device, &commandPoolInfo, nullptr, &frameResource.commandPool);
34
35 if (VK_FAILED(result)) {
36 VK_LOG_ERROR(result, "Could not create command pool.");
37 return;
38 }
39
40 const VkCommandBufferAllocateInfo cmd = {
41 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
42 nullptr,
43 frameResource.commandPool,
44 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
45 1,
46 };
47
48 result = vkAllocateCommandBuffers(device, &cmd, &frameResource.commandBuffer);
49
50 if (VK_FAILED(result)) {
51 VK_LOG_ERROR(result, "Could not create command buffer.");
52 return;
53 }
54
55 VkDescriptorPoolSize descriptorSizes[2];
56 descriptorSizes[0] = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32000, };
57 descriptorSizes[1] = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32000, };
58
59 const VkDescriptorPoolCreateInfo descriptorPoolInfo = {
60 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
61 nullptr,
62 0,
63 32000,
64 2,
65 descriptorSizes,
66 };
67
68 result = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &frameResource.descriptorPool);
69
70 /*if (VK_FAILED(result)) {
71 VK_LOG_ERROR(result, "Could not create descriptor pool.");
72 return;
73 }*/
74
75 VkFenceCreateInfo fenceInfo = {};
76 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
77 fenceInfo.flags = 0;
78 vkCreateFence(device, &fenceInfo, nullptr, &frameResource.fence);
79 }
80
81 uint8_t textureData[4 * 1] = { 0 };
82 defaultTexture = textures->loadTexture(textureData, 1, 1, TextureFormat::R8G8B8A8_UNORM, TextureFlags::Default);
83 defaultSampler = textures->loadSamplerState(SamplerState::DefaultState());
84
85 defaultDepthStencilState = renderTargets->loadDepthStencilState(DepthStencilState::DefaultState());
86 defaultRasterizerState = renderTargets->loadRasterizerState(RasterizerState::DefaultState());
87 defaultBlendState = renderTargets->loadBlendState(BlendState::DefaultState());
88}
89
90void Cogs::ContextVK::beginFrame()
91{
92 currentFrameResources = &frameResources[currentFrame % frameResources.size()];
93
94 if (currentFrame != 0) {
95 if (vkGetFenceStatus(device, currentFrameResources->fence) != VK_SUCCESS) {
96 vkWaitForFences(device, 1, &currentFrameResources->fence, VK_TRUE, 100000000);
97 }
98
99 vkResetFences(device, 1, &currentFrameResources->fence);
100
101 vkResetCommandBuffer(currentFrameResources->commandBuffer, 0);
102 vkResetDescriptorPool(device, currentFrameResources->descriptorPool, 0);
103 }
104
105 descriptorPool = currentFrameResources->descriptorPool;
106
107 currentEffect = EffectHandle::NoHandle;
108 iaState = {};
109 state = {};
110 shaderState = {};
111
112 ContextCommon::setCurrentEffect(nullptr);
113
114 setRasterizerState(defaultRasterizerState);
115 setDepthStencilState(defaultDepthStencilState);
116 setBlendState(defaultBlendState);
117
118 for (auto & ob : currentFrameResources->orhpanedBuffers) {
119 ob->pool->deallocate(ob);
120 }
121
122 currentFrameResources->orhpanedBuffers.clear();
123
124 const VkCommandBufferBeginInfo commandBufferBeginInfo = {
125 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
126 nullptr,
127 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
128 nullptr,
129 };
130
131 auto result = vkBeginCommandBuffer(currentFrameResources->commandBuffer, &commandBufferBeginInfo);
132
133 if (VK_FAILED(result)) {
134 VK_LOG_ERROR(result, "Could not begin command buffer.");
135 return;
136 }
137
138 setRenderTarget(defaultRenderTarget, DepthStencilHandle::NoHandle);
139}
140
141void Cogs::ContextVK::endFrame()
142{
143 if (renderPass) {
144 endRenderPass();
145 } else {
146 beginRenderPass();
147 endRenderPass();
148 }
149
150 auto & texture = graphicsDevice->textures.textures[graphicsDevice->backBuffers[graphicsDevice->currentFrameBuffer]];
151
152 if (graphicsDevice->getSettings().numSamples > 1) {
153 resolveResource(graphicsDevice->backBuffersMS[graphicsDevice->currentFrameBuffer], graphicsDevice->backBuffers[graphicsDevice->currentFrameBuffer]);
154 }
155
156 setImageLayout(currentFrameResources->commandBuffer, texture, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
157
158 auto result = vkEndCommandBuffer(currentFrameResources->commandBuffer);
159
160 if (VK_FAILED(result)) {
161 VK_LOG_ERROR(result, "Could not close command buffer.");
162 }
163
164 ++currentFrame;
165}
166
168{
169 if (renderPass) {
170 endRenderPass();
171 }
172
173 auto & renderTarget = renderTargets->renderTargets[HandleIsValid(handle) ? handle : defaultRenderTarget];
174
175 state.renderTarget = &renderTarget;
176 state.depthStencil = nullptr;
177
178 clearValues.resize(renderTarget.textures.size() + (renderTarget.depthTexture ? 1 : 0));
179
180 for (auto texture : renderTarget.textures) {
181 setImageLayout(
182 currentFrameResources->commandBuffer,
183 *texture,
184 VK_IMAGE_ASPECT_COLOR_BIT,
185 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
186 }
187
188 if (renderTarget.depthTexture) {
189 setImageLayout(
190 currentFrameResources->commandBuffer,
191 *renderTarget.depthTexture,
192 VK_IMAGE_ASPECT_DEPTH_BIT,
193 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
194 }
195}
196
197void Cogs::ContextVK::setViewport(const float x, const float y, const float width, const float height)
198{
199 VkViewport viewport = {};
200 viewport.height = height;
201 viewport.width = width;
202 viewport.minDepth = 0.0f;
203 viewport.maxDepth = 1.0f;
204 vkCmdSetViewport(currentFrameResources->commandBuffer, 0, 1, &viewport);
205
206 VkRect2D scissor = {};
207 scissor.extent.width = static_cast<uint32_t>(width);
208 scissor.extent.height = static_cast<uint32_t>(height);
209 scissor.offset.x = static_cast<int32_t>(x);
210 scissor.offset.y = static_cast<int32_t>(y);
211 vkCmdSetScissor(currentFrameResources->commandBuffer, 0, 1, &scissor);
212}
213
214void Cogs::ContextVK::setScissor(const int x, const int y, const int width, const int height)
215{
216}
217
218void Cogs::ContextVK::clearRenderTarget(const float * color)
219{
220 clearRenderTarget(&color, 1);
221}
222
223void Cogs::ContextVK::clearRenderTarget(const float ** colors, const int count)
224{
225 for (size_t i = 0; i < state.renderTarget->textures.size(); ++i) {
226 auto color = colors[count > 1 ? i : 0];
227
228 clearValues[i].color.float32[0] = color[0];
229 clearValues[i].color.float32[1] = color[1];
230 clearValues[i].color.float32[2] = color[2];
231 clearValues[i].color.float32[3] = color[3];
232 }
233}
234
235void Cogs::ContextVK::clearDepth(const float depth)
236{
237 clearValues.back().depthStencil = { depth, 0 };
238}
239
241{
242 state.depthStencilState = &renderTargets->depthStencilStates[handle];
243}
244
245void Cogs::ContextVK::setBlendState(const BlendStateHandle handle, const float* constant)
246{
247 assert(constant == nullptr);
248 state.blendState = &renderTargets->blendStates[handle];
249}
250
252{
253 state.rasterizerState = &renderTargets->rasterizerStates[handle];
254}
255
257{
258 currentEffect = handle;
259 state.effect = &effects->effects[handle];
260
261 auto & effect = *state.effect;
262
263 ContextCommon::setCurrentEffect(&effect);
264
265 shaderState.effectSignature = effect.signature;
266
267 for (uint32_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
268 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::CBV].values[i]; ++j) {
269 shaderState.CBVs[i].setChanged();
270 }
271
272 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::Sampler].values[i]; ++j) {
273 shaderState.Samplers[i].setChanged();
274 }
275
276 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::SRV].values[i]; ++j) {
277 shaderState.SRVs[i].setChanged();
278 }
279
280 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::UAV].values[i]; ++j) {
281 shaderState.UAVs[i].setChanged();
282 }
283 }
284}
285
286void Cogs::ContextVK::updateConstantBuffers()
287{
288 if (constantBuffersUpdated) return;
289
290 ContextCommon::updateConstantBuffers();
291
292 auto & effect = effects->effects[currentEffect];
293
294 for (auto & cb : effect.vertexShader.reflection.constantBuffers) {
295 if (HandleIsValid(cb.buffer)) {
296 shaderState.CBVs[ShaderType::VertexShader].setChanged(cb.slot, &buffers->buffers[cb.buffer]);
297 }
298 }
299
300 for (auto & cb : effect.pixelShader.reflection.constantBuffers) {
301 if (HandleIsValid(cb.buffer)) {
302 shaderState.CBVs[ShaderType::PixelShader].setChanged(cb.slot, &buffers->buffers[cb.buffer]);
303 }
304 }
305}
306
307void Cogs::ContextVK::setTexture(const TextureBindingHandle textureBindingHandle, TextureViewHandle textureViewHandle)
308{
309}
310
311void Cogs::ContextVK::setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle)
312{
313 TextureVK * texture = HandleIsValid(textureHandle) ? &textures->textures[textureHandle] : nullptr;
314
315 if (texture) {
316 if (texture->layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
317 VkImageSubresourceRange range;
318 range.aspectMask = texture->isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
319 range.baseArrayLayer = 0;
320 range.baseMipLevel = 0;
321 range.layerCount = 1;
322 range.levelCount = texture->mipLevels;
323
324 setImageLayout(currentFrameResources->commandBuffer, *texture, range.aspectMask, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range);
325 }
326 }
327
328 uint32_t slots[ShaderType::NumShaderTypes];
329 decode(textureBindingHandle.handle, slots);
330
331 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
332 if (slots[i] != NoBinding) {
333 shaderState.SRVs[i].setChanged(slots[i], texture, true);
334 }
335 }
336}
337
338void Cogs::ContextVK::setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle)
339{
340 SamplerVK * sampler = HandleIsValid(samplerStateHandle) ? &textures->samplers[samplerStateHandle] : nullptr;
341
342 uint32_t slots[ShaderType::NumShaderTypes];
343 decode(samplerStateBindingHandle.handle, slots);
344
345 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
346 if (slots[i] != NoBinding) {
347 shaderState.Samplers[i].setChanged(slots[i], sampler, true);
348 }
349 }
350}
351
352void Cogs::ContextVK::setBuffer(const BufferBindingHandle bindingHandle, BufferHandle bufferHandle)
353{
354 assert(false);
355}
356
358{
359 state.inputLayout = &buffers->inputLayouts[inputLayoutHandle];
360}
361
362void Cogs::ContextVK::setVertexBuffers(const VertexBufferHandle * vertexBufferHandles, const size_t count, const uint32_t * strides, const uint32_t * offsets)
363{
364 assert(false);
365}
366
367void Cogs::ContextVK::setVertexBuffers(const VertexBufferHandle * vertexBufferHandles, const size_t numVertexBuffers)
368{
369 iaState.numVertexBuffers = numVertexBuffers;
370
371 for (uint32_t i = 0; i < numVertexBuffers; i++) {
372 auto & buffer = this->buffers->buffers[BufferHandle(vertexBufferHandles[i].handle)];
373
374 assert(buffer.bindFlags & BindFlags::VertexBuffer && "Buffer not bindable as vertex buffer.");
375
376 iaState.currentVertexBuffers[i] = &buffer;
377 iaState.formats[i] = buffer.vertexFormat;
378
379 VkDeviceSize offsets[1] = { 0 };
380 vkCmdBindVertexBuffers(currentFrameResources->commandBuffer, i, 1, &buffer.buffer, offsets);
381 }
382}
383
384void Cogs::ContextVK::setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride, uint32_t offset_in)
385{
386 iaState.currentIndexBuffer = &buffers->buffers[bufferHandle];
387
388 uint32_t s = stride ? stride : iaState.currentIndexBuffer->indexSize;
389 VkDeviceSize offset = offset_in;
390 vkCmdBindIndexBuffer(currentFrameResources->commandBuffer,
391 iaState.currentIndexBuffer->buffer,
392 offset,
393 s == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
394}
395
397{
398 assert(false);
399}
400
401void Cogs::ContextVK::setConstantBuffer(const ConstantBufferBindingHandle bufferBindingHandle, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t size)
402{
403 assert(offset == 0 && size == ~0u && "Offset into constant buffers is not implemented");
404 auto & buffer = graphicsDevice->buffers.buffers[bufferHandle];
405
406 uint32_t slots[ShaderType::NumShaderTypes];
407 decode(bufferBindingHandle.handle, slots);
408
409 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
410 if (slots[i] != NoBinding) {
411 shaderState.CBVs[i].setChanged(slots[i], &buffer, false);
412 }
413 }
414}
415
416void Cogs::ContextVK::setBufferCounter(BufferHandle bufferHandle, uint32_t value)
417{
418}
419
420void Cogs::ContextVK::setBufferCounter(BufferHandle bufferHandle, BufferHandle sourceBufferHandle)
421{
422}
423
424void Cogs::ContextVK::getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle)
425{
426}
427
429{
430 return uint32_t();
431}
432
433void Cogs::ContextVK::draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)
434{
435 updatePipelineState(primitiveType);
436
437 vkCmdDraw(currentFrameResources->commandBuffer, static_cast<uint32_t>(numVertexes), 1, static_cast<uint32_t>(startVertex), 0);
438}
439
440void Cogs::ContextVK::drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex)
441{
442 updatePipelineState(primitiveType);
443
444 vkCmdDrawIndexed(currentFrameResources->commandBuffer, static_cast<uint32_t>(numIndexes ? numIndexes : iaState.currentIndexBuffer->size), 1, static_cast<uint32_t>(startIndex), static_cast<uint32_t>(startVertex), 0);
445}
446
447void Cogs::ContextVK::drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances)
448{
449 updatePipelineState(primitiveType);
450
451 vkCmdDraw(currentFrameResources->commandBuffer, static_cast<uint32_t>(numVertexes), static_cast<uint32_t>(numInstances), static_cast<uint32_t>(startVertex), static_cast<uint32_t>(startInstance));
452}
453
454void Cogs::ContextVK::drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes)
455{
456}
457
458void Cogs::ContextVK::dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
459{
460}
461
463{
464 auto & sourceTexture = textures->textures[source];
465 auto & destinationTexture = textures->textures[destination];
466
467 setImageLayout(currentFrameResources->commandBuffer, sourceTexture, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
468 setImageLayout(currentFrameResources->commandBuffer, destinationTexture, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
469
470 VkImageResolve resolve = {};
471 resolve.extent = { sourceTexture.width, sourceTexture.height, 1 };
472 resolve.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
473 resolve.srcSubresource.layerCount = 1;
474 resolve.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
475 resolve.dstSubresource.layerCount = 1;
476
477 vkCmdResolveImage(currentFrameResources->commandBuffer,
478 sourceTexture.image,
479 sourceTexture.layout,
480 destinationTexture.image,
481 destinationTexture.layout,
482 1,
483 &resolve);
484}
485
486void Cogs::ContextVK::readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer)
487{
488 assert(false);
489}
490
491void Cogs::ContextVK::readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer)
492{
493 assert(false);
494}
495
496void * Cogs::ContextVK::map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t * stride)
497{
498 auto & buffer = graphicsDevice->buffers.buffers[bufferHandle];
499
500 if (mapMode == MapMode::WriteDiscard) {
501 if (buffer.poolBuffer) {
502 currentFrameResources->orhpanedBuffers.push_back(buffer.poolBuffer);
503
504 buffer.poolBuffer = buffer.poolBuffer->pool->allocate();
505 buffer.bufferInfo.buffer = buffer.poolBuffer->buffer;
506 buffer.bufferInfo.offset = buffer.poolBuffer->offset;
507 buffer.bufferInfo.range = buffer.poolBuffer->size;
508
509 return buffer.poolBuffer->mappedRegion;
510 } else {
511 void * mappedMemory;
512 auto result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, buffer.size, 0, &mappedMemory);
513
514 if (VK_FAILED(result)) {
515 return nullptr;
516 }
517
518 return mappedMemory;
519 }
520 } else if (mapMode == MapMode::Write) {
521 void * mappedMemory;
522 auto result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, buffer.size, 0, &mappedMemory);
523
524 if (VK_FAILED(result)) {
525 return nullptr;
526 }
527
528 return mappedMemory;
529 } else if (mapMode == MapMode::Read) {
530 void * mappedMemory;
531 auto result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, buffer.size, 0, &mappedMemory);
532
533 if (VK_FAILED(result)) {
534 return nullptr;
535 }
536
537 return mappedMemory;
538 } else {
539 assert(false && "Map mode not supported.");
540 }
541
542 return nullptr;
543}
544
546{
547 auto & buffer = graphicsDevice->buffers.buffers[bufferHandle];
548
549 if (!buffer.poolBuffer) {
550 vkUnmapMemory(graphicsDevice->device, buffer.deviceMemory);
551 }
552}
553
554void Cogs::ContextVK::updateBuffer(BufferHandle bufferHandle, const void* data, size_t size)
555{
556 assert(false);
557}
558
559void *Cogs::ContextVK::map(TextureHandle textureHandle, MapMode::EMapMode accessMode, uint32_t * rowPitch, uint32_t * depthPitch)
560{
561 assert(false);
562 return nullptr;
563}
565{
566 assert(false);
567}
568
569void Cogs::ContextVK::updateSubTexture(TextureHandle textureHandle, const size_t level, const void * data)
570{
571 assert(false);
572 //textures->updateTextureData((const uint8_t **)&data, 1, 1, textures->textures[textureHandle]);
573}
574
575void Cogs::ContextVK::updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void * data)
576{
577 assert(false);
578}
579
580void Cogs::ContextVK::copyResource(BufferHandle destinationHandle, BufferHandle sourceHandle)
581{
582 assert(false);
583}
584
585void Cogs::ContextVK::copyResource(TextureHandle destinationHandle, TextureHandle sourceHandle)
586{
587 assert(false);
588}
589
590void Cogs::ContextVK::copyTexture(TextureHandle dstHandle, unsigned dstSub, unsigned dstX, unsigned dstY, unsigned dstZ, TextureHandle sourceHandle, unsigned srcSub)
591{
592 assert(false);
593}
594
595bool Cogs::ContextVK::updateDescriptorSet()
596{
597 auto & effect = graphicsDevice->effects.effects[currentEffect];
598
599 bool anyChanged = false;
600 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
601 if (shaderState.CBVs[i].hasChanged()) {
602 anyChanged = true;
603 break;
604 }
605 }
606
607 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
608 if (shaderState.SRVs[i].hasChanged()) {
609 anyChanged = true;
610 break;
611 }
612 }
613
614 if (!anyChanged) {
615 return false;
616 }
617
618 VkDescriptorSetAllocateInfo allocInfo = {};
619 allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
620 allocInfo.descriptorPool = descriptorPool;
621 allocInfo.descriptorSetCount = static_cast<uint32_t>(effect.descriptorSetLayouts.size());
622 allocInfo.pSetLayouts = effect.descriptorSetLayouts.data();
623
624 descriptorSets.resize(effect.descriptorSetLayouts.size());
625
626 auto result = vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data());
627
628 if (VK_FAILED(result)) {
629 VK_LOG_ERROR(result, "Could not allocate descriptor sets.");
630 }
631
632 const Shader * shaders[] = {
633 &effect.vertexShader,
634 nullptr,
635 nullptr,
636 &effect.geometryShader,
637 &effect.pixelShader,
638 };
639
640 const VkDescriptorSet * sets[] = {
641 descriptorSets.size() ? &descriptorSets.front() : nullptr,
642 nullptr,
643 nullptr,
644 descriptorSets.size() == 3 ? &descriptorSets[1] : nullptr,
645 descriptorSets.size() ? &descriptorSets.back() : nullptr,
646 };
647
648 static thread_local std::vector<VkWriteDescriptorSet> writes;
649 writes.clear();
650
651 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
652 auto & bindings = shaderState.CBVs[i];
653 auto slots = shaderState.effectSignature.slots[SlotType::CBV].values[i];
654
655 if (slots) {
656 for (size_t j = 0; j < slots; ++j) {
657 if (bindings[j]) {
658 VkWriteDescriptorSet write = {};
659 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
660 write.dstSet = *sets[i];
661 write.dstBinding = shaders[i]->reflection.constantBuffers[j].binding;
662 write.descriptorCount = 1;
663 write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
664 write.pBufferInfo = &bindings[j]->bufferInfo;
665 writes.push_back(write);
666 }
667 }
668 }
669 }
670
671 static thread_local std::vector<VkDescriptorImageInfo> imageInfos;
672 imageInfos.clear();
673 imageInfos.reserve(128);
674
675 for (size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
676 auto & bindings = shaderState.SRVs[i];
677 auto slots = shaderState.effectSignature.slots[SlotType::SRV].values[i];
678
679 if (!shaders[i]) continue;
680
681 auto offset = shaders[i]->reflection.constantBuffers.size();
682
683 if (slots) {
684 for (size_t j = 0; j < slots; ++j) {
685 imageInfos.emplace_back();
686 auto & imageInfo = imageInfos.back();
687 imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
688
689 if (bindings[j]) {
690 imageInfo.imageView = bindings[j]->imageView;
691 imageInfo.imageLayout = bindings[j]->layout;
692 } else {
693 imageInfo.imageView = textures->textures[defaultTexture].imageView;
694 }
695
696 if (shaderState.Samplers[i][j]) {
697 imageInfo.sampler = shaderState.Samplers[i][j]->sampler;
698 } else {
699 imageInfo.sampler = textures->samplers[defaultSampler].sampler;
700 }
701
702 VkWriteDescriptorSet write = {};
703 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
704 write.dstSet = *sets[i];
705 write.dstBinding = static_cast<uint32_t>(offset + j);
706 write.descriptorCount = 1;
707 write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
708 write.pImageInfo = &imageInfo;
709 writes.push_back(write);
710 }
711 }
712
713 shaderState.SRVs[i].setUnchanged();
714 }
715
716 vkUpdateDescriptorSets(device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
717
718 return true;
719}
720
721bool Cogs::ContextVK::setupPipeline(PrimitiveType::EPrimitiveType primitiveType)
722{
723 size_t hashCode = fnv1a(reinterpret_cast<const uint8_t *>(&state), sizeof(Vulkan::PipelineState) - sizeof(size_t));
724
725 if (hashCode != state.currentStateHash) {
726 auto it = PSOs.find(hashCode);
727
728 if (it == PSOs.end()) {
729 auto & effect = *state.effect;
730 auto & inputLayout = *state.inputLayout;
731
732 VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {};
733 VkPipelineDynamicStateCreateInfo dynamicState = {};
734 dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
735 dynamicState.pDynamicStates = dynamicStateEnables;
736
737 VkGraphicsPipelineCreateInfo pipelineInfo = {};
738 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
739 pipelineInfo.layout = effect.pipelineLayout;
740
741 VkPipelineInputAssemblyStateCreateInfo ia = {};
742 ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
743 ia.topology = primitiveType == PrimitiveType::TriangleList ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
744
745 VkPipelineViewportStateCreateInfo vp = {};
746 vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
747 vp.viewportCount = 1;
748 dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT;
749 vp.scissorCount = 1;
750 dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR;
751
752 std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
753
754 shaderStages.emplace_back(VkPipelineShaderStageCreateInfo{});
755 auto & vsStage = shaderStages.back();
756 vsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
757 vsStage.stage = VK_SHADER_STAGE_VERTEX_BIT;
758 vsStage.module = effect.vertexShader.shaderModule;
759 vsStage.pName = "main";
760
761 if (effect.geometryShader.shaderModule) {
762 shaderStages.emplace_back(VkPipelineShaderStageCreateInfo{});
763 auto & gsStage = shaderStages.back();
764 gsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
765 gsStage.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
766 gsStage.module = effect.geometryShader.shaderModule;
767 gsStage.pName = "main";
768 }
769
770 if (effect.pixelShader.shaderModule) {
771 shaderStages.emplace_back(VkPipelineShaderStageCreateInfo{});
772 auto & psStage = shaderStages.back();
773 psStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
774 psStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
775 psStage.module = effect.pixelShader.shaderModule;
776 psStage.pName = "main";
777 }
778
779 auto & rt = *state.renderTarget;
780 auto texture = rt.textures.size() ? rt.textures.front() : rt.depthTexture;
781
782 VkPipelineMultisampleStateCreateInfo ms = {};
783 ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
784 ms.pSampleMask = nullptr;
785 ms.rasterizationSamples = (VkSampleCountFlagBits)texture->samples;
786 ms.sampleShadingEnable = VK_FALSE;
787
788 pipelineInfo.pVertexInputState = &inputLayout.vertexInputState;
789 pipelineInfo.pInputAssemblyState = &ia;
790
791 pipelineInfo.pRasterizationState = &state.rasterizerState->state;
792 pipelineInfo.pDepthStencilState = &state.depthStencilState->state;
793 state.blendState->state.attachmentCount = static_cast<uint32_t>(rt.textures.size());
794 pipelineInfo.pColorBlendState = &state.blendState->state;
795
796 pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
797 pipelineInfo.pStages = shaderStages.data();
798
799 pipelineInfo.renderPass = rt.renderPass;
800 pipelineInfo.pMultisampleState = &ms;
801 pipelineInfo.pViewportState = &vp;
802 pipelineInfo.pDynamicState = &dynamicState;
803
804 VkPipelineCacheCreateInfo pipelineCacheInfo = {};
805 pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
806
807 auto result = vkCreatePipelineCache(device, &pipelineCacheInfo, nullptr, &pipelineCache);
808
809 if (VK_FAILED(result)) {
810 VK_LOG_ERROR(result, "Could not create pipeline cache.");
811 return false;
812 }
813
814 VkPipeline pipeline = {};
815 result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline);
816
817 if (VK_FAILED(result)) {
818 VK_LOG_ERROR(result, "Could not create graphics pipeline.");
819 return false;
820 }
821
822 vkDestroyPipelineCache(device, pipelineCache, nullptr);
823
824 PSOs[hashCode] = pipeline;
825 state.currentStateHash = hashCode;
826 }
827
828 vkCmdBindPipeline(currentFrameResources->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PSOs[hashCode]);
829 }
830
831 return true;
832}
833
834void Cogs::ContextVK::updatePipelineState(PrimitiveType::EPrimitiveType primitiveType)
835{
836 if (!renderPass) {
837 beginRenderPass();
838 }
839
840 if (!setupPipeline(primitiveType)) {
841 LOG_ERROR(logger, "Failed to update pipeline state.");
842 return;
843 }
844
845 updateConstantBuffers();
846
847 updateDescriptorSet();
848
849 vkCmdBindDescriptorSets(currentFrameResources->commandBuffer,
850 VK_PIPELINE_BIND_POINT_GRAPHICS,
851 state.effect->pipelineLayout,
852 0, static_cast<uint32_t>(descriptorSets.size()),
853 descriptorSets.data(),
854 0,
855 nullptr);
856}
857
858void Cogs::ContextVK::beginRenderPass()
859{
860 auto & renderTarget = *state.renderTarget;
861
862 VkRenderPassBeginInfo renderPassBeginInfo = {};
863 renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
864 renderPassBeginInfo.pNext = nullptr;
865 renderPassBeginInfo.renderPass = renderTarget.renderPass;
866 renderPassBeginInfo.framebuffer = renderTarget.framebuffer;
867 renderPassBeginInfo.renderArea.offset.x = 0;
868 renderPassBeginInfo.renderArea.offset.y = 0;
869 if (renderTarget.textures.size() && renderTarget.textures[0]->width != 0) {
870 renderPassBeginInfo.renderArea.extent.width = renderTarget.textures[0]->width;
871 renderPassBeginInfo.renderArea.extent.height = renderTarget.textures[0]->height;
872 } else if (renderTarget.depthTexture && renderTarget.depthTexture->width != 0) {
873 renderPassBeginInfo.renderArea.extent.width = renderTarget.depthTexture->width;
874 renderPassBeginInfo.renderArea.extent.height = renderTarget.depthTexture->height;
875 } else {
876 renderPassBeginInfo.renderArea.extent.width = graphicsDevice->width;
877 renderPassBeginInfo.renderArea.extent.height = graphicsDevice->height;
878 }
879 renderPassBeginInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
880 renderPassBeginInfo.pClearValues = clearValues.data();
881
882 vkCmdBeginRenderPass(currentFrameResources->commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
883 renderPass = renderTarget.renderPass;
884}
885
887{
888 vkCmdEndRenderPass(currentFrameResources->commandBuffer);
889 renderPass = VK_NULL_HANDLE;
890}
void setRasterizerState(const RasterizerStateHandle handle) override
Set the current rasterizer state.
Definition: ContextVK.cpp:251
void draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes) override
Draws non-indexed, non-instanced primitives.
Definition: ContextVK.cpp:433
void clearDepth(const float depth=1.0f) override
Clear the currently set depth/stencil target to the given depth.
Definition: ContextVK.cpp:235
void readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer) override
Reads data from the current depth target into the given bufferHandle.
Definition: ContextVK.cpp:486
void endRenderPass()
End a render pass.
Definition: ContextVK.cpp:886
void setViewport(const float x, const float y, const float width, const float height) override
Sets the current viewport to the given location and dimensions.
Definition: ContextVK.cpp:197
void setBufferCounter(BufferHandle bufferHandle, uint32_t value) override
Set the associated counter of a buffer.
Definition: ContextVK.cpp:416
void clearRenderTarget(const float *color) override
Clear the currently set render target to the given value (4 component floating point RGBA).
Definition: ContextVK.cpp:218
void setBuffer(const BufferBindingHandle bindingHandle, BufferHandle bufferHandle) override
Sets a buffer to bind to the given binding.
Definition: ContextVK.cpp:352
void setInputLayout(const InputLayoutHandle inputLayoutHandle) override
Sets the current input layout.
Definition: ContextVK.cpp:357
void * map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t *stride=nullptr) override
Maps the given buffer so it can be accessed.
Definition: ContextVK.cpp:496
void getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle) override
Get the associated counter of a buffer.
Definition: ContextVK.cpp:424
void updateSubTexture(TextureHandle textureHandle, const size_t level, const void *data) override
Update the data of a level in the given texture.
Definition: ContextVK.cpp:569
void updateBuffer(BufferHandle bufferHandle, const void *data, size_t size) override
Replace contents of buffer with new data.
Definition: ContextVK.cpp:554
void setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride=4, uint32_t offset=0) override
Sets the current index buffer.
Definition: ContextVK.cpp:384
void unmap(BufferHandle bufferHandle) override
Unmaps the given buffer, applying any synchronization necessary to reflect changes in the mapped memo...
Definition: ContextVK.cpp:545
void setDepthStencilState(const DepthStencilStateHandle handle) override
Set the current depth stencil state.
Definition: ContextVK.cpp:240
void setBlendState(const BlendStateHandle handle, const float *constant=nullptr) override
Set the current blend state.
Definition: ContextVK.cpp:245
void setConstantBuffer(const ConstantBufferBindingHandle bufferBindingHandle, const BufferHandle bufferHandle, const uint32_t offset=0, const uint32_t size=~0u) override
Sets a constant buffer to the given constant buffer binding.
Definition: ContextVK.cpp:401
void setEffect(EffectHandle handle) override
Set the current effect.
Definition: ContextVK.cpp:256
void setScissor(const int x, const int y, const int width, const int height) override
Sets the current scissor rectangle.
Definition: ContextVK.cpp:214
void drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex) override
Draws indexed, non-instanced primitives.
Definition: ContextVK.cpp:440
void setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle) override
Sets the texture given to the binding given by textureBindingHandle.
Definition: ContextVK.cpp:311
void resolveResource(TextureHandle source, TextureHandle destination) override
Resolves the given source resource target into the given destination texture.
Definition: ContextVK.cpp:462
void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle) override
Sets the current render target and an associated depth stencil target.
Definition: ContextVK.cpp:167
void drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances) override
Draws non-indexed, instanced primitives.
Definition: ContextVK.cpp:447
void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets) override
Sets the current vertex buffers.
Definition: ContextVK.cpp:362
void dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ) override
Dispatch computing work on the graphics device using the desired thread group count.
Definition: ContextVK.cpp:458
void readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer framebuffer) override
Reads data from the current render target into the given bufferHandle.
Definition: ContextVK.cpp:491
void setVertexArrayObject(VertexArrayObjectHandle vertexArrayObject) override
Definition: ContextVK.cpp:396
void updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void *data) override
Update a region of data in a buffer.
Definition: ContextVK.cpp:575
void drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes) override
Draws indexed, instanced primitives.
Definition: ContextVK.cpp:454
void setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle) override
Sets the sampler state binding given to the given sampler state.
Definition: ContextVK.cpp:338
Log implementation class.
Definition: LogManager.h:139
DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState) override
Load a depth stencil state object.
BlendStateHandle loadBlendState(const BlendState &blendState) override
Load a blend state object.
RasterizerStateHandle loadRasterizerState(const RasterizerState &rasterizerState) override
Load a rasterizer state object.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
constexpr size_t fnv1a(uint8_t data, size_t hashValue) noexcept
Hashes a single byte using the fnv1a algorithm.
Definition: HashFunctions.h:37
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
Definition: Flags.h:68
static BlendState DefaultState()
Creates a blend state object initialized with the default settings.
Definition: BlendState.h:55
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
handle_type handle
Internal resource handle.
Definition: Common.h:74
EMapMode
Mapping mode enumeration.
Definition: Flags.h:93
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
EPrimitiveType
Primitive type enumeration.
Definition: Common.h:114
@ TriangleList
List of triangles.
Definition: Common.h:116
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
static SamplerState & DefaultState()
Constructs a sampler state initialized with the default values.
Definition: SamplerState.h:85
@ Default
Default usage, the texture can be loaded once and bound and sampled in shaders.
Definition: Flags.h:116
TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data) override
Load a texture from the given description.
Definition: TexturesVK.cpp:113
SamplerStateHandle loadSamplerState(const SamplerState &state) override
Load a sampler state object.
Definition: TexturesVK.cpp:29