| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "BsVulkanGpuPipelineState.h"
- #include "BsVulkanDevice.h"
- #include "BsVulkanGpuProgram.h"
- #include "BsVulkanFramebuffer.h"
- #include "BsVulkanUtility.h"
- #include "BsRasterizerState.h"
- #include "BsDepthStencilState.h"
- #include "BsBlendState.h"
- #include "BsRenderStats.h"
- namespace BansheeEngine
- {
- VulkanPipeline::VulkanPipeline(VulkanResourceManager* owner, VkPipeline pipeline)
- :VulkanResource(owner, true), mPipeline(pipeline)
- { }
- VulkanPipeline::~VulkanPipeline()
- {
- vkDestroyPipeline(mOwner->getDevice().getLogical(), mPipeline, gVulkanAllocator);
- }
- VulkanGpuPipelineStateCore::VulkanGpuPipelineStateCore(const PIPELINE_STATE_CORE_DESC& desc, GpuDeviceFlags deviceMask)
- :GpuPipelineStateCore(desc, deviceMask)
- {
-
- }
- VulkanGpuPipelineStateCore::~VulkanGpuPipelineStateCore()
- {
- BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_PipelineState);
- }
- void VulkanGpuPipelineStateCore::initialize()
- {
- std::pair<VkShaderStageFlagBits, GpuProgramCore*> stages[] =
- {
- { VK_SHADER_STAGE_VERTEX_BIT, mData.vertexProgram.get() },
- { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, mData.hullProgram.get() },
- { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, mData.domainProgram.get() },
- { VK_SHADER_STAGE_GEOMETRY_BIT, mData.geometryProgram.get() },
- { VK_SHADER_STAGE_FRAGMENT_BIT, mData.fragmentProgram.get() }
- };
- UINT32 stageOutputIdx = 0;
- UINT32 numStages = sizeof(stages) / sizeof(stages[0]);
- for(UINT32 i = 0; i < numStages; i++)
- {
- VulkanGpuProgramCore* program = static_cast<VulkanGpuProgramCore*>(stages[i].second);
- if (program == nullptr)
- continue;
- VkPipelineShaderStageCreateInfo& stageCI = mShaderStageInfos[stageOutputIdx];
- stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- stageCI.pNext = nullptr;
- stageCI.flags = 0;
- stageCI.stage = stages[i].first;
- stageCI.module = program->getHandle();
- stageCI.pName = program->getProperties().getEntryPoint().c_str();
- stageCI.pSpecializationInfo = nullptr;
- stageOutputIdx++;
- }
- UINT32 numUsedStages = stageOutputIdx;
- bool tesselationEnabled = mData.hullProgram != nullptr && mData.domainProgram != nullptr;
- mInputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- mInputAssemblyInfo.pNext = nullptr;
- mInputAssemblyInfo.flags = 0;
- mInputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // Assigned at runtime
- mInputAssemblyInfo.primitiveRestartEnable = false;
- mTesselationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
- mTesselationInfo.patchControlPoints = 3; // Assigned at runtime
- mViewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- mViewportInfo.pNext = nullptr;
- mViewportInfo.flags = 0;
- mViewportInfo.viewportCount = 1; // Spec says this need to be at least 1...
- mViewportInfo.scissorCount = 1;
- mViewportInfo.pViewports = nullptr; // Dynamic
- mViewportInfo.pScissors = nullptr; // Dynamic
- const RasterizerProperties& rstProps = getRasterizerState()->getProperties();
- const BlendProperties& blendProps = getBlendState()->getProperties();
- const DepthStencilProperties dsProps = getDepthStencilState()->getProperties();
- mRasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- mRasterizationInfo.pNext = nullptr;
- mRasterizationInfo.flags = 0;
- mRasterizationInfo.depthClampEnable = !rstProps.getDepthClipEnable();
- mRasterizationInfo.rasterizerDiscardEnable = VK_FALSE;
- mRasterizationInfo.polygonMode = VulkanUtility::getPolygonMode(rstProps.getPolygonMode());
- mRasterizationInfo.cullMode = VulkanUtility::getCullMode(rstProps.getCullMode());
- mRasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
- mRasterizationInfo.depthBiasEnable = rstProps.getDepthBias() != 0.0f;
- mRasterizationInfo.depthBiasConstantFactor = rstProps.getDepthBias();
- mRasterizationInfo.depthBiasSlopeFactor = rstProps.getSlopeScaledDepthBias();
- mRasterizationInfo.depthBiasClamp = mRasterizationInfo.depthClampEnable ? rstProps.getDepthBiasClamp() : 0.0f;
- mRasterizationInfo.lineWidth = 1.0f;
- mMultiSampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- mMultiSampleInfo.pNext = nullptr;
- mMultiSampleInfo.flags = 0;
- mMultiSampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; // Assigned at runtime
- mMultiSampleInfo.sampleShadingEnable = VK_FALSE; // When enabled, perform shading per sample instead of per pixel (more expensive, essentially FSAA)
- mMultiSampleInfo.minSampleShading = 1.0f; // Minimum percent of samples to run full shading for when sampleShadingEnable is enabled (1.0f to run for all)
- mMultiSampleInfo.pSampleMask = nullptr; // Normally one bit for each sample: e.g. 0x0000000F to enable all samples in a 4-sample setup
- mMultiSampleInfo.alphaToCoverageEnable = blendProps.getAlphaToCoverageEnabled();
- mMultiSampleInfo.alphaToOneEnable = VK_FALSE;
- VkStencilOpState stencilFrontInfo;
- stencilFrontInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilFrontCompFunc());
- stencilFrontInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontZFailOp());
- stencilFrontInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontPassOp());
- stencilFrontInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontFailOp());
- stencilFrontInfo.reference = 0; // Dynamic
- stencilFrontInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
- stencilFrontInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();
- VkStencilOpState stencilBackInfo;
- stencilBackInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilBackCompFunc());
- stencilBackInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilBackZFailOp());
- stencilBackInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilBackPassOp());
- stencilBackInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilBackFailOp());
- stencilBackInfo.reference = 0; // Dynamic
- stencilBackInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
- stencilBackInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();
- mDepthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
- mDepthStencilInfo.pNext = nullptr;
- mDepthStencilInfo.flags = 0;
- mDepthStencilInfo.depthBoundsTestEnable = false;
- mDepthStencilInfo.minDepthBounds = 0.0f;
- mDepthStencilInfo.maxDepthBounds = 1.0f;
- mDepthStencilInfo.depthTestEnable = dsProps.getDepthReadEnable();
- mDepthStencilInfo.depthWriteEnable = dsProps.getDepthWriteEnable();
- mDepthStencilInfo.depthCompareOp = VulkanUtility::getCompareOp(dsProps.getDepthComparisonFunc());
- mDepthStencilInfo.front = stencilFrontInfo;
- mDepthStencilInfo.back = stencilBackInfo;
- mDepthStencilInfo.stencilTestEnable = dsProps.getStencilEnable();
- for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
- {
- UINT32 rtIdx = 0;
- if (blendProps.getIndependantBlendEnable())
- rtIdx = i;
- VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
- blendState.blendEnable = blendProps.getBlendEnabled(rtIdx);
- blendState.colorBlendOp = VulkanUtility::getBlendOp(blendProps.getBlendOperation(rtIdx));
- blendState.srcColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getSrcBlend(rtIdx));
- blendState.dstColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getDstBlend(rtIdx));
- blendState.alphaBlendOp = VulkanUtility::getBlendOp(blendProps.getAlphaBlendOperation(rtIdx));
- blendState.srcAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaSrcBlend(rtIdx));
- blendState.dstAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaDstBlend(rtIdx));
- blendState.colorWriteMask = blendProps.getRenderTargetWriteMask(rtIdx) & 0xF;
- }
- mColorBlendStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- mColorBlendStateInfo.pNext = nullptr;
- mColorBlendStateInfo.flags = 0;
- mColorBlendStateInfo.logicOpEnable = VK_FALSE;
- mColorBlendStateInfo.logicOp = VK_LOGIC_OP_NO_OP;
- mColorBlendStateInfo.attachmentCount = 0; // Assigned at runtime
- mColorBlendStateInfo.pAttachments = mAttachmentBlendStates;
- mColorBlendStateInfo.blendConstants[0] = 0.0f;
- mColorBlendStateInfo.blendConstants[1] = 0.0f;
- mColorBlendStateInfo.blendConstants[2] = 0.0f;
- mColorBlendStateInfo.blendConstants[3] = 0.0f;
- mDynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
- mDynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
- mDynamicStates[2] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
- UINT32 numDynamicStates = sizeof(mDynamicStates) / sizeof(mDynamicStates[0]);
- assert(numDynamicStates == 3);
- mDynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- mDynamicStateInfo.pNext = nullptr;
- mDynamicStateInfo.flags = 0;
- mDynamicStateInfo.dynamicStateCount = numDynamicStates;
- mDynamicStateInfo.pDynamicStates = mDynamicStates;
- mPipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- mPipelineInfo.pNext = nullptr;
- mPipelineInfo.flags = 0;
- mPipelineInfo.stageCount = numUsedStages;
- mPipelineInfo.pStages = mShaderStageInfos;
- mPipelineInfo.pVertexInputState = nullptr; // Assigned at runtime
- mPipelineInfo.pInputAssemblyState = &mInputAssemblyInfo;
- mPipelineInfo.pTessellationState = tesselationEnabled ? &mTesselationInfo : nullptr;
- mPipelineInfo.pViewportState = &mViewportInfo;
- mPipelineInfo.pRasterizationState = &mRasterizationInfo;
- mPipelineInfo.pMultisampleState = &mMultiSampleInfo;
- mPipelineInfo.pDepthStencilState = nullptr; // Assigned at runtime
- mPipelineInfo.pColorBlendState = nullptr; // Assigned at runtime
- mPipelineInfo.pDynamicState = &mDynamicStateInfo;
- mPipelineInfo.renderPass = VK_NULL_HANDLE; // Assigned at runtime
- mPipelineInfo.layout = VK_NULL_HANDLE; // Assigned at runtime
- mPipelineInfo.subpass = 0;
- mPipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
- mPipelineInfo.basePipelineIndex = -1;
- BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
- GpuPipelineStateCore::initialize();
- }
- VkPipeline VulkanGpuPipelineStateCore::createPipeline(VkDevice device, VulkanFramebuffer* framebuffer,
- bool readOnlyDepth, DrawOperationType drawOp,
- VkPipelineLayout pipelineLayout,
- VkPipelineVertexInputStateCreateInfo* vertexInputState)
- {
- mInputAssemblyInfo.topology = VulkanUtility::getDrawOp(drawOp);
- mTesselationInfo.patchControlPoints = 3; // Not provided by our shaders for now
- mMultiSampleInfo.rasterizationSamples = framebuffer->getSampleFlags();
- mColorBlendStateInfo.attachmentCount = framebuffer->getNumAttachments();
- const DepthStencilProperties dsProps = getDepthStencilState()->getProperties();
- bool enableDepthWrites = dsProps.getDepthWriteEnable() && !readOnlyDepth;
- mDepthStencilInfo.depthWriteEnable = enableDepthWrites; // If depth stencil attachment is read only, depthWriteEnable must be VK_FALSE
- // Save stencil ops as we might need to change them if depth/stencil is read-only
- VkStencilOp oldFrontPassOp = mDepthStencilInfo.front.passOp;
- VkStencilOp oldFrontFailOp = mDepthStencilInfo.front.failOp;
- VkStencilOp oldFrontZFailOp = mDepthStencilInfo.front.depthFailOp;
- VkStencilOp oldBackPassOp = mDepthStencilInfo.back.passOp;
- VkStencilOp oldBackFailOp = mDepthStencilInfo.back.failOp;
- VkStencilOp oldBackZFailOp = mDepthStencilInfo.back.depthFailOp;
- if(!enableDepthWrites)
- {
- // Disable any stencil writes
- mDepthStencilInfo.front.passOp = VK_STENCIL_OP_KEEP;
- mDepthStencilInfo.front.failOp = VK_STENCIL_OP_KEEP;
- mDepthStencilInfo.front.depthFailOp = VK_STENCIL_OP_KEEP;
- mDepthStencilInfo.back.passOp = VK_STENCIL_OP_KEEP;
- mDepthStencilInfo.back.failOp = VK_STENCIL_OP_KEEP;
- mDepthStencilInfo.back.depthFailOp = VK_STENCIL_OP_KEEP;
- }
- mPipelineInfo.renderPass = framebuffer->getRenderPass();
- mPipelineInfo.layout = pipelineLayout;
- mPipelineInfo.pVertexInputState = vertexInputState;
- if (framebuffer->hasDepthAttachment())
- mPipelineInfo.pDepthStencilState = &mDepthStencilInfo;
- else
- mPipelineInfo.pDepthStencilState = nullptr;
- if (framebuffer->getNumColorAttachments() > 0)
- mPipelineInfo.pColorBlendState = &mColorBlendStateInfo;
- else
- mPipelineInfo.pColorBlendState = nullptr;
- VkPipeline pipeline;
- VkResult result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &mPipelineInfo, gVulkanAllocator, &pipeline);
- assert(result != VK_SUCCESS);
- // Restore previous stencil op states
- mDepthStencilInfo.front.passOp = oldFrontPassOp;
- mDepthStencilInfo.front.failOp = oldFrontFailOp;
- mDepthStencilInfo.front.depthFailOp = oldFrontZFailOp;
- mDepthStencilInfo.back.passOp = oldBackPassOp;
- mDepthStencilInfo.back.failOp = oldBackFailOp;
- mDepthStencilInfo.back.depthFailOp = oldBackZFailOp;
- return pipeline;
- }
- }
|