Vulkan: Implement RenderPipeline

This commit is contained in:
Corentin Wallez 2018-01-09 10:50:07 -08:00 committed by Corentin Wallez
parent eb135f6fc0
commit 2b391dac74
12 changed files with 461 additions and 12 deletions

View File

@ -307,6 +307,10 @@ if (NXT_ENABLE_VULKAN)
${VULKAN_DIR}/PipelineLayoutVk.h ${VULKAN_DIR}/PipelineLayoutVk.h
${VULKAN_DIR}/RenderPassVk.cpp ${VULKAN_DIR}/RenderPassVk.cpp
${VULKAN_DIR}/RenderPassVk.h ${VULKAN_DIR}/RenderPassVk.h
${VULKAN_DIR}/RenderPipelineVk.cpp
${VULKAN_DIR}/RenderPipelineVk.h
${VULKAN_DIR}/ShaderModuleVk.cpp
${VULKAN_DIR}/ShaderModuleVk.h
${VULKAN_DIR}/TextureVk.cpp ${VULKAN_DIR}/TextureVk.cpp
${VULKAN_DIR}/TextureVk.h ${VULKAN_DIR}/TextureVk.h
${VULKAN_DIR}/VulkanBackend.cpp ${VULKAN_DIR}/VulkanBackend.cpp

View File

@ -15,7 +15,11 @@
#ifndef BACKEND_RENDERPIPELINE_H_ #ifndef BACKEND_RENDERPIPELINE_H_
#define BACKEND_RENDERPIPELINE_H_ #define BACKEND_RENDERPIPELINE_H_
#include "backend/BlendState.h"
#include "backend/DepthStencilState.h"
#include "backend/InputState.h"
#include "backend/Pipeline.h" #include "backend/Pipeline.h"
#include "backend/RenderPass.h"
#include "nxt/nxtcpp.h" #include "nxt/nxtcpp.h"

View File

@ -18,6 +18,7 @@
#include "backend/vulkan/BufferVk.h" #include "backend/vulkan/BufferVk.h"
#include "backend/vulkan/FramebufferVk.h" #include "backend/vulkan/FramebufferVk.h"
#include "backend/vulkan/RenderPassVk.h" #include "backend/vulkan/RenderPassVk.h"
#include "backend/vulkan/RenderPipelineVk.h"
#include "backend/vulkan/TextureVk.h" #include "backend/vulkan/TextureVk.h"
#include "backend/vulkan/VulkanBackend.h" #include "backend/vulkan/VulkanBackend.h"
@ -69,7 +70,6 @@ namespace backend { namespace vulkan {
Command type; Command type;
while (mCommands.NextCommandId(&type)) { while (mCommands.NextCommandId(&type)) {
switch (type) { switch (type) {
case Command::CopyBufferToBuffer: { case Command::CopyBufferToBuffer: {
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>(); CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
auto& src = copy->source; auto& src = copy->source;
@ -140,8 +140,40 @@ namespace backend { namespace vulkan {
beginInfo.clearValueCount = renderPass->GetAttachmentCount(); beginInfo.clearValueCount = renderPass->GetAttachmentCount();
beginInfo.pClearValues = clearValues.data(); beginInfo.pClearValues = clearValues.data();
device->fn.CmdBeginRenderPass(commands, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); device->fn.CmdBeginRenderPass(commands, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
// Set all the dynamic state just in case.
device->fn.CmdSetLineWidth(commands, 1.0f);
device->fn.CmdSetDepthBounds(commands, 0.0f, 1.0f);
float blendConstants[4] = {
1.0f,
1.0f,
1.0f,
1.0f,
};
device->fn.CmdSetBlendConstants(commands, blendConstants);
device->fn.CmdSetStencilCompareMask(commands, VK_STENCIL_FRONT_AND_BACK, 0);
device->fn.CmdSetStencilWriteMask(commands, VK_STENCIL_FRONT_AND_BACK, 0);
device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK, 0);
// The viewport and scissor default to cover all of the attachments
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(framebuffer->GetWidth());
viewport.height = static_cast<float>(framebuffer->GetHeight());
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
device->fn.CmdSetViewport(commands, 0, 1, &viewport);
VkRect2D scissorRect;
scissorRect.offset.x = 0;
scissorRect.offset.y = 0;
scissorRect.extent.width = framebuffer->GetWidth();
scissorRect.extent.height = framebuffer->GetHeight();
device->fn.CmdSetScissor(commands, 0, 1, &scissorRect);
} break; } break;
case Command::BeginRenderSubpass: { case Command::BeginRenderSubpass: {
@ -185,6 +217,14 @@ namespace backend { namespace vulkan {
VK_INDEX_TYPE_UINT16); VK_INDEX_TYPE_UINT16);
} break; } break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline->GetHandle());
} break;
case Command::SetVertexBuffers: { case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>(); SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count); auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);

View File

@ -27,8 +27,10 @@ namespace backend { namespace vulkan {
ASSERT(mImagesToDelete.Empty()); ASSERT(mImagesToDelete.Empty());
ASSERT(mImageViewsToDelete.Empty()); ASSERT(mImageViewsToDelete.Empty());
ASSERT(mMemoriesToDelete.Empty()); ASSERT(mMemoriesToDelete.Empty());
ASSERT(mPipelinesToDelete.Empty());
ASSERT(mPipelineLayoutsToDelete.Empty()); ASSERT(mPipelineLayoutsToDelete.Empty());
ASSERT(mRenderPassesToDelete.Empty()); ASSERT(mRenderPassesToDelete.Empty());
ASSERT(mShaderModulesToDelete.Empty());
} }
void FencedDeleter::DeleteWhenUnused(VkBuffer buffer) { void FencedDeleter::DeleteWhenUnused(VkBuffer buffer) {
@ -51,6 +53,10 @@ namespace backend { namespace vulkan {
mImageViewsToDelete.Enqueue(view, mDevice->GetSerial()); mImageViewsToDelete.Enqueue(view, mDevice->GetSerial());
} }
void FencedDeleter::DeleteWhenUnused(VkPipeline pipeline) {
mPipelinesToDelete.Enqueue(pipeline, mDevice->GetSerial());
}
void FencedDeleter::DeleteWhenUnused(VkPipelineLayout layout) { void FencedDeleter::DeleteWhenUnused(VkPipelineLayout layout) {
mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetSerial()); mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetSerial());
} }
@ -59,6 +65,10 @@ namespace backend { namespace vulkan {
mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetSerial()); mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetSerial());
} }
void FencedDeleter::DeleteWhenUnused(VkShaderModule module) {
mShaderModulesToDelete.Enqueue(module, mDevice->GetSerial());
}
void FencedDeleter::Tick(Serial completedSerial) { void FencedDeleter::Tick(Serial completedSerial) {
VkDevice vkDevice = mDevice->GetVkDevice(); VkDevice vkDevice = mDevice->GetVkDevice();
@ -98,6 +108,15 @@ namespace backend { namespace vulkan {
} }
mImageViewsToDelete.ClearUpTo(completedSerial); mImageViewsToDelete.ClearUpTo(completedSerial);
for (VkShaderModule module : mShaderModulesToDelete.IterateUpTo(completedSerial)) {
mDevice->fn.DestroyShaderModule(vkDevice, module, nullptr);
}
mShaderModulesToDelete.ClearUpTo(completedSerial);
for (VkPipeline pipeline : mPipelinesToDelete.IterateUpTo(completedSerial)) {
mDevice->fn.DestroyPipeline(vkDevice, pipeline, nullptr);
}
mPipelinesToDelete.ClearUpTo(completedSerial);
} }
}} // namespace backend::vulkan }} // namespace backend::vulkan

View File

@ -34,6 +34,8 @@ namespace backend { namespace vulkan {
void DeleteWhenUnused(VkImageView view); void DeleteWhenUnused(VkImageView view);
void DeleteWhenUnused(VkPipelineLayout layout); void DeleteWhenUnused(VkPipelineLayout layout);
void DeleteWhenUnused(VkRenderPass renderPass); void DeleteWhenUnused(VkRenderPass renderPass);
void DeleteWhenUnused(VkPipeline pipeline);
void DeleteWhenUnused(VkShaderModule module);
void Tick(Serial completedSerial); void Tick(Serial completedSerial);
@ -44,8 +46,10 @@ namespace backend { namespace vulkan {
SerialQueue<VkDeviceMemory> mMemoriesToDelete; SerialQueue<VkDeviceMemory> mMemoriesToDelete;
SerialQueue<VkImage> mImagesToDelete; SerialQueue<VkImage> mImagesToDelete;
SerialQueue<VkImageView> mImageViewsToDelete; SerialQueue<VkImageView> mImageViewsToDelete;
SerialQueue<VkPipeline> mPipelinesToDelete;
SerialQueue<VkPipelineLayout> mPipelineLayoutsToDelete; SerialQueue<VkPipelineLayout> mPipelineLayoutsToDelete;
SerialQueue<VkRenderPass> mRenderPassesToDelete; SerialQueue<VkRenderPass> mRenderPassesToDelete;
SerialQueue<VkShaderModule> mShaderModulesToDelete;
}; };
}} // namespace backend::vulkan }} // namespace backend::vulkan

View File

@ -18,5 +18,7 @@
#include "backend/vulkan/InputStateVk.h" #include "backend/vulkan/InputStateVk.h"
#include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/PipelineLayoutVk.h"
#include "backend/vulkan/RenderPassVk.h" #include "backend/vulkan/RenderPassVk.h"
#include "backend/vulkan/RenderPipelineVk.h"
#include "backend/vulkan/ShaderModuleVk.h"
#include "backend/vulkan/TextureVk.h" #include "backend/vulkan/TextureVk.h"
#include "backend/vulkan/VulkanBackend.h" #include "backend/vulkan/VulkanBackend.h"

View File

@ -0,0 +1,244 @@
// Copyright 2018 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "backend/vulkan/RenderPipelineVk.h"
#include "backend/vulkan/FencedDeleter.h"
#include "backend/vulkan/InputStateVk.h"
#include "backend/vulkan/PipelineLayoutVk.h"
#include "backend/vulkan/RenderPassVk.h"
#include "backend/vulkan/ShaderModuleVk.h"
#include "backend/vulkan/VulkanBackend.h"
namespace backend { namespace vulkan {
namespace {
VkPrimitiveTopology VulkanPrimitiveTopology(nxt::PrimitiveTopology topology) {
switch (topology) {
case nxt::PrimitiveTopology::PointList:
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case nxt::PrimitiveTopology::LineList:
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
case nxt::PrimitiveTopology::LineStrip:
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case nxt::PrimitiveTopology::TriangleList:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case nxt::PrimitiveTopology::TriangleStrip:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
default:
UNREACHABLE();
}
}
} // anonymous namespace
RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
: RenderPipelineBase(builder), mDevice(ToBackend(builder->GetDevice())) {
// Eventually a bunch of the structures that need to be chained in the create info will be
// held by objects such as the BlendState. They aren't implemented yet so we initialize
// everything here.
VkPipelineShaderStageCreateInfo shaderStages[2];
{
const auto& vertexStageInfo = builder->GetStageInfo(nxt::ShaderStage::Vertex);
const auto& fragmentStageInfo = builder->GetStageInfo(nxt::ShaderStage::Fragment);
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].pNext = nullptr;
shaderStages[0].flags = 0;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = ToBackend(vertexStageInfo.module)->GetHandle();
shaderStages[0].pName = vertexStageInfo.entryPoint.c_str();
shaderStages[0].pSpecializationInfo = nullptr;
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].pNext = nullptr;
shaderStages[1].flags = 0;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = ToBackend(fragmentStageInfo.module)->GetHandle();
shaderStages[1].pName = fragmentStageInfo.entryPoint.c_str();
shaderStages[1].pSpecializationInfo = nullptr;
}
VkPipelineInputAssemblyStateCreateInfo inputAssembly;
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.pNext = nullptr;
inputAssembly.flags = 0;
inputAssembly.topology = VulkanPrimitiveTopology(GetPrimitiveTopology());
// Primitive restart is always enabled in NXT (because of Metal)
inputAssembly.primitiveRestartEnable = VK_TRUE;
// A dummy viewport/scissor info. The validation layers force use to provide at least one
// scissor and one viewport here, even if we choose to make them dynamic.
VkViewport viewportDesc;
viewportDesc.x = 0.0f;
viewportDesc.y = 0.0f;
viewportDesc.width = 1.0f;
viewportDesc.height = 1.0f;
viewportDesc.minDepth = 0.0f;
viewportDesc.maxDepth = 1.0f;
VkRect2D scissorRect;
scissorRect.offset.x = 0;
scissorRect.offset.y = 0;
scissorRect.extent.width = 1;
scissorRect.extent.height = 1;
VkPipelineViewportStateCreateInfo viewport;
viewport.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport.pNext = nullptr;
viewport.flags = 0;
viewport.viewportCount = 1;
viewport.pViewports = &viewportDesc;
viewport.scissorCount = 1;
viewport.pScissors = &scissorRect;
VkPipelineRasterizationStateCreateInfo rasterization;
rasterization.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterization.pNext = nullptr;
rasterization.flags = 0;
rasterization.depthClampEnable = VK_FALSE;
rasterization.rasterizerDiscardEnable = VK_FALSE;
rasterization.polygonMode = VK_POLYGON_MODE_FILL;
rasterization.cullMode = VK_CULL_MODE_NONE;
rasterization.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterization.depthBiasEnable = VK_FALSE;
rasterization.depthBiasConstantFactor = 0.0f;
rasterization.depthBiasClamp = 0.0f;
rasterization.depthBiasSlopeFactor = 0.0f;
rasterization.lineWidth = 1.0f;
VkPipelineMultisampleStateCreateInfo multisample;
multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisample.pNext = nullptr;
multisample.flags = 0;
multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisample.sampleShadingEnable = VK_FALSE;
multisample.minSampleShading = 0.0f;
multisample.pSampleMask = nullptr;
multisample.alphaToCoverageEnable = VK_FALSE;
multisample.alphaToOneEnable = VK_FALSE;
VkPipelineDepthStencilStateCreateInfo depthStencil;
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.pNext = nullptr;
depthStencil.flags = 0;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front.failOp = VK_STENCIL_OP_KEEP;
depthStencil.front.passOp = VK_STENCIL_OP_KEEP;
depthStencil.front.depthFailOp = VK_STENCIL_OP_KEEP;
depthStencil.front.compareOp = VK_COMPARE_OP_NEVER;
depthStencil.front.compareMask = 0;
depthStencil.front.writeMask = 0;
depthStencil.front.reference = 0;
depthStencil.back.failOp = VK_STENCIL_OP_KEEP;
depthStencil.back.passOp = VK_STENCIL_OP_KEEP;
depthStencil.back.depthFailOp = VK_STENCIL_OP_KEEP;
depthStencil.back.compareOp = VK_COMPARE_OP_NEVER;
depthStencil.back.compareMask = 0;
depthStencil.back.writeMask = 0;
depthStencil.back.reference = 0;
depthStencil.minDepthBounds = 0.0f;
depthStencil.maxDepthBounds = 0.0f;
// Even when not using independent blend, we need to provide blend information for every
// single attachment.
std::array<VkPipelineColorBlendAttachmentState, kMaxColorAttachments> colorBlendAttachments;
for (auto& attachment : colorBlendAttachments) {
attachment.blendEnable = VK_FALSE;
attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.colorBlendOp = VK_BLEND_OP_ADD;
attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
attachment.alphaBlendOp = VK_BLEND_OP_ADD;
attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
}
VkPipelineColorBlendStateCreateInfo colorBlend;
colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlend.pNext = nullptr;
colorBlend.flags = 0;
colorBlend.logicOpEnable = VK_FALSE;
colorBlend.logicOp = VK_LOGIC_OP_CLEAR;
colorBlend.attachmentCount = kMaxColorAttachments;
colorBlend.pAttachments = colorBlendAttachments.data();
colorBlend.blendConstants[0] = 0.0f;
colorBlend.blendConstants[1] = 0.0f;
colorBlend.blendConstants[2] = 0.0f;
colorBlend.blendConstants[3] = 0.0f;
// Tag all state as dynamic.
VkDynamicState dynamicStates[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_DEPTH_BOUNDS,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
};
VkPipelineDynamicStateCreateInfo dynamic;
dynamic.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic.pNext = nullptr;
dynamic.flags = 0;
dynamic.dynamicStateCount = sizeof(dynamicStates) / sizeof(dynamicStates[0]);
dynamic.pDynamicStates = dynamicStates;
// The create info chains in a bunch of things created on the stack here or inside state
// objects.
VkGraphicsPipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.stageCount = 2;
createInfo.pStages = shaderStages;
createInfo.pVertexInputState = ToBackend(GetInputState())->GetCreateInfo();
createInfo.pInputAssemblyState = &inputAssembly;
createInfo.pTessellationState = nullptr;
createInfo.pViewportState = &viewport;
createInfo.pRasterizationState = &rasterization;
createInfo.pMultisampleState = &multisample;
createInfo.pDepthStencilState = &depthStencil;
createInfo.pColorBlendState = &colorBlend;
createInfo.pDynamicState = &dynamic;
createInfo.layout = ToBackend(GetLayout())->GetHandle();
createInfo.renderPass = ToBackend(GetRenderPass())->GetHandle();
createInfo.subpass = GetSubPass();
createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = -1;
if (mDevice->fn.CreateGraphicsPipelines(mDevice->GetVkDevice(), VK_NULL_HANDLE, 1,
&createInfo, nullptr, &mHandle) != VK_SUCCESS) {
ASSERT(false);
}
}
RenderPipeline::~RenderPipeline() {
if (mHandle != VK_NULL_HANDLE) {
mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle);
mHandle = VK_NULL_HANDLE;
}
}
VkPipeline RenderPipeline::GetHandle() const {
return mHandle;
}
}} // namespace backend::vulkan

View File

@ -0,0 +1,40 @@
// Copyright 2018 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BACKEND_VULKAN_RENDERPIPELINEVK_H_
#define BACKEND_VULKAN_RENDERPIPELINEVK_H_
#include "backend/RenderPipeline.h"
#include "backend/vulkan/vulkan_platform.h"
namespace backend { namespace vulkan {
class Device;
class RenderPipeline : public RenderPipelineBase {
public:
RenderPipeline(RenderPipelineBuilder* builder);
~RenderPipeline();
VkPipeline GetHandle() const;
private:
VkPipeline mHandle = VK_NULL_HANDLE;
Device* mDevice = nullptr;
};
}} // namespace backend::vulkan
#endif // BACKEND_VULKAN_RENDERPIPELINEVK_H_

View File

@ -0,0 +1,60 @@
// Copyright 2018 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "backend/vulkan/ShaderModuleVk.h"
#include "backend/vulkan/FencedDeleter.h"
#include "backend/vulkan/VulkanBackend.h"
#include <spirv-cross/spirv_cross.hpp>
namespace backend { namespace vulkan {
ShaderModule::ShaderModule(ShaderModuleBuilder* builder) : ShaderModuleBase(builder) {
std::vector<uint32_t> spirv = builder->AcquireSpirv();
// Use SPIRV-Cross to extract info from the SPIRV even if Vulkan consumes SPIRV. We want to
// have a translation step eventually anyway.
spirv_cross::Compiler compiler(spirv);
ExtractSpirvInfo(compiler);
VkShaderModuleCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.codeSize = spirv.size() * sizeof(uint32_t);
createInfo.pCode = spirv.data();
Device* device = ToBackend(GetDevice());
if (device->fn.CreateShaderModule(device->GetVkDevice(), &createInfo, nullptr, &mHandle) !=
VK_SUCCESS) {
ASSERT(false);
}
}
ShaderModule::~ShaderModule() {
Device* device = ToBackend(GetDevice());
if (mHandle != VK_NULL_HANDLE) {
device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
mHandle = VK_NULL_HANDLE;
}
}
VkShaderModule ShaderModule::GetHandle() const {
return mHandle;
}
}} // namespace backend::vulkan

View File

@ -0,0 +1,37 @@
// Copyright 2018 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BACKEND_VULKAN_SHADERMODULEVK_H_
#define BACKEND_VULKAN_SHADERMODULEVK_H_
#include "backend/ShaderModule.h"
#include "backend/vulkan/vulkan_platform.h"
namespace backend { namespace vulkan {
class ShaderModule : public ShaderModuleBase {
public:
ShaderModule(ShaderModuleBuilder* builder);
~ShaderModule();
VkShaderModule GetHandle() const;
private:
VkShaderModule mHandle = VK_NULL_HANDLE;
};
}} // namespace backend::vulkan
#endif // BACKEND_VULKAN_SHADERMODULEVK_H_

View File

@ -23,6 +23,8 @@
#include "backend/vulkan/InputStateVk.h" #include "backend/vulkan/InputStateVk.h"
#include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/PipelineLayoutVk.h"
#include "backend/vulkan/RenderPassVk.h" #include "backend/vulkan/RenderPassVk.h"
#include "backend/vulkan/RenderPipelineVk.h"
#include "backend/vulkan/ShaderModuleVk.h"
#include "backend/vulkan/TextureVk.h" #include "backend/vulkan/TextureVk.h"
#include "common/Platform.h" #include "common/Platform.h"
@ -223,12 +225,7 @@ namespace backend { namespace vulkan {
return new Sampler(builder); return new Sampler(builder);
} }
ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) {
auto module = new ShaderModule(builder); return new ShaderModule(builder);
spirv_cross::Compiler compiler(builder->AcquireSpirv());
module->ExtractSpirvInfo(compiler);
return module;
} }
SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) { SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) {
return new SwapChain(builder); return new SwapChain(builder);

View File

@ -24,9 +24,7 @@
#include "backend/DepthStencilState.h" #include "backend/DepthStencilState.h"
#include "backend/Device.h" #include "backend/Device.h"
#include "backend/Queue.h" #include "backend/Queue.h"
#include "backend/RenderPipeline.h"
#include "backend/Sampler.h" #include "backend/Sampler.h"
#include "backend/ShaderModule.h"
#include "backend/SwapChain.h" #include "backend/SwapChain.h"
#include "backend/ToBackend.h" #include "backend/ToBackend.h"
#include "backend/vulkan/VulkanFunctions.h" #include "backend/vulkan/VulkanFunctions.h"
@ -53,9 +51,9 @@ namespace backend { namespace vulkan {
class PipelineLayout; class PipelineLayout;
class Queue; class Queue;
class RenderPass; class RenderPass;
using RenderPipeline = RenderPipelineBase; class RenderPipeline;
using Sampler = SamplerBase; using Sampler = SamplerBase;
using ShaderModule = ShaderModuleBase; class ShaderModule;
class SwapChain; class SwapChain;
class Texture; class Texture;
class TextureView; class TextureView;