748 lines
30 KiB
C++

// AMD AMDUtils code
//
// Copyright(c) 2018 Advanced Micro Devices, Inc.All rights reserved.
//
// Vulkan Samples
//
// Copyright (C) 2015-2016 Valve Corporation
// Copyright (C) 2015-2016 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gltfpbrvk.h"
#include "devicevk.h"
#include "dynamicbufferringvk.h"
#include "gltfcommon.h"
#include "gltfhelpers.h"
#include "gltfhelpers_vulkan.h"
#include "resourceviewheapsvk.h"
#include "shadercompilerhelper.h"
#include "threadpool.h"
#include "uploadheapvk.h"
#include <vector>
void GltfPbrVK::AddTextureIfExists(json::object_t material, json::array_t textures, std::map<std::string, Texture*>& map, char* texturePath, char* textureName) {
int id = GetElementInt(material, texturePath, -1);
if (id >= 0) {
int tex = textures[id]["source"];
map[textureName] = &m_textures[tex];
}
}
void GltfPbrVK::OnCreate(
DeviceVK* pDevice,
VkRenderPass renderPass,
UploadHeapVK* pUploadHeap,
ResourceViewHeapsVK *pHeaps,
DynamicBufferRingVK *pDynamicBufferRing,
StaticBufferPoolVK *pStaticBufferPool,
GLTFCommon *pGLTFData,
// SkyDome *pSkyDome,
Texture *pShadowMap,
void *pluginManager,
void *msghandler
) {
m_pDevice = pDevice;
m_pGLTFData = pGLTFData;
m_pDynamicBufferRing = pDynamicBufferRing;
m_pResourceViewHeaps = pHeaps;
m_pStaticBufferPool = pStaticBufferPool;
/*
// Load cubemaps maps for IBL
m_pCubeDiffuseTexture = pSkyDome->GetDiffuseCubeMap();
m_pCubeSpecularTexture = pSkyDome->GetSpecularCubeMap();
m_BrdfTexture.InitFromFile(pDevice, pUploadHeap, L"..\\media\\envmap\\brdf.dds");
pUploadHeap->FlushAndFinish();
*/
json &j3 = pGLTFData->j3;
// Load Textures
// ToDo - Change to use TextureIO in next release
auto images = j3["images"];
m_textures.resize(images.size());
for (unsigned int i = 0; i<images.size(); i++) {
std::string filename = images[i]["uri"];
INT32 result = m_textures[i].InitFromFile(pDevice, pUploadHeap, (pGLTFData->m_path + filename).c_str(), pluginManager, msghandler);
}
pUploadHeap->FlushAndFinish();
/////////////////////////////////////////////
// Create Sampler
{
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
VkResult res = vkCreateSampler(pDevice->GetDevice(), &info, NULL, &m_sampler);
assert(res == VK_SUCCESS);
}
// Load PBR 2.0 Materials
//
std::vector<PBRMaterial *> materialsData;
auto materials = j3["materials"];
auto textures = j3["textures"];
for (unsigned int i = 0; i < materials.size(); i++) {
json::object_t material = materials[i];
PBRMaterial *tfmat = new PBRMaterial();
materialsData.push_back(tfmat);
// Load material constants
//
json::array_t ones = { 1.0, 1.0, 1.0, 1.0 };
json::array_t zeroes = { 0.0, 0.0, 0.0, 0.0 };
tfmat->emissiveFactor = GetVector(GetElementJsonArray(material, "emissiveFactor", zeroes));
tfmat->baseColorFactor = GetVector(GetElementJsonArray(material, "pbrMetallicRoughness/baseColorFactor", ones));
tfmat->metallicFactor = GetElementFloat(material, "pbrMetallicRoughness/metallicFactor", 1.0);
tfmat->roughnessFactor = GetElementFloat(material, "pbrMetallicRoughness/roughnessFactor", 1.0);
tfmat->m_defines["DEF_alphaMode_" + GetElementString(material, "alphaMode", "OPAQUE")] = std::to_string(1);
tfmat->m_defines["DEF_alphaCutoff"] = std::to_string(GetElementFloat(material, "alphaCutoff", 1.0));
// load glTF 2.0 material's textures (if present) and create descriptor set
//
std::map<std::string, Texture *> texturesBase;
if (textures.size() > 0) {
AddTextureIfExists(material, textures, texturesBase, "pbrMetallicRoughness/baseColorTexture/index", "baseColorTexture");
AddTextureIfExists(material, textures, texturesBase, "pbrMetallicRoughness/metallicRoughnessTexture/index", "metallicRoughnessTexture");
AddTextureIfExists(material, textures, texturesBase, "emissiveTexture/index", "emissiveTexture");
AddTextureIfExists(material, textures, texturesBase, "normalTexture/index", "normalTexture");
AddTextureIfExists(material, textures, texturesBase, "occlusionTexture/index", "occlusionTexture");
}
tfmat->m_textureCount = (int)texturesBase.size();
/*
if (m_pCubeDiffuseTexture)
tfmat->m_textureCount += 1;
if (m_pCubeSpecularTexture)
tfmat->m_textureCount += 1;
//+ 1 brdf lookup texture, add that to the total count of textures used
tfmat->m_textureCount += 1;
*/
// plus shadows
if (pShadowMap != NULL)
tfmat->m_textureCount += 1;
if (tfmat->m_textureCount >= 0) {
std::vector<VkDescriptorSetLayoutBinding> layout_bindings(tfmat->m_textureCount);
int cnt = 0;
//create SRVs and #defines so the shader compiler knows what the index of each texture is
for (auto it = texturesBase.begin(); it != texturesBase.end(); it++) {
tfmat->m_defines[std::string("ID_") + it->first] = std::to_string(cnt);
layout_bindings[cnt].binding = cnt;
layout_bindings[cnt].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
layout_bindings[cnt].descriptorCount = 1;
layout_bindings[cnt].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
layout_bindings[cnt].pImmutableSamplers = NULL;
cnt++;
}
if (pShadowMap != NULL) {
tfmat->m_defines["ID_shadowMap"] = std::to_string(cnt);
layout_bindings[cnt].binding = cnt;
layout_bindings[cnt].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
layout_bindings[cnt].descriptorCount = 1;
layout_bindings[cnt].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
layout_bindings[cnt].pImmutableSamplers = NULL;
cnt++;
}
m_pResourceViewHeaps->AllocDescriptor(&layout_bindings, &tfmat->m_descriptorSetLayout, &tfmat->m_descriptorSet);
cnt = 0;
std::vector<VkWriteDescriptorSet> writes(tfmat->m_textureCount);
std::vector<VkDescriptorImageInfo> desc_image(tfmat->m_textureCount);
for (auto it = texturesBase.begin(); it != texturesBase.end(); it++) {
desc_image[cnt].sampler = m_sampler;
desc_image[cnt].imageView = VK_NULL_HANDLE;
desc_image[cnt].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
writes[cnt] = {};
writes[cnt].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[cnt].dstBinding = cnt;
writes[cnt].pNext = NULL;
writes[cnt].dstSet = tfmat->m_descriptorSet;
writes[cnt].descriptorCount = 1;
writes[cnt].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writes[cnt].pImageInfo = &desc_image[cnt];
writes[cnt].dstArrayElement = 0;
it->second->CreateSRV(0, &desc_image[cnt].imageView);
cnt++;
}
/*
//create SRVs and #defines for the IBL resources
if (m_pCubeDiffuseTexture)
{
tfmat->m_defines["ID_diffuseCube"] = std::to_string(cnt);
m_pCubeDiffuseTexture->CreateCubeSRV(cnt++, tfmat->m_pTexturesTable);
tfmat->m_defines["USE_IBL"] = "1";
}
if (m_pCubeSpecularTexture)
{
tfmat->m_defines["ID_specularCube"] = std::to_string(cnt);
m_pCubeSpecularTexture->CreateCubeSRV(cnt++, tfmat->m_pTexturesTable);
tfmat->m_defines["USE_IBL"] = "1";
}
tfmat->m_defines["ID_brdfTexture"] = std::to_string(cnt);
m_BrdfTexture.CreateSRV(cnt++, tfmat->m_pTexturesTable);
*/
// add SRV for the shadowmap
if (pShadowMap!=NULL) {
desc_image[cnt].sampler = m_sampler;
desc_image[cnt].imageView = VK_NULL_HANDLE;
desc_image[cnt].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
writes[cnt] = {};
writes[cnt].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[cnt].dstBinding = cnt;
writes[cnt].pNext = NULL;
writes[cnt].dstSet = tfmat->m_descriptorSet;
writes[cnt].descriptorCount = 1;
writes[cnt].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writes[cnt].pImageInfo = &desc_image[cnt];
writes[cnt].dstArrayElement = 0;
pShadowMap->CreateSRV(cnt, &desc_image[cnt].imageView);
cnt++;
}
vkUpdateDescriptorSets(m_pDevice->GetDevice(), (uint32_t)writes.size(), writes.data(), 0, NULL);
}
}
// Load Meshes
//
json::array_t accessors = j3["accessors"];
json::array_t bufferViews = j3["bufferViews"];
json::array_t meshes = j3["meshes"];
m_meshes.resize(meshes.size());
for (unsigned int i = 0; i < meshes.size(); i++) {
PBRMesh *tfmesh = &m_meshes[i];
auto primitives = meshes[i]["primitives"];
tfmesh->m_pPrimitives.resize(primitives.size());
for (unsigned int p = 0; p < primitives.size(); p++) {
PBRPrimitives *pPrimitive = &tfmesh->m_pPrimitives[p];
auto primitive = primitives[p];
// Set Material
//
pPrimitive->m_pMaterial = materialsData[primitive["material"]];
// Set Index buffer
//
tfAccessor indexBuffer;
{
auto indicesAccessor = accessors[primitive["indices"].get<int>()];
GetBufferDetails(indicesAccessor, bufferViews, pGLTFData->buffersData, &indexBuffer);
}
// Get input layout
//
std::vector<tfAccessor> vertexBuffers;
std::vector<std::string> semanticNames;
std::vector<VkVertexInputAttributeDescription> attributes; // std::vector<D3D12_INPUT_ELEMENT_DESC> layout;
auto attribute = primitive["attributes"];
attributes.resize(attribute.size()); // layout.reserve(attribute.size());
vertexBuffers.resize(attribute.size());
semanticNames.resize(attribute.size()); // vertexBuffers.resize(attribute.size());
int cnt = 0;
for (auto it = attribute.begin(); it != attribute.end(); it++) {
int index = cnt; // std::uint32_t semanticIndex = 0;
// Diff from DX12 code =====
if (it.key() == "TANGENT") {
index = (int)attributes.size() - 1;
cnt--;
}
//=================================
semanticNames[index] = it.key(); // semanticNames.push_back(semanticName);
auto accessor = accessors[it.value().get<int>()];
// Get VB accessors
//
//................................................................................Index -> layout.size()
GetBufferDetails(accessor, bufferViews, pGLTFData->buffersData, &vertexBuffers[index]);
// Code is specific to VK here -------------
// Create Input Layout
//
VkVertexInputAttributeDescription l;
l.location = (uint32_t)index;
l.format = GetFormat_Vulkan(accessor["type"], accessor["componentType"]);
l.offset = 0;
l.binding = index;
attributes[index] = l;
cnt++; // layout.push_back(l);
}
CreateGeometry(indexBuffer, vertexBuffers, pPrimitive);
//GetThreadPool()->Add_Job([=]()
//{
CreatePipeline(pDevice, renderPass, semanticNames, attributes, pPrimitive);
//});
}
}
}
void GltfPbrVK::OnDestroy() {
for (unsigned int i = 0; i < m_textures.size(); i++) {
m_textures[i].OnDestroy();
}
/*
m_BrdfTexture.OnDestroy();
*/
}
void GltfPbrVK::CreatePipeline(DeviceVK* pDevice, VkRenderPass renderPass, std::vector<std::string> semanticNames, std::vector<VkVertexInputAttributeDescription> layout, PBRPrimitives *pPrimitive) {
VkResult res;
// let vertex shader know what buffers are present
std::map<std::string, std::string> attributeDefines;
for (unsigned int i = 0; i < semanticNames.size(); i++) {
attributeDefines[std::string("ID_") + semanticNames[i]] = std::to_string(layout[i].binding);
}
if (attributeDefines.find("ID_TANGENT")!= attributeDefines.end()) {
attributeDefines[std::string("ID_WORLDPOS")] = std::to_string(semanticNames.size() + 2);
} else {
attributeDefines[std::string("ID_WORLDPOS")] = std::to_string(semanticNames.size());
}
std::map<std::string, std::string> *pMatDefines = &pPrimitive->m_pMaterial->m_defines;
for (auto it = pMatDefines->begin(); it != pMatDefines->end(); it++)
attributeDefines[it->first] = it->second;
/////////////////////////////////////////////
// Compile and create shaders
init_glslang();
VkPipelineShaderStageCreateInfo m_vertexShader;
res = VKCompileFromFile(pDevice->GetDevice(), SST_GLSL, VK_SHADER_STAGE_VERTEX_BIT, "./plugins/shaders/glTF20-vert_vk.glsl", "main", attributeDefines, &m_vertexShader);
//res = VKCompileFromFile(pDevice->GetDevice(), SST_HLSL, VK_SHADER_STAGE_VERTEX_BIT, "./plugins/shaders/glTF20_vk.hlsl", "mainVS", attributeDefines, &m_vertexShader);
assert(res == VK_SUCCESS);
VkPipelineShaderStageCreateInfo m_fragmentShader;
res = VKCompileFromFile(pDevice->GetDevice(), SST_GLSL, VK_SHADER_STAGE_FRAGMENT_BIT, "./plugins/shaders/glTF20-frag_vk.glsl", "main", attributeDefines, &m_fragmentShader);
assert(res == VK_SUCCESS);
finalize_glslang();
std::vector<VkPipelineShaderStageCreateInfo> shaderStages = { m_vertexShader, m_fragmentShader };
/////////////////////////////////////////////
// Create pipeline layout
std::vector<VkDescriptorSetLayoutBinding> layout_bindings(2);
layout_bindings[0].binding = 0;
layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
layout_bindings[0].descriptorCount = 1;
layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
layout_bindings[0].pImmutableSamplers = NULL;
layout_bindings[1].binding = 1;
layout_bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
layout_bindings[1].descriptorCount = 1;
layout_bindings[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
layout_bindings[1].pImmutableSamplers = NULL;
m_pResourceViewHeaps->AllocDescriptor(&layout_bindings, &pPrimitive->m_descriptorSetLayout, &pPrimitive->m_descriptorSet);
VkWriteDescriptorSet writes[2];
writes[0] = {};
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[0].pNext = NULL;
writes[0].dstSet = pPrimitive->m_descriptorSet;
writes[0].descriptorCount = 1;
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
writes[0].pBufferInfo = &m_pDynamicBufferRing->GetMainBuffer(sizeof(per_batch));
writes[0].dstArrayElement = 0;
writes[0].dstBinding = 0;
writes[1] = {};
writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[1].pNext = NULL;
writes[1].dstSet = pPrimitive->m_descriptorSet;
writes[1].descriptorCount = 1;
writes[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
writes[1].pBufferInfo = &m_pDynamicBufferRing->GetMainBuffer(sizeof(per_object));
writes[1].dstArrayElement = 0;
writes[1].dstBinding = 1;
vkUpdateDescriptorSets(m_pDevice->GetDevice(), 2, writes, 0, NULL);
std::vector<VkDescriptorSetLayout> descriptorSetLayout = { pPrimitive->m_descriptorSetLayout, pPrimitive->m_pMaterial->m_descriptorSetLayout };
/* Now use the descriptor layout to create a pipeline layout */
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {};
pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pPipelineLayoutCreateInfo.pNext = NULL;
pPipelineLayoutCreateInfo.pushConstantRangeCount = 0;
pPipelineLayoutCreateInfo.pPushConstantRanges = NULL;
pPipelineLayoutCreateInfo.setLayoutCount = (uint32_t)descriptorSetLayout.size();
pPipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayout.data();
res = vkCreatePipelineLayout(pDevice->GetDevice(), &pPipelineLayoutCreateInfo, NULL, &pPrimitive->m_pipelineLayout);
assert(res == VK_SUCCESS);
/////////////////////////////////////////////
// Create pipeline
// vertex input state
std::vector<VkVertexInputBindingDescription> vi_binding(layout.size());
for (unsigned int i = 0; i < layout.size(); i++) {
vi_binding[i].binding = layout[i].binding;
vi_binding[i].stride = SizeOfFormat_Vulkan(layout[i].format);
vi_binding[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
}
VkPipelineVertexInputStateCreateInfo vi = {};
vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vi.pNext = NULL;
vi.flags = 0;
vi.vertexBindingDescriptionCount = (uint32_t)vi_binding.size();
vi.pVertexBindingDescriptions = vi_binding.data();
vi.vertexAttributeDescriptionCount = (uint32_t)layout.size();
vi.pVertexAttributeDescriptions = layout.data();
// input assembly state
VkPipelineInputAssemblyStateCreateInfo ia;
ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
ia.pNext = NULL;
ia.flags = 0;
ia.primitiveRestartEnable = VK_FALSE;
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
// rasterizer state
VkPipelineRasterizationStateCreateInfo rs;
rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rs.pNext = NULL;
rs.flags = 0;
rs.polygonMode = VK_POLYGON_MODE_FILL;
rs.cullMode = VK_CULL_MODE_BACK_BIT;
rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rs.depthClampEnable = VK_FALSE;
rs.rasterizerDiscardEnable = VK_FALSE;
rs.depthBiasEnable = VK_FALSE;
rs.depthBiasConstantFactor = 0;
rs.depthBiasClamp = 0;
rs.depthBiasSlopeFactor = 0;
rs.lineWidth = 1.0f;
VkPipelineColorBlendAttachmentState att_state[1];
att_state[0].colorWriteMask = 0xf;
att_state[0].blendEnable = VK_TRUE;
att_state[0].alphaBlendOp = VK_BLEND_OP_ADD;
att_state[0].colorBlendOp = VK_BLEND_OP_ADD;
att_state[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
att_state[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
att_state[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
att_state[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
// Color blend state
VkPipelineColorBlendStateCreateInfo cb;
cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
cb.flags = 0;
cb.pNext = NULL;
cb.attachmentCount = 1;
cb.pAttachments = att_state;
cb.logicOpEnable = VK_FALSE;
cb.logicOp = VK_LOGIC_OP_NO_OP;
cb.blendConstants[0] = 1.0f;
cb.blendConstants[1] = 1.0f;
cb.blendConstants[2] = 1.0f;
cb.blendConstants[3] = 1.0f;
std::vector<VkDynamicState> dynamicStateEnables = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.pNext = NULL;
dynamicState.pDynamicStates = dynamicStateEnables.data();
dynamicState.dynamicStateCount = (uint32_t)dynamicStateEnables.size();
// view port state
VkPipelineViewportStateCreateInfo vp = {};
vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
vp.pNext = NULL;
vp.flags = 0;
vp.viewportCount = 1;
vp.scissorCount = 1;
vp.pScissors = NULL;
vp.pViewports = NULL;
// depth stencil state
VkPipelineDepthStencilStateCreateInfo ds;
ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
ds.pNext = NULL;
ds.flags = 0;
ds.depthTestEnable = true;
ds.depthWriteEnable = true;
ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
ds.depthBoundsTestEnable = VK_FALSE;
ds.stencilTestEnable = VK_FALSE;
ds.back.failOp = VK_STENCIL_OP_KEEP;
ds.back.passOp = VK_STENCIL_OP_KEEP;
ds.back.compareOp = VK_COMPARE_OP_ALWAYS;
ds.back.compareMask = 0;
ds.back.reference = 0;
ds.back.depthFailOp = VK_STENCIL_OP_KEEP;
ds.back.writeMask = 0;
ds.minDepthBounds = 0;
ds.maxDepthBounds = 0;
ds.stencilTestEnable = VK_FALSE;
ds.front = ds.back;
// multi sample state
VkPipelineMultisampleStateCreateInfo ms;
ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms.pNext = NULL;
ms.flags = 0;
ms.pSampleMask = NULL;
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
ms.sampleShadingEnable = VK_FALSE;
ms.alphaToCoverageEnable = VK_FALSE;
ms.alphaToOneEnable = VK_FALSE;
ms.minSampleShading = 0.0;
// create pipeline cache
VkPipelineCacheCreateInfo pipelineCache;
pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
pipelineCache.pNext = NULL;
pipelineCache.initialDataSize = 0;
pipelineCache.pInitialData = NULL;
pipelineCache.flags = 0;
res = vkCreatePipelineCache(pDevice->GetDevice(), &pipelineCache, NULL, &pPrimitive->m_pipelineCache);
assert(res == VK_SUCCESS);
// create pipeline
VkGraphicsPipelineCreateInfo pipeline = {};
pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline.pNext = NULL;
pipeline.layout = pPrimitive->m_pipelineLayout;
pipeline.basePipelineHandle = VK_NULL_HANDLE;
pipeline.basePipelineIndex = 0;
pipeline.flags = 0;
pipeline.pVertexInputState = &vi;
pipeline.pInputAssemblyState = &ia;
pipeline.pRasterizationState = &rs;
pipeline.pColorBlendState = &cb;
pipeline.pTessellationState = NULL;
pipeline.pMultisampleState = &ms;
pipeline.pDynamicState = &dynamicState;
pipeline.pViewportState = &vp;
pipeline.pDepthStencilState = &ds;
pipeline.pStages = shaderStages.data();
pipeline.stageCount = (uint32_t)shaderStages.size();
pipeline.renderPass = renderPass;
pipeline.subpass = 0;
res = vkCreateGraphicsPipelines(pDevice->GetDevice(), pPrimitive->m_pipelineCache, 1, &pipeline, NULL, &pPrimitive->m_pipeline);
assert(res == VK_SUCCESS);
/*
// create samplers if not initialized (this should happen once)
if (m_sampler.GetSize()==0)
{
m_pResourceViewHeaps->AllocSamplerDescriptor(5, &m_sampler);
//for pbr materials
D3D12_SAMPLER_DESC SamplerDesc;
ZeroMemory(&SamplerDesc, sizeof(SamplerDesc));
SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
SamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
SamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
SamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
SamplerDesc.BorderColor[0] = 0.0f;
SamplerDesc.BorderColor[1] = 0.0f;
SamplerDesc.BorderColor[2] = 0.0f;
SamplerDesc.BorderColor[3] = 0.0f;
SamplerDesc.MinLOD = 0.0f;
SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
SamplerDesc.MipLODBias = 0;
SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
SamplerDesc.MaxAnisotropy = 1;
pDevice->CreateSampler(&SamplerDesc, m_sampler.GetCPU(0));
// diffuse env map sampler
ZeroMemory(&SamplerDesc, sizeof(SamplerDesc));
SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
SamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
SamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
SamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
SamplerDesc.BorderColor[0] = 0.0f;
SamplerDesc.BorderColor[1] = 0.0f;
SamplerDesc.BorderColor[2] = 0.0f;
SamplerDesc.BorderColor[3] = 0.0f;
SamplerDesc.MinLOD = 0.0f;
SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
SamplerDesc.MipLODBias = 0;
SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
SamplerDesc.MaxAnisotropy = 1;
pDevice->CreateSampler(&SamplerDesc, m_sampler.GetCPU(1));
// specular env map sampler
ZeroMemory(&SamplerDesc, sizeof(SamplerDesc));
SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
SamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
SamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
SamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
SamplerDesc.BorderColor[0] = 0.0f;
SamplerDesc.BorderColor[1] = 0.0f;
SamplerDesc.BorderColor[2] = 0.0f;
SamplerDesc.BorderColor[3] = 0.0f;
SamplerDesc.MinLOD = 0.0f;
SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
SamplerDesc.MipLODBias = 0;
SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
SamplerDesc.MaxAnisotropy = 1;
pDevice->CreateSampler(&SamplerDesc, m_sampler.GetCPU(2));
// specular BRDF lut sampler
ZeroMemory(&SamplerDesc, sizeof(SamplerDesc));
SamplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
SamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
SamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
SamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
SamplerDesc.BorderColor[0] = 0.0f;
SamplerDesc.BorderColor[1] = 0.0f;
SamplerDesc.BorderColor[2] = 0.0f;
SamplerDesc.BorderColor[3] = 0.0f;
SamplerDesc.MinLOD = 0.0f;
SamplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
SamplerDesc.MipLODBias = 0;
SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
SamplerDesc.MaxAnisotropy = 1;
pDevice->CreateSampler(&SamplerDesc, m_sampler.GetCPU(3));
// specular BRDF lut sampler
D3D12_SAMPLER_DESC samplerShadow = {
D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
0.0f,
1u,
D3D12_COMPARISON_FUNC_LESS_EQUAL,
{ 0.0f, 0.0f, 0.0f, 0.0f },
0.0f,
D3D12_FLOAT32_MAX
};
pDevice->CreateSampler(&samplerShadow, m_sampler.GetCPU(4));
}
pPrimitive->m_sampler = &m_sampler;
*/
}
GltfPbrVK::per_batch *GltfPbrVK::SetPerBatchConstants() {
per_batch *cbPerBatch;
m_pDynamicBufferRing->AllocConstantBuffer(sizeof(per_batch), (void **)&cbPerBatch, &m_perBatchDesc);
return cbPerBatch;
}
void GltfPbrVK::DrawMesh(VkCommandBuffer cmd_buf, int meshIndex, const glm::mat4x4& worldMatrix) {
PBRMesh *pMesh = &m_meshes[meshIndex];
for (unsigned int p = 0; p < pMesh->m_pPrimitives.size(); p++) {
PBRPrimitives *pPrimitive = &pMesh->m_pPrimitives[p];
if (pPrimitive->m_pipeline == VK_NULL_HANDLE)
continue;
// Set per Object constants
//
per_object *cbPerObject;
VkDescriptorBufferInfo perObjectDesc;
m_pDynamicBufferRing->AllocConstantBuffer(sizeof(per_object), (void**)&cbPerObject, &perObjectDesc);
cbPerObject->mWorld = worldMatrix;
cbPerObject->u_emissiveFactor = pPrimitive->m_pMaterial->emissiveFactor;
cbPerObject->u_baseColorFactor = pPrimitive->m_pMaterial->baseColorFactor;
cbPerObject->u_metallicRoughnessValues = glm::vec4(pPrimitive->m_pMaterial->metallicFactor, pPrimitive->m_pMaterial->roughnessFactor, 0, 0);
// Compute offsets
//
std::uint32_t size = (std::uint32_t)pPrimitive->m_VBV.size();
std::vector<VkBuffer> buffers(size);
std::vector<VkDeviceSize> offsets(size);
for (std::uint32_t i = 0; i < size; i++) {
buffers[i] = pPrimitive->m_VBV[i].buffer;
offsets[i] = pPrimitive->m_VBV[i].offset;
}
// Set state and draw
//
vkCmdBindVertexBuffers(cmd_buf, 0, size, buffers.data(), offsets.data());
vkCmdBindIndexBuffer(cmd_buf, pPrimitive->m_IBV.buffer, pPrimitive->m_IBV.offset, pPrimitive->m_indexType);
vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, pPrimitive->m_pipeline);
VkDescriptorSet descritorSets[2] = { pPrimitive->m_descriptorSet, pPrimitive->m_pMaterial->m_descriptorSet };
uint32_t uniformOffsets[2] = { (uint32_t)m_perBatchDesc.offset, (uint32_t)perObjectDesc.offset };
vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, pPrimitive->m_pipelineLayout, 0, 2, descritorSets, 2, uniformOffsets);
vkCmdDrawIndexed(cmd_buf, pPrimitive->m_NumIndices, 1, 0, 0, 0);
}
}