CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/GPU/Vulkan/VulkanUtil.cpp
Views: 1401
// Copyright (c) 2016- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include "Common/Log.h"18#include "Common/StringUtils.h"19#include "Common/GPU/Vulkan/VulkanContext.h"20#include "GPU/Vulkan/VulkanUtil.h"2122using namespace PPSSPP_VK;2324const VkComponentMapping VULKAN_4444_SWIZZLE = { VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B };25const VkComponentMapping VULKAN_1555_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A };26const VkComponentMapping VULKAN_565_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_IDENTITY };27const VkComponentMapping VULKAN_8888_SWIZZLE = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };2829VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits stage, const char *code, std::string *error) {30std::vector<uint32_t> spirv;31bool success = GLSLtoSPV(stage, code, GLSLVariant::VULKAN, spirv, error);32if (!error->empty()) {33if (success) {34ERROR_LOG(Log::G3D, "Warnings in shader compilation!");35} else {36ERROR_LOG(Log::G3D, "Error in shader compilation!");37}38ERROR_LOG(Log::G3D, "Messages: %s", error->c_str());39ERROR_LOG(Log::G3D, "Shader source:\n%s", LineNumberString(code).c_str());40OutputDebugStringUTF8("Messages:\n");41OutputDebugStringUTF8(error->c_str());42OutputDebugStringUTF8(LineNumberString(code).c_str());43return VK_NULL_HANDLE;44} else {45VkShaderModule module;46if (vulkan->CreateShaderModule(spirv, &module, stage == VK_SHADER_STAGE_VERTEX_BIT ? "system_vs" : "system_fs")) {47return module;48} else {49return VK_NULL_HANDLE;50}51}52}5354VulkanComputeShaderManager::VulkanComputeShaderManager(VulkanContext *vulkan) : vulkan_(vulkan), pipelines_(8) {}55VulkanComputeShaderManager::~VulkanComputeShaderManager() {}5657void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) {58VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };59VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_);60_assert_(VK_SUCCESS == res);6162static const BindingType bindingTypes[3] = {63BindingType::STORAGE_IMAGE_COMPUTE,64BindingType::STORAGE_BUFFER_COMPUTE,65BindingType::STORAGE_BUFFER_COMPUTE,66};6768VkDescriptorSetLayoutBinding bindings[3] = {};69bindings[0].descriptorCount = 1;70bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;71bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;72bindings[0].binding = 0;73bindings[1].descriptorCount = 1;74bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;75bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;76bindings[1].binding = 1;77bindings[2].descriptorCount = 1;78bindings[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;79bindings[2].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;80bindings[2].binding = 2;8182VkDevice device = vulkan_->GetDevice();8384VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };85dsl.bindingCount = ARRAY_SIZE(bindings);86dsl.pBindings = bindings;87res = vkCreateDescriptorSetLayout(device, &dsl, nullptr, &descriptorSetLayout_);88_assert_(VK_SUCCESS == res);8990for (int i = 0; i < ARRAY_SIZE(frameData_); i++) {91frameData_[i].descPool.Create(vulkan_, bindingTypes, ARRAY_SIZE(bindingTypes), 4096);92frameData_[i].descPoolUsed = false;93}9495VkPushConstantRange push = {};96push.offset = 0;97push.size = 16;98push.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;99100VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };101pl.pPushConstantRanges = &push;102pl.pushConstantRangeCount = 1;103VkDescriptorSetLayout setLayouts[1] = { descriptorSetLayout_ };104pl.setLayoutCount = ARRAY_SIZE(setLayouts);105pl.pSetLayouts = setLayouts;106pl.flags = 0;107res = vkCreatePipelineLayout(device, &pl, nullptr, &pipelineLayout_);108_assert_(VK_SUCCESS == res);109}110111void VulkanComputeShaderManager::DestroyDeviceObjects() {112for (int i = 0; i < ARRAY_SIZE(frameData_); i++) {113frameData_[i].descPool.Destroy();114}115if (descriptorSetLayout_) {116vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_);117}118pipelines_.Iterate([&](const PipelineKey &key, VkPipeline pipeline) {119vulkan_->Delete().QueueDeletePipeline(pipeline);120});121pipelines_.Clear();122123if (pipelineLayout_) {124vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_);125}126if (pipelineCache_ != VK_NULL_HANDLE) {127vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);128}129}130131VkDescriptorSet VulkanComputeShaderManager::GetDescriptorSet(VkImageView image, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range, VkBuffer buffer2, VkDeviceSize offset2, VkDeviceSize range2) {132int curFrame = vulkan_->GetCurFrame();133FrameData &frameData = frameData_[curFrame];134frameData.descPoolUsed = true;135VkDescriptorSet desc;136frameData.descPool.Allocate(&desc, 1, &descriptorSetLayout_);137_assert_(desc != VK_NULL_HANDLE);138139VkWriteDescriptorSet writes[3]{};140int n = 0;141VkDescriptorImageInfo imageInfo = {};142VkDescriptorBufferInfo bufferInfo[2] = {};143if (image) {144imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;145imageInfo.imageView = image;146imageInfo.sampler = VK_NULL_HANDLE;147writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;148writes[n].dstBinding = 0;149writes[n].pImageInfo = &imageInfo;150writes[n].descriptorCount = 1;151writes[n].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;152writes[n].dstSet = desc;153n++;154}155bufferInfo[0].buffer = buffer;156bufferInfo[0].offset = offset;157bufferInfo[0].range = range;158writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;159writes[n].dstBinding = 1;160writes[n].pBufferInfo = &bufferInfo[0];161writes[n].descriptorCount = 1;162writes[n].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;163writes[n].dstSet = desc;164n++;165if (buffer2) {166bufferInfo[1].buffer = buffer2;167bufferInfo[1].offset = offset2;168bufferInfo[1].range = range2;169writes[n].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;170writes[n].dstBinding = 2;171writes[n].pBufferInfo = &bufferInfo[1];172writes[n].descriptorCount = 1;173writes[n].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;174writes[n].dstSet = desc;175n++;176}177vkUpdateDescriptorSets(vulkan_->GetDevice(), n, writes, 0, nullptr);178return desc;179}180181VkPipeline VulkanComputeShaderManager::GetPipeline(VkShaderModule cs) {182PipelineKey key{ cs };183VkPipeline pipeline;184if (pipelines_.Get(key, &pipeline)) {185return pipeline;186}187188VkComputePipelineCreateInfo pci{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };189pci.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;190pci.stage.module = cs;191pci.stage.pName = "main";192pci.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;193pci.layout = pipelineLayout_;194pci.flags = 0;195196VkResult res = vkCreateComputePipelines(vulkan_->GetDevice(), pipelineCache_, 1, &pci, nullptr, &pipeline);197_assert_(res == VK_SUCCESS);198199pipelines_.Insert(key, pipeline);200return pipeline;201}202203void VulkanComputeShaderManager::BeginFrame() {204int curFrame = vulkan_->GetCurFrame();205FrameData &frame = frameData_[curFrame];206if (frame.descPoolUsed) {207frame.descPool.Reset();208frame.descPoolUsed = false;209}210}211212213