naomi2: vulkan support
oit: use #define instead of functions in GLSL
This commit is contained in:
parent
27ddc215cc
commit
1015a8c098
|
@ -1563,8 +1563,8 @@ bool ta_parse_vdrc(TA_context* ctx)
|
|||
|
||||
const bool mergeTranslucent = !config::PerStripSorting
|
||||
|| config::RendererType == RenderType::OpenGL_OIT
|
||||
|| config::RendererType == RenderType::DirectX11_OIT;
|
||||
// TODO || config::RendererType == RenderType::Vulkan_OIT
|
||||
|| config::RendererType == RenderType::DirectX11_OIT
|
||||
|| config::RendererType == RenderType::Vulkan_OIT;
|
||||
TA_context *childCtx = ctx;
|
||||
while (childCtx != nullptr)
|
||||
{
|
||||
|
@ -1684,8 +1684,8 @@ bool ta_parse_naomi2(TA_context* ctx)
|
|||
int tr_count = 0;
|
||||
const bool mergeTranslucent = !config::PerStripSorting
|
||||
|| config::RendererType == RenderType::OpenGL_OIT
|
||||
|| config::RendererType == RenderType::DirectX11_OIT;
|
||||
// TODO || config::RendererType == RenderType::Vulkan_OIT
|
||||
|| config::RendererType == RenderType::DirectX11_OIT
|
||||
|| config::RendererType == RenderType::Vulkan_OIT;
|
||||
for (const RenderPass& pass : ctx->rend.render_passes)
|
||||
{
|
||||
make_index(&ctx->rend.global_param_op, op_count, pass.op_count, true, &ctx->rend);
|
||||
|
|
|
@ -49,93 +49,40 @@ struct PolyParam { \n\
|
|||
int tsp1; \n\
|
||||
}; \n\
|
||||
\n\
|
||||
#define GET_TSP_FOR_AREA int tsp = area1 ? pp.tsp1 : pp.tsp_isp_pcw; \n\
|
||||
#define GET_TSP_FOR_AREA(pp, area1) ((area1) ? (pp).tsp1 : (pp).tsp_isp_pcw) \n\
|
||||
\n\
|
||||
int getSrcBlendFunc(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return (tsp >> 29) & 7; \n\
|
||||
} \n\
|
||||
#define getSrcBlendFunc(pp, area1) ((GET_TSP_FOR_AREA(pp, area1) >> 29) & 7) \n\
|
||||
\n\
|
||||
int getDstBlendFunc(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return (tsp >> 26) & 7; \n\
|
||||
} \n\
|
||||
#define getDstBlendFunc(pp, area1) ((GET_TSP_FOR_AREA(pp, area1) >> 26) & 7) \n\
|
||||
\n\
|
||||
bool getSrcSelect(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return ((tsp >> 25) & 1) != 0; \n\
|
||||
} \n\
|
||||
#define getSrcSelect(pp, area1) (((GET_TSP_FOR_AREA(pp, area1) >> 25) & 1) != 0) \n\
|
||||
\n\
|
||||
bool getDstSelect(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return ((tsp >> 24) & 1) != 0; \n\
|
||||
} \n\
|
||||
#define getDstSelect(pp, area1) (((GET_TSP_FOR_AREA(pp, area1) >> 24) & 1) != 0) \n\
|
||||
\n\
|
||||
int getFogControl(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return (tsp >> 22) & 3; \n\
|
||||
} \n\
|
||||
#define getFogControl(pp, area1) ((GET_TSP_FOR_AREA(pp, area1) >> 22) & 3) \n\
|
||||
\n\
|
||||
bool getUseAlpha(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return ((tsp >> 20) & 1) != 0; \n\
|
||||
} \n\
|
||||
#define getUseAlpha(pp, area1) (((GET_TSP_FOR_AREA(pp, area1) >> 20) & 1) != 0) \n\
|
||||
\n\
|
||||
bool getIgnoreTexAlpha(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return ((tsp >> 19) & 1) != 0; \n\
|
||||
} \n\
|
||||
#define getIgnoreTexAlpha(pp, area1) (((GET_TSP_FOR_AREA(pp, area1) >> 19) & 1) != 0) \n\
|
||||
\n\
|
||||
int getShadingInstruction(const PolyParam pp, bool area1) \n\
|
||||
{ \n\
|
||||
GET_TSP_FOR_AREA \n\
|
||||
return (tsp >> 6) & 3; \n\
|
||||
} \n\
|
||||
#define getShadingInstruction(pp, area1) ((GET_TSP_FOR_AREA(pp, area1) >> 6) & 3) \n\
|
||||
\n\
|
||||
int getDepthFunc(const PolyParam pp) \n\
|
||||
{ \n\
|
||||
return (pp.tsp_isp_pcw >> 13) & 7; \n\
|
||||
} \n\
|
||||
#define getDepthFunc(pp) (((pp).tsp_isp_pcw >> 13) & 7) \n\
|
||||
\n\
|
||||
bool getDepthMask(const PolyParam pp) \n\
|
||||
{ \n\
|
||||
return ((pp.tsp_isp_pcw >> 10) & 1) != 1; \n\
|
||||
} \n\
|
||||
#define getDepthMask(pp) ((((pp).tsp_isp_pcw >> 10) & 1) != 1) \n\
|
||||
\n\
|
||||
bool getShadowEnable(const PolyParam pp) \n\
|
||||
{ \n\
|
||||
return (pp.tsp_isp_pcw & 1) != 0; \n\
|
||||
} \n\
|
||||
#define getShadowEnable(pp) (((pp).tsp_isp_pcw & 1) != 0) \n\
|
||||
\n\
|
||||
uint getPolyNumber(const Pixel pixel) \n\
|
||||
{ \n\
|
||||
return (pixel.seq_num & 0x3FFFFFFFu) >> 18; \n\
|
||||
} \n\
|
||||
#define getPolyNumber(pixel) (((pixel).seq_num & 0x3FFFFFFFu) >> 18) \n\
|
||||
\n\
|
||||
uint getPolyIndex(const Pixel pixel) \n\
|
||||
{ \n\
|
||||
return pixel.seq_num & 0x3FFFFFFFu; \n\
|
||||
} \n\
|
||||
#define getPolyIndex(pixel) ((pixel).seq_num & 0x3FFFFFFFu) \n\
|
||||
\n\
|
||||
#define SHADOW_STENCIL 0x40000000u \n\
|
||||
#define SHADOW_ACC 0x80000000u \n\
|
||||
\n\
|
||||
bool isShadowed(const Pixel pixel) \n\
|
||||
{ \n\
|
||||
return (pixel.seq_num & SHADOW_ACC) == SHADOW_ACC; \n\
|
||||
} \n\
|
||||
#define isShadowed(pixel) (((pixel).seq_num & SHADOW_ACC) == SHADOW_ACC) \n\
|
||||
\n\
|
||||
bool isTwoVolumes(const PolyParam pp) \n\
|
||||
{ \n\
|
||||
return pp.tsp1 != -1; \n\
|
||||
} \n\
|
||||
#define isTwoVolumes(pp) ((pp).tsp1 != -1) \n\
|
||||
\n\
|
||||
uint packColors(vec4 v) \n\
|
||||
{ \n\
|
||||
|
|
|
@ -38,3 +38,9 @@ BufferData::BufferData(vk::DeviceSize size, const vk::BufferUsageFlags& usage, c
|
|||
#endif
|
||||
allocation = context->GetAllocator().AllocateForBuffer(*buffer, allocInfo);
|
||||
}
|
||||
|
||||
BufferPacker::BufferPacker()
|
||||
{
|
||||
uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
|
||||
storageAlignment = VulkanContext::Instance()->GetStorageBufferAlignment();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
#include "vulkan.h"
|
||||
#include "vmallocator.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct BufferData
|
||||
{
|
||||
|
@ -92,3 +93,50 @@ private:
|
|||
vk::BufferUsageFlags m_usage;
|
||||
vk::MemoryPropertyFlags m_propertyFlags;
|
||||
};
|
||||
|
||||
class BufferPacker
|
||||
{
|
||||
public:
|
||||
BufferPacker();
|
||||
|
||||
vk::DeviceSize addUniform(const void *p, size_t size) {
|
||||
return add(p, size, uniformAlignment);
|
||||
}
|
||||
|
||||
vk::DeviceSize addStorage(const void *p, size_t size) {
|
||||
return add(p, size, storageAlignment);
|
||||
}
|
||||
|
||||
vk::DeviceSize add(const void *p, size_t size, u32 alignment = 4)
|
||||
{
|
||||
u32 padding = align(offset, std::max(4u, alignment));
|
||||
if (padding != 0)
|
||||
{
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
offset += padding;
|
||||
}
|
||||
vk::DeviceSize start = offset;
|
||||
chunks.push_back(p);
|
||||
chunkSizes.push_back(size);
|
||||
offset += size;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
void upload(BufferData& bufferData, u32 bufOffset = 0)
|
||||
{
|
||||
bufferData.upload(chunks.size(), &chunkSizes[0], &chunks[0], bufOffset);
|
||||
}
|
||||
|
||||
vk::DeviceSize size() const {
|
||||
return offset;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<const void *> chunks;
|
||||
std::vector<u32> chunkSizes;
|
||||
vk::DeviceSize offset = 0;
|
||||
vk::DeviceSize uniformAlignment;
|
||||
vk::DeviceSize storageAlignment;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright 2022 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
|
||||
#include "vulkan_context.h"
|
||||
#include <array>
|
||||
|
||||
template<int Size>
|
||||
class DescSetAlloc
|
||||
{
|
||||
public:
|
||||
void setLayout(vk::DescriptorSetLayout layout) {
|
||||
this->layout = layout;
|
||||
}
|
||||
void setAllocChunk(int size) {
|
||||
this->allocChunk = size;
|
||||
}
|
||||
|
||||
void nextFrame()
|
||||
{
|
||||
index = (index + 1) % Size;
|
||||
for (auto& descset : descSetsInFlight[index])
|
||||
descSets.emplace_back(std::move(descset));
|
||||
descSetsInFlight[index].clear();
|
||||
}
|
||||
|
||||
vk::DescriptorSet alloc()
|
||||
{
|
||||
if (descSets.empty())
|
||||
{
|
||||
std::vector<vk::DescriptorSetLayout> layouts(allocChunk, layout);
|
||||
descSets = VulkanContext::Instance()->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(VulkanContext::Instance()->GetDescriptorPool(), (u32)layouts.size(), &layouts[0]));
|
||||
}
|
||||
descSetsInFlight[index].emplace_back(std::move(descSets.back()));
|
||||
descSets.pop_back();
|
||||
return *descSetsInFlight[index].back();
|
||||
}
|
||||
|
||||
private:
|
||||
vk::DescriptorSetLayout layout;
|
||||
std::vector<vk::UniqueDescriptorSet> descSets;
|
||||
std::array<std::vector<vk::UniqueDescriptorSet>, Size> descSetsInFlight;
|
||||
int index = 0;
|
||||
int allocChunk = 10;
|
||||
};
|
||||
|
||||
class DynamicDescSetAlloc
|
||||
{
|
||||
public:
|
||||
DynamicDescSetAlloc() {
|
||||
descSetsInFlight.resize(1);
|
||||
}
|
||||
|
||||
void setLayout(vk::DescriptorSetLayout layout) {
|
||||
this->layout = layout;
|
||||
}
|
||||
void setAllocChunk(int size) {
|
||||
this->allocChunk = size;
|
||||
}
|
||||
|
||||
void nextFrame()
|
||||
{
|
||||
unsigned swapChainSize = VulkanContext::Instance()->GetSwapChainSize();
|
||||
if (swapChainSize > descSetsInFlight.size())
|
||||
descSetsInFlight.resize(swapChainSize);
|
||||
else
|
||||
while (swapChainSize < descSetsInFlight.size())
|
||||
{
|
||||
for (auto& descset : descSetsInFlight[descSetsInFlight.size() - 1])
|
||||
descSets.emplace_back(std::move(descset));
|
||||
descSetsInFlight.resize(descSetsInFlight.size() - 1);
|
||||
}
|
||||
|
||||
index = (index + 1) % descSetsInFlight.size();
|
||||
for (auto& descset : descSetsInFlight[index])
|
||||
descSets.emplace_back(std::move(descset));
|
||||
descSetsInFlight[index].clear();
|
||||
}
|
||||
|
||||
vk::DescriptorSet alloc()
|
||||
{
|
||||
if (descSets.empty())
|
||||
{
|
||||
std::vector<vk::DescriptorSetLayout> layouts(allocChunk, layout);
|
||||
descSets = VulkanContext::Instance()->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(VulkanContext::Instance()->GetDescriptorPool(), (u32)layouts.size(), &layouts[0]));
|
||||
}
|
||||
descSetsInFlight[index].emplace_back(std::move(descSets.back()));
|
||||
descSets.pop_back();
|
||||
return *descSetsInFlight[index].back();
|
||||
}
|
||||
|
||||
void term()
|
||||
{
|
||||
descSets.clear();
|
||||
descSetsInFlight.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
vk::DescriptorSetLayout layout;
|
||||
std::vector<vk::UniqueDescriptorSet> descSets;
|
||||
std::vector<std::vector<vk::UniqueDescriptorSet>> descSetsInFlight;
|
||||
int index = 0;
|
||||
int allocChunk = 10;
|
||||
};
|
|
@ -143,14 +143,32 @@ void Drawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool sor
|
|||
cmdBuffer.pushConstants<float>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
|
||||
}
|
||||
|
||||
if (poly.pcw.Texture)
|
||||
GetCurrentDescSet().SetTexture((Texture *)poly.texture, poly.tsp);
|
||||
|
||||
vk::Pipeline pipeline = pipelineManager->GetPipeline(listType, sortTriangles, poly, gpuPalette);
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
if (poly.pcw.Texture)
|
||||
GetCurrentDescSet().BindPerPolyDescriptorSets(cmdBuffer, (Texture *)poly.texture, poly.tsp);
|
||||
|
||||
if (poly.pcw.Texture || poly.isNaomi2())
|
||||
{
|
||||
vk::DeviceSize offset = 0;
|
||||
u32 index = 0;
|
||||
if (poly.isNaomi2())
|
||||
{
|
||||
switch (listType)
|
||||
{
|
||||
case ListType_Opaque:
|
||||
offset = offsets.naomi2OpaqueOffset;
|
||||
index = &poly - pvrrc.global_param_op.head();
|
||||
break;
|
||||
case ListType_Punch_Through:
|
||||
offset = offsets.naomi2PunchThroughOffset;
|
||||
index = &poly - pvrrc.global_param_pt.head();
|
||||
break;
|
||||
case ListType_Translucent:
|
||||
offset = offsets.naomi2TranslucentOffset;
|
||||
index = &poly - pvrrc.global_param_tr.head();
|
||||
break;
|
||||
}
|
||||
}
|
||||
descriptorSets.bindPerPolyDescriptorSets(cmdBuffer, poly, index, *GetMainBuffer(0)->buffer, offset, offsets.lightsOffset);
|
||||
}
|
||||
cmdBuffer.drawIndexed(count, 1, first, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -165,7 +183,7 @@ void Drawer::DrawSorted(const vk::CommandBuffer& cmdBuffer, const std::vector<So
|
|||
{
|
||||
if (param.ppid->isp.ZWriteDis)
|
||||
continue;
|
||||
vk::Pipeline pipeline = pipelineManager->GetDepthPassPipeline(param.ppid->isp.CullMode);
|
||||
vk::Pipeline pipeline = pipelineManager->GetDepthPassPipeline(param.ppid->isp.CullMode, param.ppid->isNaomi2());
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
vk::Rect2D scissorRect;
|
||||
TileClipping tileClip = SetTileClip(param.ppid->tileclip, scissorRect);
|
||||
|
@ -213,16 +231,19 @@ void Drawer::DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int coun
|
|||
mod_base = param.first;
|
||||
|
||||
if (!param.isp.VolumeLast && mv_mode > 0)
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode); // OR'ing (open volume or quad)
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode, param.isNaomi2()); // OR'ing (open volume or quad)
|
||||
else
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode); // XOR'ing (closed volume)
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode, param.isNaomi2()); // XOR'ing (closed volume)
|
||||
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
descriptorSets.bindPerPolyDescriptorSets(cmdBuffer, param, first + cmv, *GetMainBuffer(0)->buffer, offsets.naomi2ModVolOffset);
|
||||
|
||||
cmdBuffer.draw(param.count * 3, 1, param.first * 3, 0);
|
||||
|
||||
if (mv_mode == 1 || mv_mode == 2)
|
||||
{
|
||||
// Sum the area
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode, param.isNaomi2());
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
cmdBuffer.draw((param.first + param.count - mod_base) * 3, 1, mod_base * 3, 0);
|
||||
mod_base = -1;
|
||||
|
@ -234,65 +255,38 @@ void Drawer::DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int coun
|
|||
std::array<float, 5> pushConstants = { 1 - FPU_SHAD_SCALE.scale_factor / 256.f, 0, 0, 0, 0 };
|
||||
cmdBuffer.pushConstants<float>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
|
||||
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Final, 0);
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Final, 0, false);
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
cmdBuffer.drawIndexed(4, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Drawer::UploadMainBuffer(const VertexShaderUniforms& vertexUniforms, const FragmentShaderUniforms& fragmentUniforms)
|
||||
{
|
||||
// TODO Put this logic in an allocator
|
||||
std::vector<const void *> chunks;
|
||||
std::vector<u32> chunkSizes;
|
||||
BufferPacker packer;
|
||||
|
||||
// Vertex
|
||||
chunks.push_back(pvrrc.verts.head());
|
||||
chunkSizes.push_back(pvrrc.verts.bytes());
|
||||
|
||||
u32 padding = align(pvrrc.verts.bytes(), 4);
|
||||
offsets.modVolOffset = pvrrc.verts.bytes() + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
packer.add(pvrrc.verts.head(), pvrrc.verts.bytes());
|
||||
// Modifier Volumes
|
||||
chunks.push_back(pvrrc.modtrig.head());
|
||||
chunkSizes.push_back(pvrrc.modtrig.bytes());
|
||||
padding = align(offsets.modVolOffset + pvrrc.modtrig.bytes(), 4);
|
||||
offsets.indexOffset = offsets.modVolOffset + pvrrc.modtrig.bytes() + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
offsets.modVolOffset = packer.add(pvrrc.modtrig.head(), pvrrc.modtrig.bytes());
|
||||
// Index
|
||||
chunks.push_back(pvrrc.idx.head());
|
||||
chunkSizes.push_back(pvrrc.idx.bytes());
|
||||
offsets.indexOffset = packer.add(pvrrc.idx.head(), pvrrc.idx.bytes());
|
||||
for (const std::vector<u32>& idx : sortedIndexes)
|
||||
{
|
||||
if (!idx.empty())
|
||||
{
|
||||
chunks.push_back(&idx[0]);
|
||||
chunkSizes.push_back(idx.size() * sizeof(u32));
|
||||
}
|
||||
}
|
||||
packer.add(&idx[0], idx.size() * sizeof(u32));
|
||||
// Uniform buffers
|
||||
u32 indexSize = pvrrc.idx.bytes() + sortedIndexCount * sizeof(u32);
|
||||
padding = align(offsets.indexOffset + indexSize, std::max(4, (int)GetContext()->GetUniformBufferAlignment()));
|
||||
offsets.vertexUniformOffset = offsets.indexOffset + indexSize + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
offsets.vertexUniformOffset = packer.addUniform(&vertexUniforms, sizeof(vertexUniforms));
|
||||
offsets.fragmentUniformOffset = packer.addUniform(&fragmentUniforms, sizeof(fragmentUniforms));
|
||||
|
||||
chunks.push_back(&vertexUniforms);
|
||||
chunkSizes.push_back(sizeof(vertexUniforms));
|
||||
padding = align(offsets.vertexUniformOffset + sizeof(VertexShaderUniforms), std::max(4, (int)GetContext()->GetUniformBufferAlignment()));
|
||||
offsets.fragmentUniformOffset = offsets.vertexUniformOffset + sizeof(VertexShaderUniforms) + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
std::vector<u8> n2uniforms;
|
||||
std::vector<u8> n2lights;
|
||||
if (settings.platform.isNaomi2())
|
||||
{
|
||||
uploadNaomi2Uniforms(packer, offsets, n2uniforms, false);
|
||||
offsets.lightsOffset = uploadNaomi2Lights(packer, n2lights);
|
||||
}
|
||||
|
||||
chunks.push_back(&fragmentUniforms);
|
||||
chunkSizes.push_back(sizeof(fragmentUniforms));
|
||||
u32 totalSize = (u32)(offsets.fragmentUniformOffset + sizeof(FragmentShaderUniforms));
|
||||
|
||||
BufferData *buffer = GetMainBuffer(totalSize);
|
||||
buffer->upload(chunks.size(), &chunkSizes[0], &chunks[0]);
|
||||
BufferData *buffer = GetMainBuffer(packer.size());
|
||||
packer.upload(*buffer);
|
||||
}
|
||||
|
||||
bool Drawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
||||
|
@ -311,16 +305,27 @@ bool Drawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
|
||||
setFirstProvokingVertex(pvrrc);
|
||||
|
||||
// Do per-poly sorting
|
||||
RenderPass previous_pass = {};
|
||||
if (config::PerStripSorting)
|
||||
for (int render_pass = 0; render_pass < pvrrc.render_passes.used(); render_pass++)
|
||||
{
|
||||
const RenderPass& current_pass = pvrrc.render_passes.head()[render_pass];
|
||||
if (current_pass.autosort)
|
||||
SortPParams(previous_pass.tr_count, current_pass.tr_count - previous_pass.tr_count);
|
||||
previous_pass = current_pass;
|
||||
}
|
||||
|
||||
// Upload vertex and index buffers
|
||||
VertexShaderUniforms vtxUniforms;
|
||||
vtxUniforms.normal_matrix = matrices.GetNormalMatrix();
|
||||
vtxUniforms.ndcMat = matrices.GetNormalMatrix();
|
||||
|
||||
UploadMainBuffer(vtxUniforms, fragUniforms);
|
||||
|
||||
// Update per-frame descriptor set and bind it
|
||||
GetCurrentDescSet().UpdateUniforms(GetMainBuffer(0)->buffer.get(), (u32)offsets.vertexUniformOffset, (u32)offsets.fragmentUniformOffset,
|
||||
descriptorSets.updateUniforms(GetMainBuffer(0)->buffer.get(), (u32)offsets.vertexUniformOffset, (u32)offsets.fragmentUniformOffset,
|
||||
fogTexture->GetImageView(), paletteTexture->GetImageView());
|
||||
GetCurrentDescSet().BindPerFrameDescriptorSets(cmdBuffer);
|
||||
descriptorSets.bindPerFrameDescriptorSets(cmdBuffer);
|
||||
|
||||
// Bind vertex and index buffers
|
||||
const vk::DeviceSize zeroOffset[] = { 0 };
|
||||
|
@ -332,7 +337,7 @@ bool Drawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
std::array<float, 5> pushConstants = { 0, 0, 0, 0, 0 };
|
||||
cmdBuffer.pushConstants<float>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
|
||||
|
||||
RenderPass previous_pass = {};
|
||||
previous_pass = {};
|
||||
for (int render_pass = 0; render_pass < pvrrc.render_passes.used(); render_pass++)
|
||||
{
|
||||
const RenderPass& current_pass = pvrrc.render_passes.head()[render_pass];
|
||||
|
@ -348,14 +353,9 @@ bool Drawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
if (current_pass.autosort)
|
||||
{
|
||||
if (!config::PerStripSorting)
|
||||
{
|
||||
DrawSorted(cmdBuffer, sortedPolys[render_pass], render_pass + 1 < pvrrc.render_passes.used());
|
||||
}
|
||||
else
|
||||
{
|
||||
SortPParams(previous_pass.tr_count, current_pass.tr_count - previous_pass.tr_count);
|
||||
DrawList(cmdBuffer, ListType_Translucent, true, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count);
|
||||
}
|
||||
}
|
||||
else
|
||||
DrawList(cmdBuffer, ListType_Translucent, false, pvrrc.global_param_tr, previous_pass.tr_count, current_pass.tr_count);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
class BaseDrawer
|
||||
{
|
||||
|
@ -51,11 +52,6 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
u32 align(vk::DeviceSize offset, u32 alignment)
|
||||
{
|
||||
return (u32)(alignment - (offset & (alignment - 1)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MakeFragmentUniforms()
|
||||
{
|
||||
|
@ -76,6 +72,117 @@ protected:
|
|||
return fragUniforms;
|
||||
}
|
||||
|
||||
template<typename Offsets>
|
||||
void uploadNaomi2Uniforms(BufferPacker& packer, Offsets& offsets, std::vector<u8>& n2uniforms, bool trModVolIncluded)
|
||||
{
|
||||
size_t n2UniformSize = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), GetContext()->GetUniformBufferAlignment());
|
||||
int items = pvrrc.global_param_op.used() + pvrrc.global_param_pt.used() + pvrrc.global_param_tr.used() + pvrrc.global_param_mvo.used();
|
||||
if (trModVolIncluded)
|
||||
items += pvrrc.global_param_mvo_tr.used();
|
||||
n2uniforms.resize(items * n2UniformSize);
|
||||
size_t bufIdx = 0;
|
||||
auto addUniform = [&](const PolyParam& pp, int polyNumber) {
|
||||
if (pp.isNaomi2())
|
||||
{
|
||||
N2VertexShaderUniforms& uni = *(N2VertexShaderUniforms *)&n2uniforms[bufIdx];
|
||||
memcpy(glm::value_ptr(uni.mvMat), pp.mvMatrix, sizeof(uni.mvMat));
|
||||
memcpy(glm::value_ptr(uni.normalMat), pp.normalMatrix, sizeof(uni.normalMat));
|
||||
memcpy(glm::value_ptr(uni.projMat), pp.projMatrix, sizeof(uni.projMat));
|
||||
uni.bumpMapping = pp.pcw.Texture == 1 && pp.tcw.PixelFmt == PixelBumpMap;
|
||||
uni.polyNumber = polyNumber;
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
{
|
||||
uni.envMapping[i] = pp.envMapping[i];
|
||||
uni.glossCoef[i] = pp.glossCoef[i];
|
||||
uni.constantColor[i] = pp.constantColor[i];
|
||||
uni.modelDiffuse[i] = pp.diffuseColor[i];
|
||||
uni.modelSpecular[i] = pp.specularColor[i];
|
||||
}
|
||||
}
|
||||
bufIdx += n2UniformSize;
|
||||
};
|
||||
for (const PolyParam& pp : pvrrc.global_param_op)
|
||||
addUniform(pp, 0);
|
||||
size_t ptOffset = bufIdx;
|
||||
for (const PolyParam& pp : pvrrc.global_param_pt)
|
||||
addUniform(pp, 0);
|
||||
size_t trOffset = bufIdx;
|
||||
for (const PolyParam& pp : pvrrc.global_param_tr)
|
||||
addUniform(pp, &pp - pvrrc.global_param_tr.head());
|
||||
size_t mvOffset = bufIdx;
|
||||
for (const ModifierVolumeParam& mvp : pvrrc.global_param_mvo)
|
||||
{
|
||||
if (mvp.isNaomi2())
|
||||
{
|
||||
N2VertexShaderUniforms& uni = *(N2VertexShaderUniforms *)&n2uniforms[bufIdx];
|
||||
memcpy(glm::value_ptr(uni.mvMat), mvp.mvMatrix, sizeof(uni.mvMat));
|
||||
memcpy(glm::value_ptr(uni.projMat), mvp.projMatrix, sizeof(uni.projMat));
|
||||
}
|
||||
bufIdx += n2UniformSize;
|
||||
}
|
||||
size_t trMvOffset = bufIdx;
|
||||
if (trModVolIncluded)
|
||||
for (const ModifierVolumeParam& mvp : pvrrc.global_param_mvo_tr)
|
||||
{
|
||||
if (mvp.isNaomi2())
|
||||
{
|
||||
N2VertexShaderUniforms& uni = *(N2VertexShaderUniforms *)&n2uniforms[bufIdx];
|
||||
memcpy(glm::value_ptr(uni.mvMat), mvp.mvMatrix, sizeof(uni.mvMat));
|
||||
memcpy(glm::value_ptr(uni.projMat), mvp.projMatrix, sizeof(uni.projMat));
|
||||
}
|
||||
bufIdx += n2UniformSize;
|
||||
}
|
||||
offsets.naomi2OpaqueOffset = packer.addUniform(n2uniforms.data(), bufIdx);
|
||||
offsets.naomi2PunchThroughOffset = offsets.naomi2OpaqueOffset + ptOffset;
|
||||
offsets.naomi2TranslucentOffset = offsets.naomi2OpaqueOffset + trOffset;
|
||||
offsets.naomi2ModVolOffset = offsets.naomi2OpaqueOffset + mvOffset;
|
||||
offsets.naomi2TrModVolOffset = offsets.naomi2OpaqueOffset + trMvOffset;
|
||||
}
|
||||
|
||||
vk::DeviceSize uploadNaomi2Lights(BufferPacker& packer, std::vector<u8>& n2lights)
|
||||
{
|
||||
size_t n2LightSize = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), GetContext()->GetUniformBufferAlignment());
|
||||
n2lights.resize(pvrrc.lightModels.used() * n2LightSize);
|
||||
size_t bufIdx = 0;
|
||||
for (const N2LightModel& lights : pvrrc.lightModels)
|
||||
{
|
||||
VkN2LightConstants& vkLights = *(VkN2LightConstants *)&n2lights[bufIdx];
|
||||
vkLights.lightCount = lights.lightCount;
|
||||
for (int i = 0; i < lights.lightCount; i++)
|
||||
{
|
||||
VkN2Light& vkLight = vkLights.lights[i];
|
||||
const N2Light& light = lights.lights[i];
|
||||
memcpy(vkLight.color, light.color, sizeof(vkLight.color));
|
||||
memcpy(vkLight.direction, light.direction, sizeof(vkLight.direction));
|
||||
memcpy(vkLight.position, light.position, sizeof(vkLight.position));
|
||||
vkLight.parallel = light.parallel;
|
||||
vkLight.routing = light.routing;
|
||||
vkLight.dmode = light.dmode;
|
||||
vkLight.smode = light.smode;
|
||||
memcpy(vkLight.diffuse, light.diffuse, sizeof(vkLight.diffuse));
|
||||
memcpy(vkLight.specular, light.specular, sizeof(vkLight.specular));
|
||||
vkLight.attnDistA = light.attnDistA;
|
||||
vkLight.attnDistB = light.attnDistB;
|
||||
vkLight.attnAngleA = light.attnAngleA;
|
||||
vkLight.attnAngleB = light.attnAngleB;
|
||||
vkLight.distAttnMode = light.distAttnMode;
|
||||
}
|
||||
memcpy(vkLights.ambientBase, lights.ambientBase, sizeof(vkLights.ambientBase));
|
||||
memcpy(vkLights.ambientOffset, lights.ambientOffset, sizeof(vkLights.ambientOffset));
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
vkLights.ambientMaterialBase[i] = lights.ambientMaterialBase[i];
|
||||
vkLights.ambientMaterialOffset[i] = lights.ambientMaterialOffset[i];
|
||||
}
|
||||
vkLights.useBaseOver = lights.useBaseOver;
|
||||
vkLights.bumpId1 = lights.bumpId1;
|
||||
vkLights.bumpId2 = lights.bumpId2;
|
||||
|
||||
bufIdx += n2LightSize;
|
||||
}
|
||||
return packer.addUniform(n2lights.data(), bufIdx);
|
||||
}
|
||||
|
||||
vk::Rect2D baseScissor;
|
||||
vk::Rect2D currentScissor;
|
||||
TransformMatrix<COORD_VULKAN> matrices;
|
||||
|
@ -95,7 +202,7 @@ protected:
|
|||
virtual vk::CommandBuffer BeginRenderPass() = 0;
|
||||
void NewImage()
|
||||
{
|
||||
GetCurrentDescSet().Reset();
|
||||
descriptorSets.reset();
|
||||
imageIndex = (imageIndex + 1) % GetSwapChainSize();
|
||||
if (perStripSorting != config::PerStripSorting)
|
||||
{
|
||||
|
@ -110,18 +217,10 @@ protected:
|
|||
this->pipelineManager = pipelineManager;
|
||||
this->samplerManager = samplerManager;
|
||||
|
||||
size_t size = GetSwapChainSize();
|
||||
if (descriptorSets.size() > size)
|
||||
descriptorSets.resize(size);
|
||||
else
|
||||
while (descriptorSets.size() < size)
|
||||
{
|
||||
descriptorSets.emplace_back();
|
||||
descriptorSets.back().Init(samplerManager, pipelineManager->GetPipelineLayout(), pipelineManager->GetPerFrameDSLayout(), pipelineManager->GetPerPolyDSLayout());
|
||||
}
|
||||
descriptorSets.init(samplerManager, pipelineManager->GetPipelineLayout(), pipelineManager->GetPerFrameDSLayout(), pipelineManager->GetPerPolyDSLayout());
|
||||
}
|
||||
|
||||
int GetCurrentImage() const { return imageIndex; }
|
||||
DescriptorSets& GetCurrentDescSet() { return descriptorSets[GetCurrentImage()]; }
|
||||
|
||||
BufferData* GetMainBuffer(u32 size)
|
||||
{
|
||||
|
@ -141,7 +240,7 @@ protected:
|
|||
vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eUniformBuffer));
|
||||
}
|
||||
return mainBuffers[bufferIndex].get();
|
||||
};
|
||||
}
|
||||
|
||||
vk::CommandBuffer currentCommandBuffer;
|
||||
SamplerManager *samplerManager = nullptr;
|
||||
|
@ -161,8 +260,14 @@ private:
|
|||
vk::DeviceSize modVolOffset = 0;
|
||||
vk::DeviceSize vertexUniformOffset = 0;
|
||||
vk::DeviceSize fragmentUniformOffset = 0;
|
||||
vk::DeviceSize naomi2OpaqueOffset = 0;
|
||||
vk::DeviceSize naomi2PunchThroughOffset = 0;
|
||||
vk::DeviceSize naomi2TranslucentOffset = 0;
|
||||
vk::DeviceSize naomi2ModVolOffset = 0;
|
||||
vk::DeviceSize naomi2TrModVolOffset = 0;
|
||||
vk::DeviceSize lightsOffset = 0;
|
||||
} offsets;
|
||||
std::vector<DescriptorSets> descriptorSets;
|
||||
DescriptorSets descriptorSets;
|
||||
std::vector<std::unique_ptr<BufferData>> mainBuffers;
|
||||
PipelineManager *pipelineManager = nullptr;
|
||||
|
||||
|
|
|
@ -30,18 +30,7 @@ public:
|
|||
void Init(int width, int height)
|
||||
{
|
||||
const VulkanContext *context = VulkanContext::Instance();
|
||||
if (!descSetLayout)
|
||||
{
|
||||
// Descriptor set and pipeline layout
|
||||
vk::DescriptorSetLayoutBinding descSetLayoutBindings[] = {
|
||||
{ 0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // pixel buffer
|
||||
{ 1, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // pixel counter
|
||||
{ 2, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // a-buffer pointers
|
||||
};
|
||||
|
||||
descSetLayout = context->GetDevice().createDescriptorSetLayoutUnique(
|
||||
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(descSetLayoutBindings), descSetLayoutBindings));
|
||||
}
|
||||
if (width <= maxWidth && height <= maxHeight)
|
||||
return;
|
||||
maxWidth = std::max(maxWidth, width);
|
||||
|
@ -66,23 +55,19 @@ public:
|
|||
abufferPointer = std::unique_ptr<BufferData>(new BufferData(maxWidth * maxHeight * sizeof(int),
|
||||
vk::BufferUsageFlagBits::eStorageBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal));
|
||||
firstFrameAfterInit = true;
|
||||
|
||||
if (!descSet)
|
||||
descSet = std::move(context->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(context->GetDescriptorPool(), 1, &descSetLayout.get())).front());
|
||||
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
||||
vk::DescriptorBufferInfo pixelBufferInfo(*pixelBuffer->buffer, 0, VK_WHOLE_SIZE);
|
||||
writeDescriptorSets.emplace_back(*descSet, 0, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &pixelBufferInfo, nullptr);
|
||||
vk::DescriptorBufferInfo pixelCounterBufferInfo(*pixelCounter->buffer, 0, 4);
|
||||
writeDescriptorSets.emplace_back(*descSet, 1, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &pixelCounterBufferInfo, nullptr);
|
||||
vk::DescriptorBufferInfo abufferPointerInfo(*abufferPointer->buffer, 0, VK_WHOLE_SIZE);
|
||||
writeDescriptorSets.emplace_back(*descSet, 2, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &abufferPointerInfo, nullptr);
|
||||
context->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
}
|
||||
|
||||
void BindDescriptorSet(vk::CommandBuffer cmdBuffer, vk::PipelineLayout pipelineLayout, u32 firstSet)
|
||||
void updateDescriptorSet(vk::DescriptorSet descSet, std::vector<vk::WriteDescriptorSet>& writeDescSets)
|
||||
{
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, firstSet, 1, &descSet.get(), 0, nullptr);
|
||||
static vk::DescriptorBufferInfo pixelBufferInfo({}, 0, VK_WHOLE_SIZE);
|
||||
pixelBufferInfo.buffer = *pixelBuffer->buffer;
|
||||
writeDescSets.emplace_back(descSet, 7, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &pixelBufferInfo, nullptr);
|
||||
static vk::DescriptorBufferInfo pixelCounterBufferInfo({}, 0, 4);
|
||||
pixelCounterBufferInfo.buffer = *pixelCounter->buffer;
|
||||
writeDescSets.emplace_back(descSet, 8, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &pixelCounterBufferInfo, nullptr);
|
||||
static vk::DescriptorBufferInfo abufferPointerInfo({}, 0, VK_WHOLE_SIZE);
|
||||
abufferPointerInfo.buffer = *abufferPointer->buffer;
|
||||
writeDescSets.emplace_back(descSet, 9, 0, 1, vk::DescriptorType::eStorageBuffer, nullptr, &abufferPointerInfo, nullptr);
|
||||
}
|
||||
|
||||
void OnNewFrame(vk::CommandBuffer commandBuffer)
|
||||
|
@ -104,13 +89,9 @@ public:
|
|||
abufferPointer.reset();
|
||||
}
|
||||
|
||||
vk::DescriptorSetLayout GetDescriptorSetLayout() const { return *descSetLayout; }
|
||||
bool isFirstFrameAfterInit() const { return firstFrameAfterInit; }
|
||||
|
||||
private:
|
||||
vk::UniqueDescriptorSet descSet;
|
||||
vk::UniqueDescriptorSetLayout descSetLayout;
|
||||
|
||||
std::unique_ptr<BufferData> pixelBuffer;
|
||||
std::unique_ptr<BufferData> pixelCounter;
|
||||
std::unique_ptr<BufferData> pixelCounterReset;
|
||||
|
|
|
@ -61,7 +61,6 @@ void OITDrawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool
|
|||
},
|
||||
{ poly.tsp.SrcInstr, poly.tsp.DstInstr, 0, 0 },
|
||||
trilinearAlpha,
|
||||
listType == ListType_Translucent ? (int)(&poly - pvrrc.global_param_tr.head()) : 0,
|
||||
palette_index,
|
||||
};
|
||||
if (twoVolumes)
|
||||
|
@ -77,15 +76,42 @@ void OITDrawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool
|
|||
pushConstants.ignore_tex_alpha1 = poly.tsp1.IgnoreTexA;
|
||||
}
|
||||
cmdBuffer.pushConstants<OITDescriptorSets::PushConstants>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
|
||||
if (!poly.isNaomi2())
|
||||
{
|
||||
OITDescriptorSets::VtxPushConstants vtxPushConstants = {
|
||||
listType == ListType_Translucent ? (int)(&poly - pvrrc.global_param_tr.head()) : 0
|
||||
};
|
||||
cmdBuffer.pushConstants<OITDescriptorSets::VtxPushConstants>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eVertex,
|
||||
sizeof(OITDescriptorSets::PushConstants), vtxPushConstants);
|
||||
}
|
||||
|
||||
bool needTexture = poly.pcw.Texture;
|
||||
if (needTexture)
|
||||
GetCurrentDescSet().SetTexture((Texture *)poly.texture, poly.tsp, (Texture *)poly.texture1, poly.tsp1);
|
||||
if (poly.pcw.Texture == 1 || poly.isNaomi2())
|
||||
{
|
||||
vk::DeviceSize offset = 0;
|
||||
u32 polyNumber = 0;
|
||||
if (poly.isNaomi2())
|
||||
{
|
||||
switch (listType)
|
||||
{
|
||||
case ListType_Opaque:
|
||||
offset = offsets.naomi2OpaqueOffset;
|
||||
polyNumber = &poly - pvrrc.global_param_op.head();
|
||||
break;
|
||||
case ListType_Punch_Through:
|
||||
offset = offsets.naomi2PunchThroughOffset;
|
||||
polyNumber = &poly - pvrrc.global_param_pt.head();
|
||||
break;
|
||||
case ListType_Translucent:
|
||||
offset = offsets.naomi2TranslucentOffset;
|
||||
polyNumber = &poly - pvrrc.global_param_tr.head();
|
||||
break;
|
||||
}
|
||||
}
|
||||
descriptorSets.bindPerPolyDescriptorSets(cmdBuffer, poly, polyNumber, *GetMainBuffer(0)->buffer, offset, offsets.lightsOffset);
|
||||
}
|
||||
|
||||
vk::Pipeline pipeline = pipelineManager->GetPipeline(listType, autosort, poly, pass, gpuPalette);
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
if (needTexture)
|
||||
GetCurrentDescSet().BindPerPolyDescriptorSets(cmdBuffer, (Texture *)poly.texture, poly.tsp, (Texture *)poly.texture1, poly.tsp1);
|
||||
|
||||
cmdBuffer.drawIndexed(count, 1, first, 0, 0);
|
||||
}
|
||||
|
@ -132,19 +158,23 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs
|
|||
{
|
||||
// OR'ing (open volume or quad)
|
||||
if (Translucent)
|
||||
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode, param.isNaomi2());
|
||||
else
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Or, param.isp.CullMode, param.isNaomi2());
|
||||
}
|
||||
else
|
||||
{
|
||||
// XOR'ing (closed volume)
|
||||
if (Translucent)
|
||||
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetTrModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode, param.isNaomi2());
|
||||
else
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(ModVolMode::Xor, param.isp.CullMode, param.isNaomi2());
|
||||
}
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
|
||||
vk::DeviceSize uniformOffset = Translucent ? offsets.naomi2TrModVolOffset : offsets.naomi2ModVolOffset;
|
||||
descriptorSets.bindPerPolyDescriptorSets(cmdBuffer, param, first + cmv, *GetMainBuffer(0)->buffer, uniformOffset);
|
||||
|
||||
cmdBuffer.draw(param.count * 3, 1, param.first * 3, 0);
|
||||
|
||||
if (mv_mode == 1 || mv_mode == 2)
|
||||
|
@ -155,10 +185,10 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs
|
|||
vk::MemoryBarrier barrier(vk::AccessFlagBits::eShaderWrite, vk::AccessFlagBits::eShaderRead);
|
||||
cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader,
|
||||
vk::DependencyFlagBits::eByRegion, barrier, nullptr, nullptr);
|
||||
pipeline = pipelineManager->GetTrModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetTrModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode, param.isNaomi2());
|
||||
}
|
||||
else
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode);
|
||||
pipeline = pipelineManager->GetModifierVolumePipeline(mv_mode == 1 ? ModVolMode::Inclusion : ModVolMode::Exclusion, param.isp.CullMode, param.isNaomi2());
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
cmdBuffer.draw((param.first + param.count - mod_base) * 3, 1, mod_base * 3, 0);
|
||||
|
||||
|
@ -178,57 +208,19 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs
|
|||
void OITDrawer::UploadMainBuffer(const OITDescriptorSets::VertexShaderUniforms& vertexUniforms,
|
||||
const OITDescriptorSets::FragmentShaderUniforms& fragmentUniforms)
|
||||
{
|
||||
using VertexShaderUniforms = OITDescriptorSets::VertexShaderUniforms;
|
||||
using FragmentShaderUniforms = OITDescriptorSets::FragmentShaderUniforms;
|
||||
|
||||
// TODO Put this logic in an allocator
|
||||
std::vector<const void *> chunks;
|
||||
std::vector<u32> chunkSizes;
|
||||
BufferPacker packer;
|
||||
|
||||
// Vertex
|
||||
chunks.push_back(pvrrc.verts.head());
|
||||
chunkSizes.push_back(pvrrc.verts.bytes());
|
||||
|
||||
u32 padding = align(pvrrc.verts.bytes(), 4);
|
||||
offsets.modVolOffset = pvrrc.verts.bytes() + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
packer.add(pvrrc.verts.head(), pvrrc.verts.bytes());
|
||||
// Modifier Volumes
|
||||
chunks.push_back(pvrrc.modtrig.head());
|
||||
chunkSizes.push_back(pvrrc.modtrig.bytes());
|
||||
padding = align(offsets.modVolOffset + pvrrc.modtrig.bytes(), 4);
|
||||
offsets.indexOffset = offsets.modVolOffset + pvrrc.modtrig.bytes() + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
offsets.modVolOffset = packer.add(pvrrc.modtrig.head(), pvrrc.modtrig.bytes());
|
||||
// Index
|
||||
chunks.push_back(pvrrc.idx.head());
|
||||
chunkSizes.push_back(pvrrc.idx.bytes());
|
||||
|
||||
offsets.indexOffset = packer.add(pvrrc.idx.head(), pvrrc.idx.bytes());
|
||||
// Uniform buffers
|
||||
u32 indexSize = pvrrc.idx.bytes();
|
||||
padding = align(offsets.indexOffset + indexSize, std::max(4, (int)GetContext()->GetUniformBufferAlignment()));
|
||||
offsets.vertexUniformOffset = offsets.indexOffset + indexSize + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
chunks.push_back(&vertexUniforms);
|
||||
chunkSizes.push_back(sizeof(vertexUniforms));
|
||||
padding = align(offsets.vertexUniformOffset + sizeof(VertexShaderUniforms), std::max(4, (int)GetContext()->GetUniformBufferAlignment()));
|
||||
offsets.fragmentUniformOffset = offsets.vertexUniformOffset + sizeof(VertexShaderUniforms) + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
chunks.push_back(&fragmentUniforms);
|
||||
chunkSizes.push_back(sizeof(fragmentUniforms));
|
||||
offsets.vertexUniformOffset = packer.addUniform(&vertexUniforms, sizeof(vertexUniforms));
|
||||
offsets.fragmentUniformOffset = packer.addUniform(&fragmentUniforms, sizeof(fragmentUniforms));
|
||||
|
||||
// Translucent poly params
|
||||
padding = align(offsets.fragmentUniformOffset + sizeof(FragmentShaderUniforms), std::max(4, (int)GetContext()->GetStorageBufferAlignment()));
|
||||
offsets.polyParamsOffset = offsets.fragmentUniformOffset + sizeof(FragmentShaderUniforms) + padding;
|
||||
chunks.push_back(nullptr);
|
||||
chunkSizes.push_back(padding);
|
||||
|
||||
std::vector<u32> trPolyParams(pvrrc.global_param_tr.used() * 2);
|
||||
if (pvrrc.global_param_tr.used() == 0)
|
||||
trPolyParams.push_back(0); // makes the validation layers happy
|
||||
|
@ -243,12 +235,18 @@ void OITDrawer::UploadMainBuffer(const OITDescriptorSets::VertexShaderUniforms&
|
|||
}
|
||||
}
|
||||
offsets.polyParamsSize = trPolyParams.size() * 4;
|
||||
chunks.push_back(trPolyParams.data());
|
||||
chunkSizes.push_back((u32)offsets.polyParamsSize);
|
||||
u32 totalSize = (u32)(offsets.polyParamsOffset + offsets.polyParamsSize);
|
||||
offsets.polyParamsOffset = packer.addStorage(trPolyParams.data(), offsets.polyParamsSize);
|
||||
|
||||
BufferData *buffer = GetMainBuffer(totalSize);
|
||||
buffer->upload(chunks.size(), &chunkSizes[0], &chunks[0]);
|
||||
std::vector<u8> n2uniforms;
|
||||
std::vector<u8> n2lights;
|
||||
if (settings.platform.isNaomi2())
|
||||
{
|
||||
uploadNaomi2Uniforms(packer, offsets, n2uniforms, true);
|
||||
offsets.lightsOffset = uploadNaomi2Lights(packer, n2lights);
|
||||
}
|
||||
|
||||
BufferData *buffer = GetMainBuffer(packer.size());
|
||||
packer.upload(*buffer);
|
||||
}
|
||||
|
||||
bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
||||
|
@ -264,7 +262,7 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
}
|
||||
|
||||
OITDescriptorSets::VertexShaderUniforms vtxUniforms;
|
||||
vtxUniforms.normal_matrix = matrices.GetNormalMatrix();
|
||||
vtxUniforms.ndcMat = matrices.GetNormalMatrix();
|
||||
|
||||
OITDescriptorSets::FragmentShaderUniforms fragUniforms = MakeFragmentUniforms<OITDescriptorSets::FragmentShaderUniforms>();
|
||||
fragUniforms.shade_scale_factor = FPU_SHAD_SCALE.scale_factor / 256.f;
|
||||
|
@ -285,14 +283,13 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
|
||||
// Update per-frame descriptor set and bind it
|
||||
const vk::Buffer mainBuffer = GetMainBuffer(0)->buffer.get();
|
||||
GetCurrentDescSet().UpdateUniforms(mainBuffer, (u32)offsets.vertexUniformOffset, (u32)offsets.fragmentUniformOffset,
|
||||
descriptorSets.updateUniforms(mainBuffer, (u32)offsets.vertexUniformOffset, (u32)offsets.fragmentUniformOffset,
|
||||
fogTexture->GetImageView(), (u32)offsets.polyParamsOffset,
|
||||
(u32)offsets.polyParamsSize, depthAttachments[0]->GetStencilView(),
|
||||
depthAttachments[0]->GetImageView(), paletteTexture->GetImageView());
|
||||
GetCurrentDescSet().BindPerFrameDescriptorSets(cmdBuffer);
|
||||
GetCurrentDescSet().UpdateColorInputDescSet(0, colorAttachments[0]->GetImageView());
|
||||
GetCurrentDescSet().UpdateColorInputDescSet(1, colorAttachments[1]->GetImageView());
|
||||
oitBuffers->BindDescriptorSet(cmdBuffer, pipelineManager->GetPipelineLayout(), 3);
|
||||
depthAttachments[0]->GetImageView(), paletteTexture->GetImageView(), oitBuffers);
|
||||
descriptorSets.bindPerFrameDescriptorSets(cmdBuffer);
|
||||
descriptorSets.updateColorInputDescSet(0, colorAttachments[0]->GetImageView());
|
||||
descriptorSets.updateColorInputDescSet(1, colorAttachments[1]->GetImageView());
|
||||
|
||||
// Bind vertex and index buffers
|
||||
const vk::DeviceSize zeroOffset[] = { 0 };
|
||||
|
@ -302,6 +299,9 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
// Make sure to push constants even if not used
|
||||
OITDescriptorSets::PushConstants pushConstants = { };
|
||||
cmdBuffer.pushConstants<OITDescriptorSets::PushConstants>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
|
||||
OITDescriptorSets::VtxPushConstants vtxPushConstants = { };
|
||||
cmdBuffer.pushConstants<OITDescriptorSets::VtxPushConstants>(pipelineManager->GetPipelineLayout(), vk::ShaderStageFlagBits::eVertex,
|
||||
sizeof(pushConstants), vtxPushConstants);
|
||||
|
||||
const std::array<vk::ClearValue, 4> clear_colors = {
|
||||
pvrrc.isRTT ? vk::ClearColorValue(std::array<float, 4>{0.f, 0.f, 0.f, 1.f}) : getBorderColor(),
|
||||
|
@ -370,7 +370,7 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
|
||||
// Final subpass
|
||||
cmdBuffer.nextSubpass(vk::SubpassContents::eInline);
|
||||
GetCurrentDescSet().BindColorInputDescSet(cmdBuffer, (pvrrc.render_passes.used() - 1 - render_pass) % 2);
|
||||
descriptorSets.bindColorInputDescSet(cmdBuffer, (pvrrc.render_passes.used() - 1 - render_pass) % 2);
|
||||
|
||||
if (initialPass && !pvrrc.isRTT && clearNeeded[GetCurrentImage()])
|
||||
{
|
||||
|
@ -381,38 +381,26 @@ bool OITDrawer::Draw(const Texture *fogTexture, const Texture *paletteTexture)
|
|||
}
|
||||
SetScissor(cmdBuffer, baseScissor);
|
||||
|
||||
if (!oitBuffers->isFirstFrameAfterInit())
|
||||
{
|
||||
// Tr modifier volumes
|
||||
if (GetContext()->GetVendorID() != VulkanContext::VENDOR_QUALCOMM) // Adreno bug
|
||||
DrawModifierVolumes<true>(cmdBuffer, previous_pass.mvo_tr_count, current_pass.mvo_tr_count - previous_pass.mvo_tr_count);
|
||||
|
||||
vk::Pipeline pipeline = pipelineManager->GetFinalPipeline();
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
quadBuffer->Bind(cmdBuffer);
|
||||
quadBuffer->Draw(cmdBuffer);
|
||||
}
|
||||
|
||||
// Clear
|
||||
vk::MemoryBarrier memoryBarrier(vk::AccessFlagBits::eShaderRead, vk::AccessFlagBits::eShaderWrite);
|
||||
cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader,
|
||||
vk::DependencyFlagBits::eByRegion, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
|
||||
vk::Pipeline pipeline = pipelineManager->GetClearPipeline();
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
quadBuffer->Bind(cmdBuffer);
|
||||
quadBuffer->Draw(cmdBuffer);
|
||||
|
||||
if (oitBuffers->isFirstFrameAfterInit())
|
||||
{
|
||||
// missing the transparent stuff on the first frame cuz I'm lazy
|
||||
// Clear
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipelineManager->GetClearPipeline());
|
||||
quadBuffer->Bind(cmdBuffer);
|
||||
quadBuffer->Draw(cmdBuffer);
|
||||
|
||||
vk::MemoryBarrier memoryBarrier(vk::AccessFlagBits::eShaderWrite, vk::AccessFlagBits::eShaderRead);
|
||||
cmdBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader,
|
||||
vk::DependencyFlagBits::eByRegion, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
|
||||
pipeline = pipelineManager->GetFinalPipeline();
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
quadBuffer->Bind(cmdBuffer);
|
||||
quadBuffer->Draw(cmdBuffer);
|
||||
}
|
||||
// Tr modifier volumes
|
||||
if (GetContext()->GetVendorID() != VulkanContext::VENDOR_QUALCOMM) // Adreno bug
|
||||
DrawModifierVolumes<true>(cmdBuffer, previous_pass.mvo_tr_count, current_pass.mvo_tr_count - previous_pass.mvo_tr_count);
|
||||
|
||||
vk::Pipeline pipeline = pipelineManager->GetFinalPipeline();
|
||||
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
|
||||
quadBuffer->Bind(cmdBuffer);
|
||||
quadBuffer->Draw(cmdBuffer);
|
||||
|
||||
if (!finalPass)
|
||||
{
|
||||
|
|
|
@ -52,18 +52,11 @@ protected:
|
|||
if (!quadBuffer)
|
||||
quadBuffer = std::unique_ptr<QuadBuffer>(new QuadBuffer());
|
||||
this->oitBuffers = oitBuffers;
|
||||
if (descriptorSets.size() > GetContext()->GetSwapChainSize())
|
||||
descriptorSets.resize(GetContext()->GetSwapChainSize());
|
||||
else
|
||||
while (descriptorSets.size() < GetContext()->GetSwapChainSize())
|
||||
{
|
||||
descriptorSets.emplace_back();
|
||||
descriptorSets.back().Init(samplerManager,
|
||||
pipelineManager->GetPipelineLayout(),
|
||||
pipelineManager->GetPerFrameDSLayout(),
|
||||
pipelineManager->GetPerPolyDSLayout(),
|
||||
pipelineManager->GetColorInputDSLayout());
|
||||
}
|
||||
descriptorSets.init(samplerManager,
|
||||
pipelineManager->GetPipelineLayout(),
|
||||
pipelineManager->GetPerFrameDSLayout(),
|
||||
pipelineManager->GetPerPolyDSLayout(),
|
||||
pipelineManager->GetColorInputDSLayout());
|
||||
}
|
||||
void Term()
|
||||
{
|
||||
|
@ -75,20 +68,18 @@ protected:
|
|||
depthAttachments[0].reset();
|
||||
depthAttachments[1].reset();
|
||||
mainBuffers.clear();
|
||||
descriptorSets.clear();
|
||||
descriptorSets.term();
|
||||
}
|
||||
|
||||
int GetCurrentImage() const { return imageIndex; }
|
||||
|
||||
void NewImage()
|
||||
{
|
||||
GetCurrentDescSet().Reset();
|
||||
descriptorSets.reset();
|
||||
imageIndex = (imageIndex + 1) % GetContext()->GetSwapChainSize();
|
||||
renderPass = 0;
|
||||
}
|
||||
|
||||
OITDescriptorSets& GetCurrentDescSet() { return descriptorSets[GetCurrentImage()]; }
|
||||
|
||||
BufferData* GetMainBuffer(u32 size)
|
||||
{
|
||||
u32 bufferIndex = imageIndex + renderPass * GetContext()->GetSwapChainSize();
|
||||
|
@ -138,6 +129,12 @@ private:
|
|||
vk::DeviceSize fragmentUniformOffset = 0;
|
||||
vk::DeviceSize polyParamsOffset = 0;
|
||||
vk::DeviceSize polyParamsSize = 0;
|
||||
vk::DeviceSize naomi2OpaqueOffset = 0;
|
||||
vk::DeviceSize naomi2PunchThroughOffset = 0;
|
||||
vk::DeviceSize naomi2TranslucentOffset = 0;
|
||||
vk::DeviceSize naomi2ModVolOffset = 0;
|
||||
vk::DeviceSize naomi2TrModVolOffset = 0;
|
||||
vk::DeviceSize lightsOffset = 0;
|
||||
} offsets;
|
||||
|
||||
std::unique_ptr<QuadBuffer> quadBuffer;
|
||||
|
@ -152,7 +149,7 @@ private:
|
|||
bool needDepthTransition = false;
|
||||
int imageIndex = 0;
|
||||
int renderPass = 0;
|
||||
std::vector<OITDescriptorSets> descriptorSets;
|
||||
OITDescriptorSets descriptorSets;
|
||||
std::vector<std::unique_ptr<BufferData>> mainBuffers;
|
||||
};
|
||||
|
||||
|
|
|
@ -139,7 +139,9 @@ void OITPipelineManager::CreatePipeline(u32 listType, bool autosort, const PolyP
|
|||
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
|
||||
|
||||
vk::ShaderModule vertex_module = shaderManager->GetVertexShader(OITShaderManager::VertexShaderParams{ pp.pcw.Gouraud == 1 });
|
||||
bool twoVolume = pp.tsp1.full != (u32)-1 || pp.tcw1.full != (u32)-1;
|
||||
vk::ShaderModule vertex_module = shaderManager->GetVertexShader(
|
||||
OITShaderManager::VertexShaderParams{ pp.pcw.Gouraud == 1, pp.isNaomi2(), pass != Pass::Depth, twoVolume, pp.pcw.Texture == 1 });
|
||||
OITShaderManager::FragmentShaderParams params = {};
|
||||
params.alphaTest = listType == ListType_Punch_Through;
|
||||
params.bumpmap = pp.tcw.PixelFmt == PixelBumpMap;
|
||||
|
@ -153,7 +155,7 @@ void OITPipelineManager::CreatePipeline(u32 listType, bool autosort, const PolyP
|
|||
params.texture = pp.pcw.Texture;
|
||||
params.useAlpha = pp.tsp.UseAlpha;
|
||||
params.pass = pass;
|
||||
params.twoVolume = pp.tsp1.full != (u32)-1 || pp.tcw1.full != (u32)-1;
|
||||
params.twoVolume = twoVolume;
|
||||
params.palette = gpuPalette;
|
||||
vk::ShaderModule fragment_module = shaderManager->GetFragmentShader(params);
|
||||
|
||||
|
@ -346,7 +348,7 @@ void OITPipelineManager::CreateClearPipeline()
|
|||
clearPipeline = GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(), graphicsPipelineCreateInfo);
|
||||
}
|
||||
|
||||
void OITPipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
|
||||
void OITPipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode, bool naomi2)
|
||||
{
|
||||
verify(mode != ModVolMode::Final);
|
||||
|
||||
|
@ -438,7 +440,7 @@ void OITPipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
|
|||
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
|
||||
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader();
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader(naomi2);
|
||||
vk::ShaderModule fragment_module = shaderManager->GetModVolShader();
|
||||
|
||||
vk::PipelineShaderStageCreateInfo stages[] = {
|
||||
|
@ -464,12 +466,12 @@ void OITPipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
|
|||
0 // subpass
|
||||
);
|
||||
|
||||
modVolPipelines[hash(mode, cullMode)] =
|
||||
modVolPipelines[hash(mode, cullMode, naomi2)] =
|
||||
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
|
||||
graphicsPipelineCreateInfo);
|
||||
}
|
||||
|
||||
void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode, int cullMode)
|
||||
void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode, int cullMode, bool naomi2)
|
||||
{
|
||||
verify(mode != ModVolMode::Final);
|
||||
|
||||
|
@ -533,7 +535,7 @@ void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode, int cullMode)
|
|||
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
|
||||
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader();
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader(naomi2);
|
||||
vk::ShaderModule fragment_module = shaderManager->GetTrModVolShader(mode);
|
||||
|
||||
vk::PipelineShaderStageCreateInfo stages[] = {
|
||||
|
@ -559,7 +561,7 @@ void OITPipelineManager::CreateTrModVolPipeline(ModVolMode mode, int cullMode)
|
|||
2 // subpass
|
||||
);
|
||||
|
||||
trModVolPipelines[hash(mode, cullMode)] =
|
||||
trModVolPipelines[hash(mode, cullMode, naomi2)] =
|
||||
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
|
||||
graphicsPipelineCreateInfo);
|
||||
}
|
||||
|
|
|
@ -24,23 +24,17 @@
|
|||
#include "oit_renderpass.h"
|
||||
#include "oit_buffer.h"
|
||||
#include "../texture.h"
|
||||
#include "../desc_set.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <tuple>
|
||||
|
||||
class OITDescriptorSets
|
||||
{
|
||||
public:
|
||||
OITDescriptorSets() = default;
|
||||
OITDescriptorSets(OITDescriptorSets&&) = default;
|
||||
OITDescriptorSets(const OITDescriptorSets&) = delete;
|
||||
OITDescriptorSets& operator=(OITDescriptorSets&&) = default;
|
||||
OITDescriptorSets& operator=(const OITDescriptorSets&) = delete;
|
||||
|
||||
// std140 alignment required
|
||||
struct VertexShaderUniforms
|
||||
{
|
||||
glm::mat4 normal_matrix;
|
||||
glm::mat4 ndcMat;
|
||||
};
|
||||
|
||||
// std140 alignment required
|
||||
|
@ -62,9 +56,8 @@ public:
|
|||
glm::vec4 clipTest;
|
||||
glm::ivec4 blend_mode0; // Only using 2 elements but easier for std140
|
||||
float trilinearAlpha;
|
||||
int pp_Number;
|
||||
float palette_index;
|
||||
int _pad;
|
||||
int _pad[2];
|
||||
|
||||
// two volume mode
|
||||
glm::ivec4 blend_mode1; // Only using 2 elements but easier for std140
|
||||
|
@ -77,29 +70,31 @@ public:
|
|||
int ignore_tex_alpha0;
|
||||
int ignore_tex_alpha1;
|
||||
};
|
||||
static_assert(sizeof(PushConstants) == 96, "PushConstants size changed. Update vertex push constant layout(offset) in vertex shaders");
|
||||
|
||||
void Init(SamplerManager* samplerManager, vk::PipelineLayout pipelineLayout, vk::DescriptorSetLayout perFrameLayout,
|
||||
struct VtxPushConstants
|
||||
{
|
||||
int polyNumber;
|
||||
};
|
||||
|
||||
void init(SamplerManager* samplerManager, vk::PipelineLayout pipelineLayout, vk::DescriptorSetLayout perFrameLayout,
|
||||
vk::DescriptorSetLayout perPolyLayout, vk::DescriptorSetLayout colorInputLayout)
|
||||
{
|
||||
this->samplerManager = samplerManager;
|
||||
this->pipelineLayout = pipelineLayout;
|
||||
this->perFrameLayout = perFrameLayout;
|
||||
this->perPolyLayout = perPolyLayout;
|
||||
this->colorInputLayout = colorInputLayout;
|
||||
|
||||
perFrameAlloc.setLayout(perFrameLayout);
|
||||
perPolyAlloc.setLayout(perPolyLayout);
|
||||
colorInputAlloc.setLayout(colorInputLayout);
|
||||
}
|
||||
|
||||
// FIXME way too many params
|
||||
void UpdateUniforms(vk::Buffer buffer, u32 vertexUniformOffset, u32 fragmentUniformOffset, vk::ImageView fogImageView,
|
||||
void updateUniforms(vk::Buffer buffer, u32 vertexUniformOffset, u32 fragmentUniformOffset, vk::ImageView fogImageView,
|
||||
u32 polyParamsOffset, u32 polyParamsSize, vk::ImageView stencilImageView, vk::ImageView depthImageView,
|
||||
vk::ImageView paletteImageView)
|
||||
vk::ImageView paletteImageView, OITBuffers *oitBuffers)
|
||||
{
|
||||
if (perFrameDescSets.empty())
|
||||
{
|
||||
perFrameDescSets = GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), 1, &perFrameLayout));
|
||||
}
|
||||
perFrameDescSetsInFlight.emplace_back(std::move(perFrameDescSets.back()));
|
||||
perFrameDescSets.pop_back();
|
||||
vk::DescriptorSet perFrameDescSet = *perFrameDescSetsInFlight.back();
|
||||
if (!perFrameDescSet)
|
||||
perFrameDescSet = perFrameAlloc.alloc();
|
||||
|
||||
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
||||
bufferInfos.emplace_back(buffer, vertexUniformOffset, sizeof(VertexShaderUniforms));
|
||||
|
@ -140,92 +135,119 @@ public:
|
|||
writeDescriptorSets.emplace_back(perFrameDescSet, 4, 0, 1, vk::DescriptorType::eInputAttachment, &stencilImageInfo, nullptr, nullptr);
|
||||
vk::DescriptorImageInfo depthImageInfo(vk::Sampler(), depthImageView, vk::ImageLayout::eDepthStencilReadOnlyOptimal);
|
||||
writeDescriptorSets.emplace_back(perFrameDescSet, 5, 0, 1, vk::DescriptorType::eInputAttachment, &depthImageInfo, nullptr, nullptr);
|
||||
oitBuffers->updateDescriptorSet(perFrameDescSet, writeDescriptorSets);
|
||||
|
||||
GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
}
|
||||
|
||||
void UpdateColorInputDescSet(int index, vk::ImageView colorImageView)
|
||||
void updateColorInputDescSet(int index, vk::ImageView colorImageView)
|
||||
{
|
||||
if (!colorInputDescSets[index])
|
||||
{
|
||||
colorInputDescSets[index] = std::move(GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), 1, &colorInputLayout)).front());
|
||||
}
|
||||
colorInputDescSets[index] = colorInputAlloc.alloc();
|
||||
|
||||
vk::DescriptorImageInfo colorImageInfo(vk::Sampler(), colorImageView, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
vk::WriteDescriptorSet writeDescriptorSet(*colorInputDescSets[index], 0, 0, 1, vk::DescriptorType::eInputAttachment, &colorImageInfo, nullptr, nullptr);
|
||||
vk::WriteDescriptorSet writeDescriptorSet(colorInputDescSets[index], 0, 0, 1, vk::DescriptorType::eInputAttachment, &colorImageInfo, nullptr, nullptr);
|
||||
|
||||
GetContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
||||
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void SetTexture(Texture *texture0, TSP tsp0, Texture *texture1, TSP tsp1)
|
||||
void bindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, const PolyParam& poly, int polyNumber, vk::Buffer buffer,
|
||||
vk::DeviceSize uniformOffset, vk::DeviceSize lightOffset)
|
||||
{
|
||||
auto index = std::make_tuple(texture0, tsp0.full & SamplerManager::TSP_Mask,
|
||||
texture1, tsp1.full & SamplerManager::TSP_Mask);
|
||||
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(), (u32)layouts.size(), &layouts[0]));
|
||||
}
|
||||
vk::DescriptorImageInfo imageInfo0(samplerManager->GetSampler(tsp0), texture0->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
|
||||
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
||||
writeDescriptorSets.emplace_back(*perPolyDescSets.back(), 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo0, nullptr, nullptr);
|
||||
|
||||
if (texture1 != nullptr)
|
||||
vk::DescriptorImageInfo imageInfo0;
|
||||
if (poly.texture != nullptr)
|
||||
{
|
||||
vk::DescriptorImageInfo imageInfo1(samplerManager->GetSampler(tsp1), texture1->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
writeDescriptorSets.emplace_back(*perPolyDescSets.back(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo1, nullptr, nullptr);
|
||||
imageInfo0 = vk::DescriptorImageInfo{ samplerManager->GetSampler(poly.tsp), ((Texture *)poly.texture)->GetReadOnlyImageView(),
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal };
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo0, nullptr, nullptr);
|
||||
}
|
||||
GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
perPolyDescSetsInFlight[index] = std::move(perPolyDescSets.back());
|
||||
perPolyDescSets.pop_back();
|
||||
vk::DescriptorImageInfo imageInfo1;
|
||||
if (poly.texture1 != nullptr)
|
||||
{
|
||||
imageInfo1 = vk::DescriptorImageInfo{ samplerManager->GetSampler(poly.tsp1), ((Texture *)poly.texture1)->GetReadOnlyImageView(),
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal };
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo1, nullptr, nullptr);
|
||||
}
|
||||
|
||||
vk::DescriptorBufferInfo uniBufferInfo;
|
||||
vk::DescriptorBufferInfo lightBufferInfo;
|
||||
if (poly.isNaomi2())
|
||||
{
|
||||
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
|
||||
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
|
||||
uniBufferInfo = vk::DescriptorBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
|
||||
|
||||
if (poly.lightModel != nullptr)
|
||||
{
|
||||
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
|
||||
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
|
||||
}
|
||||
// TODO no light
|
||||
}
|
||||
|
||||
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void BindPerFrameDescriptorSets(vk::CommandBuffer cmdBuffer)
|
||||
void bindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, const ModifierVolumeParam& mvParam, int polyNumber, vk::Buffer buffer, vk::DeviceSize uniformOffset)
|
||||
{
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &perFrameDescSetsInFlight.back().get(), 0, nullptr);
|
||||
if (!mvParam.isNaomi2())
|
||||
return;
|
||||
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
|
||||
|
||||
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
|
||||
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
|
||||
vk::DescriptorBufferInfo uniBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
|
||||
vk::WriteDescriptorSet writeDescriptorSet(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
|
||||
|
||||
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
||||
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void BindColorInputDescSet(vk::CommandBuffer cmdBuffer, int index)
|
||||
void bindPerFrameDescriptorSets(vk::CommandBuffer cmdBuffer)
|
||||
{
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 2, 1, &colorInputDescSets[index].get(), 0, nullptr);
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &perFrameDescSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void BindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, Texture *texture0, TSP tsp0, Texture *texture1, TSP tsp1)
|
||||
void bindColorInputDescSet(vk::CommandBuffer cmdBuffer, int index)
|
||||
{
|
||||
auto index = std::make_tuple(texture0, tsp0.full & SamplerManager::TSP_Mask, texture1, tsp1.full & SamplerManager::TSP_Mask);
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1,
|
||||
&perPolyDescSetsInFlight[index].get(), 0, nullptr);
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 2, 1, &colorInputDescSets[index], 0, nullptr);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void reset()
|
||||
{
|
||||
for (auto& pair : perPolyDescSetsInFlight)
|
||||
perPolyDescSets.emplace_back(std::move(pair.second));
|
||||
perPolyDescSetsInFlight.clear();
|
||||
for (auto& descset : perFrameDescSetsInFlight)
|
||||
perFrameDescSets.emplace_back(std::move(descset));
|
||||
perFrameDescSetsInFlight.clear();
|
||||
perFrameDescSet = vk::DescriptorSet{};
|
||||
colorInputDescSets[0] = vk::DescriptorSet{};
|
||||
colorInputDescSets[1] = vk::DescriptorSet{};
|
||||
perFrameAlloc.nextFrame();
|
||||
perPolyAlloc.nextFrame();
|
||||
colorInputAlloc.nextFrame();
|
||||
}
|
||||
|
||||
void term()
|
||||
{
|
||||
perFrameAlloc.term();
|
||||
perPolyAlloc.term();
|
||||
colorInputAlloc.term();
|
||||
}
|
||||
|
||||
private:
|
||||
VulkanContext *GetContext() const { return VulkanContext::Instance(); }
|
||||
VulkanContext *getContext() const { return VulkanContext::Instance(); }
|
||||
|
||||
vk::DescriptorSetLayout perFrameLayout;
|
||||
vk::DescriptorSetLayout perPolyLayout;
|
||||
vk::DescriptorSetLayout colorInputLayout;
|
||||
vk::PipelineLayout pipelineLayout;
|
||||
|
||||
std::vector<vk::UniqueDescriptorSet> perFrameDescSets;
|
||||
std::vector<vk::UniqueDescriptorSet> perFrameDescSetsInFlight;
|
||||
std::array<vk::UniqueDescriptorSet, 2> colorInputDescSets;
|
||||
std::vector<vk::UniqueDescriptorSet> perPolyDescSets;
|
||||
std::map<std::tuple<Texture *, u32, Texture *, u32>, vk::UniqueDescriptorSet> perPolyDescSetsInFlight;
|
||||
std::array<vk::DescriptorSet, 2> colorInputDescSets;
|
||||
DynamicDescSetAlloc perFrameAlloc;
|
||||
DynamicDescSetAlloc perPolyAlloc;
|
||||
DynamicDescSetAlloc colorInputAlloc;
|
||||
vk::DescriptorSet perFrameDescSet = {};
|
||||
|
||||
SamplerManager* samplerManager;
|
||||
};
|
||||
|
@ -242,6 +264,7 @@ public:
|
|||
|
||||
if (!perFrameLayout)
|
||||
{
|
||||
vk::Device device = GetContext()->GetDevice();
|
||||
// Descriptor set and pipeline layout
|
||||
vk::DescriptorSetLayoutBinding perFrameBindings[] = {
|
||||
{ 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }, // vertex uniforms
|
||||
|
@ -251,27 +274,37 @@ public:
|
|||
{ 4, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment }, // stencil input attachment
|
||||
{ 5, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment }, // depth input attachment
|
||||
{ 6, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// palette texture
|
||||
// OIT buffers
|
||||
{ 7, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // pixel buffer
|
||||
{ 8, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // pixel counter
|
||||
{ 9, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eFragment }, // a-buffer pointers
|
||||
};
|
||||
perFrameLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
||||
perFrameLayout = device.createDescriptorSetLayoutUnique(
|
||||
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(perFrameBindings), perFrameBindings));
|
||||
|
||||
vk::DescriptorSetLayoutBinding colorInputBindings[] = {
|
||||
{ 0, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment }, // color input attachment
|
||||
};
|
||||
colorInputLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
||||
colorInputLayout = device.createDescriptorSetLayoutUnique(
|
||||
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(colorInputBindings), colorInputBindings));
|
||||
|
||||
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)
|
||||
{ 0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment }, // texture 0
|
||||
{ 1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment }, // texture 1 (for 2-volume mode)
|
||||
{ 2, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }, // Naomi2 uniforms
|
||||
{ 3, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }, // Naomi2 lights
|
||||
};
|
||||
perPolyLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
||||
perPolyLayout = device.createDescriptorSetLayoutUnique(
|
||||
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(perPolyBindings), perPolyBindings));
|
||||
|
||||
vk::PushConstantRange pushConstant(vk::ShaderStageFlagBits::eFragment, 0, sizeof(OITDescriptorSets::PushConstants));
|
||||
vk::DescriptorSetLayout layouts[] = { *perFrameLayout, *perPolyLayout, *colorInputLayout, oitBuffers->GetDescriptorSetLayout() };
|
||||
pipelineLayout = GetContext()->GetDevice().createPipelineLayoutUnique(
|
||||
vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), ARRAY_SIZE(layouts), layouts, 1, &pushConstant));
|
||||
vk::PushConstantRange pushConstants[] = {
|
||||
vk::PushConstantRange(vk::ShaderStageFlagBits::eFragment, 0, sizeof(OITDescriptorSets::PushConstants)),
|
||||
vk::PushConstantRange(vk::ShaderStageFlagBits::eVertex, sizeof(OITDescriptorSets::PushConstants), sizeof(OITDescriptorSets::VtxPushConstants)),
|
||||
};
|
||||
|
||||
vk::DescriptorSetLayout layouts[] = { *perFrameLayout, *perPolyLayout, *colorInputLayout };
|
||||
pipelineLayout = device.createPipelineLayoutUnique(
|
||||
vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), ARRAY_SIZE(layouts), layouts, ARRAY_SIZE(pushConstants), pushConstants));
|
||||
}
|
||||
|
||||
pipelines.clear();
|
||||
|
@ -290,23 +323,23 @@ public:
|
|||
return *pipelines[pipehash];
|
||||
}
|
||||
|
||||
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode)
|
||||
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode, bool naomi2)
|
||||
{
|
||||
u32 pipehash = hash(mode, cullMode);
|
||||
u32 pipehash = hash(mode, cullMode, naomi2);
|
||||
const auto &pipeline = modVolPipelines.find(pipehash);
|
||||
if (pipeline != modVolPipelines.end())
|
||||
return pipeline->second.get();
|
||||
CreateModVolPipeline(mode, cullMode);
|
||||
CreateModVolPipeline(mode, cullMode, naomi2);
|
||||
|
||||
return *modVolPipelines[pipehash];
|
||||
}
|
||||
vk::Pipeline GetTrModifierVolumePipeline(ModVolMode mode, int cullMode)
|
||||
vk::Pipeline GetTrModifierVolumePipeline(ModVolMode mode, int cullMode, bool naomi2)
|
||||
{
|
||||
u32 pipehash = hash(mode, cullMode);
|
||||
u32 pipehash = hash(mode, cullMode, naomi2);
|
||||
const auto &pipeline = trModVolPipelines.find(pipehash);
|
||||
if (pipeline != trModVolPipelines.end())
|
||||
return pipeline->second.get();
|
||||
CreateTrModVolPipeline(mode, cullMode);
|
||||
CreateTrModVolPipeline(mode, cullMode, naomi2);
|
||||
|
||||
return *trModVolPipelines[pipehash];
|
||||
}
|
||||
|
@ -330,8 +363,8 @@ public:
|
|||
vk::RenderPass GetRenderPass(bool initial, bool last) { return renderPasses->GetRenderPass(initial, last); }
|
||||
|
||||
private:
|
||||
void CreateModVolPipeline(ModVolMode mode, int cullMode);
|
||||
void CreateTrModVolPipeline(ModVolMode mode, int cullMode);
|
||||
void CreateModVolPipeline(ModVolMode mode, int cullMode, bool naomi2);
|
||||
void CreateTrModVolPipeline(ModVolMode mode, int cullMode, bool naomi2);
|
||||
|
||||
u32 hash(u32 listType, bool autosort, const PolyParam *pp, Pass pass, bool gpuPalette) const
|
||||
{
|
||||
|
@ -351,13 +384,13 @@ private:
|
|||
| (pp->tsp.SrcInstr << 14) | (pp->tsp.DstInstr << 17);
|
||||
}
|
||||
hash |= (pp->isp.ZWriteDis << 20) | (pp->isp.CullMode << 21) | ((autosort ? 6 : pp->isp.DepthMode) << 23);
|
||||
hash |= ((u32)gpuPalette << 26) | ((u32)pass << 27);
|
||||
hash |= ((u32)gpuPalette << 26) | ((u32)pass << 27) | ((u32)pp->isNaomi2() << 29);
|
||||
|
||||
return hash;
|
||||
}
|
||||
u32 hash(ModVolMode mode, int cullMode) const
|
||||
u32 hash(ModVolMode mode, int cullMode, bool naomi2) const
|
||||
{
|
||||
return ((int)mode << 2) | cullMode;
|
||||
return ((int)mode << 2) | cullMode | ((u32)naomi2 << 5);
|
||||
}
|
||||
|
||||
vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo(bool full = true) const
|
||||
|
@ -376,6 +409,7 @@ private:
|
|||
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
|
||||
vk::VertexInputAttributeDescription(7, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, nx)), // naomi2 normal
|
||||
};
|
||||
static const vk::VertexInputAttributeDescription vertexInputLightAttributeDescriptions[] =
|
||||
{
|
||||
|
|
|
@ -25,9 +25,14 @@
|
|||
static const char OITVertexShaderSource[] = R"(
|
||||
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
|
||||
{
|
||||
mat4 normal_matrix;
|
||||
mat4 ndcMat;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (push_constant) uniform constants
|
||||
{
|
||||
layout(offset = 96) int polyNumber;
|
||||
} pushConstants;
|
||||
|
||||
layout (location = 0) in vec4 in_pos;
|
||||
layout (location = 1) in uvec4 in_base;
|
||||
layout (location = 2) in uvec4 in_offs;
|
||||
|
@ -42,10 +47,11 @@ layout (location = 2) noperspective out highp vec3 vtx_uv;
|
|||
layout (location = 3) INTERPOLATION out highp vec4 vtx_base1; // New for OIT, only for OP/PT with 2-volume
|
||||
layout (location = 4) INTERPOLATION out highp vec4 vtx_offs1;
|
||||
layout (location = 5) noperspective out highp vec2 vtx_uv1;
|
||||
layout (location = 6) flat out uint vtx_index;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 vpos = uniformBuffer.normal_matrix * in_pos;
|
||||
vec4 vpos = uniformBuffer.ndcMat * in_pos;
|
||||
vtx_base = vec4(in_base) / 255.0;
|
||||
vtx_offs = vec4(in_offs) / 255.0;
|
||||
vtx_uv = vec3(in_uv * vpos.z, vpos.z);
|
||||
|
@ -58,7 +64,7 @@ void main()
|
|||
vtx_base1 *= vpos.z;
|
||||
vtx_offs1 *= vpos.z;
|
||||
#endif
|
||||
// FIXME need pushConstants.pp_Number and gl_VertexID...
|
||||
vtx_index = (uint(pushConstants.polyNumber) << 18) + uint(gl_VertexIndex);
|
||||
vpos.w = 1.0;
|
||||
vpos.z = 0.0;
|
||||
gl_Position = vpos;
|
||||
|
@ -81,18 +87,18 @@ layout (std140, set = 0, binding = 1) uniform FragmentShaderUniforms
|
|||
uint viewportWidth;
|
||||
} uniformBuffer;
|
||||
|
||||
layout(set = 3, binding = 2) buffer abufferPointer_ {
|
||||
layout(set = 0, binding = 9) buffer abufferPointer_ {
|
||||
uint pointers[];
|
||||
} abufferPointer;
|
||||
|
||||
layout(set = 3, binding = 1) buffer PixelCounter_ {
|
||||
layout(set = 0, binding = 8) buffer PixelCounter_ {
|
||||
uint buffer_index;
|
||||
} PixelCounter;
|
||||
)"
|
||||
OIT_POLY_PARAM
|
||||
R"(
|
||||
|
||||
layout (set = 3, binding = 0, std430) coherent restrict buffer PixelBuffer_ {
|
||||
layout (set = 0, binding = 7, std430) coherent restrict buffer PixelBuffer_ {
|
||||
Pixel pixels[];
|
||||
} PixelBuffer;
|
||||
|
||||
|
@ -138,7 +144,6 @@ layout (push_constant) uniform pushBlock
|
|||
vec4 clipTest;
|
||||
ivec4 blend_mode0;
|
||||
float trilinearAlpha;
|
||||
int pp_Number;
|
||||
float palette_index;
|
||||
|
||||
// two volume mode
|
||||
|
@ -177,6 +182,7 @@ layout (location = 2) noperspective in highp vec3 vtx_uv;
|
|||
layout (location = 3) INTERPOLATION in highp vec4 vtx_base1; // new for OIT. Only if 2 vol
|
||||
layout (location = 4) INTERPOLATION in highp vec4 vtx_offs1;
|
||||
layout (location = 5) noperspective in highp vec2 vtx_uv1;
|
||||
layout (location = 6) flat in uint vtx_index;
|
||||
|
||||
#if pp_FogCtrl != 2 || pp_TwoVolumes == 1
|
||||
layout (set = 0, binding = 2) uniform sampler2D fog_table;
|
||||
|
@ -422,7 +428,7 @@ void main()
|
|||
Pixel pixel;
|
||||
pixel.color = packColors(clamp(color, vec4(0.0), vec4(1.0)));
|
||||
pixel.depth = vtx_uv.z;
|
||||
pixel.seq_num = uint(pushConstants.pp_Number);
|
||||
pixel.seq_num = vtx_index;
|
||||
pixel.next = atomicExchange(abufferPointer.pointers[coords.x + coords.y * uniformBuffer.viewportWidth], idx);
|
||||
PixelBuffer.pixels[idx] = pixel;
|
||||
|
||||
|
@ -460,20 +466,25 @@ int fillAndSortFragmentArray(ivec2 coords)
|
|||
idx = PixelBuffer.pixels[idx].next;
|
||||
for (; idx != EOL && count < MAX_PIXELS_PER_FRAGMENT; count++)
|
||||
{
|
||||
const Pixel p = PixelBuffer.pixels[idx];
|
||||
float depth = PixelBuffer.pixels[idx].depth;
|
||||
uint index = getPolyIndex(PixelBuffer.pixels[idx]);
|
||||
int j = count - 1;
|
||||
Pixel jp = PixelBuffer.pixels[pixel_list[j]];
|
||||
float jdepth = PixelBuffer.pixels[pixel_list[j]].depth;
|
||||
uint jindex = getPolyIndex(PixelBuffer.pixels[pixel_list[j]]);
|
||||
while (j >= 0
|
||||
&& (jp.depth > p.depth
|
||||
|| (jp.depth == p.depth && getPolyIndex(jp) > getPolyIndex(p))))
|
||||
&& (jdepth > depth
|
||||
|| (jdepth == depth && jindex > index)))
|
||||
{
|
||||
pixel_list[j + 1] = pixel_list[j];
|
||||
j--;
|
||||
if (j >= 0)
|
||||
jp = PixelBuffer.pixels[pixel_list[j]];
|
||||
{
|
||||
jdepth = PixelBuffer.pixels[pixel_list[j]].depth;
|
||||
jindex = getPolyIndex(PixelBuffer.pixels[pixel_list[j]]);
|
||||
}
|
||||
}
|
||||
pixel_list[j + 1] = idx;
|
||||
idx = p.next;
|
||||
idx = PixelBuffer.pixels[idx].next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -490,7 +501,7 @@ vec4 resolveAlphaBlend(ivec2 coords) {
|
|||
for (int i = 0; i < num_frag; i++)
|
||||
{
|
||||
const Pixel pixel = PixelBuffer.pixels[pixel_list[i]];
|
||||
const PolyParam pp = TrPolyParam.tr_poly_params[getPolyIndex(pixel)];
|
||||
const PolyParam pp = TrPolyParam.tr_poly_params[getPolyNumber(pixel)];
|
||||
bool area1 = false;
|
||||
bool shadowed = false;
|
||||
if (isShadowed(pixel))
|
||||
|
@ -587,6 +598,9 @@ void main(void)
|
|||
// Visualize the number of layers in use
|
||||
//FragColor = vec4(float(fillAndSortFragmentArray(coords)) / MAX_PIXELS_PER_FRAGMENT * 4, 0, 0, 1);
|
||||
FragColor = resolveAlphaBlend(coords);
|
||||
|
||||
// Reset pointers
|
||||
abufferPointer.pointers[coords.x + coords.y * uniformBuffer.viewportWidth] = EOL;
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -618,7 +632,7 @@ void main()
|
|||
while (idx != EOL && list_len < MAX_PIXELS_PER_FRAGMENT)
|
||||
{
|
||||
const Pixel pixel = PixelBuffer.pixels[idx];
|
||||
const PolyParam pp = TrPolyParam.tr_poly_params[getPolyIndex(pixel)];
|
||||
const PolyParam pp = TrPolyParam.tr_poly_params[getPolyNumber(pixel)];
|
||||
if (getShadowEnable(pp))
|
||||
{
|
||||
#if MV_MODE == MV_XOR
|
||||
|
@ -646,20 +660,135 @@ void main()
|
|||
static const char OITFinalVertexShaderSource[] = R"(
|
||||
layout (location = 0) in vec3 in_pos;
|
||||
|
||||
layout (push_constant) uniform pushBlock
|
||||
{
|
||||
int polyNumber_not_used;
|
||||
} pushConstants;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(in_pos, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
static const char OITN2VertexShaderSource[] = R"(
|
||||
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
|
||||
{
|
||||
mat4 ndcMat;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (push_constant) uniform constants
|
||||
{
|
||||
layout(offset = 96) int polyNumber_not_used;
|
||||
} pushConstants;
|
||||
|
||||
layout (location = 0) in vec4 in_pos;
|
||||
layout (location = 1) in uvec4 in_base;
|
||||
layout (location = 2) in uvec4 in_offs;
|
||||
layout (location = 3) in mediump vec2 in_uv;
|
||||
layout (location = 4) in uvec4 in_base1;
|
||||
layout (location = 5) in uvec4 in_offs1;
|
||||
layout (location = 6) in mediump vec2 in_uv1;
|
||||
layout (location = 7) in vec3 in_normal;
|
||||
|
||||
layout (location = 0) INTERPOLATION out highp vec4 vtx_base;
|
||||
layout (location = 1) INTERPOLATION out highp vec4 vtx_offs;
|
||||
layout (location = 2) noperspective out highp vec3 vtx_uv;
|
||||
layout (location = 3) INTERPOLATION out highp vec4 vtx_base1;
|
||||
layout (location = 4) INTERPOLATION out highp vec4 vtx_offs1;
|
||||
layout (location = 5) noperspective out highp vec2 vtx_uv1;
|
||||
layout (location = 6) flat out uint vtx_index;
|
||||
|
||||
void wDivide(inout vec4 vpos)
|
||||
{
|
||||
vpos = vec4(vpos.xy / vpos.w, 1.0 / vpos.w, 1.0);
|
||||
vpos = uniformBuffer.ndcMat * vpos;
|
||||
#if pp_Gouraud == 1
|
||||
vtx_base *= vpos.z;
|
||||
vtx_offs *= vpos.z;
|
||||
#if pp_TwoVolumes == 1
|
||||
vtx_base1 *= vpos.z;
|
||||
vtx_offs1 *= vpos.z;
|
||||
#endif
|
||||
#endif
|
||||
vtx_uv = vec3(vtx_uv.xy * vpos.z, vpos.z);
|
||||
#if pp_TwoVolumes == 1
|
||||
vtx_uv1 *= vpos.z;
|
||||
#endif
|
||||
vpos.w = 1.0;
|
||||
vpos.z = 0.0;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 vpos = n2Uniform.mvMat * in_pos;
|
||||
vtx_base = vec4(in_base) / 255.0;
|
||||
vtx_offs = vec4(in_offs) / 255.0;
|
||||
|
||||
#if LIGHT_ON == 1
|
||||
vec3 vnorm = normalize(mat3(n2Uniform.normalMat) * in_normal);
|
||||
#endif
|
||||
|
||||
#if pp_TwoVolumes == 1
|
||||
vtx_base1 = vec4(in_base1) / 255.0;
|
||||
vtx_offs1 = vec4(in_offs1) / 255.0;
|
||||
vtx_uv1 = in_uv1;
|
||||
#if LIGHT_ON == 1
|
||||
// FIXME need offset0 and offset1 for bump maps
|
||||
if (n2Uniform.bumpMapping == 1)
|
||||
computeBumpMap(vtx_offs, vtx_offs1, vpos.xyz, in_normal, n2Uniform.normalMat);
|
||||
else
|
||||
{
|
||||
computeColors(vtx_base1, vtx_offs1, 1, vpos.xyz, vnorm);
|
||||
#if pp_Texture == 0
|
||||
vtx_base1 += vtx_offs1;
|
||||
#endif
|
||||
}
|
||||
if (n2Uniform.envMapping[1] == 1)
|
||||
computeEnvMap(vtx_uv1.xy, vpos.xyz, vnorm);
|
||||
#endif
|
||||
#endif
|
||||
#if LIGHT_ON == 1
|
||||
if (n2Uniform.bumpMapping == 0)
|
||||
{
|
||||
computeColors(vtx_base, vtx_offs, 0, vpos.xyz, vnorm);
|
||||
#if pp_Texture == 0
|
||||
vtx_base += vtx_offs;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
vtx_uv.xy = in_uv;
|
||||
#if LIGHT_ON == 1
|
||||
if (n2Uniform.envMapping[0] == 1)
|
||||
computeEnvMap(vtx_uv.xy, vpos.xyz, vnorm);
|
||||
#endif
|
||||
|
||||
vpos = n2Uniform.projMat * vpos;
|
||||
wDivide(vpos);
|
||||
vtx_index = (uint(n2Uniform.polyNumber) << 18) + uint(gl_VertexIndex);
|
||||
|
||||
gl_Position = vpos;
|
||||
}
|
||||
)";
|
||||
|
||||
extern const char ModVolVertexShaderSource[];
|
||||
extern const char N2ModVolVertexShaderSource[];
|
||||
extern const char N2LightShaderSource[];
|
||||
|
||||
vk::UniqueShaderModule OITShaderManager::compileShader(const VertexShaderParams& params)
|
||||
{
|
||||
VulkanSource src;
|
||||
src.addConstant("pp_Gouraud", (int)params.gouraud)
|
||||
.addSource(GouraudSource)
|
||||
.addSource(OITVertexShaderSource);
|
||||
.addSource(GouraudSource);
|
||||
if (params.naomi2)
|
||||
src.addConstant("pp_TwoVolumes", (int)params.twoVolume)
|
||||
.addConstant("LIGHT_ON", (int)params.lightOn)
|
||||
.addConstant("pp_Texture", (int)params.texture)
|
||||
.addSource(N2LightShaderSource)
|
||||
.addSource(OITN2VertexShaderSource);
|
||||
else
|
||||
src.addSource(OITVertexShaderSource);
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, src.generate());
|
||||
}
|
||||
|
||||
|
@ -699,6 +828,7 @@ vk::UniqueShaderModule OITShaderManager::compileFinalVertexShader()
|
|||
{
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(OITFinalVertexShaderSource).generate());
|
||||
}
|
||||
|
||||
vk::UniqueShaderModule OITShaderManager::compileClearShader()
|
||||
{
|
||||
VulkanSource src;
|
||||
|
@ -706,9 +836,15 @@ vk::UniqueShaderModule OITShaderManager::compileClearShader()
|
|||
.addSource(OITClearShaderSource);
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
|
||||
}
|
||||
vk::UniqueShaderModule OITShaderManager::compileModVolVertexShader()
|
||||
|
||||
vk::UniqueShaderModule OITShaderManager::compileModVolVertexShader(bool naomi2)
|
||||
{
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(ModVolVertexShaderSource).generate());
|
||||
VulkanSource src;
|
||||
if (naomi2)
|
||||
src.addSource(N2ModVolVertexShaderSource);
|
||||
else
|
||||
src.addSource(ModVolVertexShaderSource);
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, src.generate());
|
||||
}
|
||||
vk::UniqueShaderModule OITShaderManager::compileModVolFragmentShader()
|
||||
{
|
||||
|
|
|
@ -30,8 +30,13 @@ public:
|
|||
struct VertexShaderParams
|
||||
{
|
||||
bool gouraud;
|
||||
bool naomi2;
|
||||
bool lightOn;
|
||||
bool twoVolume;
|
||||
bool texture;
|
||||
|
||||
u32 hash() { return (u32)gouraud; }
|
||||
u32 hash() { return (u32)gouraud | ((u32)naomi2 << 1) | ((u32)lightOn << 2)
|
||||
| ((u32)twoVolume << 3) | ((u32)texture << 4); }
|
||||
};
|
||||
|
||||
// alpha test, clip test, use alpha, texture, ignore alpha, shader instr, offset, fog, gouraud, bump, clamp
|
||||
|
@ -64,11 +69,12 @@ public:
|
|||
|
||||
vk::ShaderModule GetVertexShader(const VertexShaderParams& params) { return getShader(vertexShaders, params); }
|
||||
vk::ShaderModule GetFragmentShader(const FragmentShaderParams& params) { return getShader(fragmentShaders, params); }
|
||||
vk::ShaderModule GetModVolVertexShader()
|
||||
vk::ShaderModule GetModVolVertexShader(bool naomi2)
|
||||
{
|
||||
if (!modVolVertexShader)
|
||||
modVolVertexShader = compileModVolVertexShader();
|
||||
return *modVolVertexShader;
|
||||
vk::UniqueShaderModule& shader = naomi2 ? n2ModVolVertexShader : modVolVertexShader;
|
||||
if (!shader)
|
||||
shader = compileModVolVertexShader(naomi2);
|
||||
return *shader;
|
||||
}
|
||||
vk::ShaderModule GetModVolShader()
|
||||
{
|
||||
|
@ -85,9 +91,9 @@ public:
|
|||
|
||||
vk::ShaderModule GetFinalShader()
|
||||
{
|
||||
if (!finalAutosortShader)
|
||||
finalAutosortShader = compileFinalShader();
|
||||
return *finalAutosortShader;
|
||||
if (!finalFragmentShader)
|
||||
finalFragmentShader = compileFinalShader();
|
||||
return *finalFragmentShader;
|
||||
}
|
||||
vk::ShaderModule GetFinalVertexShader()
|
||||
{
|
||||
|
@ -114,7 +120,7 @@ private:
|
|||
}
|
||||
vk::UniqueShaderModule compileShader(const VertexShaderParams& params);
|
||||
vk::UniqueShaderModule compileShader(const FragmentShaderParams& params);
|
||||
vk::UniqueShaderModule compileModVolVertexShader();
|
||||
vk::UniqueShaderModule compileModVolVertexShader(bool naomi2);
|
||||
vk::UniqueShaderModule compileModVolFragmentShader();
|
||||
void compileTrModVolFragmentShader(ModVolMode mode);
|
||||
vk::UniqueShaderModule compileFinalShader();
|
||||
|
@ -124,12 +130,12 @@ private:
|
|||
std::map<u32, vk::UniqueShaderModule> vertexShaders;
|
||||
std::map<u32, vk::UniqueShaderModule> fragmentShaders;
|
||||
vk::UniqueShaderModule modVolVertexShader;
|
||||
vk::UniqueShaderModule n2ModVolVertexShader;
|
||||
vk::UniqueShaderModule modVolShader;
|
||||
std::vector<vk::UniqueShaderModule> trModVolShaders;
|
||||
|
||||
vk::UniqueShaderModule finalVertexShader;
|
||||
vk::UniqueShaderModule finalAutosortShader;
|
||||
vk::UniqueShaderModule finalSortedShader;
|
||||
vk::UniqueShaderModule finalFragmentShader;
|
||||
vk::UniqueShaderModule clearShader;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "rend/osd.h"
|
||||
#include "quad.h"
|
||||
|
||||
void PipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
|
||||
void PipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode, bool naomi2)
|
||||
{
|
||||
// Vertex input state
|
||||
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo;
|
||||
|
@ -138,7 +138,7 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
|
|||
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
|
||||
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader();
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader(naomi2);
|
||||
vk::ShaderModule fragment_module = shaderManager->GetModVolShader();
|
||||
|
||||
vk::PipelineShaderStageCreateInfo stages[] = {
|
||||
|
@ -163,12 +163,12 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode, int cullMode)
|
|||
renderPass // renderPass
|
||||
);
|
||||
|
||||
modVolPipelines[hash(mode, cullMode)] =
|
||||
modVolPipelines[hash(mode, cullMode, naomi2)] =
|
||||
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
|
||||
graphicsPipelineCreateInfo);
|
||||
}
|
||||
|
||||
void PipelineManager::CreateDepthPassPipeline(int cullMode)
|
||||
void PipelineManager::CreateDepthPassPipeline(int cullMode, bool naomi2)
|
||||
{
|
||||
// Vertex input state
|
||||
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = GetMainVertexInputStateCreateInfo(false);
|
||||
|
@ -241,7 +241,7 @@ void PipelineManager::CreateDepthPassPipeline(int cullMode)
|
|||
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
|
||||
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader();
|
||||
vk::ShaderModule vertex_module = shaderManager->GetModVolVertexShader(naomi2);
|
||||
vk::ShaderModule fragment_module = shaderManager->GetModVolShader();
|
||||
|
||||
vk::PipelineShaderStageCreateInfo stages[] = {
|
||||
|
@ -266,7 +266,7 @@ void PipelineManager::CreateDepthPassPipeline(int cullMode)
|
|||
renderPass // renderPass
|
||||
);
|
||||
|
||||
depthPassPipelines[cullMode] =
|
||||
depthPassPipelines[hash(cullMode, naomi2)] =
|
||||
GetContext()->GetDevice().createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
|
||||
graphicsPipelineCreateInfo);
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ void PipelineManager::CreatePipeline(u32 listType, bool sortTriangles, const Pol
|
|||
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
|
||||
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
|
||||
|
||||
vk::ShaderModule vertex_module = shaderManager->GetVertexShader(VertexShaderParams{ pp.pcw.Gouraud == 1 });
|
||||
vk::ShaderModule vertex_module = shaderManager->GetVertexShader(VertexShaderParams{ pp.pcw.Gouraud == 1, pp.isNaomi2() });
|
||||
FragmentShaderParams params = {};
|
||||
params.alphaTest = listType == ListType_Punch_Through;
|
||||
params.bumpmap = pp.tcw.PixelFmt == PixelBumpMap;
|
||||
|
|
|
@ -24,35 +24,24 @@
|
|||
#include "texture.h"
|
||||
#include "utils.h"
|
||||
#include "vulkan_context.h"
|
||||
#include "desc_set.h"
|
||||
#include <array>
|
||||
|
||||
class DescriptorSets
|
||||
{
|
||||
public:
|
||||
DescriptorSets() = default;
|
||||
DescriptorSets(DescriptorSets &&) = default;
|
||||
DescriptorSets(const DescriptorSets &) = delete;
|
||||
DescriptorSets& operator=(DescriptorSets &&) = default;
|
||||
DescriptorSets& operator=(const DescriptorSets &) = delete;
|
||||
|
||||
void Init(SamplerManager* samplerManager, vk::PipelineLayout pipelineLayout, vk::DescriptorSetLayout perFrameLayout, vk::DescriptorSetLayout perPolyLayout)
|
||||
void init(SamplerManager* samplerManager, vk::PipelineLayout pipelineLayout, vk::DescriptorSetLayout perFrameLayout, vk::DescriptorSetLayout perPolyLayout)
|
||||
{
|
||||
this->samplerManager = samplerManager;
|
||||
this->pipelineLayout = pipelineLayout;
|
||||
this->perFrameLayout = perFrameLayout;
|
||||
this->perPolyLayout = perPolyLayout;
|
||||
perFrameAlloc.setLayout(perFrameLayout);
|
||||
perPolyAlloc.setLayout(perPolyLayout);
|
||||
|
||||
}
|
||||
void UpdateUniforms(vk::Buffer buffer, u32 vertexUniformOffset, u32 fragmentUniformOffset, vk::ImageView fogImageView, vk::ImageView paletteImageView)
|
||||
void updateUniforms(vk::Buffer buffer, u32 vertexUniformOffset, u32 fragmentUniformOffset, vk::ImageView fogImageView, vk::ImageView paletteImageView)
|
||||
{
|
||||
if (perFrameDescSets.empty())
|
||||
{
|
||||
perFrameDescSets = GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), 1, &perFrameLayout));
|
||||
}
|
||||
perFrameDescSetsInFlight.emplace_back(std::move(perFrameDescSets.back()));
|
||||
perFrameDescSets.pop_back();
|
||||
vk::DescriptorSet perFrameDescSet = *perFrameDescSetsInFlight.back();
|
||||
if (!perFrameDescSet)
|
||||
perFrameDescSet = perFrameAlloc.alloc();
|
||||
|
||||
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
||||
bufferInfos.emplace_back(buffer, vertexUniformOffset, sizeof(VertexShaderUniforms));
|
||||
|
@ -83,64 +72,87 @@ public:
|
|||
imageInfo = { palSampler, paletteImageView, vk::ImageLayout::eShaderReadOnlyOptimal };
|
||||
writeDescriptorSets.emplace_back(perFrameDescSet, 3, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
|
||||
}
|
||||
GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
}
|
||||
|
||||
void SetTexture(Texture *texture, TSP tsp)
|
||||
void bindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, const PolyParam& poly, int polyNumber, vk::Buffer buffer,
|
||||
vk::DeviceSize uniformOffset, vk::DeviceSize lightOffset)
|
||||
{
|
||||
auto& inFlight = perPolyDescSetsInFlight;
|
||||
std::pair<Texture *, u32> index = std::make_pair(texture, tsp.full & SamplerManager::TSP_Mask);
|
||||
if (inFlight.find(index) != inFlight.end())
|
||||
return;
|
||||
|
||||
if (perPolyDescSets.empty())
|
||||
{
|
||||
std::vector<vk::DescriptorSetLayout> layouts(10, perPolyLayout);
|
||||
perPolyDescSets = GetContext()->GetDevice().allocateDescriptorSetsUnique(
|
||||
vk::DescriptorSetAllocateInfo(GetContext()->GetDescriptorPool(), (u32)layouts.size(), &layouts[0]));
|
||||
}
|
||||
vk::DescriptorImageInfo imageInfo(samplerManager->GetSampler(tsp), texture->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
|
||||
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
||||
writeDescriptorSets.emplace_back(*perPolyDescSets.back(), 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
|
||||
|
||||
GetContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
inFlight[index] = std::move(perPolyDescSets.back());
|
||||
perPolyDescSets.pop_back();
|
||||
vk::DescriptorImageInfo imageInfo;
|
||||
if (poly.texture != nullptr)
|
||||
{
|
||||
imageInfo = vk::DescriptorImageInfo(samplerManager->GetSampler(poly.tsp),
|
||||
((Texture *)poly.texture)->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
|
||||
}
|
||||
|
||||
vk::DescriptorBufferInfo uniBufferInfo;
|
||||
vk::DescriptorBufferInfo lightBufferInfo;
|
||||
if (poly.isNaomi2())
|
||||
{
|
||||
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
|
||||
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
|
||||
uniBufferInfo = vk::DescriptorBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
|
||||
|
||||
if (poly.lightModel != nullptr)
|
||||
{
|
||||
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
|
||||
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
|
||||
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
|
||||
}
|
||||
// TODO no light
|
||||
}
|
||||
|
||||
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void BindPerFrameDescriptorSets(vk::CommandBuffer cmdBuffer)
|
||||
void bindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, const ModifierVolumeParam& mvParam, int polyNumber, vk::Buffer buffer,
|
||||
vk::DeviceSize uniformOffset)
|
||||
{
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &perFrameDescSetsInFlight.back().get(), 0, nullptr);
|
||||
if (!mvParam.isNaomi2())
|
||||
return;
|
||||
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
|
||||
|
||||
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
|
||||
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
|
||||
vk::DescriptorBufferInfo uniBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
|
||||
vk::WriteDescriptorSet writeDescriptorSet(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
|
||||
|
||||
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
||||
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void BindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, Texture *texture, TSP tsp)
|
||||
void bindPerFrameDescriptorSets(vk::CommandBuffer cmdBuffer)
|
||||
{
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1,
|
||||
&perPolyDescSetsInFlight[std::make_pair(texture, tsp.full & SamplerManager::TSP_Mask)].get(), 0, nullptr);
|
||||
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &perFrameDescSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void reset()
|
||||
{
|
||||
for (auto& pair : perPolyDescSetsInFlight)
|
||||
perPolyDescSets.emplace_back(std::move(pair.second));
|
||||
perPolyDescSetsInFlight.clear();
|
||||
for (auto& descset : perFrameDescSetsInFlight)
|
||||
perFrameDescSets.emplace_back(std::move(descset));
|
||||
perFrameDescSetsInFlight.clear();
|
||||
perFrameAlloc.nextFrame();
|
||||
perPolyAlloc.nextFrame();
|
||||
perFrameDescSet = vk::DescriptorSet{};
|
||||
}
|
||||
|
||||
void term()
|
||||
{
|
||||
perFrameAlloc.term();
|
||||
perPolyAlloc.term();
|
||||
}
|
||||
|
||||
private:
|
||||
VulkanContext *GetContext() const { return VulkanContext::Instance(); }
|
||||
VulkanContext *getContext() const { return VulkanContext::Instance(); }
|
||||
|
||||
vk::DescriptorSetLayout perFrameLayout;
|
||||
vk::DescriptorSetLayout perPolyLayout;
|
||||
vk::PipelineLayout pipelineLayout;
|
||||
|
||||
std::vector<vk::UniqueDescriptorSet> perFrameDescSets;
|
||||
std::vector<vk::UniqueDescriptorSet> perFrameDescSetsInFlight;
|
||||
std::vector<vk::UniqueDescriptorSet> perPolyDescSets;
|
||||
std::map<std::pair<Texture *, u32>, vk::UniqueDescriptorSet> perPolyDescSetsInFlight;
|
||||
DynamicDescSetAlloc perFrameAlloc;
|
||||
DynamicDescSetAlloc perPolyAlloc;
|
||||
vk::DescriptorSet perFrameDescSet = {};
|
||||
|
||||
SamplerManager* samplerManager = nullptr;
|
||||
};
|
||||
|
@ -165,6 +177,8 @@ public:
|
|||
};
|
||||
vk::DescriptorSetLayoutBinding perPolyBindings[] = {
|
||||
{ 0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment },// texture
|
||||
{ 2, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }, // Naomi2 uniforms
|
||||
{ 3, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex }, // Naomi2 lights
|
||||
};
|
||||
perFrameLayout = GetContext()->GetDevice().createDescriptorSetLayoutUnique(
|
||||
vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), ARRAY_SIZE(perFrameBindings), perFrameBindings));
|
||||
|
@ -195,25 +209,26 @@ public:
|
|||
return *pipelines[pipehash];
|
||||
}
|
||||
|
||||
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode)
|
||||
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode, int cullMode, bool naomi2)
|
||||
{
|
||||
u32 pipehash = hash(mode, cullMode);
|
||||
u32 pipehash = hash(mode, cullMode, naomi2);
|
||||
const auto &pipeline = modVolPipelines.find(pipehash);
|
||||
if (pipeline != modVolPipelines.end())
|
||||
return pipeline->second.get();
|
||||
CreateModVolPipeline(mode, cullMode);
|
||||
CreateModVolPipeline(mode, cullMode, naomi2);
|
||||
|
||||
return *modVolPipelines[pipehash];
|
||||
}
|
||||
|
||||
vk::Pipeline GetDepthPassPipeline(int cullMode)
|
||||
vk::Pipeline GetDepthPassPipeline(int cullMode, bool naomi2)
|
||||
{
|
||||
cullMode = std::max(std::min(cullMode, (int)depthPassPipelines.size() - 1), 0);
|
||||
const auto &pipeline = depthPassPipelines[cullMode];
|
||||
if (!pipeline)
|
||||
CreateDepthPassPipeline(cullMode);
|
||||
u32 pipehash = hash(cullMode, naomi2);
|
||||
const auto &pipeline = depthPassPipelines.find(pipehash);
|
||||
if (pipeline != depthPassPipelines.end())
|
||||
return pipeline->second.get();
|
||||
CreateDepthPassPipeline(cullMode, naomi2);
|
||||
|
||||
return *pipeline;
|
||||
return *depthPassPipelines[pipehash];
|
||||
}
|
||||
|
||||
void Reset()
|
||||
|
@ -228,8 +243,8 @@ public:
|
|||
vk::RenderPass GetRenderPass() const { return renderPass; }
|
||||
|
||||
private:
|
||||
void CreateModVolPipeline(ModVolMode mode, int cullMode);
|
||||
void CreateDepthPassPipeline(int cullMode);
|
||||
void CreateModVolPipeline(ModVolMode mode, int cullMode, bool naomi2);
|
||||
void CreateDepthPassPipeline(int cullMode, bool naomi2);
|
||||
|
||||
u32 hash(u32 listType, bool sortTriangles, const PolyParam *pp, bool gpuPalette) const
|
||||
{
|
||||
|
@ -241,13 +256,17 @@ private:
|
|||
| (pp->tsp.ColorClamp << 11) | ((config::Fog ? pp->tsp.FogCtrl : 2) << 12) | (pp->tsp.SrcInstr << 14)
|
||||
| (pp->tsp.DstInstr << 17);
|
||||
hash |= (pp->isp.ZWriteDis << 20) | (pp->isp.CullMode << 21) | (pp->isp.DepthMode << 23);
|
||||
hash |= ((u32)sortTriangles << 26) | ((u32)gpuPalette << 27);
|
||||
hash |= ((u32)sortTriangles << 26) | ((u32)gpuPalette << 27) | ((u32)pp->isNaomi2() << 28);
|
||||
|
||||
return hash;
|
||||
}
|
||||
u32 hash(ModVolMode mode, int cullMode) const
|
||||
u32 hash(ModVolMode mode, int cullMode, bool naomi2) const
|
||||
{
|
||||
return ((int)mode << 2) | cullMode;
|
||||
return ((int)mode << 2) | cullMode | ((int)naomi2 << 5);
|
||||
}
|
||||
u32 hash(int cullMode, bool naomi2) const
|
||||
{
|
||||
return cullMode | ((int)naomi2 << 2);
|
||||
}
|
||||
|
||||
vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo(bool full = true) const
|
||||
|
@ -263,6 +282,7 @@ private:
|
|||
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::eR32G32B32Sfloat, offsetof(Vertex, nx)), // naomi2 normal
|
||||
};
|
||||
static const vk::VertexInputAttributeDescription vertexInputLightAttributeDescriptions[] =
|
||||
{
|
||||
|
@ -280,7 +300,7 @@ private:
|
|||
|
||||
std::map<u32, vk::UniquePipeline> pipelines;
|
||||
std::map<u32, vk::UniquePipeline> modVolPipelines;
|
||||
std::array<vk::UniquePipeline, 4> depthPassPipelines;
|
||||
std::map<u32, vk::UniquePipeline> depthPassPipelines;
|
||||
|
||||
vk::UniquePipelineLayout pipelineLayout;
|
||||
vk::UniqueDescriptorSetLayout perFrameLayout;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
static const char VertexShaderSource[] = R"(
|
||||
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
|
||||
{
|
||||
mat4 normal_matrix;
|
||||
mat4 ndcMat;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (location = 0) in vec4 in_pos;
|
||||
|
@ -40,7 +40,7 @@ layout (location = 2) noperspective out highp vec3 vtx_uv;
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 vpos = uniformBuffer.normal_matrix * in_pos;
|
||||
vec4 vpos = uniformBuffer.ndcMat * in_pos;
|
||||
vtx_base = vec4(in_base) / 255.0;
|
||||
vtx_offs = vec4(in_offs) / 255.0;
|
||||
vtx_uv = vec3(in_uv * vpos.z, vpos.z);
|
||||
|
@ -226,7 +226,7 @@ void main()
|
|||
extern const char ModVolVertexShaderSource[] = R"(
|
||||
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
|
||||
{
|
||||
mat4 normal_matrix;
|
||||
mat4 ndcMat;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (location = 0) in vec4 in_pos;
|
||||
|
@ -234,7 +234,7 @@ layout (location = 0) noperspective out highp float depth;
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 vpos = uniformBuffer.normal_matrix * in_pos;
|
||||
vec4 vpos = uniformBuffer.ndcMat * in_pos;
|
||||
depth = vpos.z;
|
||||
vpos.w = 1.0;
|
||||
vpos.z = 0.0;
|
||||
|
@ -325,12 +325,363 @@ void main()
|
|||
}
|
||||
)";
|
||||
|
||||
extern const char N2LightShaderSource[] = R"(
|
||||
|
||||
layout (std140, set = 1, binding = 2) uniform N2VertexShaderUniforms
|
||||
{
|
||||
mat4 mvMat;
|
||||
mat4 normalMat;
|
||||
mat4 projMat;
|
||||
ivec2 envMapping;
|
||||
int bumpMapping;
|
||||
int polyNumber;
|
||||
|
||||
vec2 glossCoef;
|
||||
ivec2 constantColor;
|
||||
ivec2 modelDiffuse;
|
||||
ivec2 modelSpecular;
|
||||
} n2Uniform;
|
||||
|
||||
#define PI 3.1415926
|
||||
|
||||
#define LMODE_SINGLE_SIDED 0
|
||||
#define LMODE_DOUBLE_SIDED 1
|
||||
#define LMODE_DOUBLE_SIDED_WITH_TOLERANCE 2
|
||||
#define LMODE_SPECIAL_EFFECT 3
|
||||
#define LMODE_THIN_SURFACE 4
|
||||
#define LMODE_BUMP_MAP 5
|
||||
|
||||
#define ROUTING_BASEDIFF_BASESPEC_ADD 0
|
||||
#define ROUTING_BASEDIFF_OFFSSPEC_ADD 1
|
||||
#define ROUTING_OFFSDIFF_BASESPEC_ADD 2
|
||||
#define ROUTING_OFFSDIFF_OFFSSPEC_ADD 3
|
||||
#define ROUTING_ALPHADIFF_ADD 4
|
||||
#define ROUTING_ALPHAATTEN_ADD 5
|
||||
#define ROUTING_FOGDIFF_ADD 6
|
||||
#define ROUTING_FOGATTENUATION_ADD 7
|
||||
#define ROUTING_BASEDIFF_BASESPEC_SUB 8
|
||||
#define ROUTING_BASEDIFF_OFFSSPEC_SUB 9
|
||||
#define ROUTING_OFFSDIFF_BASESPEC_SUB 10
|
||||
#define ROUTING_OFFSDIFF_OFFSSPEC_SUB 11
|
||||
#define ROUTING_ALPHADIFF_SUB 12
|
||||
#define ROUTING_ALPHAATTEN_SUB 13
|
||||
|
||||
struct N2Light
|
||||
{
|
||||
vec4 color;
|
||||
vec4 direction; // For parallel/spot
|
||||
vec4 position; // For spot/point
|
||||
|
||||
int parallel;
|
||||
int routing;
|
||||
int dmode;
|
||||
int smode;
|
||||
|
||||
ivec2 diffuse;
|
||||
ivec2 specular;
|
||||
|
||||
float attnDistA;
|
||||
float attnDistB;
|
||||
float attnAngleA; // For spot
|
||||
float attnAngleB;
|
||||
|
||||
int distAttnMode; // For spot/point
|
||||
int _pad1;
|
||||
int _pad2;
|
||||
int _pad3;
|
||||
};
|
||||
|
||||
layout (std140, set = 1, binding = 3) uniform N2Lights
|
||||
{
|
||||
N2Light lights[16];
|
||||
vec4 ambientBase[2];
|
||||
vec4 ambientOffset[2];
|
||||
ivec2 ambientMaterialBase;
|
||||
ivec2 ambientMaterialOffset;
|
||||
int lightCount;
|
||||
int useBaseOver;
|
||||
int bumpId0;
|
||||
int bumpId1;
|
||||
} n2Lights;
|
||||
|
||||
void computeColors(inout vec4 baseCol, inout vec4 offsetCol, in int volIdx, in vec3 position, in vec3 normal)
|
||||
{
|
||||
if (n2Uniform.constantColor[volIdx] == 1)
|
||||
return;
|
||||
vec3 diffuse = vec3(0.0);
|
||||
vec3 specular = vec3(0.0);
|
||||
float diffuseAlpha = 0.0;
|
||||
float specularAlpha = 0.0;
|
||||
vec3 reflectDir = reflect(normalize(position), normal);
|
||||
const float BASE_FACTOR = 1.45;
|
||||
|
||||
for (int i = 0; i < n2Lights.lightCount; i++)
|
||||
{
|
||||
vec3 lightDir; // direction to the light
|
||||
vec3 lightColor = n2Lights.lights[i].color.rgb;
|
||||
if (n2Lights.lights[i].parallel == 1)
|
||||
{
|
||||
lightDir = normalize(n2Lights.lights[i].direction.xyz);
|
||||
}
|
||||
else
|
||||
{
|
||||
lightDir = normalize(n2Lights.lights[i].position.xyz - position);
|
||||
if (n2Lights.lights[i].attnDistA != 1.0 || n2Lights.lights[i].attnDistB != 0.0)
|
||||
{
|
||||
float distance = length(n2Lights.lights[i].position.xyz - position);
|
||||
if (n2Lights.lights[i].distAttnMode == 0)
|
||||
distance = 1.0 / distance;
|
||||
lightColor *= clamp(n2Lights.lights[i].attnDistB * distance + n2Lights.lights[i].attnDistA, 0.0, 1.0);
|
||||
}
|
||||
if (n2Lights.lights[i].attnAngleA != 1.0 || n2Lights.lights[i].attnAngleB != 0.0)
|
||||
{
|
||||
vec3 spotDir = n2Lights.lights[i].direction.xyz;
|
||||
float cosAngle = 1.0 - max(0.0, dot(lightDir, spotDir));
|
||||
lightColor *= clamp(cosAngle * n2Lights.lights[i].attnAngleB + n2Lights.lights[i].attnAngleA, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (n2Lights.lights[i].diffuse[volIdx] == 1)
|
||||
{
|
||||
float factor = BASE_FACTOR;
|
||||
if (n2Lights.lights[i].dmode == LMODE_SINGLE_SIDED)
|
||||
factor *= max(dot(normal, lightDir), 0.0);
|
||||
else if (n2Lights.lights[i].dmode == LMODE_DOUBLE_SIDED)
|
||||
factor *= abs(dot(normal, lightDir));
|
||||
|
||||
if (n2Lights.lights[i].routing == ROUTING_ALPHADIFF_SUB)
|
||||
diffuseAlpha -= lightColor.r * factor;
|
||||
else if (n2Lights.lights[i].routing == ROUTING_BASEDIFF_BASESPEC_ADD || n2Lights.lights[i].routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
|
||||
diffuse += lightColor * factor;
|
||||
if (n2Lights.lights[i].routing == ROUTING_OFFSDIFF_BASESPEC_ADD || n2Lights.lights[i].routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD)
|
||||
specular += lightColor * factor;
|
||||
}
|
||||
if (n2Lights.lights[i].specular[volIdx] == 1)
|
||||
{
|
||||
float factor = BASE_FACTOR;
|
||||
if (n2Lights.lights[i].smode == LMODE_SINGLE_SIDED)
|
||||
factor *= clamp(pow(max(dot(lightDir, reflectDir), 0.0), n2Uniform.glossCoef[volIdx]), 0.0, 1.0);
|
||||
else if (n2Lights.lights[i].smode == LMODE_DOUBLE_SIDED)
|
||||
factor *= clamp(pow(abs(dot(lightDir, reflectDir)), n2Uniform.glossCoef[volIdx]), 0.0, 1.0);
|
||||
|
||||
if (n2Lights.lights[i].routing == ROUTING_ALPHADIFF_SUB)
|
||||
specularAlpha -= lightColor.r * factor;
|
||||
else if (n2Lights.lights[i].routing == ROUTING_OFFSDIFF_OFFSSPEC_ADD || n2Lights.lights[i].routing == ROUTING_BASEDIFF_OFFSSPEC_ADD)
|
||||
specular += lightColor * factor;
|
||||
if (n2Lights.lights[i].routing == ROUTING_BASEDIFF_BASESPEC_ADD || n2Lights.lights[i].routing == ROUTING_OFFSDIFF_BASESPEC_ADD)
|
||||
diffuse += lightColor * factor;
|
||||
}
|
||||
}
|
||||
// ambient with material
|
||||
if (n2Lights.ambientMaterialBase[volIdx] == 1)
|
||||
diffuse += n2Lights.ambientBase[volIdx].rgb;
|
||||
if (n2Lights.ambientMaterialOffset[volIdx] == 1)
|
||||
specular += n2Lights.ambientOffset[volIdx].rgb;
|
||||
|
||||
if (n2Uniform.modelDiffuse[volIdx] == 1)
|
||||
baseCol.rgb *= diffuse;
|
||||
if (n2Uniform.modelSpecular[volIdx] == 1)
|
||||
offsetCol.rgb *= specular;
|
||||
|
||||
// ambient w/o material
|
||||
if (n2Lights.ambientMaterialBase[volIdx] == 0 && n2Uniform.modelDiffuse[volIdx] == 1)
|
||||
baseCol.rgb += n2Lights.ambientBase[volIdx].rgb;
|
||||
if (n2Lights.ambientMaterialOffset[volIdx] == 0 && n2Uniform.modelSpecular[volIdx] == 1)
|
||||
offsetCol.rgb += n2Lights.ambientOffset[volIdx].rgb;
|
||||
|
||||
baseCol.a += diffuseAlpha;
|
||||
offsetCol.a += specularAlpha;
|
||||
if (n2Lights.useBaseOver == 1)
|
||||
{
|
||||
vec4 overflow = max(baseCol - vec4(1.0), 0.0);
|
||||
offsetCol += overflow;
|
||||
}
|
||||
baseCol = clamp(baseCol, 0.0, 1.0);
|
||||
offsetCol = clamp(offsetCol, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void computeEnvMap(inout vec2 uv, in vec3 position, in vec3 normal)
|
||||
{
|
||||
// Spherical mapping
|
||||
//vec3 r = reflect(normalize(position), normal);
|
||||
//float m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));
|
||||
//uv += r.xy / m + 0.5;
|
||||
|
||||
// Cheap env mapping
|
||||
uv += normal.xy / 2.0 + 0.5;
|
||||
uv = clamp(uv, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void computeBumpMap(inout vec4 color0, in vec4 color1, in vec3 position, in vec3 normal, in mat4 normalMat)
|
||||
{
|
||||
// TODO
|
||||
if (n2Lights.bumpId0 == -1)
|
||||
return;
|
||||
normal = normalize(normal);
|
||||
vec3 tangent = color0.xyz;
|
||||
if (tangent.x > 0.5)
|
||||
tangent.x -= 1.0;
|
||||
if (tangent.y > 0.5)
|
||||
tangent.y -= 1.0;
|
||||
if (tangent.z > 0.5)
|
||||
tangent.z -= 1.0;
|
||||
//tangent = normalize(normalMat * vec4(tangent, 0.0)).xyz;
|
||||
tangent = normalize(tangent);
|
||||
vec3 bitangent = color1.xyz;
|
||||
if (bitangent.x > 0.5)
|
||||
bitangent.x -= 1.0;
|
||||
if (bitangent.y > 0.5)
|
||||
bitangent.y -= 1.0;
|
||||
if (bitangent.z > 0.5)
|
||||
bitangent.z -= 1.0;
|
||||
//bitangent = normalize(normalMat * vec4(bitangent, 0.0)).xyz;
|
||||
bitangent = normalize(bitangent);
|
||||
|
||||
float scaleDegree = color0.w;
|
||||
float scaleOffset = color1.w;
|
||||
|
||||
vec3 lightDir; // direction to the light
|
||||
if (n2Lights.lights[n2Lights.bumpId0].parallel == 1)
|
||||
lightDir = n2Lights.lights[n2Lights.bumpId0].direction.xyz;
|
||||
else
|
||||
lightDir = n2Lights.lights[n2Lights.bumpId0].position.xyz - position;
|
||||
lightDir = normalize(lightDir * mat3(normalMat));
|
||||
|
||||
float n = dot(lightDir, normal);
|
||||
float cosQ = dot(lightDir, tangent);
|
||||
float sinQ = dot(lightDir, bitangent);
|
||||
|
||||
float sinT = clamp(n, 0.0, 1.0);
|
||||
float k1 = 1.0 - scaleDegree;
|
||||
float k2 = scaleDegree * sinT;
|
||||
float k3 = scaleDegree * sqrt(1.0 - sinT * sinT); // cos T
|
||||
|
||||
float q = acos(cosQ);
|
||||
if (sinQ < 0.0)
|
||||
q = 2.0 * PI - q;
|
||||
|
||||
color0.r = k2;
|
||||
color0.g = k3;
|
||||
color0.b = q / PI / 2.0;
|
||||
color0.a = k1;
|
||||
}
|
||||
)";
|
||||
|
||||
static const char N2VertexShaderSource[] = R"(
|
||||
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
|
||||
{
|
||||
mat4 ndcMat;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (location = 0) in vec4 in_pos;
|
||||
layout (location = 1) in uvec4 in_base;
|
||||
layout (location = 2) in uvec4 in_offs;
|
||||
layout (location = 3) in mediump vec2 in_uv;
|
||||
layout (location = 4) in vec3 in_normal;
|
||||
|
||||
layout (location = 0) INTERPOLATION out highp vec4 vtx_base;
|
||||
layout (location = 1) INTERPOLATION out highp vec4 vtx_offs;
|
||||
layout (location = 2) noperspective out highp vec3 vtx_uv;
|
||||
|
||||
void wDivide(inout vec4 vpos)
|
||||
{
|
||||
vpos = vec4(vpos.xy / vpos.w, 1.0 / vpos.w, 1.0);
|
||||
vpos = uniformBuffer.ndcMat * vpos;
|
||||
#if pp_Gouraud == 1
|
||||
vtx_base *= vpos.z;
|
||||
vtx_offs *= vpos.z;
|
||||
#endif
|
||||
vtx_uv = vec3(vtx_uv.xy * vpos.z, vpos.z);
|
||||
vpos.w = 1.0;
|
||||
vpos.z = 0.0;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 vpos = n2Uniform.mvMat * in_pos;
|
||||
vtx_base = vec4(in_base) / 255.0;
|
||||
vtx_offs = vec4(in_offs) / 255.0;
|
||||
|
||||
vec3 vnorm = normalize(mat3(n2Uniform.normalMat) * in_normal);
|
||||
|
||||
// TODO bump mapping
|
||||
if (n2Uniform.bumpMapping == 0)
|
||||
{
|
||||
computeColors(vtx_base, vtx_offs, 0, vpos.xyz, vnorm);
|
||||
#if pp_Texture == 0
|
||||
vtx_base += vtx_offs;
|
||||
#endif
|
||||
}
|
||||
|
||||
vtx_uv.xy = in_uv;
|
||||
if (n2Uniform.envMapping[0] == 1)
|
||||
computeEnvMap(vtx_uv.xy, vpos.xyz, vnorm);
|
||||
|
||||
vpos = n2Uniform.projMat * vpos;
|
||||
wDivide(vpos);
|
||||
|
||||
gl_Position = vpos;
|
||||
}
|
||||
)";
|
||||
|
||||
extern const char N2ModVolVertexShaderSource[] = R"(
|
||||
layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
|
||||
{
|
||||
mat4 ndcMat;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (std140, set = 1, binding = 2) uniform N2VertexShaderUniforms
|
||||
{
|
||||
mat4 mvMat;
|
||||
mat4 normalMat;
|
||||
mat4 projMat;
|
||||
ivec2 envMapping;
|
||||
int bumpMapping;
|
||||
int polyNumber;
|
||||
|
||||
vec2 glossCoef;
|
||||
ivec2 constantColor;
|
||||
ivec2 modelDiffuse;
|
||||
ivec2 modelSpecular;
|
||||
} n2Uniform;
|
||||
|
||||
layout (location = 0) in vec4 in_pos;
|
||||
layout (location = 0) noperspective out highp float depth;
|
||||
|
||||
void wDivide(inout vec4 vpos)
|
||||
{
|
||||
vpos = vec4(vpos.xy / vpos.w, 1.0 / vpos.w, 1.0);
|
||||
vpos = uniformBuffer.ndcMat * vpos;
|
||||
depth = vpos.z;
|
||||
vpos.w = 1.0;
|
||||
vpos.z = 0.0;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 vpos = n2Uniform.mvMat * in_pos;
|
||||
vpos = n2Uniform.projMat * vpos;
|
||||
wDivide(vpos);
|
||||
|
||||
gl_Position = vpos;
|
||||
}
|
||||
)";
|
||||
|
||||
vk::UniqueShaderModule ShaderManager::compileShader(const VertexShaderParams& params)
|
||||
{
|
||||
VulkanSource src;
|
||||
src.addConstant("pp_Gouraud", (int)params.gouraud)
|
||||
.addSource(GouraudSource)
|
||||
.addSource(VertexShaderSource);
|
||||
if (!params.naomi2)
|
||||
{
|
||||
src.addConstant("pp_Gouraud", (int)params.gouraud)
|
||||
.addSource(GouraudSource)
|
||||
.addSource(VertexShaderSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
src.addConstant("pp_Gouraud", (int)params.gouraud)
|
||||
.addSource(GouraudSource)
|
||||
.addSource(N2LightShaderSource)
|
||||
.addSource(N2VertexShaderSource);
|
||||
}
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, src.generate());
|
||||
}
|
||||
|
||||
|
@ -355,9 +706,10 @@ vk::UniqueShaderModule ShaderManager::compileShader(const FragmentShaderParams&
|
|||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eFragment, src.generate());
|
||||
}
|
||||
|
||||
vk::UniqueShaderModule ShaderManager::compileModVolVertexShader()
|
||||
vk::UniqueShaderModule ShaderManager::compileModVolVertexShader(bool naomi2)
|
||||
{
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex, VulkanSource().addSource(ModVolVertexShaderSource).generate());
|
||||
return ShaderCompiler::Compile(vk::ShaderStageFlagBits::eVertex,
|
||||
VulkanSource().addSource(naomi2 ? N2ModVolVertexShaderSource : ModVolVertexShaderSource).generate());
|
||||
}
|
||||
|
||||
vk::UniqueShaderModule ShaderManager::compileModVolFragmentShader()
|
||||
|
|
|
@ -28,8 +28,9 @@
|
|||
struct VertexShaderParams
|
||||
{
|
||||
bool gouraud;
|
||||
bool naomi2;
|
||||
|
||||
u32 hash() { return (u32)gouraud; }
|
||||
u32 hash() { return (u32)gouraud | ((u32)naomi2 << 1); }
|
||||
};
|
||||
|
||||
// alpha test, clip test, use alpha, texture, ignore alpha, shader instr, offset, fog, gouraud, bump, clamp, trilinear
|
||||
|
@ -62,7 +63,7 @@ struct FragmentShaderParams
|
|||
// std140 alignment required
|
||||
struct VertexShaderUniforms
|
||||
{
|
||||
glm::mat4 normal_matrix;
|
||||
glm::mat4 ndcMat;
|
||||
};
|
||||
|
||||
// std140 alignment required
|
||||
|
@ -76,16 +77,71 @@ struct FragmentShaderUniforms
|
|||
float sp_FOG_DENSITY;
|
||||
};
|
||||
|
||||
// std140 alignment required
|
||||
struct N2VertexShaderUniforms
|
||||
{
|
||||
glm::mat4 mvMat;
|
||||
glm::mat4 normalMat;
|
||||
glm::mat4 projMat;
|
||||
int envMapping[2];
|
||||
int bumpMapping;
|
||||
int polyNumber;
|
||||
|
||||
float glossCoef[2];
|
||||
int constantColor[2];
|
||||
int modelDiffuse[2];
|
||||
int modelSpecular[2];
|
||||
};
|
||||
|
||||
// std140 alignment required
|
||||
struct VkN2Light
|
||||
{
|
||||
float color[4];
|
||||
float direction[4];
|
||||
float position[4];
|
||||
|
||||
int parallel;
|
||||
int routing;
|
||||
int dmode;
|
||||
int smode;
|
||||
|
||||
int diffuse[2];
|
||||
int specular[2];
|
||||
|
||||
float attnDistA;
|
||||
float attnDistB;
|
||||
float attnAngleA;
|
||||
float attnAngleB;
|
||||
|
||||
int distAttnMode;
|
||||
int _pad[3];
|
||||
};
|
||||
|
||||
// std140 alignment required
|
||||
struct VkN2LightConstants
|
||||
{
|
||||
VkN2Light lights[16];
|
||||
float ambientBase[2][4];
|
||||
float ambientOffset[2][4];
|
||||
int ambientMaterialBase[2];
|
||||
int ambientMaterialOffset[2];
|
||||
int lightCount;
|
||||
int useBaseOver;
|
||||
int bumpId1;
|
||||
int bumpId2;
|
||||
};
|
||||
|
||||
class ShaderManager
|
||||
{
|
||||
public:
|
||||
vk::ShaderModule GetVertexShader(const VertexShaderParams& params) { return getShader(vertexShaders, params); }
|
||||
vk::ShaderModule GetFragmentShader(const FragmentShaderParams& params) { return getShader(fragmentShaders, params); }
|
||||
vk::ShaderModule GetModVolVertexShader()
|
||||
vk::ShaderModule GetModVolVertexShader(bool naomi2)
|
||||
{
|
||||
if (!modVolVertexShader)
|
||||
modVolVertexShader = compileModVolVertexShader();
|
||||
return *modVolVertexShader;
|
||||
vk::UniqueShaderModule& shader = naomi2 ? n2ModVolVertexShader : modVolVertexShader;
|
||||
if (!shader)
|
||||
shader = compileModVolVertexShader(naomi2);
|
||||
return *shader;
|
||||
}
|
||||
vk::ShaderModule GetModVolShader()
|
||||
{
|
||||
|
@ -148,7 +204,7 @@ private:
|
|||
}
|
||||
vk::UniqueShaderModule compileShader(const VertexShaderParams& params);
|
||||
vk::UniqueShaderModule compileShader(const FragmentShaderParams& params);
|
||||
vk::UniqueShaderModule compileModVolVertexShader();
|
||||
vk::UniqueShaderModule compileModVolVertexShader(bool naomi2);
|
||||
vk::UniqueShaderModule compileModVolFragmentShader();
|
||||
vk::UniqueShaderModule compileQuadVertexShader(bool rotate);
|
||||
vk::UniqueShaderModule compileQuadFragmentShader(bool ignoreTexAlpha);
|
||||
|
@ -158,6 +214,7 @@ private:
|
|||
std::map<u32, vk::UniqueShaderModule> vertexShaders;
|
||||
std::map<u32, vk::UniqueShaderModule> fragmentShaders;
|
||||
vk::UniqueShaderModule modVolVertexShader;
|
||||
vk::UniqueShaderModule n2ModVolVertexShader;
|
||||
vk::UniqueShaderModule modVolShader;
|
||||
vk::UniqueShaderModule quadVertexShader;
|
||||
vk::UniqueShaderModule quadRotateVertexShader;
|
||||
|
|
|
@ -96,3 +96,9 @@ public:
|
|||
static inline vk::ClearColorValue getBorderColor() {
|
||||
return vk::ClearColorValue(std::array<float, 4>{ VO_BORDER_COL.red(), VO_BORDER_COL.green(), VO_BORDER_COL.blue(), 1.f });
|
||||
}
|
||||
|
||||
static inline u32 align(vk::DeviceSize offset, u32 alignment)
|
||||
{
|
||||
u32 pad = (u32)(offset & (alignment - 1));
|
||||
return pad == 0 ? 0 : alignment - pad;
|
||||
}
|
||||
|
|
|
@ -431,19 +431,19 @@ bool VulkanContext::InitDevice()
|
|||
vk::DescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ vk::DescriptorType::eSampler, 2 },
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 15000 },
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 40000 },
|
||||
{ vk::DescriptorType::eSampledImage, 2 },
|
||||
{ vk::DescriptorType::eStorageImage, 12 },
|
||||
{ vk::DescriptorType::eUniformTexelBuffer, 2 },
|
||||
{ vk::DescriptorType::eStorageTexelBuffer, 2 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 36 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 80000 },
|
||||
{ vk::DescriptorType::eStorageBuffer, 36 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 2 },
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 2 },
|
||||
{ vk::DescriptorType::eInputAttachment, 36 }
|
||||
};
|
||||
descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
|
||||
10000, ARRAY_SIZE(pool_sizes), pool_sizes));
|
||||
40000, ARRAY_SIZE(pool_sizes), pool_sizes));
|
||||
|
||||
|
||||
std::string cachePath = hostfs::getShaderCachePath("vulkan_pipeline.cache");
|
||||
|
|
|
@ -140,6 +140,8 @@ public:
|
|||
bool result;
|
||||
if (ctx->rend.isRenderFramebuffer)
|
||||
result = RenderFramebuffer(ctx);
|
||||
else if (settings.platform.isNaomi2())
|
||||
result = ta_parse_naomi2(ctx);
|
||||
else
|
||||
result = ta_parse_vdrc(ctx);
|
||||
|
||||
|
|
Loading…
Reference in New Issue