void ShadingModel::construct_from_file(TextFile const& file) { shader_stages_ = std::vector<ShaderStage>(4); Json::Value value; Json::Reader reader; if (!reader.parse(file.get_content(), value)) { Logger::LOG_WARNING << "Failed to parse shading model \"" << file.get_file_name() << "\": " "File does not exist!" << std::endl; return; } if (value["gbuffer_vertex_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model \"" << file.get_file_name() << "\": " "Gbuffer-Vertex-Stage is missing!" << std::endl; return; } if (value["gbuffer_fragment_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model \"" << file.get_file_name() << "\": " "Gbuffer-Fragment-Stage is missing!" << std::endl; return; } if (value["lbuffer_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model \"" << file.get_file_name() << "\": " "Lbuffer-stage is missing!" << std::endl; return; } if (value["final_shading_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model \"" << file.get_file_name() << "\": " "Final-Shading-Stage is missing!" << std::endl; return; } shader_stages_[GBUFFER_VERTEX_STAGE] = ShaderStage(value["gbuffer_vertex_stage"]); shader_stages_[GBUFFER_FRAGMENT_STAGE] = ShaderStage(value["gbuffer_fragment_stage"]); shader_stages_[LIGHTING_STAGE] = ShaderStage(value["lbuffer_stage"]); shader_stages_[FINAL_STAGE] = ShaderStage(value["final_shading_stage"]); // add default layers shader_stages_[GBUFFER_VERTEX_STAGE].get_outputs()["gua_position"] = BufferComponent::F3; shader_stages_[GBUFFER_FRAGMENT_STAGE].get_outputs()["gua_normal"] = BufferComponent::F3; shader_stages_[FINAL_STAGE].get_outputs()["gua_color"] = BufferComponent::F3; }
void Driver::checkCurrentShaderBuffers() { auto sq_config = getRegister<latte::SQ_CONFIG>(latte::Register::SQ_CONFIG); bool isDx9Consts = sq_config.DX9_CONSTS(); for (auto shaderStage = 0; shaderStage < 3; ++shaderStage) { if (!isDx9Consts) { for (auto i = 0u; i < latte::MaxUniformBlocks; ++i) { checkCurrentUniformBuffer(ShaderStage(shaderStage), i); } } else { for (auto i = 1u; i < latte::MaxUniformBlocks; ++i) { mCurrentUniformBlocks[shaderStage][i] = nullptr; } checkCurrentGprBuffer(ShaderStage(shaderStage)); } } }
void ShadingModel::construct_from_buffer(const char* buffer, unsigned buffer_size) { Json::Value value; Json::Reader reader; if (!reader.parse(buffer, buffer + buffer_size, value)) { Logger::LOG_WARNING << "Failed to parse shading model from buffer: " "Buffer invalid!" << std::endl; return; } if (value["gbuffer_vertex_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model from buffer: " "Gbuffer-Vertex-Stage is missing!" << std::endl; return; } if (value["gbuffer_fragment_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model from buffer: " "Gbuffer-Fragment-Stage is missing!" << std::endl; return; } if (value["lbuffer_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model from buffer: " "Lbuffer-stage is missing!" << std::endl; return; } if (value["final_shading_stage"] == Json::Value::null) { Logger::LOG_WARNING << "Failed to parse shading model from buffer: " "Final-Shading-Stage is missing!" << std::endl; return; } shader_stages_[GBUFFER_VERTEX_STAGE] = ShaderStage(value["gbuffer_vertex_stage"]); shader_stages_[GBUFFER_FRAGMENT_STAGE] = ShaderStage(value["gbuffer_fragment_stage"]); shader_stages_[LIGHTING_STAGE] = ShaderStage(value["lbuffer_stage"]); shader_stages_[FINAL_STAGE] = ShaderStage(value["final_shading_stage"]); // add default layers shader_stages_[GBUFFER_VERTEX_STAGE].get_outputs()["gua_position"] = BufferComponent::F3; shader_stages_[GBUFFER_FRAGMENT_STAGE].get_outputs()["gua_normal"] = BufferComponent::F3; shader_stages_[FINAL_STAGE].get_outputs()["gua_color"] = BufferComponent::F3; }
void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, const VkGraphicsPipelineCreateInfo *pCreateInfo) { flags = pCreateInfo->flags; layout = GetResID(pCreateInfo->layout); renderpass = GetResID(pCreateInfo->renderPass); subpass = pCreateInfo->subpass; // need to figure out which states are valid to be NULL // VkPipelineShaderStageCreateInfo for(uint32_t i = 0; i < pCreateInfo->stageCount; i++) { ResourceId id = GetResID(pCreateInfo->pStages[i].module); // convert shader bit to shader index int stageIndex = StageIndex(pCreateInfo->pStages[i].stage); Shader &shad = shaders[stageIndex]; shad.module = id; shad.entryPoint = pCreateInfo->pStages[i].pName; ShaderModule::Reflection &reflData = info.m_ShaderModule[id].m_Reflections[shad.entryPoint]; if(reflData.entryPoint.empty()) { SPVModule &spv = info.m_ShaderModule[id].spirv; spv.MakeReflection(ShaderStage(reflData.stage), shad.entryPoint, reflData.refl, reflData.mapping, reflData.patchData); reflData.entryPoint = shad.entryPoint; reflData.stage = stageIndex; reflData.refl.resourceId = resourceMan->GetOriginalID(id); if(!spv.spirv.empty()) { const std::vector<uint32_t> &spirv = spv.spirv; reflData.refl.encoding = ShaderEncoding::SPIRV; reflData.refl.rawBytes.assign((byte *)spirv.data(), spirv.size() * sizeof(uint32_t)); } } if(pCreateInfo->pStages[i].pSpecializationInfo) { shad.specdata.resize(pCreateInfo->pStages[i].pSpecializationInfo->dataSize); memcpy(&shad.specdata[0], pCreateInfo->pStages[i].pSpecializationInfo->pData, shad.specdata.size()); const VkSpecializationMapEntry *maps = pCreateInfo->pStages[i].pSpecializationInfo->pMapEntries; for(uint32_t s = 0; s < pCreateInfo->pStages[i].pSpecializationInfo->mapEntryCount; s++) { Shader::SpecInfo spec; spec.specID = maps[s].constantID; spec.data = &shad.specdata[maps[s].offset]; spec.size = maps[s].size; // ignore maps[s].size, assume it's enough for the type shad.specialization.push_back(spec); } } shad.refl = &reflData.refl; shad.mapping = &reflData.mapping; shad.patchData = &reflData.patchData; } if(pCreateInfo->pVertexInputState) { vertexBindings.resize(pCreateInfo->pVertexInputState->vertexBindingDescriptionCount); for(uint32_t i = 0; i < pCreateInfo->pVertexInputState->vertexBindingDescriptionCount; i++) { vertexBindings[i].vbufferBinding = pCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].binding; vertexBindings[i].bytestride = pCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].stride; vertexBindings[i].perInstance = pCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].inputRate == VK_VERTEX_INPUT_RATE_INSTANCE; } vertexAttrs.resize(pCreateInfo->pVertexInputState->vertexAttributeDescriptionCount); for(uint32_t i = 0; i < pCreateInfo->pVertexInputState->vertexAttributeDescriptionCount; i++) { vertexAttrs[i].binding = pCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].binding; vertexAttrs[i].location = pCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].location; vertexAttrs[i].format = pCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].format; vertexAttrs[i].byteoffset = pCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].offset; } } topology = pCreateInfo->pInputAssemblyState->topology; primitiveRestartEnable = pCreateInfo->pInputAssemblyState->primitiveRestartEnable ? true : false; if(pCreateInfo->pTessellationState) patchControlPoints = pCreateInfo->pTessellationState->patchControlPoints; else patchControlPoints = 0; if(pCreateInfo->pViewportState) viewportCount = pCreateInfo->pViewportState->viewportCount; else viewportCount = 0; viewports.resize(viewportCount); scissors.resize(viewportCount); for(uint32_t i = 0; i < viewportCount; i++) { if(pCreateInfo->pViewportState->pViewports) viewports[i] = pCreateInfo->pViewportState->pViewports[i]; if(pCreateInfo->pViewportState->pScissors) scissors[i] = pCreateInfo->pViewportState->pScissors[i]; } // VkPipelineRasterStateCreateInfo depthClampEnable = pCreateInfo->pRasterizationState->depthClampEnable ? true : false; rasterizerDiscardEnable = pCreateInfo->pRasterizationState->rasterizerDiscardEnable ? true : false; polygonMode = pCreateInfo->pRasterizationState->polygonMode; cullMode = pCreateInfo->pRasterizationState->cullMode; frontFace = pCreateInfo->pRasterizationState->frontFace; depthBiasEnable = pCreateInfo->pRasterizationState->depthBiasEnable ? true : false; depthBiasConstantFactor = pCreateInfo->pRasterizationState->depthBiasConstantFactor; depthBiasClamp = pCreateInfo->pRasterizationState->depthBiasClamp; depthBiasSlopeFactor = pCreateInfo->pRasterizationState->depthBiasSlopeFactor; lineWidth = pCreateInfo->pRasterizationState->lineWidth; // VkPipelineMultisampleStateCreateInfo if(pCreateInfo->pMultisampleState) { rasterizationSamples = pCreateInfo->pMultisampleState->rasterizationSamples; sampleShadingEnable = pCreateInfo->pMultisampleState->sampleShadingEnable ? true : false; minSampleShading = pCreateInfo->pMultisampleState->minSampleShading; sampleMask = pCreateInfo->pMultisampleState->pSampleMask ? *pCreateInfo->pMultisampleState->pSampleMask : ~0U; alphaToCoverageEnable = pCreateInfo->pMultisampleState->alphaToCoverageEnable ? true : false; alphaToOneEnable = pCreateInfo->pMultisampleState->alphaToOneEnable ? true : false; } else { rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; sampleShadingEnable = false; minSampleShading = 1.0f; sampleMask = ~0U; alphaToCoverageEnable = false; alphaToOneEnable = false; } // VkPipelineDepthStencilStateCreateInfo if(pCreateInfo->pDepthStencilState) { depthTestEnable = pCreateInfo->pDepthStencilState->depthTestEnable ? true : false; depthWriteEnable = pCreateInfo->pDepthStencilState->depthWriteEnable ? true : false; depthCompareOp = pCreateInfo->pDepthStencilState->depthCompareOp; depthBoundsEnable = pCreateInfo->pDepthStencilState->depthBoundsTestEnable ? true : false; stencilTestEnable = pCreateInfo->pDepthStencilState->stencilTestEnable ? true : false; front = pCreateInfo->pDepthStencilState->front; back = pCreateInfo->pDepthStencilState->back; minDepthBounds = pCreateInfo->pDepthStencilState->minDepthBounds; maxDepthBounds = pCreateInfo->pDepthStencilState->maxDepthBounds; } else { depthTestEnable = false; depthWriteEnable = false; depthCompareOp = VK_COMPARE_OP_ALWAYS; depthBoundsEnable = false; stencilTestEnable = false; front.failOp = VK_STENCIL_OP_KEEP; front.passOp = VK_STENCIL_OP_KEEP; front.depthFailOp = VK_STENCIL_OP_KEEP; front.compareOp = VK_COMPARE_OP_ALWAYS; front.compareMask = 0xff; front.writeMask = 0xff; front.reference = 0; back = front; minDepthBounds = 0.0f; maxDepthBounds = 1.0f; } // VkPipelineColorBlendStateCreateInfo if(pCreateInfo->pColorBlendState) { logicOpEnable = pCreateInfo->pColorBlendState->logicOpEnable ? true : false; logicOp = pCreateInfo->pColorBlendState->logicOp; memcpy(blendConst, pCreateInfo->pColorBlendState->blendConstants, sizeof(blendConst)); attachments.resize(pCreateInfo->pColorBlendState->attachmentCount); for(uint32_t i = 0; i < pCreateInfo->pColorBlendState->attachmentCount; i++) { attachments[i].blendEnable = pCreateInfo->pColorBlendState->pAttachments[i].blendEnable ? true : false; attachments[i].blend.Source = pCreateInfo->pColorBlendState->pAttachments[i].srcColorBlendFactor; attachments[i].blend.Destination = pCreateInfo->pColorBlendState->pAttachments[i].dstColorBlendFactor; attachments[i].blend.Operation = pCreateInfo->pColorBlendState->pAttachments[i].colorBlendOp; attachments[i].alphaBlend.Source = pCreateInfo->pColorBlendState->pAttachments[i].srcAlphaBlendFactor; attachments[i].alphaBlend.Destination = pCreateInfo->pColorBlendState->pAttachments[i].dstAlphaBlendFactor; attachments[i].alphaBlend.Operation = pCreateInfo->pColorBlendState->pAttachments[i].alphaBlendOp; attachments[i].channelWriteMask = (uint8_t)pCreateInfo->pColorBlendState->pAttachments[i].colorWriteMask; } } else { logicOpEnable = false; logicOp = VK_LOGIC_OP_NO_OP; RDCEraseEl(blendConst); attachments.clear(); } RDCEraseEl(dynamicStates); if(pCreateInfo->pDynamicState) { for(uint32_t i = 0; i < pCreateInfo->pDynamicState->dynamicStateCount; i++) dynamicStates[pCreateInfo->pDynamicState->pDynamicStates[i]] = true; } }
ShaderProgram ShaderManager::CompileShaderInternal(const std::string& sourceCode, ShaderParts parts, const std::string& macros) { class IncludeProvider : public gxapi::IShaderIncludeProvider { public: IncludeProvider(std::function<std::string(const char*)> findShader) : m_findShader(findShader) {} std::string LoadInclude(const char* includeName, bool systemInclude) override { return m_findShader(includeName); } private: std::function<std::string(const char*)> m_findShader; }; IncludeProvider includeProvider([this](const char* name) { return FindShaderCode(name).second; }); ShaderProgram ret; static const char* const mainNames[] = { "VSMain", "HSMain", "DSMain", "GSMain", "PSMain", "CSMain", }; static const gxapi::eShaderType types[] = { gxapi::eShaderType::VERTEX, gxapi::eShaderType::HULL, gxapi::eShaderType::DOMAIN, gxapi::eShaderType::GEOMETRY, gxapi::eShaderType::PIXEL, gxapi::eShaderType::COMPUTE, }; int compileIndices[7]; // last item is a guard (-1), not used otherwise { for (auto& v : compileIndices) { v = -1; } int idx = 0; if (parts.vs) { compileIndices[idx] = 0; ++idx; } if (parts.hs) { compileIndices[idx] = 1; ++idx; } if (parts.ds) { compileIndices[idx] = 2; ++idx; } if (parts.gs) { compileIndices[idx] = 3; ++idx; } if (parts.ps) { compileIndices[idx] = 4; ++idx; } if (parts.cs) { compileIndices[idx] = 5; ++idx; } } int idx = 0; while (compileIndices[idx] != -1) { const int stageId = compileIndices[idx]; const char* mainName = mainNames[stageId]; gxapi::eShaderType type = types[stageId]; auto binary = m_gxapiManager->CompileShader(sourceCode.c_str(), mainName, type, m_compileFlags, &includeProvider, macros.c_str()); ShaderStage* dest = nullptr; switch (type) { case gxapi::eShaderType::VERTEX: dest = &ret.vs; break; case gxapi::eShaderType::HULL: dest = &ret.hs; break; case gxapi::eShaderType::DOMAIN: dest = &ret.ds; break; case gxapi::eShaderType::GEOMETRY: dest = &ret.gs; break; case gxapi::eShaderType::PIXEL: dest = &ret.ps; break; case gxapi::eShaderType::COMPUTE: dest = &ret.cs; break; } *dest = ShaderStage(std::move(binary.data)); ++idx; } return ret; }