vulkan: modifier volumes

This commit is contained in:
Flyinghead 2019-10-07 12:30:56 +02:00
parent 8d520fa5e4
commit b790a336e9
7 changed files with 165 additions and 69 deletions

View File

@ -67,19 +67,19 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
if (mode == ModVolMode::Final) if (mode == ModVolMode::Final)
{ {
pipelineVertexInputStateCreateInfo = GetMainVertexInputStateCreateInfo(); pipelineVertexInputStateCreateInfo = GetMainVertexInputStateCreateInfo(false);
pipelineInputAssemblyStateCreateInfo = vk::PipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), pipelineInputAssemblyStateCreateInfo = vk::PipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(),
vk::PrimitiveTopology::eTriangleStrip); vk::PrimitiveTopology::eTriangleStrip);
} }
else else
{ {
const vk::VertexInputBindingDescription vertexBindingDescriptions[] = static const vk::VertexInputBindingDescription vertexBindingDescriptions[] =
{ {
{ 0, sizeof(ModTriangle) }, { 0, sizeof(float) * 3 },
}; };
const vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[] = static const vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[] =
{ {
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x)), // pos vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, 0), // pos
}; };
pipelineVertexInputStateCreateInfo = vk::PipelineVertexInputStateCreateInfo( pipelineVertexInputStateCreateInfo = vk::PipelineVertexInputStateCreateInfo(
vk::PipelineVertexInputStateCreateFlags(), vk::PipelineVertexInputStateCreateFlags(),
@ -99,7 +99,7 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
( (
vk::PipelineRasterizationStateCreateFlags(), // flags vk::PipelineRasterizationStateCreateFlags(), // flags
false, // depthClampEnable false, // depthClampEnable
mode != ModVolMode::Final, // rasterizerDiscardEnable false, // rasterizerDiscardEnable
vk::PolygonMode::eFill, // polygonMode vk::PolygonMode::eFill, // polygonMode
vk::CullModeFlagBits::eNone, // cullMode vk::CullModeFlagBits::eNone, // cullMode
vk::FrontFace::eCounterClockwise, // frontFace vk::FrontFace::eCounterClockwise, // frontFace
@ -122,10 +122,10 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 2, 2, 2); stencilOpState = vk::StencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 2, 2, 2);
break; break;
case ModVolMode::Inclusion: case ModVolMode::Inclusion:
stencilOpState = vk::StencilOpState(vk::StencilOp::eZero, vk::StencilOp::eReplace, vk::StencilOp::eZero, vk::CompareOp::eLessOrEqual, 1, 3, 3); stencilOpState = vk::StencilOpState(vk::StencilOp::eZero, vk::StencilOp::eReplace, vk::StencilOp::eZero, vk::CompareOp::eLessOrEqual, 3, 3, 1);
break; break;
case ModVolMode::Exclusion: case ModVolMode::Exclusion:
stencilOpState = vk::StencilOpState(vk::StencilOp::eZero, vk::StencilOp::eKeep, vk::StencilOp::eZero, vk::CompareOp::eEqual, 1, 3, 3); stencilOpState = vk::StencilOpState(vk::StencilOp::eZero, vk::StencilOp::eKeep, vk::StencilOp::eZero, vk::CompareOp::eEqual, 3, 3, 1);
break; break;
case ModVolMode::Final: case ModVolMode::Final:
stencilOpState = vk::StencilOpState(vk::StencilOp::eZero, vk::StencilOp::eZero, vk::StencilOp::eZero, vk::CompareOp::eEqual, 0x81, 3, 0x81); stencilOpState = vk::StencilOpState(vk::StencilOp::eZero, vk::StencilOp::eZero, vk::StencilOp::eZero, vk::CompareOp::eEqual, 0x81, 3, 0x81);
@ -140,11 +140,13 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
false, // depthBoundTestEnable false, // depthBoundTestEnable
true, // stencilTestEnable true, // stencilTestEnable
stencilOpState, // front stencilOpState, // front
vk::StencilOpState() // back stencilOpState // back
); );
// Color flags and blending // Color flags and blending
vk::ColorComponentFlags colorComponentFlags(vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA); vk::ColorComponentFlags colorComponentFlags(
mode != ModVolMode::Final ? (vk::ColorComponentFlagBits)0
: vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA);
vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState( vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState(
mode == ModVolMode::Final, // blendEnable mode == ModVolMode::Final, // blendEnable
vk::BlendFactor::eSrcAlpha, // srcColorBlendFactor vk::BlendFactor::eSrcAlpha, // srcColorBlendFactor
@ -169,7 +171,7 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates); vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates);
vk::ShaderModule vertex_module = shaderManager.GetVertexShader(VertexShaderParams{ false, false }); // TODO rotate90 vk::ShaderModule vertex_module = shaderManager.GetModVolVertexShader();
vk::ShaderModule fragment_module = shaderManager.GetModVolShader(); vk::ShaderModule fragment_module = shaderManager.GetModVolShader();
vk::PipelineShaderStageCreateInfo stages[] = { vk::PipelineShaderStageCreateInfo stages[] = {
@ -195,7 +197,7 @@ void PipelineManager::CreateModVolPipeline(ModVolMode mode)
); );
if (modVolPipelines.empty()) if (modVolPipelines.empty())
modVolPipelines.reserve((size_t)ModVolMode::Final + 1); modVolPipelines.resize((size_t)ModVolMode::Final + 1);
modVolPipelines[(size_t)mode] = modVolPipelines[(size_t)mode] =
GetContext()->GetDevice()->createGraphicsPipelineUnique(GetContext()->GetPipelineCache(), GetContext()->GetDevice()->createGraphicsPipelineUnique(GetContext()->GetPipelineCache(),
graphicsPipelineCreateInfo); graphicsPipelineCreateInfo);
@ -250,7 +252,7 @@ void PipelineManager::CreatePipeline(u32 listType, bool sortTriangles, const Pol
depthWriteEnable = !pp.isp.ZWriteDis; depthWriteEnable = !pp.isp.ZWriteDis;
} }
vk::StencilOpState stencilOpStateSet(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0x80); vk::StencilOpState stencilOpStateSet(vk::StencilOp::eKeep, vk::StencilOp::eReplace, vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0, 0x80, 0x80);
vk::StencilOpState stencilOpStateNop(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways); vk::StencilOpState stencilOpStateNop(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways);
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo
( (
@ -260,8 +262,8 @@ void PipelineManager::CreatePipeline(u32 listType, bool sortTriangles, const Pol
depthOp, // depthCompareOp depthOp, // depthCompareOp
false, // depthBoundTestEnable false, // depthBoundTestEnable
listType == ListType_Opaque || listType == ListType_Punch_Through, // stencilTestEnable listType == ListType_Opaque || listType == ListType_Punch_Through, // stencilTestEnable
pp.pcw.Shadow != 0 ? stencilOpStateSet : stencilOpStateNop, // front pp.pcw.Shadow != 0 ? stencilOpStateSet : stencilOpStateNop, // front
stencilOpStateNop // back pp.pcw.Shadow != 0 ? stencilOpStateSet : stencilOpStateNop // back
); );
// Color flags and blending // Color flags and blending

View File

@ -54,7 +54,7 @@ public:
void UpdateUniforms(const vk::Buffer& vertexUniformBuffer, const vk::Buffer& fragmentUniformBuffer, vk::ImageView fogImageView) void UpdateUniforms(const vk::Buffer& vertexUniformBuffer, const vk::Buffer& fragmentUniformBuffer, vk::ImageView fogImageView)
{ {
while (perFrameDescSets.empty()) if (perFrameDescSets.empty())
{ {
std::vector<vk::DescriptorSetLayout> layouts(GetContext()->GetSwapChainSize(), *perFrameLayout); std::vector<vk::DescriptorSetLayout> layouts(GetContext()->GetSwapChainSize(), *perFrameLayout);
perFrameDescSets = GetContext()->GetDevice()->allocateDescriptorSetsUnique( perFrameDescSets = GetContext()->GetDevice()->allocateDescriptorSetsUnique(
@ -170,6 +170,13 @@ public:
return *pipelines[pipehash]; return *pipelines[pipehash];
} }
vk::Pipeline GetModifierVolumePipeline(ModVolMode mode)
{
if (modVolPipelines.empty() || !modVolPipelines[(size_t)mode])
CreateModVolPipeline(mode);
return *modVolPipelines[(size_t)mode];
}
private: private:
VulkanContext *GetContext() const { return VulkanContext::Instance(); } VulkanContext *GetContext() const { return VulkanContext::Instance(); }
void CreateModVolPipeline(ModVolMode mode); void CreateModVolPipeline(ModVolMode mode);
@ -189,7 +196,7 @@ private:
return hash; return hash;
} }
vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo() const vk::PipelineVertexInputStateCreateInfo GetMainVertexInputStateCreateInfo(bool full = true) const
{ {
// Vertex input state // Vertex input state
static const vk::VertexInputBindingDescription vertexBindingDescriptions[] = static const vk::VertexInputBindingDescription vertexBindingDescriptions[] =
@ -203,12 +210,16 @@ private:
vk::VertexInputAttributeDescription(2, 0, vk::Format::eR8G8B8A8Uint, offsetof(Vertex, spc)), // offset 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(3, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, u)), // tex coord
}; };
static const vk::VertexInputAttributeDescription vertexInputLightAttributeDescriptions[] =
{
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x)), // pos
};
return vk::PipelineVertexInputStateCreateInfo( return vk::PipelineVertexInputStateCreateInfo(
vk::PipelineVertexInputStateCreateFlags(), vk::PipelineVertexInputStateCreateFlags(),
ARRAY_SIZE(vertexBindingDescriptions), ARRAY_SIZE(vertexBindingDescriptions),
vertexBindingDescriptions, vertexBindingDescriptions,
ARRAY_SIZE(vertexInputAttributeDescriptions), full ? ARRAY_SIZE(vertexInputAttributeDescriptions) : ARRAY_SIZE(vertexInputLightAttributeDescriptions),
vertexInputAttributeDescriptions); full ? vertexInputAttributeDescriptions : vertexInputLightAttributeDescriptions);
} }
void CreatePipeline(u32 listType, bool sortTriangles, const PolyParam& pp); void CreatePipeline(u32 listType, bool sortTriangles, const PolyParam& pp);

View File

@ -251,23 +251,53 @@ void main()
} }
)"; )";
static const char ModVolShaderSource[] = R"( static const char ModVolVertexShaderSource[] = R"(
#version 400 #version 400
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable #extension GL_ARB_shading_language_420pack : enable
out vec4 FragColor; layout (std140, set = 0, binding = 0) uniform VertexShaderUniforms
{
vec4 scale;
float extra_depth_scale;
} uniformBuffer;
layout (std140, binding = 1) uniform buffer layout (location = 0) in vec4 in_pos;
void main()
{
vec4 vpos = in_pos;
if (vpos.z < 0.0 || vpos.z > 3.4e37)
{
gl_Position = vec4(0.0, 0.0, 1.0, 1.0 / vpos.z);
return;
}
vpos.w = uniformBuffer.extra_depth_scale / vpos.z;
vpos.z = vpos.w;
vpos.xy = vpos.xy * uniformBuffer.scale.xy - uniformBuffer.scale.zw;
vpos.xy *= vpos.w;
gl_Position = vpos;
}
)";
static const char ModVolFragmentShaderSource[] = R"(
#version 400
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (location = 0) out vec4 FragColor;
layout (push_constant) uniform pushBlock
{ {
float sp_ShaderColor; float sp_ShaderColor;
} uniformBuffer; } pushConstants;
void main() void main()
{ {
float w = gl_FragCoord.w * 100000.0; float w = gl_FragCoord.w * 100000.0;
gl_FragDepth = log2(1.0 + w) / 34.0; gl_FragDepth = log2(1.0 + w) / 34.0;
FragColor = vec4(0.0, 0.0, 0.0, uniformBuffer.sp_ShaderColor); FragColor = vec4(0.0, 0.0, 0.0, pushConstants.sp_ShaderColor);
} }
)"; )";
@ -468,7 +498,12 @@ vk::UniqueShaderModule ShaderManager::compileShader(const FragmentShaderParams&
return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eFragment, buf); return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eFragment, buf);
} }
vk::UniqueShaderModule ShaderManager::compileVertexModVolShader()
{
return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eVertex, ModVolVertexShaderSource);
}
vk::UniqueShaderModule ShaderManager::compileModVolShader() vk::UniqueShaderModule ShaderManager::compileModVolShader()
{ {
return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eFragment, ModVolShaderSource); return createShaderModule(VulkanContext::Instance()->GetDevice(), vk::ShaderStageFlagBits::eFragment, ModVolFragmentShaderSource);
} }

View File

@ -74,11 +74,6 @@ struct FragmentShaderUniforms
float extra_depth_scale; float extra_depth_scale;
}; };
struct ModVolShaderUniforms
{
float sp_ShaderColor;
};
class ShaderManager class ShaderManager
{ {
public: public:
@ -88,6 +83,12 @@ public:
} }
vk::ShaderModule GetVertexShader(const VertexShaderParams& params) { return getShader(vertexShaders, params); } vk::ShaderModule GetVertexShader(const VertexShaderParams& params) { return getShader(vertexShaders, params); }
vk::ShaderModule GetFragmentShader(const FragmentShaderParams& params) { return getShader(fragmentShaders, params); } vk::ShaderModule GetFragmentShader(const FragmentShaderParams& params) { return getShader(fragmentShaders, params); }
vk::ShaderModule GetModVolVertexShader()
{
if (!modVolVertexShader)
modVolVertexShader = compileVertexModVolShader();
return *modVolVertexShader;
}
vk::ShaderModule GetModVolShader() vk::ShaderModule GetModVolShader()
{ {
if (!modVolShader) if (!modVolShader)
@ -107,9 +108,11 @@ private:
} }
vk::UniqueShaderModule compileShader(const VertexShaderParams& params); vk::UniqueShaderModule compileShader(const VertexShaderParams& params);
vk::UniqueShaderModule compileShader(const FragmentShaderParams& params); vk::UniqueShaderModule compileShader(const FragmentShaderParams& params);
vk::UniqueShaderModule compileVertexModVolShader();
vk::UniqueShaderModule compileModVolShader(); vk::UniqueShaderModule compileModVolShader();
std::map<u32, vk::UniqueShaderModule> vertexShaders; std::map<u32, vk::UniqueShaderModule> vertexShaders;
std::map<u32, vk::UniqueShaderModule> fragmentShaders; std::map<u32, vk::UniqueShaderModule> fragmentShaders;
vk::UniqueShaderModule modVolVertexShader;
vk::UniqueShaderModule modVolShader; vk::UniqueShaderModule modVolShader;
}; };

View File

@ -74,7 +74,7 @@ public:
static VulkanContext *Instance() { return contextInstance; } static VulkanContext *Instance() { return contextInstance; }
private: private:
void InitDepthBuffer(); vk::Format InitDepthBuffer();
void InitImgui(); void InitImgui();
bool HasSurfaceDimensionChanged() bool HasSurfaceDimensionChanged()

View File

@ -144,23 +144,31 @@ void VulkanContext::InitInstance(const char** extensions, uint32_t extensions_co
} }
} }
void VulkanContext::InitDepthBuffer() vk::Format VulkanContext::InitDepthBuffer()
{ {
const vk::Format depthFormat = vk::Format::eD16Unorm; const vk::Format depthFormats[] = { vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint };
vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(depthFormat);
vk::ImageTiling tiling; vk::ImageTiling tiling;
if (formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment) vk::Format depthFormat = vk::Format::eUndefined;
for (int i = 0; i < ARRAY_SIZE(depthFormats); i++)
{ {
tiling = vk::ImageTiling::eLinear; vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(depthFormats[i]);
if (formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment)
{
tiling = vk::ImageTiling::eLinear;
depthFormat = depthFormats[i];
break;
}
else if (formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment)
{
tiling = vk::ImageTiling::eOptimal;
depthFormat = depthFormats[i];
break;
}
} }
else if (formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment) if (depthFormat == vk::Format::eUndefined)
{ {
tiling = vk::ImageTiling::eOptimal; die("No supported depth/stencil format found");
}
else
{
die("DepthStencilAttachment is not supported for D16Unorm depth format.");
} }
vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, depthFormat, vk::Extent3D(width, height, 1), 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, depthFormat, vk::Extent3D(width, height, 1), 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment);
@ -187,6 +195,8 @@ void VulkanContext::InitDepthBuffer()
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA);
vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1); vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1);
depthView = device->createImageViewUnique(vk::ImageViewCreateInfo(vk::ImageViewCreateFlags(), *depthImage, vk::ImageViewType::e2D, depthFormat, componentMapping, subResourceRange)); depthView = device->createImageViewUnique(vk::ImageViewCreateInfo(vk::ImageViewCreateFlags(), *depthImage, vk::ImageViewType::e2D, depthFormat, componentMapping, subResourceRange));
return depthFormat;
} }
void VulkanContext::InitImgui() void VulkanContext::InitImgui()
@ -415,8 +425,9 @@ void VulkanContext::CreateSwapChain()
commandBuffers.push_back(std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(*commandPools.back(), vk::CommandBufferLevel::ePrimary, 1)).front())); commandBuffers.push_back(std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(*commandPools.back(), vk::CommandBufferLevel::ePrimary, 1)).front()));
} }
vk::Format depthFormat = InitDepthBuffer();
// Render pass // Render pass
vk::Format depthFormat = vk::Format::eD16Unorm;
vk::AttachmentDescription attachmentDescriptions[2]; vk::AttachmentDescription attachmentDescriptions[2];
// FIXME we should use vk::AttachmentLoadOp::eLoad for loadOp to preserve previous framebuffer but it fails on the first render // FIXME we should use vk::AttachmentLoadOp::eLoad for loadOp to preserve previous framebuffer but it fails on the first render
attachmentDescriptions[0] = vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, attachmentDescriptions[0] = vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear,
@ -430,8 +441,6 @@ void VulkanContext::CreateSwapChain()
renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpass)); renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpass));
InitDepthBuffer();
// Framebuffers, fences, semaphores // Framebuffers, fences, semaphores
vk::ImageView attachments[2]; vk::ImageView attachments[2];
attachments[1] = *depthView; attachments[1] = *depthView;

View File

@ -199,12 +199,9 @@ public:
fragUniforms.cp_AlphaTestValue = (PT_ALPHA_REF & 0xFF) / 255.0f; fragUniforms.cp_AlphaTestValue = (PT_ALPHA_REF & 0xFF) / 255.0f;
ModVolShaderUniforms modVolUniforms;
modVolUniforms.sp_ShaderColor = 1 - FPU_SHAD_SCALE.scale_factor / 256.f;
SortTriangles(); SortTriangles();
UploadUniforms(vtxUniforms, fragUniforms, modVolUniforms); UploadUniforms(vtxUniforms, fragUniforms);
GetContext()->BeginRenderPass(); GetContext()->BeginRenderPass();
vk::CommandBuffer cmdBuffer = GetContext()->GetCurrentCommandBuffer(); vk::CommandBuffer cmdBuffer = GetContext()->GetCurrentCommandBuffer();
@ -220,7 +217,7 @@ public:
// Bind vertex and index buffers // Bind vertex and index buffers
const vk::DeviceSize offsets[] = { 0 }; const vk::DeviceSize offsets[] = { 0 };
cmdBuffer.bindVertexBuffers(0, 1, &mainBuffers[GetCurrentImage()]->buffer.get(), offsets); cmdBuffer.bindVertexBuffers(0, 1, &mainBuffers[GetCurrentImage()]->buffer.get(), offsets);
cmdBuffer.bindIndexBuffer(*mainBuffers[GetCurrentImage()]->buffer, pvrrc.verts.bytes(), vk::IndexType::eUint32); cmdBuffer.bindIndexBuffer(*mainBuffers[GetCurrentImage()]->buffer, pvrrc.verts.bytes() + pvrrc.modtrig.bytes(), vk::IndexType::eUint32);
cmdBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(GetContext()->GetViewPort().width), cmdBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(GetContext()->GetViewPort().width),
static_cast<float>(GetContext()->GetViewPort().width), 1.0f, 0.0f)); static_cast<float>(GetContext()->GetViewPort().width), 1.0f, 0.0f));
@ -238,6 +235,7 @@ public:
current_pass.mvo_count - previous_pass.mvo_count); current_pass.mvo_count - previous_pass.mvo_count);
DrawList(cmdBuffer, ListType_Opaque, false, pvrrc.global_param_op, previous_pass.op_count, current_pass.op_count - previous_pass.op_count); DrawList(cmdBuffer, ListType_Opaque, false, pvrrc.global_param_op, previous_pass.op_count, current_pass.op_count - previous_pass.op_count);
DrawList(cmdBuffer, ListType_Punch_Through, false, pvrrc.global_param_pt, previous_pass.pt_count, current_pass.pt_count - previous_pass.pt_count); DrawList(cmdBuffer, ListType_Punch_Through, false, pvrrc.global_param_pt, previous_pass.pt_count, current_pass.pt_count - previous_pass.pt_count);
DrawModVols(cmdBuffer, previous_pass.mvo_count, current_pass.mvo_count - previous_pass.mvo_count);
if (current_pass.autosort) if (current_pass.autosort)
{ {
if (!settings.rend.PerStripSorting) if (!settings.rend.PerStripSorting)
@ -458,6 +456,58 @@ private:
} }
} }
void DrawModVols(const vk::CommandBuffer& cmdBuffer, int first, int count)
{
if (count == 0 || pvrrc.modtrig.used() == 0)
return;
vk::DeviceSize offsets[] = { (vk::DeviceSize)pvrrc.verts.bytes() };
cmdBuffer.bindVertexBuffers(0, 1, &mainBuffers[GetCurrentImage()]->buffer.get(), offsets);
ModifierVolumeParam* params = &pvrrc.global_param_mvo.head()[first];
int mod_base = -1;
vk::Pipeline pipeline;
for (u32 cmv = 0; cmv < count; cmv++)
{
ModifierVolumeParam& param = params[cmv];
if (param.count == 0)
continue;
u32 mv_mode = param.isp.DepthMode;
if (mod_base == -1)
mod_base = param.first;
if (!param.isp.VolumeLast && mv_mode > 0)
pipeline = pipelineManager.GetModifierVolumePipeline(ModVolMode::Or); // OR'ing (open volume or quad)
else
pipeline = pipelineManager.GetModifierVolumePipeline(ModVolMode::Xor); // XOR'ing (closed volume)
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
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);
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.draw((param.first + param.count - mod_base) * 3, 1, mod_base * 3, 0);
mod_base = -1;
}
}
offsets[0] = 0;
cmdBuffer.bindVertexBuffers(0, 1, &mainBuffers[GetCurrentImage()]->buffer.get(), offsets);
std::array<float, 5> pushConstants = { 1 - FPU_SHAD_SCALE.scale_factor / 256.f, 0, 0, 0, 0 };
cmdBuffer.pushConstants<float>(pipelineManager.GetDescriptorSets().GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants);
pipeline = pipelineManager.GetModifierVolumePipeline(ModVolMode::Final);
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cmdBuffer.drawIndexed(4, 1, 0, 0, 0);
}
void InitUniforms() void InitUniforms()
{ {
vertexUniformBuffer = GetContext()->GetDevice()->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), vertexUniformBuffer = GetContext()->GetDevice()->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(),
@ -477,18 +527,9 @@ private:
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
fragmentUniformMemory = GetContext()->GetDevice()->allocateMemoryUnique(vk::MemoryAllocateInfo(fragmentUniformsMemSize, typeIndex)); fragmentUniformMemory = GetContext()->GetDevice()->allocateMemoryUnique(vk::MemoryAllocateInfo(fragmentUniformsMemSize, typeIndex));
GetContext()->GetDevice()->bindBufferMemory(fragmentUniformBuffer.get(), fragmentUniformMemory.get(), 0); GetContext()->GetDevice()->bindBufferMemory(fragmentUniformBuffer.get(), fragmentUniformMemory.get(), 0);
modVolUniformBuffer = GetContext()->GetDevice()->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(),
sizeof(ModVolShaderUniforms), vk::BufferUsageFlagBits::eUniformBuffer));
memRequirements = GetContext()->GetDevice()->getBufferMemoryRequirements(modVolUniformBuffer.get());
modVolUniformsMemSize = memRequirements.size;
typeIndex = findMemoryType(GetContext()->GetPhysicalDevice().getMemoryProperties(), memRequirements.memoryTypeBits,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
modVolUniformMemory = GetContext()->GetDevice()->allocateMemoryUnique(vk::MemoryAllocateInfo(modVolUniformsMemSize, typeIndex));
GetContext()->GetDevice()->bindBufferMemory(modVolUniformBuffer.get(), modVolUniformMemory.get(), 0);
} }
void UploadUniforms(const VertexShaderUniforms& vertexUniforms, const FragmentShaderUniforms& fragmentUniforms, const ModVolShaderUniforms& modVolUniforms) void UploadUniforms(const VertexShaderUniforms& vertexUniforms, const FragmentShaderUniforms& fragmentUniforms)
{ {
uint8_t* pData = static_cast<uint8_t*>(GetContext()->GetDevice()->mapMemory(vertexUniformMemory.get(), 0, vertexUniformMemSize)); uint8_t* pData = static_cast<uint8_t*>(GetContext()->GetDevice()->mapMemory(vertexUniformMemory.get(), 0, vertexUniformMemSize));
memcpy(pData, &vertexUniforms, sizeof(vertexUniforms)); memcpy(pData, &vertexUniforms, sizeof(vertexUniforms));
@ -497,15 +538,11 @@ private:
pData = static_cast<uint8_t*>(GetContext()->GetDevice()->mapMemory(fragmentUniformMemory.get(), 0, fragmentUniformsMemSize)); pData = static_cast<uint8_t*>(GetContext()->GetDevice()->mapMemory(fragmentUniformMemory.get(), 0, fragmentUniformsMemSize));
memcpy(pData, &fragmentUniforms, sizeof(fragmentUniforms)); memcpy(pData, &fragmentUniforms, sizeof(fragmentUniforms));
GetContext()->GetDevice()->unmapMemory(fragmentUniformMemory.get()); GetContext()->GetDevice()->unmapMemory(fragmentUniformMemory.get());
pData = static_cast<uint8_t*>(GetContext()->GetDevice()->mapMemory(modVolUniformMemory.get(), 0, modVolUniformsMemSize));
memcpy(pData, &modVolUniforms, sizeof(modVolUniforms));
GetContext()->GetDevice()->unmapMemory(modVolUniformMemory.get());
} }
void UploadMainBuffer() void UploadMainBuffer()
{ {
u32 totalSize = pvrrc.verts.bytes() + pvrrc.idx.bytes() + sortedIndexCount * sizeof(u32); u32 totalSize = pvrrc.verts.bytes() + pvrrc.idx.bytes() + pvrrc.modtrig.bytes() + sortedIndexCount * sizeof(u32);
if (mainBuffers.empty()) if (mainBuffers.empty())
{ {
for (int i = 0; i < GetContext()->GetSwapChainSize(); i++) for (int i = 0; i < GetContext()->GetSwapChainSize(); i++)
@ -527,6 +564,8 @@ private:
chunks.push_back(pvrrc.verts.head()); chunks.push_back(pvrrc.verts.head());
chunkSizes.push_back(pvrrc.verts.bytes()); chunkSizes.push_back(pvrrc.verts.bytes());
chunks.push_back(pvrrc.modtrig.head());
chunkSizes.push_back(pvrrc.modtrig.bytes());
chunks.push_back(pvrrc.idx.head()); chunks.push_back(pvrrc.idx.head());
chunkSizes.push_back(pvrrc.idx.bytes()); chunkSizes.push_back(pvrrc.idx.bytes());
for (const std::vector<u32>& idx : sortedIndexes) for (const std::vector<u32>& idx : sortedIndexes)
@ -568,13 +607,10 @@ private:
// Uniforms // Uniforms
vk::UniqueBuffer vertexUniformBuffer; vk::UniqueBuffer vertexUniformBuffer;
vk::UniqueBuffer fragmentUniformBuffer; vk::UniqueBuffer fragmentUniformBuffer;
vk::UniqueBuffer modVolUniformBuffer;
vk::UniqueDeviceMemory vertexUniformMemory; vk::UniqueDeviceMemory vertexUniformMemory;
vk::UniqueDeviceMemory fragmentUniformMemory; vk::UniqueDeviceMemory fragmentUniformMemory;
vk::UniqueDeviceMemory modVolUniformMemory;
vk::DeviceSize vertexUniformMemSize; vk::DeviceSize vertexUniformMemSize;
vk::DeviceSize fragmentUniformsMemSize; vk::DeviceSize fragmentUniformsMemSize;
vk::DeviceSize modVolUniformsMemSize;
// Buffers // Buffers
std::vector<std::unique_ptr<BufferData>> mainBuffers; std::vector<std::unique_ptr<BufferData>> mainBuffers;