2019-11-10 10:27:19 +00:00
|
|
|
/*
|
|
|
|
Created on: Nov 6, 2019
|
|
|
|
|
|
|
|
Copyright 2019 flyinghead
|
|
|
|
|
|
|
|
This file is part of Flycast.
|
|
|
|
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#pragma once
|
2019-12-04 08:41:27 +00:00
|
|
|
#include "../vulkan.h"
|
2019-11-10 10:27:19 +00:00
|
|
|
#include "oit_shaders.h"
|
2019-11-12 18:39:58 +00:00
|
|
|
#include "oit_renderpass.h"
|
2019-11-13 19:08:14 +00:00
|
|
|
#include "oit_buffer.h"
|
2019-12-04 08:41:27 +00:00
|
|
|
#include "../texture.h"
|
2020-03-28 16:58:01 +00:00
|
|
|
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
#include <tuple>
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
class OITDescriptorSets
|
|
|
|
{
|
|
|
|
public:
|
2021-01-04 17:56:15 +00:00
|
|
|
OITDescriptorSets() = default;
|
|
|
|
OITDescriptorSets(OITDescriptorSets&&) = default;
|
|
|
|
OITDescriptorSets(const OITDescriptorSets&) = delete;
|
|
|
|
OITDescriptorSets& operator=(OITDescriptorSets&&) = default;
|
|
|
|
OITDescriptorSets& operator=(const OITDescriptorSets&) = delete;
|
|
|
|
|
2019-11-10 10:27:19 +00:00
|
|
|
// std140 alignment required
|
|
|
|
struct VertexShaderUniforms
|
|
|
|
{
|
|
|
|
glm::mat4 normal_matrix;
|
|
|
|
};
|
|
|
|
|
|
|
|
// std140 alignment required
|
|
|
|
struct FragmentShaderUniforms
|
|
|
|
{
|
|
|
|
float colorClampMin[4];
|
|
|
|
float colorClampMax[4];
|
|
|
|
float sp_FOG_COL_RAM[4]; // Only using 3 elements but easier for std140
|
|
|
|
float sp_FOG_COL_VERT[4]; // same comment
|
|
|
|
float cp_AlphaTestValue;
|
|
|
|
float sp_FOG_DENSITY;
|
|
|
|
float shade_scale_factor; // new for OIT
|
2021-09-18 16:08:52 +00:00
|
|
|
u32 pixelBufferSize;
|
2019-11-10 10:27:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct PushConstants
|
|
|
|
{
|
|
|
|
glm::vec4 clipTest;
|
|
|
|
glm::ivec4 blend_mode0; // Only using 2 elements but easier for std140
|
|
|
|
float trilinearAlpha;
|
|
|
|
int pp_Number;
|
2020-07-08 16:17:15 +00:00
|
|
|
float palette_index;
|
|
|
|
int _pad;
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
// two volume mode
|
|
|
|
glm::ivec4 blend_mode1; // Only using 2 elements but easier for std140
|
|
|
|
int shading_instr0;
|
|
|
|
int shading_instr1;
|
|
|
|
int fog_control0;
|
|
|
|
int fog_control1;
|
|
|
|
int use_alpha0;
|
|
|
|
int use_alpha1;
|
|
|
|
int ignore_tex_alpha0;
|
|
|
|
int ignore_tex_alpha1;
|
|
|
|
};
|
|
|
|
|
|
|
|
void Init(SamplerManager* samplerManager, vk::PipelineLayout pipelineLayout, vk::DescriptorSetLayout perFrameLayout,
|
2019-11-12 18:39:58 +00:00
|
|
|
vk::DescriptorSetLayout perPolyLayout, vk::DescriptorSetLayout colorInputLayout)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
|
|
|
this->samplerManager = samplerManager;
|
|
|
|
this->pipelineLayout = pipelineLayout;
|
|
|
|
this->perFrameLayout = perFrameLayout;
|
|
|
|
this->perPolyLayout = perPolyLayout;
|
2019-11-12 18:39:58 +00:00
|
|
|
this->colorInputLayout = colorInputLayout;
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
// FIXME way too many params
|
|
|
|
void UpdateUniforms(vk::Buffer buffer, u32 vertexUniformOffset, u32 fragmentUniformOffset, vk::ImageView fogImageView,
|
2020-07-08 16:17:15 +00:00
|
|
|
u32 polyParamsOffset, u32 polyParamsSize, vk::ImageView stencilImageView, vk::ImageView depthImageView,
|
|
|
|
vk::ImageView paletteImageView)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2020-12-15 14:09:42 +00:00
|
|
|
if (perFrameDescSets.empty())
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2021-01-04 17:56:15 +00:00
|
|
|
perFrameDescSets = std::move(GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
|
|
|
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), 1, &perFrameLayout)));
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
2020-12-15 14:09:42 +00:00
|
|
|
perFrameDescSetsInFlight.emplace_back(std::move(perFrameDescSets.back()));
|
|
|
|
perFrameDescSets.pop_back();
|
|
|
|
vk::DescriptorSet perFrameDescSet = *perFrameDescSetsInFlight.back();
|
|
|
|
|
2019-11-10 10:27:19 +00:00
|
|
|
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
2021-03-13 12:47:38 +00:00
|
|
|
bufferInfos.emplace_back(buffer, vertexUniformOffset, sizeof(VertexShaderUniforms));
|
|
|
|
bufferInfos.emplace_back(buffer, fragmentUniformOffset, sizeof(FragmentShaderUniforms));
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfos[0], nullptr);
|
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 1, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfos[1], nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
if (fogImageView)
|
|
|
|
{
|
|
|
|
TSP fogTsp = {};
|
|
|
|
fogTsp.FilterMode = 1;
|
|
|
|
fogTsp.ClampU = 1;
|
|
|
|
fogTsp.ClampV = 1;
|
|
|
|
vk::Sampler fogSampler = samplerManager->GetSampler(fogTsp);
|
|
|
|
static vk::DescriptorImageInfo imageInfo;
|
|
|
|
imageInfo = { fogSampler, fogImageView, vk::ImageLayout::eShaderReadOnlyOptimal };
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 2, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
2020-07-08 16:17:15 +00:00
|
|
|
if (paletteImageView)
|
|
|
|
{
|
|
|
|
TSP palTsp = {};
|
|
|
|
palTsp.FilterMode = 0;
|
|
|
|
palTsp.ClampU = 1;
|
|
|
|
palTsp.ClampV = 1;
|
|
|
|
vk::Sampler palSampler = samplerManager->GetSampler(palTsp);
|
|
|
|
static vk::DescriptorImageInfo imageInfo;
|
|
|
|
imageInfo = { palSampler, paletteImageView, vk::ImageLayout::eShaderReadOnlyOptimal };
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 6, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
|
2020-07-08 16:17:15 +00:00
|
|
|
}
|
2019-11-10 10:27:19 +00:00
|
|
|
if (polyParamsSize > 0)
|
|
|
|
{
|
|
|
|
static vk::DescriptorBufferInfo polyParamsBufferInfo;
|
|
|
|
polyParamsBufferInfo = vk::DescriptorBufferInfo(buffer, polyParamsOffset, polyParamsSize);
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 3, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &polyParamsBufferInfo, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
2019-11-10 16:59:21 +00:00
|
|
|
vk::DescriptorImageInfo stencilImageInfo(vk::Sampler(), stencilImageView, vk::ImageLayout::eDepthStencilReadOnlyOptimal);
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 4, 0, 1, vk::DescriptorType::eInputAttachment, &stencilImageInfo, nullptr, nullptr);
|
2019-11-10 16:59:21 +00:00
|
|
|
vk::DescriptorImageInfo depthImageInfo(vk::Sampler(), depthImageView, vk::ImageLayout::eDepthStencilReadOnlyOptimal);
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(perFrameDescSet, 5, 0, 1, vk::DescriptorType::eInputAttachment, &depthImageInfo, nullptr, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
|
|
|
}
|
|
|
|
|
2019-11-12 18:39:58 +00:00
|
|
|
void UpdateColorInputDescSet(int index, vk::ImageView colorImageView)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2019-11-12 18:39:58 +00:00
|
|
|
if (!colorInputDescSets[index])
|
2020-12-15 14:09:42 +00:00
|
|
|
{
|
2019-11-12 18:39:58 +00:00
|
|
|
colorInputDescSets[index] = std::move(GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
|
|
|
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), 1, &colorInputLayout)).front());
|
2020-12-15 14:09:42 +00:00
|
|
|
}
|
2021-01-09 17:16:39 +00:00
|
|
|
vk::DescriptorImageInfo colorImageInfo(vk::Sampler(), colorImageView, vk::ImageLayout::eShaderReadOnlyOptimal);
|
|
|
|
vk::WriteDescriptorSet writeDescriptorSet(*colorInputDescSets[index], 0, 0, 1, vk::DescriptorType::eInputAttachment, &colorImageInfo, nullptr, nullptr);
|
|
|
|
|
|
|
|
GetContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
|
2021-04-17 17:04:00 +00:00
|
|
|
void SetTexture(Texture *texture0, TSP tsp0, Texture *texture1, TSP tsp1)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2021-04-17 17:04:00 +00:00
|
|
|
auto index = std::make_tuple(texture0, tsp0.full & SamplerManager::TSP_Mask,
|
|
|
|
texture1, tsp1.full & SamplerManager::TSP_Mask);
|
2019-11-10 10:27:19 +00:00
|
|
|
if (perPolyDescSetsInFlight.find(index) != perPolyDescSetsInFlight.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (perPolyDescSets.empty())
|
|
|
|
{
|
|
|
|
std::vector<vk::DescriptorSetLayout> layouts(10, perPolyLayout);
|
|
|
|
perPolyDescSets = GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
|
|
|
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), layouts.size(), &layouts[0]));
|
|
|
|
}
|
2021-04-17 17:04:00 +00:00
|
|
|
vk::DescriptorImageInfo imageInfo0(samplerManager->GetSampler(tsp0), texture0->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(*perPolyDescSets.back(), 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo0, nullptr, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
2021-04-17 16:40:58 +00:00
|
|
|
if (texture1 != nullptr)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2019-12-09 18:37:14 +00:00
|
|
|
vk::DescriptorImageInfo imageInfo1(samplerManager->GetSampler(tsp1), texture1->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
2021-03-13 12:47:38 +00:00
|
|
|
writeDescriptorSets.emplace_back(*perPolyDescSets.back(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo1, nullptr, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
|
|
|
perPolyDescSetsInFlight[index] = std::move(perPolyDescSets.back());
|
|
|
|
perPolyDescSets.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BindPerFrameDescriptorSets(vk::CommandBuffer cmdBuffer)
|
|
|
|
{
|
2020-12-15 14:09:42 +00:00
|
|
|
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &perFrameDescSetsInFlight.back().get(), 0, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
|
2019-11-12 18:39:58 +00:00
|
|
|
void BindColorInputDescSet(vk::CommandBuffer cmdBuffer, int index)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2019-11-12 18:39:58 +00:00
|
|
|
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 2, 1, &colorInputDescSets[index].get(), 0, nullptr);
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
|
2021-04-17 17:04:00 +00:00
|
|
|
void BindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, Texture *texture0, TSP tsp0, Texture *texture1, TSP tsp1)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2021-04-17 17:04:00 +00:00
|
|
|
auto index = std::make_tuple(texture0, tsp0.full & SamplerManager::TSP_Mask, texture1, tsp1.full & SamplerManager::TSP_Mask);
|
2019-11-10 10:27:19 +00:00
|
|
|
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1,
|
|
|
|
&perPolyDescSetsInFlight[index].get(), 0, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
for (auto& pair : perPolyDescSetsInFlight)
|
|
|
|
perPolyDescSets.emplace_back(std::move(pair.second));
|
|
|
|
perPolyDescSetsInFlight.clear();
|
2020-12-15 14:09:42 +00:00
|
|
|
for (auto& descset : perFrameDescSetsInFlight)
|
|
|
|
perFrameDescSets.emplace_back(std::move(descset));
|
|
|
|
perFrameDescSetsInFlight.clear();
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
VulkanContext *GetContext() const { return VulkanContext::Instance(); }
|
|
|
|
|
|
|
|
vk::DescriptorSetLayout perFrameLayout;
|
|
|
|
vk::DescriptorSetLayout perPolyLayout;
|
2019-11-12 18:39:58 +00:00
|
|
|
vk::DescriptorSetLayout colorInputLayout;
|
2019-11-10 10:27:19 +00:00
|
|
|
vk::PipelineLayout pipelineLayout;
|
|
|
|
|
2020-12-15 14:09:42 +00:00
|
|
|
std::vector<vk::UniqueDescriptorSet> perFrameDescSets;
|
|
|
|
std::vector<vk::UniqueDescriptorSet> perFrameDescSetsInFlight;
|
2019-11-12 18:39:58 +00:00
|
|
|
std::array<vk::UniqueDescriptorSet, 2> colorInputDescSets;
|
2019-11-10 10:27:19 +00:00
|
|
|
std::vector<vk::UniqueDescriptorSet> perPolyDescSets;
|
2021-04-17 17:04:00 +00:00
|
|
|
std::map<std::tuple<Texture *, u32, Texture *, u32>, vk::UniqueDescriptorSet> perPolyDescSetsInFlight;
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
SamplerManager* samplerManager;
|
|
|
|
};
|
|
|
|
|
|
|
|
class OITPipelineManager
|
|
|
|
{
|
|
|
|
public:
|
2019-11-12 18:39:58 +00:00
|
|
|
OITPipelineManager() : renderPasses(&ownRenderPasses) {}
|
2019-11-10 10:27:19 +00:00
|
|
|
virtual ~OITPipelineManager() = default;
|
|
|
|
|
2019-11-13 19:08:14 +00:00
|
|
|
virtual void Init(OITShaderManager *shaderManager, OITBuffers *oitBuffers)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
|
|
|
this->shaderManager = shaderManager;
|
|
|
|
|
|
|
|
if (!perFrameLayout)
|
|
|
|
{
|
|
|
|
// Descriptor set and pipeline layout
|
|
|
|
vk::DescriptorSetLayoutBinding perFrameBindings[] = {
|
|
|
|
{ 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }, // vertex uniforms
|
|
|
|
{ 1, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // fragment uniforms
|
|
|
|
{ 2, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// fog texture
|
2019-11-13 19:08:14 +00:00
|
|
|
{ 3, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // Tr poly params
|
|
|
|
{ 4, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment }, // stencil input attachment
|
|
|
|
{ 5, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment }, // depth input attachment
|
2020-07-08 16:17:15 +00:00
|
|
|
{ 6, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// palette texture
|
2019-11-10 10:27:19 +00:00
|
|
|
};
|
|
|
|
perFrameLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
|
|
|
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(perFrameBindings), perFrameBindings));
|
|
|
|
|
2019-11-12 18:39:58 +00:00
|
|
|
vk::DescriptorSetLayoutBinding colorInputBindings[] = {
|
2019-11-10 10:27:19 +00:00
|
|
|
{ 0, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment }, // color input attachment
|
|
|
|
};
|
2019-11-12 18:39:58 +00:00
|
|
|
colorInputLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
|
|
|
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(colorInputBindings), colorInputBindings));
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
vk::DescriptorSetLayoutBinding perPolyBindings[] = {
|
|
|
|
{ 0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// texture 0
|
|
|
|
{ 1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// texture 1 (for 2-volume mode)
|
|
|
|
};
|
|
|
|
perPolyLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
|
|
|
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(perPolyBindings), perPolyBindings));
|
|
|
|
|
|
|
|
vk::PushConstantRange pushConstant(vk::ShaderStageFlagBits::eFragment, 0, sizeof(OITDescriptorSets::PushConstants));
|
2019-11-13 19:08:14 +00:00
|
|
|
vk::DescriptorSetLayout layouts[] = { *perFrameLayout, *perPolyLayout, *colorInputLayout, oitBuffers->GetDescriptorSetLayout() };
|
2019-11-10 10:27:19 +00:00
|
|
|
pipelineLayout = GetContext()->GetDevice().createPipelineLayoutUnique(
|
|
|
|
vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), ARRAY_SIZE(layouts), layouts, 1, &pushConstant));
|
|
|
|
}
|
|
|
|
|
|
|
|
pipelines.clear();
|
|
|
|
modVolPipelines.clear();
|
|
|
|
}
|
|
|
|
|
2021-04-17 16:40:58 +00:00
|
|
|
vk::Pipeline GetPipeline(u32 listType, bool autosort, const PolyParam& pp, Pass pass, bool gpuPalette)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2021-04-17 16:40:58 +00:00
|
|
|
u32 pipehash = hash(listType, autosort, &pp, pass, gpuPalette);
|
2019-11-10 10:27:19 +00:00
|
|
|
const auto &pipeline = pipelines.find(pipehash);
|
|
|
|
if (pipeline != pipelines.end())
|
|
|
|
return pipeline->second.get();
|
|
|
|
|
2021-04-17 16:40:58 +00:00
|
|
|
CreatePipeline(listType, autosort, pp, pass, gpuPalette);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
return *pipelines[pipehash];
|
|
|
|
}
|
|
|
|
|
2019-12-05 17:48:54 +00:00
|
|
|
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2019-12-05 17:48:54 +00:00
|
|
|
u32 pipehash = hash(mode, cullMode);
|
|
|
|
const auto &pipeline = modVolPipelines.find(pipehash);
|
|
|
|
if (pipeline != modVolPipelines.end())
|
|
|
|
return pipeline->second.get();
|
|
|
|
CreateModVolPipeline(mode, cullMode);
|
|
|
|
|
|
|
|
return *modVolPipelines[pipehash];
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
2019-12-05 17:48:54 +00:00
|
|
|
vk::Pipeline GetTrModifierVolumePipeline(ModVolMode mode, int cullMode)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2019-12-05 17:48:54 +00:00
|
|
|
u32 pipehash = hash(mode, cullMode);
|
|
|
|
const auto &pipeline = trModVolPipelines.find(pipehash);
|
|
|
|
if (pipeline != trModVolPipelines.end())
|
|
|
|
return pipeline->second.get();
|
|
|
|
CreateTrModVolPipeline(mode, cullMode);
|
|
|
|
|
|
|
|
return *trModVolPipelines[pipehash];
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
2020-01-05 22:03:44 +00:00
|
|
|
vk::Pipeline GetFinalPipeline()
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2020-01-05 22:03:44 +00:00
|
|
|
if (!finalPipeline)
|
|
|
|
CreateFinalPipeline();
|
|
|
|
return *finalPipeline;
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
vk::Pipeline GetClearPipeline()
|
|
|
|
{
|
|
|
|
if (!clearPipeline)
|
|
|
|
CreateClearPipeline();
|
|
|
|
return *clearPipeline;
|
|
|
|
}
|
|
|
|
vk::PipelineLayout GetPipelineLayout() const { return *pipelineLayout; }
|
|
|
|
vk::DescriptorSetLayout GetPerFrameDSLayout() const { return *perFrameLayout; }
|
|
|
|
vk::DescriptorSetLayout GetPerPolyDSLayout() const { return *perPolyLayout; }
|
2019-11-12 18:39:58 +00:00
|
|
|
vk::DescriptorSetLayout GetColorInputDSLayout() const { return *colorInputLayout; }
|
2019-11-10 10:27:19 +00:00
|
|
|
|
2019-11-12 18:39:58 +00:00
|
|
|
vk::RenderPass GetRenderPass(bool initial, bool last) { return renderPasses->GetRenderPass(initial, last); }
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
private:
|
2019-12-05 17:48:54 +00:00
|
|
|
void CreateModVolPipeline(ModVolMode mode, int cullMode);
|
|
|
|
void CreateTrModVolPipeline(ModVolMode mode, int cullMode);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
2021-04-17 16:40:58 +00:00
|
|
|
u32 hash(u32 listType, bool autosort, const PolyParam *pp, Pass pass, bool gpuPalette) const
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
|
|
|
u32 hash = pp->pcw.Gouraud | (pp->pcw.Offset << 1) | (pp->pcw.Texture << 2) | (pp->pcw.Shadow << 3)
|
|
|
|
| (((pp->tileclip >> 28) == 3) << 4);
|
|
|
|
hash |= ((listType >> 1) << 5);
|
2020-07-08 16:17:15 +00:00
|
|
|
if (pp->tcw1.full != (u32)-1 || pp->tsp1.full != (u32)-1)
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
|
|
|
// Two-volume mode
|
|
|
|
hash |= (1 << 31) | (pp->tsp.ColorClamp << 11);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-12-15 14:09:42 +00:00
|
|
|
bool ignoreTexAlpha = pp->tsp.IgnoreTexA || pp->tcw.PixelFmt == Pixel565;
|
|
|
|
hash |= (pp->tsp.ShadInstr << 7) | (ignoreTexAlpha << 9) | (pp->tsp.UseAlpha << 10)
|
2021-03-01 09:13:40 +00:00
|
|
|
| (pp->tsp.ColorClamp << 11) | ((config::Fog ? pp->tsp.FogCtrl : 2) << 12)
|
2019-11-10 10:27:19 +00:00
|
|
|
| (pp->tsp.SrcInstr << 14) | (pp->tsp.DstInstr << 17);
|
|
|
|
}
|
|
|
|
hash |= (pp->isp.ZWriteDis << 20) | (pp->isp.CullMode << 21) | ((autosort ? 6 : pp->isp.DepthMode) << 23);
|
2021-04-17 16:40:58 +00:00
|
|
|
hash |= ((u32)gpuPalette << 26) | ((u32)pass << 27);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
return hash;
|
|
|
|
}
|
2019-12-05 17:48:54 +00:00
|
|
|
u32 hash(ModVolMode mode, int cullMode) const
|
|
|
|
{
|
|
|
|
return ((int)mode << 2) | cullMode;
|
|
|
|
}
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo(bool full = true) const
|
|
|
|
{
|
|
|
|
// Vertex input state
|
|
|
|
static const vk::VertexInputBindingDescription vertexBindingDescriptions[] =
|
|
|
|
{
|
|
|
|
{ 0, sizeof(Vertex) },
|
|
|
|
};
|
|
|
|
static const vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[] =
|
|
|
|
{
|
|
|
|
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x)), // pos
|
|
|
|
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR8G8B8A8Uint, offsetof(Vertex, col)), // base color
|
|
|
|
vk::VertexInputAttributeDescription(2, 0, vk::Format::eR8G8B8A8Uint, offsetof(Vertex, spc)), // offset color
|
|
|
|
vk::VertexInputAttributeDescription(3, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, u)), // tex coord
|
|
|
|
vk::VertexInputAttributeDescription(4, 0, vk::Format::eR8G8B8A8Uint, offsetof(Vertex, col1)), // base1 color
|
|
|
|
vk::VertexInputAttributeDescription(5, 0, vk::Format::eR8G8B8A8Uint, offsetof(Vertex, spc1)), // offset1 color
|
|
|
|
vk::VertexInputAttributeDescription(6, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, u1)), // tex1 coord
|
|
|
|
};
|
|
|
|
static const vk::VertexInputAttributeDescription vertexInputLightAttributeDescriptions[] =
|
|
|
|
{
|
|
|
|
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x)), // pos
|
|
|
|
};
|
|
|
|
return vk::PipelineVertexInputStateCreateInfo(
|
|
|
|
vk::PipelineVertexInputStateCreateFlags(),
|
|
|
|
ARRAY_SIZE(vertexBindingDescriptions),
|
|
|
|
vertexBindingDescriptions,
|
|
|
|
full ? ARRAY_SIZE(vertexInputAttributeDescriptions) : ARRAY_SIZE(vertexInputLightAttributeDescriptions),
|
|
|
|
full ? vertexInputAttributeDescriptions : vertexInputLightAttributeDescriptions);
|
|
|
|
}
|
|
|
|
|
2021-04-17 16:40:58 +00:00
|
|
|
void CreatePipeline(u32 listType, bool autosort, const PolyParam& pp, Pass pass, bool gpuPalette);
|
2020-01-05 22:03:44 +00:00
|
|
|
void CreateFinalPipeline();
|
2019-11-10 10:27:19 +00:00
|
|
|
void CreateClearPipeline();
|
|
|
|
|
|
|
|
std::map<u32, vk::UniquePipeline> pipelines;
|
2019-12-05 17:48:54 +00:00
|
|
|
std::map<u32, vk::UniquePipeline> modVolPipelines;
|
|
|
|
std::map<u32, vk::UniquePipeline> trModVolPipelines;
|
2020-01-05 22:03:44 +00:00
|
|
|
vk::UniquePipeline finalPipeline;
|
2019-11-10 10:27:19 +00:00
|
|
|
vk::UniquePipeline clearPipeline;
|
|
|
|
|
|
|
|
vk::UniquePipelineLayout pipelineLayout;
|
|
|
|
vk::UniqueDescriptorSetLayout perFrameLayout;
|
2019-11-12 18:39:58 +00:00
|
|
|
vk::UniqueDescriptorSetLayout colorInputLayout;
|
2019-11-10 10:27:19 +00:00
|
|
|
vk::UniqueDescriptorSetLayout perPolyLayout;
|
2019-11-12 18:39:58 +00:00
|
|
|
RenderPasses ownRenderPasses;
|
2019-11-10 10:27:19 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
VulkanContext *GetContext() const { return VulkanContext::Instance(); }
|
|
|
|
|
2019-11-12 18:39:58 +00:00
|
|
|
RenderPasses *renderPasses;
|
|
|
|
OITShaderManager *shaderManager = nullptr;
|
2019-11-10 10:27:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class RttOITPipelineManager : public OITPipelineManager
|
|
|
|
{
|
|
|
|
public:
|
2019-11-12 18:39:58 +00:00
|
|
|
RttOITPipelineManager() { renderPasses = &rttRenderPasses; }
|
2019-11-13 19:08:14 +00:00
|
|
|
void Init(OITShaderManager *shaderManager, OITBuffers *oitBuffers) override
|
2019-11-10 10:27:19 +00:00
|
|
|
{
|
2019-11-13 19:08:14 +00:00
|
|
|
this->oitBuffers = oitBuffers;
|
|
|
|
OITPipelineManager::Init(shaderManager, oitBuffers);
|
2019-11-10 10:27:19 +00:00
|
|
|
|
2021-03-01 09:13:40 +00:00
|
|
|
renderToTextureBuffer = config::RenderToTextureBuffer;
|
2019-11-12 18:39:58 +00:00
|
|
|
rttRenderPasses.Reset();
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
void CheckSettingsChange()
|
|
|
|
{
|
2021-03-01 09:13:40 +00:00
|
|
|
if (renderToTextureBuffer != config::RenderToTextureBuffer)
|
2019-11-12 18:39:58 +00:00
|
|
|
{
|
2019-11-13 19:08:14 +00:00
|
|
|
Init(shaderManager, oitBuffers);
|
2019-11-12 18:39:58 +00:00
|
|
|
}
|
2019-11-10 10:27:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-11-12 18:39:58 +00:00
|
|
|
bool renderToTextureBuffer = false;
|
|
|
|
RttRenderPasses rttRenderPasses;
|
2019-11-13 19:08:14 +00:00
|
|
|
OITBuffers *oitBuffers = nullptr;
|
2019-11-10 10:27:19 +00:00
|
|
|
};
|