2015-10-10 16:41:19 +02:00
|
|
|
#include <cstring>
|
|
|
|
|
2017-08-18 13:39:42 +02:00
|
|
|
#include "profiler/profiler.h"
|
|
|
|
|
2015-10-10 16:41:19 +02:00
|
|
|
#include "Common/Log.h"
|
2016-01-09 21:19:18 +01:00
|
|
|
#include "Common/StringUtils.h"
|
2016-02-21 20:21:24 +01:00
|
|
|
#include "Common/Vulkan/VulkanContext.h"
|
2015-10-10 16:41:19 +02:00
|
|
|
#include "GPU/Vulkan/VulkanUtil.h"
|
|
|
|
#include "GPU/Vulkan/PipelineManagerVulkan.h"
|
2016-01-24 17:30:26 +01:00
|
|
|
#include "GPU/Vulkan/ShaderManagerVulkan.h"
|
2016-01-03 18:31:03 +01:00
|
|
|
|
2017-08-20 11:30:19 +02:00
|
|
|
PipelineManagerVulkan::PipelineManagerVulkan(VulkanContext *vulkan) : vulkan_(vulkan), pipelines_(256) {
|
2016-01-03 18:31:03 +01:00
|
|
|
pipelineCache_ = vulkan->CreatePipelineCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
PipelineManagerVulkan::~PipelineManagerVulkan() {
|
2016-01-10 14:24:10 +01:00
|
|
|
Clear();
|
2016-10-09 12:16:42 -07:00
|
|
|
if (pipelineCache_ != VK_NULL_HANDLE)
|
|
|
|
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
|
2016-01-10 14:24:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void PipelineManagerVulkan::Clear() {
|
2016-01-09 01:23:32 +01:00
|
|
|
// This should kill off all the shaders at once.
|
|
|
|
// This could also be an opportunity to store the whole cache to disk. Will need to also
|
|
|
|
// store the keys.
|
2017-08-20 11:30:19 +02:00
|
|
|
|
|
|
|
pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) {
|
|
|
|
vulkan_->Delete().QueueDeletePipeline(value->pipeline);
|
|
|
|
delete value;
|
|
|
|
});
|
|
|
|
|
|
|
|
pipelines_.Clear();
|
2016-01-03 18:31:03 +01:00
|
|
|
}
|
2015-10-10 16:41:19 +02:00
|
|
|
|
2016-10-09 11:17:03 -07:00
|
|
|
void PipelineManagerVulkan::DeviceLost() {
|
|
|
|
Clear();
|
2016-10-09 11:39:09 -07:00
|
|
|
if (pipelineCache_ != VK_NULL_HANDLE)
|
|
|
|
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
|
2016-10-09 11:17:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void PipelineManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
|
|
|
|
vulkan_ = vulkan;
|
|
|
|
pipelineCache_ = vulkan->CreatePipelineCache();
|
|
|
|
}
|
|
|
|
|
2015-10-10 16:41:19 +02:00
|
|
|
struct DeclTypeInfo {
|
|
|
|
VkFormat type;
|
2016-02-21 18:05:01 +01:00
|
|
|
const char *name;
|
2015-10-10 16:41:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const DeclTypeInfo VComp[] = {
|
|
|
|
{ VK_FORMAT_UNDEFINED, "NULL" }, // DEC_NONE,
|
|
|
|
{ VK_FORMAT_R32_SFLOAT, "R32_SFLOAT " }, // DEC_FLOAT_1,
|
|
|
|
{ VK_FORMAT_R32G32_SFLOAT, "R32G32_SFLOAT " }, // DEC_FLOAT_2,
|
|
|
|
{ VK_FORMAT_R32G32B32_SFLOAT, "R32G32B32_SFLOAT " }, // DEC_FLOAT_3,
|
|
|
|
{ VK_FORMAT_R32G32B32A32_SFLOAT, "R32G32B32A32_SFLOAT " }, // DEC_FLOAT_4,
|
|
|
|
|
2016-01-09 23:27:53 +01:00
|
|
|
{ VK_FORMAT_R8G8B8A8_SNORM, "R8G8B8A8_SNORM" }, // DEC_S8_3,
|
2015-10-10 16:41:19 +02:00
|
|
|
{ VK_FORMAT_R16G16B16A16_SNORM, "R16G16B16A16_SNORM " }, // DEC_S16_3,
|
2016-01-09 13:31:36 +01:00
|
|
|
|
|
|
|
{ VK_FORMAT_R8G8B8A8_UNORM, "R8G8B8A8_UNORM " }, // DEC_U8_1,
|
|
|
|
{ VK_FORMAT_R8G8B8A8_UNORM, "R8G8B8A8_UNORM " }, // DEC_U8_2,
|
|
|
|
{ VK_FORMAT_R8G8B8A8_UNORM, "R8G8B8A8_UNORM " }, // DEC_U8_3,
|
|
|
|
{ VK_FORMAT_R8G8B8A8_UNORM, "R8G8B8A8_UNORM " }, // DEC_U8_4,
|
2015-10-10 16:41:19 +02:00
|
|
|
{ VK_FORMAT_R16G16_UNORM, "R16G16_UNORM" }, // DEC_U16_1,
|
|
|
|
{ VK_FORMAT_R16G16_UNORM, "R16G16_UNORM" }, // DEC_U16_2,
|
|
|
|
{ VK_FORMAT_R16G16B16A16_UNORM, "R16G16B16A16_UNORM " }, // DEC_U16_3,
|
|
|
|
{ VK_FORMAT_R16G16B16A16_UNORM, "R16G16B16A16_UNORM " }, // DEC_U16_4,
|
2016-03-20 14:33:37 +01:00
|
|
|
|
2016-01-09 23:27:53 +01:00
|
|
|
{ VK_FORMAT_R8G8_UINT, "R8G8_UINT" }, // DEC_U8A_2,
|
|
|
|
{ VK_FORMAT_R16G16_UINT, "R16G16_UINT" }, // DEC_U16A_2,
|
2015-10-10 16:41:19 +02:00
|
|
|
};
|
|
|
|
|
2016-03-28 22:14:04 +02:00
|
|
|
static void VertexAttribSetup(VkVertexInputAttributeDescription *attr, int fmt, int offset, PspAttributeLocation location) {
|
2015-10-10 16:41:19 +02:00
|
|
|
attr->location = (uint32_t)location;
|
|
|
|
attr->binding = 0;
|
|
|
|
attr->format = VComp[fmt].type;
|
|
|
|
attr->offset = offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the number of attributes that were set.
|
|
|
|
// We could cache these AttributeDescription arrays (with pspFmt as the key), but hardly worth bothering
|
|
|
|
// as we will only call this code when we need to create a new VkPipeline.
|
2016-03-28 22:14:04 +02:00
|
|
|
static int SetupVertexAttribs(VkVertexInputAttributeDescription attrs[], const DecVtxFormat &decFmt) {
|
2015-10-10 16:41:19 +02:00
|
|
|
int count = 0;
|
|
|
|
if (decFmt.w0fmt != 0) {
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.w0fmt, decFmt.w0off, PspAttributeLocation::W1);
|
|
|
|
}
|
|
|
|
if (decFmt.w1fmt != 0) {
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.w1fmt, decFmt.w1off, PspAttributeLocation::W2);
|
|
|
|
}
|
|
|
|
if (decFmt.uvfmt != 0) {
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.uvfmt, decFmt.uvoff, PspAttributeLocation::TEXCOORD);
|
|
|
|
}
|
|
|
|
if (decFmt.c0fmt != 0) {
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.c0fmt, decFmt.c0off, PspAttributeLocation::COLOR0);
|
|
|
|
}
|
|
|
|
if (decFmt.c1fmt != 0) {
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.c1fmt, decFmt.c1off, PspAttributeLocation::COLOR1);
|
|
|
|
}
|
|
|
|
if (decFmt.nrmfmt != 0) {
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.nrmfmt, decFmt.nrmoff, PspAttributeLocation::NORMAL);
|
|
|
|
}
|
|
|
|
// Position is always there.
|
|
|
|
VertexAttribSetup(&attrs[count++], decFmt.posfmt, decFmt.posoff, PspAttributeLocation::POSITION);
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2016-03-28 22:14:04 +02:00
|
|
|
static int SetupVertexAttribsPretransformed(VkVertexInputAttributeDescription attrs[], const DecVtxFormat &decFmt) {
|
2016-03-06 12:00:57 +01:00
|
|
|
int count = 0;
|
|
|
|
VertexAttribSetup(&attrs[count++], DEC_FLOAT_4, 0, PspAttributeLocation::POSITION);
|
|
|
|
VertexAttribSetup(&attrs[count++], DEC_FLOAT_3, 16, PspAttributeLocation::TEXCOORD);
|
|
|
|
VertexAttribSetup(&attrs[count++], DEC_U8_4, 28, PspAttributeLocation::COLOR0);
|
|
|
|
VertexAttribSetup(&attrs[count++], DEC_U8_4, 32, PspAttributeLocation::COLOR1);
|
|
|
|
return count;
|
2015-10-10 16:41:19 +02:00
|
|
|
}
|
|
|
|
|
2016-04-02 11:06:39 +02:00
|
|
|
static bool UsesBlendConstant(int factor) {
|
|
|
|
return factor == VK_BLEND_FACTOR_CONSTANT_ALPHA || factor == VK_BLEND_FACTOR_CONSTANT_COLOR;
|
|
|
|
}
|
|
|
|
|
2016-03-20 16:33:34 +01:00
|
|
|
static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pipelineCache,
|
|
|
|
VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &key,
|
|
|
|
const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
|
2017-10-20 18:09:05 +02:00
|
|
|
bool useBlendConstant = false;
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineColorBlendAttachmentState blend0 = {};
|
2015-10-10 16:41:19 +02:00
|
|
|
blend0.blendEnable = key.blendEnable;
|
|
|
|
if (key.blendEnable) {
|
2016-01-09 01:23:32 +01:00
|
|
|
blend0.colorBlendOp = (VkBlendOp)key.blendOpColor;
|
|
|
|
blend0.alphaBlendOp = (VkBlendOp)key.blendOpAlpha;
|
|
|
|
blend0.srcColorBlendFactor = (VkBlendFactor)key.srcColor;
|
|
|
|
blend0.srcAlphaBlendFactor = (VkBlendFactor)key.srcAlpha;
|
|
|
|
blend0.dstColorBlendFactor = (VkBlendFactor)key.destColor;
|
|
|
|
blend0.dstAlphaBlendFactor = (VkBlendFactor)key.destAlpha;
|
2015-10-10 16:41:19 +02:00
|
|
|
}
|
|
|
|
blend0.colorWriteMask = key.colorWriteMask;
|
2016-03-14 00:53:57 +01:00
|
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo cbs = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
|
2016-01-09 01:23:32 +01:00
|
|
|
cbs.flags = 0;
|
2015-10-10 16:41:19 +02:00
|
|
|
cbs.pAttachments = &blend0;
|
|
|
|
cbs.attachmentCount = 1;
|
|
|
|
cbs.logicOpEnable = key.logicOpEnable;
|
|
|
|
if (key.logicOpEnable)
|
2016-01-09 01:23:32 +01:00
|
|
|
cbs.logicOp = (VkLogicOp)key.logicOp;
|
2015-10-10 16:41:19 +02:00
|
|
|
else
|
|
|
|
cbs.logicOp = VK_LOGIC_OP_COPY;
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineDepthStencilStateCreateInfo dss = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
|
2015-10-10 16:41:19 +02:00
|
|
|
dss.depthBoundsTestEnable = false;
|
|
|
|
dss.stencilTestEnable = key.stencilTestEnable;
|
|
|
|
if (key.stencilTestEnable) {
|
2016-01-09 01:23:32 +01:00
|
|
|
dss.front.compareOp = (VkCompareOp)key.stencilCompareOp;
|
|
|
|
dss.front.passOp = (VkStencilOp)key.stencilPassOp;
|
|
|
|
dss.front.failOp = (VkStencilOp)key.stencilFailOp;
|
|
|
|
dss.front.depthFailOp = (VkStencilOp)key.stencilDepthFailOp;
|
2015-10-10 16:41:19 +02:00
|
|
|
// Back stencil is always the same as front on PSP.
|
|
|
|
memcpy(&dss.back, &dss.front, sizeof(dss.front));
|
|
|
|
}
|
|
|
|
dss.depthTestEnable = key.depthTestEnable;
|
|
|
|
if (key.depthTestEnable) {
|
2016-01-09 01:23:32 +01:00
|
|
|
dss.depthCompareOp = (VkCompareOp)key.depthCompareOp;
|
2015-10-10 16:41:19 +02:00
|
|
|
dss.depthWriteEnable = key.depthWriteEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkDynamicState dynamicStates[8];
|
|
|
|
int numDyn = 0;
|
2016-04-02 11:06:39 +02:00
|
|
|
if (key.blendEnable &&
|
|
|
|
(UsesBlendConstant(key.srcAlpha) || UsesBlendConstant(key.srcColor) || UsesBlendConstant(key.destAlpha) || UsesBlendConstant(key.destColor))) {
|
2015-10-10 16:41:19 +02:00
|
|
|
dynamicStates[numDyn++] = VK_DYNAMIC_STATE_BLEND_CONSTANTS;
|
2017-10-20 18:09:05 +02:00
|
|
|
useBlendConstant = true;
|
2015-10-10 16:41:19 +02:00
|
|
|
}
|
|
|
|
dynamicStates[numDyn++] = VK_DYNAMIC_STATE_SCISSOR;
|
|
|
|
dynamicStates[numDyn++] = VK_DYNAMIC_STATE_VIEWPORT;
|
|
|
|
if (key.stencilTestEnable) {
|
2016-03-26 19:43:42 -07:00
|
|
|
dynamicStates[numDyn++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
|
2015-10-10 16:41:19 +02:00
|
|
|
dynamicStates[numDyn++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
|
|
|
|
dynamicStates[numDyn++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
|
|
|
|
}
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineDynamicStateCreateInfo ds = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
2016-01-09 01:23:32 +01:00
|
|
|
ds.flags = 0;
|
2015-10-10 16:41:19 +02:00
|
|
|
ds.pDynamicStates = dynamicStates;
|
|
|
|
ds.dynamicStateCount = numDyn;
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineRasterizationStateCreateInfo rs = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
|
2016-01-09 01:23:32 +01:00
|
|
|
rs.flags = 0;
|
2015-10-10 16:41:19 +02:00
|
|
|
rs.depthBiasEnable = false;
|
|
|
|
rs.cullMode = key.cullMode;
|
|
|
|
rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
|
|
|
rs.lineWidth = 1.0f;
|
|
|
|
rs.rasterizerDiscardEnable = false;
|
|
|
|
rs.polygonMode = VK_POLYGON_MODE_FILL;
|
|
|
|
rs.depthClampEnable = false;
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineMultisampleStateCreateInfo ms = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
2016-01-03 18:31:03 +01:00
|
|
|
ms.pSampleMask = nullptr;
|
|
|
|
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
2015-10-10 16:41:19 +02:00
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo ss[2];
|
2016-01-09 01:23:32 +01:00
|
|
|
ss[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
2015-10-10 16:41:19 +02:00
|
|
|
ss[0].pNext = nullptr;
|
|
|
|
ss[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
ss[0].pSpecializationInfo = nullptr;
|
2016-01-28 23:44:05 +01:00
|
|
|
ss[0].module = vs->GetModule();
|
2015-10-10 16:41:19 +02:00
|
|
|
ss[0].pName = "main";
|
|
|
|
ss[0].flags = 0;
|
2016-01-09 01:23:32 +01:00
|
|
|
ss[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
2015-10-10 16:41:19 +02:00
|
|
|
ss[1].pNext = nullptr;
|
|
|
|
ss[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
ss[1].pSpecializationInfo = nullptr;
|
2016-01-28 23:44:05 +01:00
|
|
|
ss[1].module = fs->GetModule();
|
2015-10-10 16:41:19 +02:00
|
|
|
ss[1].pName = "main";
|
|
|
|
ss[1].flags = 0;
|
2016-01-03 18:31:03 +01:00
|
|
|
|
2016-03-12 09:21:13 -08:00
|
|
|
if (!ss[0].module || !ss[1].module) {
|
|
|
|
ERROR_LOG(G3D, "Failed creating graphics pipeline - bad shaders");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineInputAssemblyStateCreateInfo inputAssembly = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
2016-01-09 01:23:32 +01:00
|
|
|
inputAssembly.flags = 0;
|
|
|
|
inputAssembly.topology = (VkPrimitiveTopology)key.topology;
|
2016-01-03 18:31:03 +01:00
|
|
|
inputAssembly.primitiveRestartEnable = false;
|
2015-10-10 16:41:19 +02:00
|
|
|
|
|
|
|
int vertexStride = 0;
|
|
|
|
|
|
|
|
int offset = 0;
|
|
|
|
VkVertexInputAttributeDescription attrs[8];
|
|
|
|
int attributeCount;
|
|
|
|
if (useHwTransform) {
|
2016-01-09 01:23:32 +01:00
|
|
|
attributeCount = SetupVertexAttribs(attrs, vtxDec->decFmt);
|
|
|
|
vertexStride = vtxDec->decFmt.stride;
|
2015-10-10 16:41:19 +02:00
|
|
|
} else {
|
2016-03-06 12:00:57 +01:00
|
|
|
attributeCount = SetupVertexAttribsPretransformed(attrs, vtxDec->decFmt);
|
2016-01-09 01:23:32 +01:00
|
|
|
vertexStride = 36;
|
2015-10-10 16:41:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription ibd;
|
|
|
|
ibd.binding = 0;
|
|
|
|
ibd.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
ibd.stride = vertexStride;
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineVertexInputStateCreateInfo vis = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
2016-01-09 01:23:32 +01:00
|
|
|
vis.flags = 0;
|
2015-10-10 16:41:19 +02:00
|
|
|
vis.vertexBindingDescriptionCount = 1;
|
|
|
|
vis.pVertexBindingDescriptions = &ibd;
|
|
|
|
vis.vertexAttributeDescriptionCount = attributeCount;
|
|
|
|
vis.pVertexAttributeDescriptions = attrs;
|
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkPipelineViewportStateCreateInfo views = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
2016-01-28 23:44:05 +01:00
|
|
|
views.flags = 0;
|
|
|
|
views.viewportCount = 1;
|
|
|
|
views.scissorCount = 1;
|
|
|
|
views.pViewports = nullptr; // dynamic
|
|
|
|
views.pScissors = nullptr; // dynamic
|
2016-01-03 18:31:03 +01:00
|
|
|
|
2016-03-14 00:53:57 +01:00
|
|
|
VkGraphicsPipelineCreateInfo pipe = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
2016-01-09 01:23:32 +01:00
|
|
|
pipe.flags = 0;
|
2016-01-03 18:31:03 +01:00
|
|
|
pipe.stageCount = 2;
|
|
|
|
pipe.pStages = ss;
|
|
|
|
pipe.basePipelineIndex = 0;
|
|
|
|
|
|
|
|
pipe.pColorBlendState = &cbs;
|
2016-03-20 14:33:37 +01:00
|
|
|
pipe.pDepthStencilState = &dss;
|
2016-01-03 18:31:03 +01:00
|
|
|
pipe.pRasterizationState = &rs;
|
|
|
|
|
|
|
|
// We will use dynamic viewport state.
|
2016-01-09 01:23:32 +01:00
|
|
|
pipe.pVertexInputState = &vis;
|
2016-01-28 23:44:05 +01:00
|
|
|
pipe.pViewportState = &views;
|
2016-01-09 01:23:32 +01:00
|
|
|
pipe.pTessellationState = nullptr;
|
2016-01-03 18:31:03 +01:00
|
|
|
pipe.pDynamicState = &ds;
|
|
|
|
pipe.pInputAssemblyState = &inputAssembly;
|
|
|
|
pipe.pMultisampleState = &ms;
|
2016-01-09 01:23:32 +01:00
|
|
|
pipe.layout = layout;
|
2016-02-21 18:05:01 +01:00
|
|
|
pipe.basePipelineHandle = VK_NULL_HANDLE;
|
2016-01-09 01:23:32 +01:00
|
|
|
pipe.basePipelineIndex = 0;
|
|
|
|
pipe.renderPass = renderPass;
|
|
|
|
pipe.subpass = 0;
|
2016-01-03 18:31:03 +01:00
|
|
|
|
2015-10-10 16:41:19 +02:00
|
|
|
VkPipeline pipeline;
|
|
|
|
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
ERROR_LOG(G3D, "Failed creating graphics pipeline!");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
VulkanPipeline *vulkanPipeline = new VulkanPipeline();
|
|
|
|
vulkanPipeline->pipeline = pipeline;
|
2016-01-09 01:23:32 +01:00
|
|
|
vulkanPipeline->uniformBlocks = UB_VS_FS_BASE;
|
2017-10-20 18:09:05 +02:00
|
|
|
vulkanPipeline->useBlendConstant = useBlendConstant;
|
2016-01-09 01:23:32 +01:00
|
|
|
if (useHwTransform) {
|
2016-03-20 16:33:34 +01:00
|
|
|
if (vs->HasLights()) {
|
|
|
|
vulkanPipeline->uniformBlocks |= UB_VS_LIGHTS;
|
|
|
|
}
|
|
|
|
if (vs->HasBones()) {
|
|
|
|
vulkanPipeline->uniformBlocks |= UB_VS_BONES;
|
|
|
|
}
|
2016-01-09 01:23:32 +01:00
|
|
|
}
|
2015-10-10 16:41:19 +02:00
|
|
|
return vulkanPipeline;
|
|
|
|
}
|
2016-01-09 01:23:32 +01:00
|
|
|
|
2017-05-19 17:21:08 +02:00
|
|
|
VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &rasterKey, const VertexDecoder *vtxDec, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform) {
|
2016-01-09 01:23:32 +01:00
|
|
|
VulkanPipelineKey key;
|
2017-05-22 14:48:20 +02:00
|
|
|
if (!renderPass)
|
|
|
|
Crash();
|
|
|
|
|
2016-01-09 01:23:32 +01:00
|
|
|
key.raster = rasterKey;
|
2017-05-19 17:21:08 +02:00
|
|
|
key.renderPass = renderPass;
|
2016-01-09 11:07:14 +01:00
|
|
|
key.useHWTransform = useHwTransform;
|
2016-01-24 17:30:26 +01:00
|
|
|
key.vShader = vs->GetModule();
|
|
|
|
key.fShader = fs->GetModule();
|
2016-03-20 14:33:37 +01:00
|
|
|
key.vtxDec = useHwTransform ? vtxDec : nullptr;
|
2017-08-20 11:30:19 +02:00
|
|
|
|
|
|
|
auto iter = pipelines_.Get(key);
|
|
|
|
if (iter)
|
|
|
|
return iter;
|
2017-08-18 13:39:42 +02:00
|
|
|
|
|
|
|
PROFILE_THIS_SCOPE("pipelinebuild");
|
|
|
|
|
2016-01-09 01:23:32 +01:00
|
|
|
VulkanPipeline *pipeline = CreateVulkanPipeline(
|
2017-05-19 17:21:08 +02:00
|
|
|
vulkan_->GetDevice(), pipelineCache_, layout, renderPass,
|
2016-01-28 23:44:05 +01:00
|
|
|
rasterKey, vtxDec, vs, fs, useHwTransform);
|
2017-08-20 11:30:19 +02:00
|
|
|
pipelines_.Insert(key, pipeline);
|
2016-01-09 01:23:32 +01:00
|
|
|
return pipeline;
|
|
|
|
}
|
2016-01-09 21:19:18 +01:00
|
|
|
|
|
|
|
std::vector<std::string> PipelineManagerVulkan::DebugGetObjectIDs(DebugShaderType type) {
|
|
|
|
std::vector<std::string> ids;
|
|
|
|
switch (type) {
|
|
|
|
case SHADER_TYPE_PIPELINE:
|
|
|
|
{
|
2017-08-20 11:30:19 +02:00
|
|
|
pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) {
|
|
|
|
std::string id;
|
|
|
|
key.ToString(&id);
|
2016-01-09 21:19:18 +01:00
|
|
|
ids.push_back(id);
|
2017-08-20 11:30:19 +02:00
|
|
|
});
|
2016-01-09 21:19:18 +01:00
|
|
|
}
|
|
|
|
break;
|
2016-02-21 18:05:01 +01:00
|
|
|
default:
|
|
|
|
break;
|
2016-01-09 21:19:18 +01:00
|
|
|
}
|
|
|
|
return ids;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string PipelineManagerVulkan::DebugGetObjectString(std::string id, DebugShaderType type, DebugShaderStringType stringType) {
|
|
|
|
if (type != SHADER_TYPE_PIPELINE)
|
|
|
|
return "N/A";
|
|
|
|
|
|
|
|
VulkanPipelineKey shaderId;
|
|
|
|
shaderId.FromString(id);
|
|
|
|
|
2017-08-20 11:30:19 +02:00
|
|
|
VulkanPipeline *iter = pipelines_.Get(shaderId);
|
|
|
|
if (!iter) {
|
2016-01-09 21:19:18 +01:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (stringType) {
|
|
|
|
case SHADER_STRING_SHORT_DESC:
|
|
|
|
{
|
2017-08-20 11:30:19 +02:00
|
|
|
return StringFromFormat("%p", iter);
|
2016-01-09 21:19:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case SHADER_STRING_SOURCE_CODE:
|
|
|
|
{
|
|
|
|
return "N/A";
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return "N/A";
|
|
|
|
}
|
|
|
|
}
|