3#include "GraphicsDeviceVK.h"
8#include "Foundation/HashFunctions.h"
15void Cogs::ContextVK::initialize(GraphicsDeviceVK * graphicsDevice)
17 this->graphicsDevice = graphicsDevice;
18 device = graphicsDevice->device;
20 effects = &graphicsDevice->effects;
21 buffers = &graphicsDevice->buffers;
22 textures = &graphicsDevice->textures;
23 renderTargets = &graphicsDevice->renderTargets;
25 for (
auto & frameResource : frameResources) {
26 const VkCommandPoolCreateInfo commandPoolInfo = {
27 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
29 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
33 auto result = vkCreateCommandPool(device, &commandPoolInfo,
nullptr, &frameResource.commandPool);
35 if (VK_FAILED(result)) {
36 VK_LOG_ERROR(result,
"Could not create command pool.");
40 const VkCommandBufferAllocateInfo cmd = {
41 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
43 frameResource.commandPool,
44 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
48 result = vkAllocateCommandBuffers(device, &cmd, &frameResource.commandBuffer);
50 if (VK_FAILED(result)) {
51 VK_LOG_ERROR(result,
"Could not create command buffer.");
55 VkDescriptorPoolSize descriptorSizes[2];
56 descriptorSizes[0] = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32000, };
57 descriptorSizes[1] = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32000, };
59 const VkDescriptorPoolCreateInfo descriptorPoolInfo = {
60 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
68 result = vkCreateDescriptorPool(device, &descriptorPoolInfo,
nullptr, &frameResource.descriptorPool);
75 VkFenceCreateInfo fenceInfo = {};
76 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
78 vkCreateFence(device, &fenceInfo,
nullptr, &frameResource.fence);
81 uint8_t textureData[4 * 1] = { 0 };
90void Cogs::ContextVK::beginFrame()
92 currentFrameResources = &frameResources[currentFrame % frameResources.size()];
94 if (currentFrame != 0) {
95 if (vkGetFenceStatus(device, currentFrameResources->fence) != VK_SUCCESS) {
96 vkWaitForFences(device, 1, ¤tFrameResources->fence, VK_TRUE, 100000000);
99 vkResetFences(device, 1, ¤tFrameResources->fence);
101 vkResetCommandBuffer(currentFrameResources->commandBuffer, 0);
102 vkResetDescriptorPool(device, currentFrameResources->descriptorPool, 0);
105 descriptorPool = currentFrameResources->descriptorPool;
112 ContextCommon::setCurrentEffect(
nullptr);
114 setRasterizerState(defaultRasterizerState);
115 setDepthStencilState(defaultDepthStencilState);
116 setBlendState(defaultBlendState);
118 for (
auto & ob : currentFrameResources->orhpanedBuffers) {
119 ob->pool->deallocate(ob);
122 currentFrameResources->orhpanedBuffers.clear();
124 const VkCommandBufferBeginInfo commandBufferBeginInfo = {
125 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
127 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
131 auto result = vkBeginCommandBuffer(currentFrameResources->commandBuffer, &commandBufferBeginInfo);
133 if (VK_FAILED(result)) {
134 VK_LOG_ERROR(result,
"Could not begin command buffer.");
141void Cogs::ContextVK::endFrame()
150 auto & texture = graphicsDevice->textures.textures[graphicsDevice->backBuffers[graphicsDevice->currentFrameBuffer]];
152 if (graphicsDevice->getSettings().numSamples > 1) {
153 resolveResource(graphicsDevice->backBuffersMS[graphicsDevice->currentFrameBuffer], graphicsDevice->backBuffers[graphicsDevice->currentFrameBuffer]);
156 setImageLayout(currentFrameResources->commandBuffer, texture, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
158 auto result = vkEndCommandBuffer(currentFrameResources->commandBuffer);
160 if (VK_FAILED(result)) {
161 VK_LOG_ERROR(result,
"Could not close command buffer.");
173 auto & renderTarget = renderTargets->renderTargets[HandleIsValid(handle) ? handle : defaultRenderTarget];
175 state.renderTarget = &renderTarget;
176 state.depthStencil =
nullptr;
178 clearValues.resize(renderTarget.textures.size() + (renderTarget.depthTexture ? 1 : 0));
180 for (
auto texture : renderTarget.textures) {
182 currentFrameResources->commandBuffer,
184 VK_IMAGE_ASPECT_COLOR_BIT,
185 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
188 if (renderTarget.depthTexture) {
190 currentFrameResources->commandBuffer,
191 *renderTarget.depthTexture,
192 VK_IMAGE_ASPECT_DEPTH_BIT,
193 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
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);
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);
220 clearRenderTarget(&color, 1);
225 for (
size_t i = 0; i < state.renderTarget->textures.size(); ++i) {
226 auto color = colors[count > 1 ? i : 0];
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];
237 clearValues.back().depthStencil = { depth, 0 };
242 state.depthStencilState = &renderTargets->depthStencilStates[handle];
247 assert(constant ==
nullptr);
248 state.blendState = &renderTargets->blendStates[handle];
253 state.rasterizerState = &renderTargets->rasterizerStates[handle];
258 currentEffect = handle;
259 state.effect = &effects->effects[handle];
261 auto & effect = *state.effect;
263 ContextCommon::setCurrentEffect(&effect);
265 shaderState.effectSignature = effect.signature;
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();
272 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::Sampler].values[i]; ++j) {
273 shaderState.Samplers[i].setChanged();
276 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::SRV].values[i]; ++j) {
277 shaderState.SRVs[i].setChanged();
280 for (uint32_t j = 0; j < shaderState.effectSignature.slots[SlotType::UAV].values[i]; ++j) {
281 shaderState.UAVs[i].setChanged();
286void Cogs::ContextVK::updateConstantBuffers()
288 if (constantBuffersUpdated)
return;
290 ContextCommon::updateConstantBuffers();
292 auto & effect = effects->effects[currentEffect];
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]);
300 for (
auto & cb : effect.pixelShader.reflection.constantBuffers) {
302 shaderState.CBVs[ShaderType::PixelShader].setChanged(cb.slot, &buffers->buffers[cb.buffer]);
313 TextureVK * texture = HandleIsValid(textureHandle) ? &textures->textures[textureHandle] :
nullptr;
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;
324 setImageLayout(currentFrameResources->commandBuffer, *texture, range.aspectMask, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, range);
328 uint32_t slots[ShaderType::NumShaderTypes];
329 decode(textureBindingHandle.
handle, slots);
331 for (
size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
332 if (slots[i] != NoBinding) {
333 shaderState.SRVs[i].setChanged(slots[i], texture,
true);
340 SamplerVK * sampler = HandleIsValid(samplerStateHandle) ? &textures->samplers[samplerStateHandle] :
nullptr;
342 uint32_t slots[ShaderType::NumShaderTypes];
343 decode(samplerStateBindingHandle.
handle, slots);
345 for (
size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
346 if (slots[i] != NoBinding) {
347 shaderState.Samplers[i].setChanged(slots[i], sampler,
true);
359 state.inputLayout = &buffers->inputLayouts[inputLayoutHandle];
369 iaState.numVertexBuffers = numVertexBuffers;
371 for (uint32_t i = 0; i < numVertexBuffers; i++) {
372 auto & buffer = this->buffers->buffers[
BufferHandle(vertexBufferHandles[i].handle)];
376 iaState.currentVertexBuffers[i] = &buffer;
377 iaState.formats[i] = buffer.vertexFormat;
379 VkDeviceSize offsets[1] = { 0 };
380 vkCmdBindVertexBuffers(currentFrameResources->commandBuffer, i, 1, &buffer.buffer, offsets);
386 iaState.currentIndexBuffer = &buffers->buffers[bufferHandle];
388 uint32_t s = stride ? stride : iaState.currentIndexBuffer->indexSize;
389 VkDeviceSize offset = offset_in;
390 vkCmdBindIndexBuffer(currentFrameResources->commandBuffer,
391 iaState.currentIndexBuffer->buffer,
393 s == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
403 assert(offset == 0 && size == ~0u &&
"Offset into constant buffers is not implemented");
404 auto & buffer = graphicsDevice->buffers.buffers[bufferHandle];
406 uint32_t slots[ShaderType::NumShaderTypes];
407 decode(bufferBindingHandle.
handle, slots);
409 for (
size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
410 if (slots[i] != NoBinding) {
411 shaderState.CBVs[i].setChanged(slots[i], &buffer,
false);
435 updatePipelineState(primitiveType);
437 vkCmdDraw(currentFrameResources->commandBuffer,
static_cast<uint32_t
>(numVertexes), 1,
static_cast<uint32_t
>(startVertex), 0);
442 updatePipelineState(primitiveType);
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);
449 updatePipelineState(primitiveType);
451 vkCmdDraw(currentFrameResources->commandBuffer,
static_cast<uint32_t
>(numVertexes),
static_cast<uint32_t
>(numInstances),
static_cast<uint32_t
>(startVertex),
static_cast<uint32_t
>(startInstance));
464 auto & sourceTexture = textures->textures[source];
465 auto & destinationTexture = textures->textures[destination];
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);
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;
477 vkCmdResolveImage(currentFrameResources->commandBuffer,
479 sourceTexture.layout,
480 destinationTexture.image,
481 destinationTexture.layout,
498 auto & buffer = graphicsDevice->buffers.buffers[bufferHandle];
501 if (buffer.poolBuffer) {
502 currentFrameResources->orhpanedBuffers.push_back(buffer.poolBuffer);
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;
509 return buffer.poolBuffer->mappedRegion;
512 auto result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, buffer.size, 0, &mappedMemory);
514 if (VK_FAILED(result)) {
522 auto result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, buffer.size, 0, &mappedMemory);
524 if (VK_FAILED(result)) {
531 auto result = vkMapMemory(graphicsDevice->device, buffer.deviceMemory, 0, buffer.size, 0, &mappedMemory);
533 if (VK_FAILED(result)) {
539 assert(
false &&
"Map mode not supported.");
547 auto & buffer = graphicsDevice->buffers.buffers[bufferHandle];
549 if (!buffer.poolBuffer) {
550 vkUnmapMemory(graphicsDevice->device, buffer.deviceMemory);
585void Cogs::ContextVK::copyResource(TextureHandle destinationHandle, TextureHandle sourceHandle)
590void Cogs::ContextVK::copyTexture(TextureHandle dstHandle,
unsigned dstSub,
unsigned dstX,
unsigned dstY,
unsigned dstZ, TextureHandle sourceHandle,
unsigned srcSub)
595bool Cogs::ContextVK::updateDescriptorSet()
597 auto & effect = graphicsDevice->effects.effects[currentEffect];
599 bool anyChanged =
false;
600 for (
size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
601 if (shaderState.CBVs[i].hasChanged()) {
607 for (
size_t i = 0; i < ShaderType::NumShaderTypes; ++i) {
608 if (shaderState.SRVs[i].hasChanged()) {
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();
624 descriptorSets.resize(effect.descriptorSetLayouts.size());
626 auto result = vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data());
628 if (VK_FAILED(result)) {
629 VK_LOG_ERROR(result,
"Could not allocate descriptor sets.");
632 const Shader * shaders[] = {
633 &effect.vertexShader,
636 &effect.geometryShader,
640 const VkDescriptorSet * sets[] = {
641 descriptorSets.size() ? &descriptorSets.front() :
nullptr,
644 descriptorSets.size() == 3 ? &descriptorSets[1] :
nullptr,
645 descriptorSets.size() ? &descriptorSets.back() :
nullptr,
648 static thread_local std::vector<VkWriteDescriptorSet> writes;
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];
656 for (
size_t j = 0; j < slots; ++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);
671 static thread_local std::vector<VkDescriptorImageInfo> imageInfos;
673 imageInfos.reserve(128);
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];
679 if (!shaders[i])
continue;
681 auto offset = shaders[i]->reflection.constantBuffers.size();
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;
690 imageInfo.imageView = bindings[j]->imageView;
691 imageInfo.imageLayout = bindings[j]->layout;
693 imageInfo.imageView = textures->textures[defaultTexture].imageView;
696 if (shaderState.Samplers[i][j]) {
697 imageInfo.sampler = shaderState.Samplers[i][j]->sampler;
699 imageInfo.sampler = textures->samplers[defaultSampler].sampler;
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);
713 shaderState.SRVs[i].setUnchanged();
716 vkUpdateDescriptorSets(device,
static_cast<uint32_t
>(writes.size()), writes.data(), 0,
nullptr);
723 size_t hashCode =
fnv1a(
reinterpret_cast<const uint8_t *
>(&state),
sizeof(Vulkan::PipelineState) -
sizeof(
size_t));
725 if (hashCode != state.currentStateHash) {
726 auto it = PSOs.find(hashCode);
728 if (it == PSOs.end()) {
729 auto & effect = *state.effect;
730 auto & inputLayout = *state.inputLayout;
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;
737 VkGraphicsPipelineCreateInfo pipelineInfo = {};
738 pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
739 pipelineInfo.layout = effect.pipelineLayout;
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;
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;
750 dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR;
752 std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
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";
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";
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";
779 auto & rt = *state.renderTarget;
780 auto texture = rt.textures.size() ? rt.textures.front() : rt.depthTexture;
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;
788 pipelineInfo.pVertexInputState = &inputLayout.vertexInputState;
789 pipelineInfo.pInputAssemblyState = &ia;
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;
796 pipelineInfo.stageCount =
static_cast<uint32_t
>(shaderStages.size());
797 pipelineInfo.pStages = shaderStages.data();
799 pipelineInfo.renderPass = rt.renderPass;
800 pipelineInfo.pMultisampleState = &ms;
801 pipelineInfo.pViewportState = &vp;
802 pipelineInfo.pDynamicState = &dynamicState;
804 VkPipelineCacheCreateInfo pipelineCacheInfo = {};
805 pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
807 auto result = vkCreatePipelineCache(device, &pipelineCacheInfo,
nullptr, &pipelineCache);
809 if (VK_FAILED(result)) {
810 VK_LOG_ERROR(result,
"Could not create pipeline cache.");
814 VkPipeline pipeline = {};
815 result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineInfo,
nullptr, &pipeline);
817 if (VK_FAILED(result)) {
818 VK_LOG_ERROR(result,
"Could not create graphics pipeline.");
822 vkDestroyPipelineCache(device, pipelineCache,
nullptr);
824 PSOs[hashCode] = pipeline;
825 state.currentStateHash = hashCode;
828 vkCmdBindPipeline(currentFrameResources->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PSOs[hashCode]);
840 if (!setupPipeline(primitiveType)) {
841 LOG_ERROR(logger,
"Failed to update pipeline state.");
845 updateConstantBuffers();
847 updateDescriptorSet();
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(),
858void Cogs::ContextVK::beginRenderPass()
860 auto & renderTarget = *state.renderTarget;
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;
876 renderPassBeginInfo.renderArea.extent.width = graphicsDevice->width;
877 renderPassBeginInfo.renderArea.extent.height = graphicsDevice->height;
879 renderPassBeginInfo.clearValueCount =
static_cast<uint32_t
>(clearValues.size());
880 renderPassBeginInfo.pClearValues = clearValues.data();
882 vkCmdBeginRenderPass(currentFrameResources->commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
883 renderPass = renderTarget.renderPass;
888 vkCmdEndRenderPass(currentFrameResources->commandBuffer);
889 renderPass = VK_NULL_HANDLE;
void setRasterizerState(const RasterizerStateHandle handle) override
Set the current rasterizer state.
void draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes) override
Draws non-indexed, non-instanced primitives.
void clearDepth(const float depth=1.0f) override
Clear the currently set depth/stencil target to the given depth.
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.
void endRenderPass()
End a render pass.
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.
void setBufferCounter(BufferHandle bufferHandle, uint32_t value) override
Set the associated counter of a buffer.
void clearRenderTarget(const float *color) override
Clear the currently set render target to the given value (4 component floating point RGBA).
void setBuffer(const BufferBindingHandle bindingHandle, BufferHandle bufferHandle) override
Sets a buffer to bind to the given binding.
void setInputLayout(const InputLayoutHandle inputLayoutHandle) override
Sets the current input layout.
void * map(BufferHandle bufferHandle, MapMode::EMapMode mapMode, uint32_t *stride=nullptr) override
Maps the given buffer so it can be accessed.
void getBufferCounter(BufferHandle bufferHandle, BufferHandle destinationBufferHandle) override
Get the associated counter of a buffer.
void updateSubTexture(TextureHandle textureHandle, const size_t level, const void *data) override
Update the data of a level in the given texture.
void updateBuffer(BufferHandle bufferHandle, const void *data, size_t size) override
Replace contents of buffer with new data.
void setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride=4, uint32_t offset=0) override
Sets the current index buffer.
void unmap(BufferHandle bufferHandle) override
Unmaps the given buffer, applying any synchronization necessary to reflect changes in the mapped memo...
void setDepthStencilState(const DepthStencilStateHandle handle) override
Set the current depth stencil state.
void setBlendState(const BlendStateHandle handle, const float *constant=nullptr) override
Set the current blend state.
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.
void setEffect(EffectHandle handle) override
Set the current effect.
void setScissor(const int x, const int y, const int width, const int height) override
Sets the current scissor rectangle.
void drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex) override
Draws indexed, non-instanced primitives.
void setTexture(const TextureBindingHandle textureBindingHandle, const TextureHandle textureHandle) override
Sets the texture given to the binding given by textureBindingHandle.
void resolveResource(TextureHandle source, TextureHandle destination) override
Resolves the given source resource target into the given destination texture.
void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle) override
Sets the current render target and an associated depth stencil target.
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.
void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets) override
Sets the current vertex buffers.
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.
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.
void setVertexArrayObject(VertexArrayObjectHandle vertexArrayObject) override
void updateSubBuffer(BufferHandle bufferHandle, const size_t offset, const size_t size, const void *data) override
Update a region of data in a buffer.
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.
void setSamplerState(const SamplerStateBindingHandle samplerStateBindingHandle, const SamplerStateHandle samplerStateHandle) override
Sets the sampler state binding given to the given sampler state.
Log implementation class.
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
constexpr size_t fnv1a(uint8_t data, size_t hashValue) noexcept
Hashes a single byte using the fnv1a algorithm.
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
static BlendState DefaultState()
Creates a blend state object initialized with the default settings.
static DepthStencilState DefaultState()
Constructs a depth stencil state object initialized with the default values.
static const Handle_t NoHandle
Represents a handle to nothing.
handle_type handle
Internal resource handle.
EMapMode
Mapping mode enumeration.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
EPrimitiveType
Primitive type enumeration.
@ TriangleList
List of triangles.
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
static SamplerState & DefaultState()
Constructs a sampler state initialized with the default values.
@ Default
Default usage, the texture can be loaded once and bound and sampled in shaders.
TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data) override
Load a texture from the given description.
SamplerStateHandle loadSamplerState(const SamplerState &state) override
Load a sampler state object.