mirror of
https://github.com/ZDoom/Raze.git
synced 2025-05-30 00:41:24 +00:00
- glslang compiler and Vulkan backend update.
This commit is contained in:
parent
0c03d3e364
commit
2c3fcbaf51
127 changed files with 25652 additions and 11531 deletions
289
source/common/rendering/vulkan/renderer/vk_descriptorset.cpp
Normal file
289
source/common/rendering/vulkan/renderer/vk_descriptorset.cpp
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_descriptorset.h"
|
||||
#include "vk_streambuffer.h"
|
||||
#include "vk_raytrace.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/textures/vk_samplers.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_hwtexture.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_hwbuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/system/vk_buffer.h"
|
||||
#include "flatvertices.h"
|
||||
#include "hw_viewpointuniforms.h"
|
||||
#include "v_2ddrawer.h"
|
||||
|
||||
VkDescriptorSetManager::VkDescriptorSetManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
CreateHWBufferSetLayout();
|
||||
CreateFixedSetLayout();
|
||||
CreateHWBufferPool();
|
||||
CreateFixedSetPool();
|
||||
}
|
||||
|
||||
VkDescriptorSetManager::~VkDescriptorSetManager()
|
||||
{
|
||||
while (!Materials.empty())
|
||||
RemoveMaterial(Materials.back());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::Init()
|
||||
{
|
||||
UpdateFixedSet();
|
||||
UpdateHWBufferSet();
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::Deinit()
|
||||
{
|
||||
while (!Materials.empty())
|
||||
RemoveMaterial(Materials.back());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::BeginFrame()
|
||||
{
|
||||
UpdateFixedSet();
|
||||
UpdateHWBufferSet();
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::UpdateHWBufferSet()
|
||||
{
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(HWBufferSet));
|
||||
|
||||
HWBufferSet = HWBufferDescriptorPool->tryAllocate(HWBufferSetLayout.get());
|
||||
if (!HWBufferSet)
|
||||
{
|
||||
fb->GetCommands()->WaitForCommands(false);
|
||||
HWBufferSet = HWBufferDescriptorPool->allocate(HWBufferSetLayout.get());
|
||||
}
|
||||
|
||||
WriteDescriptors()
|
||||
.AddBuffer(HWBufferSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms))
|
||||
.AddBuffer(HWBufferSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO))
|
||||
.AddBuffer(HWBufferSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO))
|
||||
.AddBuffer(HWBufferSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightBufferSSO->mBuffer.get())
|
||||
.Execute(fb->device);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::UpdateFixedSet()
|
||||
{
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(FixedSet));
|
||||
|
||||
FixedSet = FixedDescriptorPool->tryAllocate(FixedSetLayout.get());
|
||||
if (!FixedSet)
|
||||
{
|
||||
fb->GetCommands()->WaitForCommands(false);
|
||||
FixedSet = FixedDescriptorPool->allocate(FixedSetLayout.get());
|
||||
}
|
||||
|
||||
WriteDescriptors update;
|
||||
update.AddCombinedImageSampler(FixedSet.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.AddCombinedImageSampler(FixedSet.get(), 1, fb->GetTextureManager()->Lightmap.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
if (fb->RaytracingEnabled())
|
||||
update.AddAccelerationStructure(FixedSet.get(), 2, fb->GetRaytrace()->GetAccelStruct());
|
||||
update.Execute(fb->device);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::ResetHWTextureSets()
|
||||
{
|
||||
for (auto mat : Materials)
|
||||
mat->DeleteDescriptors();
|
||||
|
||||
auto deleteList = fb->GetCommands()->DrawDeleteList.get();
|
||||
for (auto& desc : TextureDescriptorPools)
|
||||
{
|
||||
deleteList->Add(std::move(desc));
|
||||
}
|
||||
deleteList->Add(std::move(NullTextureDescriptorSet));
|
||||
|
||||
TextureDescriptorPools.clear();
|
||||
TextureDescriptorSetsLeft = 0;
|
||||
TextureDescriptorsLeft = 0;
|
||||
}
|
||||
|
||||
VulkanDescriptorSet* VkDescriptorSetManager::GetNullTextureDescriptorSet()
|
||||
{
|
||||
if (!NullTextureDescriptorSet)
|
||||
{
|
||||
NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS);
|
||||
|
||||
WriteDescriptors update;
|
||||
for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++)
|
||||
{
|
||||
update.AddCombinedImageSampler(NullTextureDescriptorSet.get(), i, fb->GetTextureManager()->GetNullTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
update.Execute(fb->device);
|
||||
}
|
||||
|
||||
return NullTextureDescriptorSet.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> VkDescriptorSetManager::AllocateTextureDescriptorSet(int numLayers)
|
||||
{
|
||||
if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers)
|
||||
{
|
||||
TextureDescriptorSetsLeft = 1000;
|
||||
TextureDescriptorsLeft = 2000;
|
||||
|
||||
TextureDescriptorPools.push_back(DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TextureDescriptorsLeft)
|
||||
.MaxSets(TextureDescriptorSetsLeft)
|
||||
.DebugName("VkDescriptorSetManager.TextureDescriptorPool")
|
||||
.Create(fb->device));
|
||||
}
|
||||
|
||||
TextureDescriptorSetsLeft--;
|
||||
TextureDescriptorsLeft -= numLayers;
|
||||
return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers));
|
||||
}
|
||||
|
||||
VulkanDescriptorSetLayout* VkDescriptorSetManager::GetTextureSetLayout(int numLayers)
|
||||
{
|
||||
if (TextureSetLayouts.size() < (size_t)numLayers)
|
||||
TextureSetLayouts.resize(numLayers);
|
||||
|
||||
auto& layout = TextureSetLayouts[numLayers - 1];
|
||||
if (layout)
|
||||
return layout.get();
|
||||
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
for (int i = 0; i < numLayers; i++)
|
||||
{
|
||||
builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
builder.DebugName("VkDescriptorSetManager.TextureSetLayout");
|
||||
layout = builder.Create(fb->device);
|
||||
return layout.get();
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::AddMaterial(VkMaterial* texture)
|
||||
{
|
||||
texture->it = Materials.insert(Materials.end(), texture);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::RemoveMaterial(VkMaterial* texture)
|
||||
{
|
||||
texture->DeleteDescriptors();
|
||||
texture->fb = nullptr;
|
||||
Materials.erase(texture->it);
|
||||
}
|
||||
|
||||
VulkanDescriptorSet* VkDescriptorSetManager::GetInput(VkPPRenderPassSetup* passSetup, const TArray<PPTextureInput>& textures, bool bindShadowMapBuffers)
|
||||
{
|
||||
auto descriptors = AllocatePPDescriptorSet(passSetup->DescriptorLayout.get());
|
||||
descriptors->SetDebugName("VkPostprocess.descriptors");
|
||||
|
||||
WriteDescriptors write;
|
||||
VkImageTransition imageTransition;
|
||||
|
||||
for (unsigned int index = 0; index < textures.Size(); index++)
|
||||
{
|
||||
const PPTextureInput& input = textures[index];
|
||||
VulkanSampler* sampler = fb->GetSamplerManager()->Get(input.Filter, input.Wrap);
|
||||
VkTextureImage* tex = fb->GetTextureManager()->GetTexture(input.Type, input.Texture);
|
||||
|
||||
write.AddCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||
}
|
||||
|
||||
if (bindShadowMapBuffers)
|
||||
{
|
||||
write.AddBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightNodes->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightLines->mBuffer.get());
|
||||
write.AddBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->LightList->mBuffer.get());
|
||||
}
|
||||
|
||||
write.Execute(fb->device);
|
||||
imageTransition.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
|
||||
VulkanDescriptorSet* set = descriptors.get();
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(descriptors));
|
||||
return set;
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> VkDescriptorSetManager::AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout)
|
||||
{
|
||||
if (PPDescriptorPool)
|
||||
{
|
||||
auto descriptors = PPDescriptorPool->tryAllocate(layout);
|
||||
if (descriptors)
|
||||
return descriptors;
|
||||
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(PPDescriptorPool));
|
||||
}
|
||||
|
||||
PPDescriptorPool = DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4)
|
||||
.MaxSets(100)
|
||||
.DebugName("PPDescriptorPool")
|
||||
.Create(fb->device);
|
||||
|
||||
return PPDescriptorPool->allocate(layout);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateHWBufferSetLayout()
|
||||
{
|
||||
HWBufferSetLayout = DescriptorSetLayoutBuilder()
|
||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.DebugName("VkDescriptorSetManager.HWBufferSetLayout")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateFixedSetLayout()
|
||||
{
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
if (fb->RaytracingEnabled())
|
||||
builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.DebugName("VkDescriptorSetManager.FixedSetLayout");
|
||||
FixedSetLayout = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateHWBufferPool()
|
||||
{
|
||||
HWBufferDescriptorPool = DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3 * maxSets)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 * maxSets)
|
||||
.MaxSets(maxSets)
|
||||
.DebugName("VkDescriptorSetManager.HWBufferDescriptorPool")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateFixedSetPool()
|
||||
{
|
||||
DescriptorPoolBuilder poolbuilder;
|
||||
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * maxSets);
|
||||
if (fb->RaytracingEnabled())
|
||||
poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * maxSets);
|
||||
poolbuilder.MaxSets(maxSets);
|
||||
poolbuilder.DebugName("VkDescriptorSetManager.FixedDescriptorPool");
|
||||
FixedDescriptorPool = poolbuilder.Create(fb->device);
|
||||
}
|
70
source/common/rendering/vulkan/renderer/vk_descriptorset.h
Normal file
70
source/common/rendering/vulkan/renderer/vk_descriptorset.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include <list>
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
class VkMaterial;
|
||||
class PPTextureInput;
|
||||
class VkPPRenderPassSetup;
|
||||
|
||||
class VkDescriptorSetManager
|
||||
{
|
||||
public:
|
||||
VkDescriptorSetManager(VulkanFrameBuffer* fb);
|
||||
~VkDescriptorSetManager();
|
||||
|
||||
void Init();
|
||||
void Deinit();
|
||||
void BeginFrame();
|
||||
void UpdateFixedSet();
|
||||
void UpdateHWBufferSet();
|
||||
void ResetHWTextureSets();
|
||||
|
||||
VulkanDescriptorSetLayout* GetHWBufferSetLayout() { return HWBufferSetLayout.get(); }
|
||||
VulkanDescriptorSetLayout* GetFixedSetLayout() { return FixedSetLayout.get(); }
|
||||
VulkanDescriptorSetLayout* GetTextureSetLayout(int numLayers);
|
||||
|
||||
VulkanDescriptorSet* GetHWBufferDescriptorSet() { return HWBufferSet.get(); }
|
||||
VulkanDescriptorSet* GetFixedDescriptorSet() { return FixedSet.get(); }
|
||||
VulkanDescriptorSet* GetNullTextureDescriptorSet();
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> AllocateTextureDescriptorSet(int numLayers);
|
||||
|
||||
VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray<PPTextureInput>& textures, bool bindShadowMapBuffers);
|
||||
|
||||
void AddMaterial(VkMaterial* texture);
|
||||
void RemoveMaterial(VkMaterial* texture);
|
||||
|
||||
private:
|
||||
void CreateHWBufferSetLayout();
|
||||
void CreateFixedSetLayout();
|
||||
void CreateHWBufferPool();
|
||||
void CreateFixedSetPool();
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> AllocatePPDescriptorSet(VulkanDescriptorSetLayout* layout);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> HWBufferSetLayout;
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> FixedSetLayout;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorSetLayout>> TextureSetLayouts;
|
||||
|
||||
std::unique_ptr<VulkanDescriptorPool> HWBufferDescriptorPool;
|
||||
std::unique_ptr<VulkanDescriptorPool> FixedDescriptorPool;
|
||||
|
||||
std::unique_ptr<VulkanDescriptorPool> PPDescriptorPool;
|
||||
|
||||
int TextureDescriptorSetsLeft = 0;
|
||||
int TextureDescriptorsLeft = 0;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorPool>> TextureDescriptorPools;
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> HWBufferSet;
|
||||
std::unique_ptr<VulkanDescriptorSet> FixedSet;
|
||||
std::unique_ptr<VulkanDescriptorSet> NullTextureDescriptorSet;
|
||||
|
||||
std::list<VkMaterial*> Materials;
|
||||
|
||||
static const int maxSets = 10;
|
||||
};
|
|
@ -21,26 +21,29 @@
|
|||
*/
|
||||
|
||||
#include "vk_postprocess.h"
|
||||
#include "vk_renderbuffers.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_buffers.h"
|
||||
#include "vulkan/system/vk_hwbuffer.h"
|
||||
#include "vulkan/system/vk_swapchain.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/renderer/vk_renderstate.h"
|
||||
#include "vulkan/renderer/vk_pprenderstate.h"
|
||||
#include "vulkan/shaders/vk_ppshader.h"
|
||||
#include "vulkan/textures/vk_pptexture.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_imagetransition.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||
#include "hw_vrmodes.h"
|
||||
#include "flatvertices.h"
|
||||
#include "r_videoscale.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
|
||||
EXTERN_CVAR(Int, gl_dither_bpc)
|
||||
|
||||
VkPostprocess::VkPostprocess()
|
||||
VkPostprocess::VkPostprocess(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -50,23 +53,21 @@ VkPostprocess::~VkPostprocess()
|
|||
|
||||
void VkPostprocess::SetActiveRenderTarget()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto buffers = fb->GetBuffers();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
|
||||
imageTransition.execute(fb->GetDrawCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
|
||||
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
|
||||
}
|
||||
|
||||
void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
|
||||
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
|
||||
|
||||
VkPPRenderState renderstate;
|
||||
VkPPRenderState renderstate(fb);
|
||||
|
||||
hw_postprocess.Pass1(&renderstate, fixedcm, sceneWidth, sceneHeight);
|
||||
SetActiveRenderTarget();
|
||||
|
@ -76,19 +77,17 @@ void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::functi
|
|||
|
||||
void VkPostprocess::BlitSceneToPostprocess()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
|
||||
auto buffers = fb->GetBuffers();
|
||||
auto cmdbuffer = fb->GetDrawCommands();
|
||||
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
|
||||
|
||||
mCurrentPipelineImage = 0;
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
|
||||
imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||
imageTransition.execute(fb->GetDrawCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false)
|
||||
.AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
|
||||
if (buffers->GetSceneSamples() != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
|
@ -135,30 +134,27 @@ void VkPostprocess::BlitSceneToPostprocess()
|
|||
|
||||
void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto buffers = fb->GetBuffers();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
|
||||
imageTransition.addImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
|
||||
imageTransition.addImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
|
||||
imageTransition.addImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
|
||||
imageTransition.execute(fb->GetDrawCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
|
||||
.AddImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
|
||||
.AddImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
|
||||
.AddImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout finallayout)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
|
||||
auto srcimage = &fb->GetBuffers()->PipelineImage[mCurrentPipelineImage];
|
||||
auto cmdbuffer = fb->GetDrawCommands();
|
||||
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
|
||||
|
||||
VkImageTransition imageTransition0;
|
||||
imageTransition0.addImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
|
||||
imageTransition0.addImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||
imageTransition0.execute(cmdbuffer);
|
||||
VkImageTransition()
|
||||
.AddImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false)
|
||||
.AddImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
VkImageBlit blit = {};
|
||||
blit.srcOffsets[0] = { 0, 0, 0 };
|
||||
|
@ -173,21 +169,20 @@ void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout f
|
|||
blit.dstSubresource.mipLevel = 0;
|
||||
blit.dstSubresource.baseArrayLayer = 0;
|
||||
blit.dstSubresource.layerCount = 1;
|
||||
|
||||
cmdbuffer->blitImage(
|
||||
srcimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
dstimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, &blit, VK_FILTER_NEAREST);
|
||||
|
||||
VkImageTransition imageTransition1;
|
||||
imageTransition1.addImage(dstimage, finallayout, false);
|
||||
imageTransition1.execute(cmdbuffer);
|
||||
VkImageTransition()
|
||||
.AddImage(dstimage, finallayout, false)
|
||||
.Execute(cmdbuffer);
|
||||
}
|
||||
|
||||
void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool screenshot)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkPPRenderState renderstate;
|
||||
VkPPRenderState renderstate(fb);
|
||||
|
||||
if (!screenshot) // Already applied as we are actually copying the last frame here (GetScreenshotBuffer is called after swap)
|
||||
hw_postprocess.customShaders.Run(&renderstate, "screen");
|
||||
|
@ -221,7 +216,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
|||
uniforms.Offset = { 0.0f, 1.0f };
|
||||
}
|
||||
|
||||
if (applyGamma && fb->swapChain->IsHdrModeActive() && !screenshot)
|
||||
if (applyGamma && fb->GetCommands()->swapChain->IsHdrModeActive() && !screenshot)
|
||||
{
|
||||
uniforms.HdrMode = 1;
|
||||
}
|
||||
|
@ -246,11 +241,10 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
|||
|
||||
void VkPostprocess::AmbientOccludeScene(float m5)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
|
||||
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
|
||||
|
||||
VkPPRenderState renderstate;
|
||||
VkPPRenderState renderstate(fb);
|
||||
hw_postprocess.ssao.Render(&renderstate, m5, sceneWidth, sceneHeight);
|
||||
|
||||
ImageTransitionScene(false);
|
||||
|
@ -258,11 +252,10 @@ void VkPostprocess::AmbientOccludeScene(float m5)
|
|||
|
||||
void VkPostprocess::BlurScene(float gameinfobluramount)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
int sceneWidth = fb->GetBuffers()->GetSceneWidth();
|
||||
int sceneHeight = fb->GetBuffers()->GetSceneHeight();
|
||||
|
||||
VkPPRenderState renderstate;
|
||||
VkPPRenderState renderstate(fb);
|
||||
|
||||
auto vrmode = VRMode::GetVRMode(true);
|
||||
int eyeCount = vrmode->mEyeCount;
|
||||
|
@ -282,537 +275,17 @@ void VkPostprocess::UpdateShadowMap()
|
|||
{
|
||||
if (screen->mShadowMap.PerformUpdate())
|
||||
{
|
||||
VkPPRenderState renderstate;
|
||||
VkPPRenderState renderstate(fb);
|
||||
hw_postprocess.shadowmap.Update(&renderstate);
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto buffers = fb->GetBuffers();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&buffers->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||
imageTransition.execute(fb->GetDrawCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&fb->GetTextureManager()->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
|
||||
screen->mShadowMap.FinishUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> VkPostprocess::AllocateDescriptorSet(VulkanDescriptorSetLayout *layout)
|
||||
{
|
||||
if (mDescriptorPool)
|
||||
{
|
||||
auto descriptors = mDescriptorPool->tryAllocate(layout);
|
||||
if (descriptors)
|
||||
return descriptors;
|
||||
|
||||
GetVulkanFrameBuffer()->FrameDeleteList.DescriptorPools.push_back(std::move(mDescriptorPool));
|
||||
}
|
||||
|
||||
DescriptorPoolBuilder builder;
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 200);
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4);
|
||||
builder.setMaxSets(100);
|
||||
mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
||||
mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool");
|
||||
|
||||
return mDescriptorPool->allocate(layout);
|
||||
}
|
||||
|
||||
void VkPostprocess::RenderBuffersReset()
|
||||
{
|
||||
mRenderPassSetup.clear();
|
||||
}
|
||||
|
||||
VulkanSampler *VkPostprocess::GetSampler(PPFilterMode filter, PPWrapMode wrap)
|
||||
{
|
||||
int index = (((int)filter) << 1) | (int)wrap;
|
||||
auto &sampler = mSamplers[index];
|
||||
if (sampler)
|
||||
return sampler.get();
|
||||
|
||||
SamplerBuilder builder;
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
builder.setMinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
||||
builder.setMagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
|
||||
builder.setAddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||
sampler = builder.create(GetVulkanFrameBuffer()->device);
|
||||
sampler->SetDebugName("VkPostprocess.mSamplers");
|
||||
return sampler.get();
|
||||
}
|
||||
|
||||
void VkPostprocess::NextEye(int eyeCount)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkPPTexture::VkPPTexture(PPTexture *texture)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkFormat format;
|
||||
int pixelsize;
|
||||
switch (texture->Format)
|
||||
{
|
||||
default:
|
||||
case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break;
|
||||
case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break;
|
||||
case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break;
|
||||
case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break;
|
||||
case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break;
|
||||
}
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(texture->Width, texture->Height);
|
||||
if (texture->Data)
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
else
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
if (!imgbuilder.isFormatSupported(fb->device))
|
||||
I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n");
|
||||
TexImage.Image = imgbuilder.create(fb->device);
|
||||
TexImage.Image->SetDebugName("VkPPTexture");
|
||||
Format = format;
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(TexImage.Image.get(), format);
|
||||
TexImage.View = viewbuilder.create(fb->device);
|
||||
TexImage.View->SetDebugName("VkPPTextureView");
|
||||
|
||||
if (texture->Data)
|
||||
{
|
||||
size_t totalsize = texture->Width * texture->Height * pixelsize;
|
||||
BufferBuilder stagingbuilder;
|
||||
stagingbuilder.setSize(totalsize);
|
||||
stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
Staging = stagingbuilder.create(fb->device);
|
||||
Staging->SetDebugName("VkPPTextureStaging");
|
||||
|
||||
VkImageTransition barrier0;
|
||||
barrier0.addImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||
barrier0.execute(fb->GetTransferCommands());
|
||||
|
||||
void *data = Staging->Map(0, totalsize);
|
||||
memcpy(data, texture->Data.get(), totalsize);
|
||||
Staging->Unmap();
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = texture->Width;
|
||||
region.imageExtent.height = texture->Height;
|
||||
fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageTransition barrier1;
|
||||
barrier1.addImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||
barrier1.execute(fb->GetTransferCommands());
|
||||
}
|
||||
else
|
||||
{
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
barrier.execute(fb->GetTransferCommands());
|
||||
}
|
||||
}
|
||||
|
||||
VkPPTexture::~VkPPTexture()
|
||||
{
|
||||
if (auto fb = GetVulkanFrameBuffer())
|
||||
{
|
||||
if (TexImage.Image) fb->FrameDeleteList.Images.push_back(std::move(TexImage.Image));
|
||||
if (TexImage.View) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.View));
|
||||
if (TexImage.DepthOnlyView) fb->FrameDeleteList.ImageViews.push_back(std::move(TexImage.DepthOnlyView));
|
||||
if (TexImage.PPFramebuffer) fb->FrameDeleteList.Framebuffers.push_back(std::move(TexImage.PPFramebuffer));
|
||||
if (Staging) fb->FrameDeleteList.Buffers.push_back(std::move(Staging));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkPPShader::VkPPShader(PPShader *shader)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
FString prolog;
|
||||
if (!shader->Uniforms.empty())
|
||||
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1);
|
||||
prolog += shader->Defines;
|
||||
|
||||
ShaderBuilder vertbuilder;
|
||||
vertbuilder.setVertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version));
|
||||
VertexShader = vertbuilder.create(shader->VertexShader.GetChars(), fb->device);
|
||||
VertexShader->SetDebugName(shader->VertexShader.GetChars());
|
||||
|
||||
ShaderBuilder fragbuilder;
|
||||
fragbuilder.setFragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version));
|
||||
FragmentShader = fragbuilder.create(shader->FragmentShader.GetChars(), fb->device);
|
||||
FragmentShader->SetDebugName(shader->FragmentShader.GetChars());
|
||||
}
|
||||
|
||||
FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
|
||||
{
|
||||
int lump = fileSystem.CheckNumForFullName(lumpName);
|
||||
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
|
||||
FString code = fileSystem.ReadFile(lump).GetString().GetChars();
|
||||
|
||||
FString patchedCode;
|
||||
patchedCode.AppendFormat("#version %d\n", 450);
|
||||
patchedCode << defines;
|
||||
patchedCode << "#line 1\n";
|
||||
patchedCode << code;
|
||||
return patchedCode;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void VkPPRenderState::PushGroup(const FString &name)
|
||||
{
|
||||
GetVulkanFrameBuffer()->PushGroup(name);
|
||||
}
|
||||
|
||||
void VkPPRenderState::PopGroup()
|
||||
{
|
||||
GetVulkanFrameBuffer()->PopGroup();
|
||||
}
|
||||
|
||||
void VkPPRenderState::Draw()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto pp = fb->GetPostprocess();
|
||||
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
|
||||
VkPPRenderPassKey key;
|
||||
key.BlendMode = BlendMode;
|
||||
key.InputTextures = Textures.Size();
|
||||
key.Uniforms = Uniforms.Data.Size();
|
||||
key.Shader = GetVkShader(Shader);
|
||||
key.SwapChain = (Output.Type == PPTextureType::SwapChain);
|
||||
key.ShadowMapBuffers = ShadowMapBuffers;
|
||||
if (Output.Type == PPTextureType::PPTexture)
|
||||
key.OutputFormat = GetVkTexture(Output.Texture)->Format;
|
||||
else if (Output.Type == PPTextureType::SwapChain)
|
||||
key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
|
||||
else if (Output.Type == PPTextureType::ShadowMap)
|
||||
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
|
||||
else
|
||||
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
|
||||
if (Output.Type == PPTextureType::SceneColor)
|
||||
{
|
||||
key.StencilTest = 1;
|
||||
key.Samples = fb->GetBuffers()->GetSceneSamples();
|
||||
}
|
||||
else
|
||||
{
|
||||
key.StencilTest = 0;
|
||||
key.Samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
}
|
||||
|
||||
auto &passSetup = pp->mRenderPassSetup[key];
|
||||
if (!passSetup)
|
||||
passSetup.reset(new VkPPRenderPassSetup(key));
|
||||
|
||||
int framebufferWidth = 0, framebufferHeight = 0;
|
||||
VulkanDescriptorSet *input = GetInput(passSetup.get(), Textures, ShadowMapBuffers);
|
||||
VulkanFramebuffer *output = GetOutput(passSetup.get(), Output, key.StencilTest, framebufferWidth, framebufferHeight);
|
||||
|
||||
RenderScreenQuad(passSetup.get(), input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest);
|
||||
|
||||
// Advance to next PP texture if our output was sent there
|
||||
if (Output.Type == PPTextureType::NextPipelineTexture)
|
||||
{
|
||||
pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages;
|
||||
}
|
||||
}
|
||||
|
||||
void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto cmdbuffer = fb->GetDrawCommands();
|
||||
|
||||
VkViewport viewport = { };
|
||||
viewport.x = (float)x;
|
||||
viewport.y = (float)y;
|
||||
viewport.width = (float)width;
|
||||
viewport.height = (float)height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
VkRect2D scissor = { };
|
||||
scissor.offset.x = 0;
|
||||
scissor.offset.y = 0;
|
||||
scissor.extent.width = framebufferWidth;
|
||||
scissor.extent.height = framebufferHeight;
|
||||
|
||||
RenderPassBegin beginInfo;
|
||||
beginInfo.setRenderPass(passSetup->RenderPass.get());
|
||||
beginInfo.setRenderArea(0, 0, framebufferWidth, framebufferHeight);
|
||||
beginInfo.setFramebuffer(framebuffer);
|
||||
beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
VkBuffer vertexBuffers[] = { static_cast<VKVertexBuffer*>(screen->mVertexData->GetBufferObjects().first)->mBuffer->buffer };
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
|
||||
cmdbuffer->beginRenderPass(beginInfo);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->PipelineLayout.get(), 0, descriptorSet);
|
||||
cmdbuffer->bindVertexBuffers(0, 1, vertexBuffers, offsets);
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
cmdbuffer->setScissor(0, 1, &scissor);
|
||||
if (stencilTest)
|
||||
cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, screen->stencilValue);
|
||||
if (pushConstantsSize > 0)
|
||||
cmdbuffer->pushConstants(passSetup->PipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, pushConstantsSize, pushConstants);
|
||||
cmdbuffer->draw(3, 1, FFlatVertexBuffer::PRESENT_INDEX, 0);
|
||||
cmdbuffer->endRenderPass();
|
||||
}
|
||||
|
||||
VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto pp = fb->GetPostprocess();
|
||||
auto descriptors = pp->AllocateDescriptorSet(passSetup->DescriptorLayout.get());
|
||||
descriptors->SetDebugName("VkPostprocess.descriptors");
|
||||
|
||||
WriteDescriptors write;
|
||||
VkImageTransition imageTransition;
|
||||
|
||||
for (unsigned int index = 0; index < textures.Size(); index++)
|
||||
{
|
||||
const PPTextureInput &input = textures[index];
|
||||
VulkanSampler *sampler = pp->GetSampler(input.Filter, input.Wrap);
|
||||
VkTextureImage *tex = GetTexture(input.Type, input.Texture);
|
||||
|
||||
write.addCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
imageTransition.addImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||
}
|
||||
|
||||
if (bindShadowMapBuffers)
|
||||
{
|
||||
write.addBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightNodes->mBuffer.get());
|
||||
write.addBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightLines->mBuffer.get());
|
||||
write.addBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightList->mBuffer.get());
|
||||
}
|
||||
|
||||
write.updateSets(fb->device);
|
||||
imageTransition.execute(fb->GetDrawCommands());
|
||||
|
||||
VulkanDescriptorSet *set = descriptors.get();
|
||||
fb->FrameDeleteList.Descriptors.push_back(std::move(descriptors));
|
||||
return set;
|
||||
}
|
||||
|
||||
VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, bool stencilTest, int &framebufferWidth, int &framebufferHeight)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkTextureImage *tex = GetTexture(output.Type, output.Texture);
|
||||
|
||||
VkImageView view;
|
||||
std::unique_ptr<VulkanFramebuffer> *framebufferptr = nullptr;
|
||||
int w, h;
|
||||
if (tex)
|
||||
{
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture);
|
||||
if (stencilTest)
|
||||
imageTransition.addImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false);
|
||||
imageTransition.execute(fb->GetDrawCommands());
|
||||
|
||||
view = tex->View->view;
|
||||
w = tex->Image->width;
|
||||
h = tex->Image->height;
|
||||
framebufferptr = &tex->PPFramebuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
|
||||
framebufferptr = &fb->swapChain->framebuffers[fb->presentImageIndex];
|
||||
w = fb->swapChain->actualExtent.width;
|
||||
h = fb->swapChain->actualExtent.height;
|
||||
}
|
||||
|
||||
auto &framebuffer = *framebufferptr;
|
||||
if (!framebuffer)
|
||||
{
|
||||
FramebufferBuilder builder;
|
||||
builder.setRenderPass(passSetup->RenderPass.get());
|
||||
builder.setSize(w, h);
|
||||
builder.addAttachment(view);
|
||||
if (stencilTest)
|
||||
builder.addAttachment(fb->GetBuffers()->SceneDepthStencil.View.get());
|
||||
framebuffer = builder.create(GetVulkanFrameBuffer()->device);
|
||||
}
|
||||
|
||||
framebufferWidth = w;
|
||||
framebufferHeight = h;
|
||||
return framebuffer.get();
|
||||
}
|
||||
|
||||
VkTextureImage *VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture)
|
||||
{
|
||||
int idx = fb->GetPostprocess()->mCurrentPipelineImage;
|
||||
if (type == PPTextureType::NextPipelineTexture)
|
||||
idx = (idx + 1) % VkRenderBuffers::NumPipelineImages;
|
||||
|
||||
return &fb->GetBuffers()->PipelineImage[idx];
|
||||
}
|
||||
else if (type == PPTextureType::PPTexture)
|
||||
{
|
||||
auto vktex = GetVkTexture(pptexture);
|
||||
return &vktex->TexImage;
|
||||
}
|
||||
else if (type == PPTextureType::SceneColor)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneColor;
|
||||
}
|
||||
else if (type == PPTextureType::SceneNormal)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneNormal;
|
||||
}
|
||||
else if (type == PPTextureType::SceneFog)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneFog;
|
||||
}
|
||||
else if (type == PPTextureType::SceneDepth)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneDepthStencil;
|
||||
}
|
||||
else if (type == PPTextureType::ShadowMap)
|
||||
{
|
||||
return &fb->GetBuffers()->Shadowmap;
|
||||
}
|
||||
else if (type == PPTextureType::SwapChain)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader)
|
||||
{
|
||||
if (!shader->Backend)
|
||||
shader->Backend = std::make_unique<VkPPShader>(shader);
|
||||
return static_cast<VkPPShader*>(shader->Backend.get());
|
||||
}
|
||||
|
||||
VkPPTexture *VkPPRenderState::GetVkTexture(PPTexture *texture)
|
||||
{
|
||||
if (!texture->Backend)
|
||||
texture->Backend = std::make_unique<VkPPTexture>(texture);
|
||||
return static_cast<VkPPTexture*>(texture->Backend.get());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkPPRenderPassSetup::VkPPRenderPassSetup(const VkPPRenderPassKey &key)
|
||||
{
|
||||
CreateDescriptorLayout(key);
|
||||
CreatePipelineLayout(key);
|
||||
CreateRenderPass(key);
|
||||
CreatePipeline(key);
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey &key)
|
||||
{
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
for (int i = 0; i < key.InputTextures; i++)
|
||||
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
if (key.ShadowMapBuffers)
|
||||
{
|
||||
builder.addBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
DescriptorLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
DescriptorLayout->SetDebugName("VkPPRenderPassSetup.DescriptorLayout");
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreatePipelineLayout(const VkPPRenderPassKey &key)
|
||||
{
|
||||
PipelineLayoutBuilder builder;
|
||||
builder.addSetLayout(DescriptorLayout.get());
|
||||
if (key.Uniforms > 0)
|
||||
builder.addPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, key.Uniforms);
|
||||
PipelineLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
PipelineLayout->SetDebugName("VkPPRenderPassSetup.PipelineLayout");
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey &key)
|
||||
{
|
||||
GraphicsPipelineBuilder builder;
|
||||
builder.addVertexShader(key.Shader->VertexShader.get());
|
||||
builder.addFragmentShader(key.Shader->FragmentShader.get());
|
||||
|
||||
builder.addVertexBufferBinding(0, sizeof(FFlatVertex));
|
||||
builder.addVertexAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(FFlatVertex, x));
|
||||
builder.addVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u));
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR);
|
||||
// Note: the actual values are ignored since we use dynamic viewport+scissor states
|
||||
builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f);
|
||||
builder.setScissor(0, 0, 320, 200);
|
||||
if (key.StencilTest)
|
||||
{
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||
builder.setDepthStencilEnable(false, false, true);
|
||||
builder.setStencil(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
|
||||
}
|
||||
builder.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
|
||||
builder.setBlendMode(key.BlendMode);
|
||||
builder.setRasterizationSamples(key.Samples);
|
||||
builder.setLayout(PipelineLayout.get());
|
||||
builder.setRenderPass(RenderPass.get());
|
||||
Pipeline = builder.create(GetVulkanFrameBuffer()->device);
|
||||
Pipeline->SetDebugName("VkPPRenderPassSetup.Pipeline");
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey &key)
|
||||
{
|
||||
RenderPassBuilder builder;
|
||||
if (key.SwapChain)
|
||||
builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
else
|
||||
builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
if (key.StencilTest)
|
||||
{
|
||||
builder.addDepthStencilAttachment(
|
||||
GetVulkanFrameBuffer()->GetBuffers()->SceneDepthStencilFormat, key.Samples,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
builder.addSubpass();
|
||||
builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
if (key.StencilTest)
|
||||
{
|
||||
builder.addSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
builder.addExternalSubpassDependency(
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.addExternalSubpassDependency(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
}
|
||||
|
||||
RenderPass = builder.create(GetVulkanFrameBuffer()->device);
|
||||
RenderPass->SetDebugName("VkPPRenderPassSetup.RenderPass");
|
||||
}
|
||||
|
|
|
@ -14,35 +14,15 @@ class FString;
|
|||
|
||||
class VkPPShader;
|
||||
class VkPPTexture;
|
||||
class VkPPRenderPassSetup;
|
||||
class PipelineBarrier;
|
||||
|
||||
class VkPPRenderPassKey
|
||||
{
|
||||
public:
|
||||
VkPPShader *Shader;
|
||||
int Uniforms;
|
||||
int InputTextures;
|
||||
PPBlendMode BlendMode;
|
||||
VkFormat OutputFormat;
|
||||
int SwapChain;
|
||||
int ShadowMapBuffers;
|
||||
int StencilTest;
|
||||
VkSampleCountFlagBits Samples;
|
||||
|
||||
bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
|
||||
bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; }
|
||||
bool operator!=(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; }
|
||||
};
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkPostprocess
|
||||
{
|
||||
public:
|
||||
VkPostprocess();
|
||||
VkPostprocess(VulkanFrameBuffer* fb);
|
||||
~VkPostprocess();
|
||||
|
||||
void RenderBuffersReset();
|
||||
|
||||
void SetActiveRenderTarget();
|
||||
void PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D);
|
||||
|
||||
|
@ -58,76 +38,14 @@ public:
|
|||
void BlitCurrentToImage(VkTextureImage *image, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
void DrawPresentTexture(const IntRect &box, bool applyGamma, bool screenshot);
|
||||
|
||||
int GetCurrentPipelineImage() const { return mCurrentPipelineImage; }
|
||||
|
||||
private:
|
||||
void NextEye(int eyeCount);
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> AllocateDescriptorSet(VulkanDescriptorSetLayout *layout);
|
||||
VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap);
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
std::array<std::unique_ptr<VulkanSampler>, 4> mSamplers;
|
||||
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> mRenderPassSetup;
|
||||
std::unique_ptr<VulkanDescriptorPool> mDescriptorPool;
|
||||
int mCurrentPipelineImage = 0;
|
||||
|
||||
friend class VkPPRenderState;
|
||||
};
|
||||
|
||||
class VkPPShader : public PPShaderBackend
|
||||
{
|
||||
public:
|
||||
VkPPShader(PPShader *shader);
|
||||
|
||||
std::unique_ptr<VulkanShader> VertexShader;
|
||||
std::unique_ptr<VulkanShader> FragmentShader;
|
||||
|
||||
private:
|
||||
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
|
||||
};
|
||||
|
||||
class VkPPTexture : public PPTextureBackend
|
||||
{
|
||||
public:
|
||||
VkPPTexture(PPTexture *texture);
|
||||
~VkPPTexture();
|
||||
|
||||
VkTextureImage TexImage;
|
||||
std::unique_ptr<VulkanBuffer> Staging;
|
||||
VkFormat Format;
|
||||
};
|
||||
|
||||
class VkPPRenderPassSetup
|
||||
{
|
||||
public:
|
||||
VkPPRenderPassSetup(const VkPPRenderPassKey &key);
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> DescriptorLayout;
|
||||
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
|
||||
std::unique_ptr<VulkanRenderPass> RenderPass;
|
||||
std::unique_ptr<VulkanPipeline> Pipeline;
|
||||
|
||||
private:
|
||||
void CreateDescriptorLayout(const VkPPRenderPassKey &key);
|
||||
void CreatePipelineLayout(const VkPPRenderPassKey &key);
|
||||
void CreatePipeline(const VkPPRenderPassKey &key);
|
||||
void CreateRenderPass(const VkPPRenderPassKey &key);
|
||||
};
|
||||
|
||||
class VkPPRenderState : public PPRenderState
|
||||
{
|
||||
public:
|
||||
void PushGroup(const FString &name) override;
|
||||
void PopGroup() override;
|
||||
|
||||
void Draw() override;
|
||||
|
||||
private:
|
||||
void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest);
|
||||
|
||||
VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray<PPTextureInput> &textures, bool bindShadowMapBuffers);
|
||||
VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, bool stencilTest, int &framebufferWidth, int &framebufferHeight);
|
||||
|
||||
VkPPShader *GetVkShader(PPShader *shader);
|
||||
VkPPTexture *GetVkTexture(PPTexture *texture);
|
||||
|
||||
VkTextureImage *GetTexture(const PPTextureType &type, PPTexture *tex);
|
||||
};
|
||||
|
|
138
source/common/rendering/vulkan/renderer/vk_pprenderstate.cpp
Normal file
138
source/common/rendering/vulkan/renderer/vk_pprenderstate.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_pprenderstate.h"
|
||||
#include "vk_postprocess.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/system/vk_swapchain.h"
|
||||
#include "vulkan/system/vk_buffer.h"
|
||||
#include "vulkan/shaders/vk_ppshader.h"
|
||||
#include "vulkan/textures/vk_pptexture.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_samplers.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "vulkan/renderer/vk_renderstate.h"
|
||||
#include "vulkan/renderer/vk_descriptorset.h"
|
||||
#include "flatvertices.h"
|
||||
|
||||
VkPPRenderState::VkPPRenderState(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
void VkPPRenderState::PushGroup(const FString &name)
|
||||
{
|
||||
fb->GetCommands()->PushGroup(name);
|
||||
}
|
||||
|
||||
void VkPPRenderState::PopGroup()
|
||||
{
|
||||
fb->GetCommands()->PopGroup();
|
||||
}
|
||||
|
||||
void VkPPRenderState::Draw()
|
||||
{
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
|
||||
VkPPRenderPassKey key;
|
||||
key.BlendMode = BlendMode;
|
||||
key.InputTextures = Textures.Size();
|
||||
key.Uniforms = Uniforms.Data.Size();
|
||||
key.Shader = fb->GetShaderManager()->GetVkShader(Shader);
|
||||
key.SwapChain = (Output.Type == PPTextureType::SwapChain);
|
||||
key.ShadowMapBuffers = ShadowMapBuffers;
|
||||
if (Output.Type == PPTextureType::PPTexture)
|
||||
key.OutputFormat = fb->GetTextureManager()->GetTextureFormat(Output.Texture);
|
||||
else if (Output.Type == PPTextureType::SwapChain)
|
||||
key.OutputFormat = fb->GetCommands()->swapChain->swapChainFormat.format;
|
||||
else if (Output.Type == PPTextureType::ShadowMap)
|
||||
key.OutputFormat = VK_FORMAT_R32_SFLOAT;
|
||||
else
|
||||
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
|
||||
if (Output.Type == PPTextureType::SceneColor)
|
||||
{
|
||||
key.StencilTest = 1;
|
||||
key.Samples = fb->GetBuffers()->GetSceneSamples();
|
||||
}
|
||||
else
|
||||
{
|
||||
key.StencilTest = 0;
|
||||
key.Samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
}
|
||||
|
||||
auto passSetup = fb->GetRenderPassManager()->GetPPRenderPass(key);
|
||||
|
||||
int framebufferWidth = 0, framebufferHeight = 0;
|
||||
VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers);
|
||||
VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight);
|
||||
|
||||
RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest);
|
||||
|
||||
// Advance to next PP texture if our output was sent there
|
||||
if (Output.Type == PPTextureType::NextPipelineTexture)
|
||||
{
|
||||
auto pp = fb->GetPostprocess();
|
||||
pp->mCurrentPipelineImage = (pp->mCurrentPipelineImage + 1) % VkRenderBuffers::NumPipelineImages;
|
||||
}
|
||||
}
|
||||
|
||||
void VkPPRenderState::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest)
|
||||
{
|
||||
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
|
||||
|
||||
VkViewport viewport = { };
|
||||
viewport.x = (float)x;
|
||||
viewport.y = (float)y;
|
||||
viewport.width = (float)width;
|
||||
viewport.height = (float)height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
VkRect2D scissor = { };
|
||||
scissor.offset.x = 0;
|
||||
scissor.offset.y = 0;
|
||||
scissor.extent.width = framebufferWidth;
|
||||
scissor.extent.height = framebufferHeight;
|
||||
|
||||
RenderPassBegin beginInfo;
|
||||
beginInfo.setRenderPass(passSetup->RenderPass.get());
|
||||
beginInfo.setRenderArea(0, 0, framebufferWidth, framebufferHeight);
|
||||
beginInfo.setFramebuffer(framebuffer);
|
||||
beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
VkBuffer vertexBuffers[] = { static_cast<VkHardwareVertexBuffer*>(screen->mVertexData->GetBufferObjects().first)->mBuffer->buffer };
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
|
||||
cmdbuffer->beginRenderPass(beginInfo);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->PipelineLayout.get(), 0, descriptorSet);
|
||||
cmdbuffer->bindVertexBuffers(0, 1, vertexBuffers, offsets);
|
||||
cmdbuffer->setViewport(0, 1, &viewport);
|
||||
cmdbuffer->setScissor(0, 1, &scissor);
|
||||
if (stencilTest)
|
||||
cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, screen->stencilValue);
|
||||
if (pushConstantsSize > 0)
|
||||
cmdbuffer->pushConstants(passSetup->PipelineLayout.get(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, pushConstantsSize, pushConstants);
|
||||
cmdbuffer->draw(3, 1, FFlatVertexBuffer::PRESENT_INDEX, 0);
|
||||
cmdbuffer->endRenderPass();
|
||||
}
|
27
source/common/rendering/vulkan/renderer/vk_pprenderstate.h
Normal file
27
source/common/rendering/vulkan/renderer/vk_pprenderstate.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
|
||||
class VkPPRenderPassSetup;
|
||||
class VkPPShader;
|
||||
class VkPPTexture;
|
||||
class VkTextureImage;
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkPPRenderState : public PPRenderState
|
||||
{
|
||||
public:
|
||||
VkPPRenderState(VulkanFrameBuffer* fb);
|
||||
|
||||
void PushGroup(const FString &name) override;
|
||||
void PopGroup() override;
|
||||
|
||||
void Draw() override;
|
||||
|
||||
private:
|
||||
void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize, bool stencilTest);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
};
|
283
source/common/rendering/vulkan/renderer/vk_raytrace.cpp
Normal file
283
source/common/rendering/vulkan/renderer/vk_raytrace.cpp
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_raytrace.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
//#include "doom_levelmesh.h"
|
||||
|
||||
VkRaytrace::VkRaytrace(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f });
|
||||
NullMesh.MeshVertices.Push({ 1.0f, -1.0f, -1.0f });
|
||||
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f });
|
||||
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, -1.0f });
|
||||
NullMesh.MeshVertices.Push({ -1.0f, 1.0f, -1.0f });
|
||||
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, -1.0f });
|
||||
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, 1.0f });
|
||||
NullMesh.MeshVertices.Push({ 1.0f, -1.0f, 1.0f });
|
||||
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, 1.0f });
|
||||
NullMesh.MeshVertices.Push({ -1.0f, -1.0f, 1.0f });
|
||||
NullMesh.MeshVertices.Push({ -1.0f, 1.0f, 1.0f });
|
||||
NullMesh.MeshVertices.Push({ 1.0f, 1.0f, 1.0f });
|
||||
for (int i = 0; i < 3 * 4; i++)
|
||||
NullMesh.MeshElements.Push(i);
|
||||
|
||||
SetLevelMesh(nullptr);
|
||||
}
|
||||
|
||||
void VkRaytrace::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
||||
{
|
||||
if (!mesh)
|
||||
mesh = &NullMesh;
|
||||
|
||||
if (mesh != Mesh)
|
||||
{
|
||||
Reset();
|
||||
Mesh = mesh;
|
||||
if (fb->RaytracingEnabled())
|
||||
{
|
||||
CreateVulkanObjects();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VkRaytrace::Reset()
|
||||
{
|
||||
auto deletelist = fb->GetCommands()->DrawDeleteList.get();
|
||||
deletelist->Add(std::move(vertexBuffer));
|
||||
deletelist->Add(std::move(indexBuffer));
|
||||
deletelist->Add(std::move(transferBuffer));
|
||||
deletelist->Add(std::move(blScratchBuffer));
|
||||
deletelist->Add(std::move(blAccelStructBuffer));
|
||||
deletelist->Add(std::move(blAccelStruct));
|
||||
deletelist->Add(std::move(tlTransferBuffer));
|
||||
deletelist->Add(std::move(tlScratchBuffer));
|
||||
deletelist->Add(std::move(tlInstanceBuffer));
|
||||
deletelist->Add(std::move(tlAccelStructBuffer));
|
||||
deletelist->Add(std::move(tlAccelStruct));
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateVulkanObjects()
|
||||
{
|
||||
CreateVertexAndIndexBuffers();
|
||||
CreateBottomLevelAccelerationStructure();
|
||||
CreateTopLevelAccelerationStructure();
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateVertexAndIndexBuffers()
|
||||
{
|
||||
static_assert(sizeof(FVector3) == 3 * 4, "sizeof(FVector3) is not 12 bytes!");
|
||||
|
||||
size_t vertexbuffersize = (size_t)Mesh->MeshVertices.Size() * sizeof(FVector3);
|
||||
size_t indexbuffersize = (size_t)Mesh->MeshElements.Size() * sizeof(uint32_t);
|
||||
size_t transferbuffersize = vertexbuffersize + indexbuffersize;
|
||||
size_t vertexoffset = 0;
|
||||
size_t indexoffset = vertexoffset + vertexbuffersize;
|
||||
|
||||
transferBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.Size(transferbuffersize)
|
||||
.DebugName("transferBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
uint8_t* data = (uint8_t*)transferBuffer->Map(0, transferbuffersize);
|
||||
memcpy(data + vertexoffset, Mesh->MeshVertices.Data(), vertexbuffersize);
|
||||
memcpy(data + indexoffset, Mesh->MeshElements.Data(), indexbuffersize);
|
||||
transferBuffer->Unmap();
|
||||
|
||||
vertexBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
.Size(vertexbuffersize)
|
||||
.DebugName("vertexBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
indexBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
.Size(indexbuffersize)
|
||||
.DebugName("indexBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), vertexBuffer.get(), vertexoffset);
|
||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(transferBuffer.get(), indexBuffer.get(), indexoffset);
|
||||
|
||||
// Finish transfer before using it for building
|
||||
PipelineBarrier()
|
||||
.AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateBottomLevelAccelerationStructure()
|
||||
{
|
||||
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
|
||||
VkAccelerationStructureGeometryKHR accelStructBLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
|
||||
VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructBLDesc };
|
||||
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
|
||||
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
|
||||
|
||||
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
buildInfo.geometryCount = 1;
|
||||
buildInfo.ppGeometries = geometries;
|
||||
|
||||
accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
|
||||
accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
|
||||
accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR };
|
||||
accelStructBLDesc.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
accelStructBLDesc.geometry.triangles.vertexData.deviceAddress = vertexBuffer->GetDeviceAddress();
|
||||
accelStructBLDesc.geometry.triangles.vertexStride = sizeof(FVector3);
|
||||
accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
|
||||
accelStructBLDesc.geometry.triangles.indexData.deviceAddress = indexBuffer->GetDeviceAddress();
|
||||
accelStructBLDesc.geometry.triangles.maxVertex = Mesh->MeshVertices.Size() - 1;
|
||||
//accelStructBLDesc.geometry.triangles.transformData = transformAddress; // optional; VkTransformMatrixKHR transfered to a buffer?
|
||||
|
||||
rangeInfo.primitiveCount = Mesh->MeshElements.Size() / 3;
|
||||
uint32_t maxPrimitiveCount = rangeInfo.primitiveCount;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
|
||||
vkGetAccelerationStructureBuildSizesKHR(fb->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo);
|
||||
|
||||
blAccelStructBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
|
||||
.Size(sizeInfo.accelerationStructureSize)
|
||||
.DebugName("blAccelStructBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
VkAccelerationStructureKHR blAccelStructHandle = {};
|
||||
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
|
||||
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
|
||||
createInfo.buffer = blAccelStructBuffer->buffer;
|
||||
createInfo.size = sizeInfo.accelerationStructureSize;
|
||||
VkResult result = vkCreateAccelerationStructureKHR(fb->device->device, &createInfo, nullptr, &blAccelStructHandle);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkCreateAccelerationStructureKHR failed");
|
||||
blAccelStruct = std::make_unique<VulkanAccelerationStructure>(fb->device, blAccelStructHandle);
|
||||
blAccelStruct->SetDebugName("blAccelStruct");
|
||||
|
||||
blScratchBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
.Size(sizeInfo.buildScratchSize)
|
||||
.DebugName("blScratchBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
buildInfo.dstAccelerationStructure = blAccelStruct->accelstruct;
|
||||
buildInfo.scratchData.deviceAddress = blScratchBuffer->GetDeviceAddress();
|
||||
|
||||
fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
|
||||
|
||||
// Finish building before using it as input to a toplevel accel structure
|
||||
PipelineBarrier()
|
||||
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
|
||||
}
|
||||
|
||||
void VkRaytrace::CreateTopLevelAccelerationStructure()
|
||||
{
|
||||
VkAccelerationStructureInstanceKHR instance = {};
|
||||
instance.transform.matrix[0][0] = 1.0f;
|
||||
instance.transform.matrix[1][1] = 1.0f;
|
||||
instance.transform.matrix[2][2] = 1.0f;
|
||||
instance.mask = 0xff;
|
||||
instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
instance.accelerationStructureReference = blAccelStruct->GetDeviceAddress();
|
||||
|
||||
tlTransferBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.Size(sizeof(VkAccelerationStructureInstanceKHR))
|
||||
.DebugName("tlTransferBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
auto data = (uint8_t*)tlTransferBuffer->Map(0, sizeof(VkAccelerationStructureInstanceKHR));
|
||||
memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR));
|
||||
tlTransferBuffer->Unmap();
|
||||
|
||||
tlInstanceBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT)
|
||||
.Size(sizeof(VkAccelerationStructureInstanceKHR))
|
||||
.DebugName("tlInstanceBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(tlTransferBuffer.get(), tlInstanceBuffer.get());
|
||||
|
||||
// Finish transfering before using it as input
|
||||
VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
|
||||
fb->GetCommands()->GetTransferCommands()->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
|
||||
|
||||
VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
|
||||
VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
|
||||
VkAccelerationStructureGeometryKHR* geometries[] = { &accelStructTLDesc };
|
||||
VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {};
|
||||
VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo };
|
||||
|
||||
buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
|
||||
buildInfo.geometryCount = 1;
|
||||
buildInfo.ppGeometries = geometries;
|
||||
buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
|
||||
buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
|
||||
|
||||
accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
|
||||
accelStructTLDesc.geometry.instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR };
|
||||
accelStructTLDesc.geometry.instances.data.deviceAddress = tlInstanceBuffer->GetDeviceAddress();
|
||||
|
||||
uint32_t maxInstanceCount = 1;
|
||||
rangeInfo.primitiveCount = 1;
|
||||
|
||||
VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
|
||||
vkGetAccelerationStructureBuildSizesKHR(fb->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo);
|
||||
|
||||
tlAccelStructBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
|
||||
.Size(sizeInfo.accelerationStructureSize)
|
||||
.DebugName("tlAccelStructBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
VkAccelerationStructureKHR tlAccelStructHandle = {};
|
||||
VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR };
|
||||
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
|
||||
createInfo.buffer = tlAccelStructBuffer->buffer;
|
||||
createInfo.size = sizeInfo.accelerationStructureSize;
|
||||
VkResult result = vkCreateAccelerationStructureKHR(fb->device->device, &createInfo, nullptr, &tlAccelStructHandle);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkCreateAccelerationStructureKHR failed");
|
||||
tlAccelStruct = std::make_unique<VulkanAccelerationStructure>(fb->device, tlAccelStructHandle);
|
||||
|
||||
tlScratchBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
.Size(sizeInfo.buildScratchSize)
|
||||
.DebugName("tlScratchBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
buildInfo.dstAccelerationStructure = tlAccelStruct->accelstruct;
|
||||
buildInfo.scratchData.deviceAddress = tlScratchBuffer->GetDeviceAddress();
|
||||
|
||||
fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos);
|
||||
|
||||
// Finish building the accel struct before using as input in a fragment shader
|
||||
PipelineBarrier()
|
||||
.AddMemory(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
43
source/common/rendering/vulkan/renderer/vk_raytrace.h
Normal file
43
source/common/rendering/vulkan/renderer/vk_raytrace.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include "hw_levelmesh.h"
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkRaytrace
|
||||
{
|
||||
public:
|
||||
VkRaytrace(VulkanFrameBuffer* fb);
|
||||
|
||||
void SetLevelMesh(hwrenderer::LevelMesh* mesh);
|
||||
|
||||
VulkanAccelerationStructure* GetAccelStruct() { return tlAccelStruct.get(); }
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void CreateVulkanObjects();
|
||||
void CreateVertexAndIndexBuffers();
|
||||
void CreateBottomLevelAccelerationStructure();
|
||||
void CreateTopLevelAccelerationStructure();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
hwrenderer::LevelMesh NullMesh;
|
||||
hwrenderer::LevelMesh* Mesh = nullptr;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> vertexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> indexBuffer;
|
||||
std::unique_ptr<VulkanBuffer> transferBuffer;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> blScratchBuffer;
|
||||
std::unique_ptr<VulkanBuffer> blAccelStructBuffer;
|
||||
std::unique_ptr<VulkanAccelerationStructure> blAccelStruct;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> tlTransferBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlScratchBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlInstanceBuffer;
|
||||
std::unique_ptr<VulkanBuffer> tlAccelStructBuffer;
|
||||
std::unique_ptr<VulkanAccelerationStructure> tlAccelStruct;
|
||||
};
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_renderbuffers.h"
|
||||
#include "vk_renderpass.h"
|
||||
#include "vk_postprocess.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "hw_cvars.h"
|
||||
|
||||
|
||||
VkRenderBuffers::VkRenderBuffers()
|
||||
{
|
||||
}
|
||||
|
||||
VkRenderBuffers::~VkRenderBuffers()
|
||||
{
|
||||
}
|
||||
|
||||
VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
const auto &limits = fb->device->PhysicalDevice.Properties.limits;
|
||||
VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts;
|
||||
|
||||
int requestedSamples = clamp((int)gl_multisample, 0, 64);
|
||||
|
||||
int samples = 1;
|
||||
VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT;
|
||||
VkSampleCountFlags best = bit;
|
||||
while (samples <= requestedSamples)
|
||||
{
|
||||
if (deviceSampleCounts & bit)
|
||||
{
|
||||
best = bit;
|
||||
}
|
||||
samples <<= 1;
|
||||
bit <<= 1;
|
||||
}
|
||||
return (VkSampleCountFlagBits)best;
|
||||
}
|
||||
|
||||
void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
VkSampleCountFlagBits samples = GetBestSampleCount();
|
||||
|
||||
if (width != mWidth || height != mHeight || mSamples != samples)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
fb->GetRenderPassManager()->RenderBuffersReset();
|
||||
fb->GetPostprocess()->RenderBuffersReset();
|
||||
}
|
||||
|
||||
if (width != mWidth || height != mHeight)
|
||||
CreatePipeline(width, height);
|
||||
|
||||
if (width != mWidth || height != mHeight || mSamples != samples)
|
||||
CreateScene(width, height, samples);
|
||||
|
||||
CreateShadowmap();
|
||||
CreateLightmapSampler();
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mSamples = samples;
|
||||
mSceneWidth = sceneWidth;
|
||||
mSceneHeight = sceneHeight;
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreatePipeline(int width, int height)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
for (int i = 0; i < NumPipelineImages; i++)
|
||||
{
|
||||
PipelineImage[i].reset();
|
||||
}
|
||||
|
||||
VkImageTransition barrier;
|
||||
for (int i = 0; i < NumPipelineImages; i++)
|
||||
{
|
||||
ImageBuilder builder;
|
||||
builder.setSize(width, height);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
PipelineImage[i].Image = builder.create(fb->device);
|
||||
PipelineImage[i].Image->SetDebugName("VkRenderBuffers.PipelineImage");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
PipelineImage[i].View = viewbuilder.create(fb->device);
|
||||
PipelineImage[i].View->SetDebugName("VkRenderBuffers.PipelineView");
|
||||
|
||||
barrier.addImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
}
|
||||
barrier.execute(fb->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
SceneColor.reset();
|
||||
SceneDepthStencil.reset();
|
||||
SceneNormal.reset();
|
||||
SceneFog.reset();
|
||||
|
||||
CreateSceneColor(width, height, samples);
|
||||
CreateSceneDepthStencil(width, height, samples);
|
||||
CreateSceneNormal(width, height, samples);
|
||||
CreateSceneFog(width, height, samples);
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
barrier.addImage(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true);
|
||||
barrier.addImage(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
barrier.addImage(&SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
barrier.execute(fb->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(width, height);
|
||||
builder.setSamples(samples);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
|
||||
SceneColor.Image = builder.create(fb->device);
|
||||
SceneColor.Image->SetDebugName("VkRenderBuffers.SceneColor");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
SceneColor.View = viewbuilder.create(fb->device);
|
||||
SceneColor.View->SetDebugName("VkRenderBuffers.SceneColorView");
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(width, height);
|
||||
builder.setSamples(samples);
|
||||
builder.setFormat(SceneDepthStencilFormat);
|
||||
builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
if (!builder.isFormatSupported(fb->device))
|
||||
{
|
||||
SceneDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
builder.setFormat(SceneDepthStencilFormat);
|
||||
if (!builder.isFormatSupported(fb->device))
|
||||
{
|
||||
I_FatalError("This device does not support any of the required depth stencil image formats.");
|
||||
}
|
||||
}
|
||||
SceneDepthStencil.Image = builder.create(fb->device);
|
||||
SceneDepthStencil.Image->SetDebugName("VkRenderBuffers.SceneDepthStencil");
|
||||
SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
SceneDepthStencil.View = viewbuilder.create(fb->device);
|
||||
SceneDepthStencil.View->SetDebugName("VkRenderBuffers.SceneDepthStencilView");
|
||||
|
||||
viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
SceneDepthStencil.DepthOnlyView = viewbuilder.create(fb->device);
|
||||
SceneDepthStencil.DepthOnlyView->SetDebugName("VkRenderBuffers.SceneDepthView");
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(width, height);
|
||||
builder.setSamples(samples);
|
||||
builder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
|
||||
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
SceneFog.Image = builder.create(fb->device);
|
||||
SceneFog.Image->SetDebugName("VkRenderBuffers.SceneFog");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM);
|
||||
SceneFog.View = viewbuilder.create(fb->device);
|
||||
SceneFog.View->SetDebugName("VkRenderBuffers.SceneFogView");
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(width, height);
|
||||
builder.setSamples(samples);
|
||||
builder.setFormat(SceneNormalFormat);
|
||||
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
|
||||
{
|
||||
SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
builder.setFormat(SceneNormalFormat);
|
||||
}
|
||||
SceneNormal.Image = builder.create(fb->device);
|
||||
SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(SceneNormal.Image.get(), SceneNormalFormat);
|
||||
SceneNormal.View = viewbuilder.create(fb->device);
|
||||
SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView");
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateShadowmap()
|
||||
{
|
||||
if (Shadowmap.Image && Shadowmap.Image->width == gl_shadowmap_quality)
|
||||
return;
|
||||
|
||||
Shadowmap.reset();
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(gl_shadowmap_quality, 1024);
|
||||
builder.setFormat(VK_FORMAT_R32_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
Shadowmap.Image = builder.create(fb->device);
|
||||
Shadowmap.Image->SetDebugName("VkRenderBuffers.Shadowmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT);
|
||||
Shadowmap.View = viewbuilder.create(fb->device);
|
||||
Shadowmap.View->SetDebugName("VkRenderBuffers.ShadowmapView");
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
|
||||
barrier.execute(fb->GetDrawCommands());
|
||||
|
||||
if (!ShadowmapSampler)
|
||||
{
|
||||
SamplerBuilder samplerBuilder;
|
||||
samplerBuilder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
samplerBuilder.setMinFilter(VK_FILTER_NEAREST);
|
||||
samplerBuilder.setMagFilter(VK_FILTER_NEAREST);
|
||||
samplerBuilder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||
ShadowmapSampler = samplerBuilder.create(fb->device);
|
||||
ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler");
|
||||
}
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateLightmapSampler()
|
||||
{
|
||||
if (!Lightmap.Image)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(1, 1);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
Lightmap.Image = builder.create(fb->device);
|
||||
Lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
|
||||
viewbuilder.setImage(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
Lightmap.View = viewbuilder.create(fb->device);
|
||||
Lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
|
||||
barrier.execute(fb->GetDrawCommands());
|
||||
}
|
||||
|
||||
if (!LightmapSampler)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
SamplerBuilder builder;
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR);
|
||||
builder.setMinFilter(VK_FILTER_LINEAR);
|
||||
builder.setMagFilter(VK_FILTER_LINEAR);
|
||||
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||
LightmapSampler = builder.create(fb->device);
|
||||
LightmapSampler->SetDebugName("VkRenderBuffers.LightmapSampler");
|
||||
}
|
||||
}
|
|
@ -21,61 +21,39 @@
|
|||
*/
|
||||
|
||||
#include "vk_renderpass.h"
|
||||
#include "vk_renderbuffers.h"
|
||||
#include "vk_renderstate.h"
|
||||
#include "vk_descriptorset.h"
|
||||
#include "vk_raytrace.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_samplers.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/shaders/vk_ppshader.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_buffers.h"
|
||||
#include "vulkan/system/vk_hwbuffer.h"
|
||||
#include "flatvertices.h"
|
||||
#include "hw_viewpointuniforms.h"
|
||||
#include "v_2ddrawer.h"
|
||||
|
||||
VkRenderPassManager::VkRenderPassManager()
|
||||
VkRenderPassManager::VkRenderPassManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
VkRenderPassManager::~VkRenderPassManager()
|
||||
{
|
||||
DynamicSet.reset(); // Needed since it must come before destruction of DynamicDescriptorPool
|
||||
}
|
||||
|
||||
void VkRenderPassManager::Init()
|
||||
{
|
||||
CreateDynamicSetLayout();
|
||||
CreateDescriptorPool();
|
||||
CreateDynamicSet();
|
||||
CreateNullTexture();
|
||||
}
|
||||
|
||||
void VkRenderPassManager::RenderBuffersReset()
|
||||
{
|
||||
RenderPassSetup.clear();
|
||||
}
|
||||
|
||||
void VkRenderPassManager::TextureSetPoolReset()
|
||||
{
|
||||
if (auto fb = GetVulkanFrameBuffer())
|
||||
{
|
||||
auto &deleteList = fb->FrameDeleteList;
|
||||
|
||||
for (auto &desc : TextureDescriptorPools)
|
||||
{
|
||||
deleteList.DescriptorPools.push_back(std::move(desc));
|
||||
}
|
||||
}
|
||||
NullTextureDescriptorSet.reset();
|
||||
TextureDescriptorPools.clear();
|
||||
TextureDescriptorSetsLeft = 0;
|
||||
TextureDescriptorsLeft = 0;
|
||||
PPRenderPassSetup.clear();
|
||||
}
|
||||
|
||||
VkRenderPassSetup *VkRenderPassManager::GetRenderPass(const VkRenderPassKey &key)
|
||||
{
|
||||
auto &item = RenderPassSetup[key];
|
||||
if (!item)
|
||||
item.reset(new VkRenderPassSetup(key));
|
||||
item.reset(new VkRenderPassSetup(fb, key));
|
||||
return item.get();
|
||||
}
|
||||
|
||||
|
@ -122,38 +100,6 @@ VkVertexFormat *VkRenderPassManager::GetVertexFormat(int index)
|
|||
return &VertexFormats[index];
|
||||
}
|
||||
|
||||
void VkRenderPassManager::CreateDynamicSetLayout()
|
||||
{
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
builder.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.addBinding(5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout");
|
||||
}
|
||||
|
||||
VulkanDescriptorSetLayout *VkRenderPassManager::GetTextureSetLayout(int numLayers)
|
||||
{
|
||||
if (TextureSetLayouts.size() < (size_t)numLayers)
|
||||
TextureSetLayouts.resize(numLayers);
|
||||
|
||||
auto &layout = TextureSetLayouts[numLayers - 1];
|
||||
if (layout)
|
||||
return layout.get();
|
||||
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
for (int i = 0; i < numLayers; i++)
|
||||
{
|
||||
builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
layout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
layout->SetDebugName("VkRenderPassManager.TextureSetLayout");
|
||||
return layout.get();
|
||||
}
|
||||
|
||||
VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers)
|
||||
{
|
||||
if (PipelineLayouts.size() <= (size_t)numLayers)
|
||||
|
@ -163,157 +109,68 @@ VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(int numLayers)
|
|||
if (layout)
|
||||
return layout.get();
|
||||
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
|
||||
PipelineLayoutBuilder builder;
|
||||
builder.addSetLayout(DynamicSetLayout.get());
|
||||
builder.AddSetLayout(descriptors->GetFixedSetLayout());
|
||||
builder.AddSetLayout(descriptors->GetHWBufferSetLayout());
|
||||
if (numLayers != 0)
|
||||
builder.addSetLayout(GetTextureSetLayout(numLayers));
|
||||
builder.addPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants));
|
||||
layout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
layout->SetDebugName("VkRenderPassManager.PipelineLayout");
|
||||
builder.AddSetLayout(descriptors->GetTextureSetLayout(numLayers));
|
||||
builder.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants));
|
||||
builder.DebugName("VkRenderPassManager.PipelineLayout");
|
||||
layout = builder.Create(fb->device);
|
||||
return layout.get();
|
||||
}
|
||||
|
||||
void VkRenderPassManager::CreateDescriptorPool()
|
||||
VkPPRenderPassSetup* VkRenderPassManager::GetPPRenderPass(const VkPPRenderPassKey& key)
|
||||
{
|
||||
DescriptorPoolBuilder builder;
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3);
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1);
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2);
|
||||
builder.setMaxSets(1);
|
||||
DynamicDescriptorPool = builder.create(GetVulkanFrameBuffer()->device);
|
||||
DynamicDescriptorPool->SetDebugName("VkRenderPassManager.DynamicDescriptorPool");
|
||||
}
|
||||
|
||||
void VkRenderPassManager::CreateDynamicSet()
|
||||
{
|
||||
DynamicSet = DynamicDescriptorPool->allocate(DynamicSetLayout.get());
|
||||
if (!DynamicSet)
|
||||
I_FatalError("CreateDynamicSet failed.\n");
|
||||
}
|
||||
|
||||
void VkRenderPassManager::CreateNullTexture()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
|
||||
imgbuilder.setSize(1, 1);
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
NullTexture = imgbuilder.create(fb->device);
|
||||
NullTexture->SetDebugName("VkRenderPassManager.NullTexture");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(NullTexture.get(), VK_FORMAT_R8G8B8A8_UNORM);
|
||||
NullTextureView = viewbuilder.create(fb->device);
|
||||
NullTextureView->SetDebugName("VkRenderPassManager.NullTextureView");
|
||||
|
||||
PipelineBarrier barrier;
|
||||
barrier.addImage(NullTexture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
barrier.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
VulkanDescriptorSet* VkRenderPassManager::GetNullTextureDescriptorSet()
|
||||
{
|
||||
if (!NullTextureDescriptorSet)
|
||||
{
|
||||
NullTextureDescriptorSet = AllocateTextureDescriptorSet(SHADER_MIN_REQUIRED_TEXTURE_LAYERS);
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
WriteDescriptors update;
|
||||
for (int i = 0; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++)
|
||||
{
|
||||
update.addCombinedImageSampler(NullTextureDescriptorSet.get(), i, NullTextureView.get(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
update.updateSets(fb->device);
|
||||
}
|
||||
|
||||
return NullTextureDescriptorSet.get();
|
||||
}
|
||||
|
||||
VulkanImageView* VkRenderPassManager::GetNullTextureView()
|
||||
{
|
||||
return NullTextureView.get();
|
||||
}
|
||||
|
||||
void VkRenderPassManager::UpdateDynamicSet()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
// In some rare cases drawing commands may already have been created before VulkanFrameBuffer::BeginFrame is called.
|
||||
// Make sure there there are no active command buffers using DynamicSet when we update it:
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
fb->WaitForCommands(false);
|
||||
|
||||
WriteDescriptors update;
|
||||
update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms));
|
||||
update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightBufferSSO->mBuffer.get());
|
||||
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO));
|
||||
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO));
|
||||
update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.addCombinedImageSampler(DynamicSet.get(), 5, fb->GetBuffers()->Lightmap.View.get(), fb->GetBuffers()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.updateSets(fb->device);
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> VkRenderPassManager::AllocateTextureDescriptorSet(int numLayers)
|
||||
{
|
||||
if (TextureDescriptorSetsLeft == 0 || TextureDescriptorsLeft < numLayers)
|
||||
{
|
||||
TextureDescriptorSetsLeft = 1000;
|
||||
TextureDescriptorsLeft = 2000;
|
||||
|
||||
DescriptorPoolBuilder builder;
|
||||
builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TextureDescriptorsLeft);
|
||||
builder.setMaxSets(TextureDescriptorSetsLeft);
|
||||
TextureDescriptorPools.push_back(builder.create(GetVulkanFrameBuffer()->device));
|
||||
TextureDescriptorPools.back()->SetDebugName("VkRenderPassManager.TextureDescriptorPool");
|
||||
}
|
||||
|
||||
TextureDescriptorSetsLeft--;
|
||||
TextureDescriptorsLeft -= numLayers;
|
||||
return TextureDescriptorPools.back()->allocate(GetTextureSetLayout(numLayers));
|
||||
auto& passSetup = PPRenderPassSetup[key];
|
||||
if (!passSetup)
|
||||
passSetup.reset(new VkPPRenderPassSetup(fb, key));
|
||||
return passSetup.get();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key) : PassKey(key)
|
||||
VkRenderPassSetup::VkRenderPassSetup(VulkanFrameBuffer* fb, const VkRenderPassKey &key) : PassKey(key), fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanRenderPass> VkRenderPassSetup::CreateRenderPass(int clearTargets)
|
||||
{
|
||||
auto buffers = GetVulkanFrameBuffer()->GetBuffers();
|
||||
auto buffers = fb->GetBuffers();
|
||||
|
||||
VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, buffers->SceneNormalFormat };
|
||||
|
||||
RenderPassBuilder builder;
|
||||
|
||||
builder.addAttachment(
|
||||
builder.AddAttachment(
|
||||
PassKey.DrawBufferFormat, (VkSampleCountFlagBits)PassKey.Samples,
|
||||
(clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
for (int i = 1; i < PassKey.DrawBuffers; i++)
|
||||
{
|
||||
builder.addAttachment(
|
||||
builder.AddAttachment(
|
||||
drawBufferFormats[i], buffers->GetSceneSamples(),
|
||||
(clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
if (PassKey.DepthStencil)
|
||||
{
|
||||
builder.addDepthStencilAttachment(
|
||||
builder.AddDepthStencilAttachment(
|
||||
buffers->SceneDepthStencilFormat, PassKey.DrawBufferFormat == VK_FORMAT_R8G8B8A8_UNORM ? VK_SAMPLE_COUNT_1_BIT : buffers->GetSceneSamples(),
|
||||
(clearTargets & CT_Depth) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
(clearTargets & CT_Stencil) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
builder.addSubpass();
|
||||
builder.AddSubpass();
|
||||
for (int i = 0; i < PassKey.DrawBuffers; i++)
|
||||
builder.addSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
builder.AddSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
if (PassKey.DepthStencil)
|
||||
{
|
||||
builder.addSubpassDepthStencilAttachmentRef(PassKey.DrawBuffers, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
builder.addExternalSubpassDependency(
|
||||
builder.AddSubpassDepthStencilAttachmentRef(PassKey.DrawBuffers, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
builder.AddExternalSubpassDependency(
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
|
@ -321,15 +178,14 @@ std::unique_ptr<VulkanRenderPass> VkRenderPassSetup::CreateRenderPass(int clearT
|
|||
}
|
||||
else
|
||||
{
|
||||
builder.addExternalSubpassDependency(
|
||||
builder.AddExternalSubpassDependency(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
|
||||
}
|
||||
auto renderpass = builder.create(GetVulkanFrameBuffer()->device);
|
||||
renderpass->SetDebugName("VkRenderPassSetup.RenderPass");
|
||||
return renderpass;
|
||||
builder.DebugName("VkRenderPassSetup.RenderPass");
|
||||
return builder.Create(fb->device);
|
||||
}
|
||||
|
||||
VulkanRenderPass *VkRenderPassSetup::GetRenderPass(int clearTargets)
|
||||
|
@ -349,7 +205,6 @@ VulkanPipeline *VkRenderPassSetup::GetPipeline(const VkPipelineKey &key)
|
|||
|
||||
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipelineKey &key)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
GraphicsPipelineBuilder builder;
|
||||
|
||||
VkShaderProgram *program;
|
||||
|
@ -361,13 +216,13 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
{
|
||||
program = fb->GetShaderManager()->Get(key.EffectState, key.AlphaTest, PassKey.DrawBuffers > 1 ? GBUFFER_PASS : NORMAL_PASS);
|
||||
}
|
||||
builder.addVertexShader(program->vert.get());
|
||||
builder.addFragmentShader(program->frag.get());
|
||||
builder.AddVertexShader(program->vert.get());
|
||||
builder.AddFragmentShader(program->frag.get());
|
||||
|
||||
const VkVertexFormat &vfmt = *fb->GetRenderPassManager()->GetVertexFormat(key.VertexFormat);
|
||||
|
||||
for (int i = 0; i < vfmt.NumBindingPoints; i++)
|
||||
builder.addVertexBufferBinding(i, vfmt.Stride);
|
||||
builder.AddVertexBufferBinding(i, vfmt.Stride);
|
||||
|
||||
const static VkFormat vkfmts[] = {
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
|
@ -383,7 +238,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
for (size_t i = 0; i < vfmt.Attrs.size(); i++)
|
||||
{
|
||||
const auto &attr = vfmt.Attrs[i];
|
||||
builder.addVertexAttribute(attr.location, attr.binding, vkfmts[attr.format], attr.offset);
|
||||
builder.AddVertexAttribute(attr.location, attr.binding, vkfmts[attr.format], attr.offset);
|
||||
inputLocations[attr.location] = true;
|
||||
}
|
||||
|
||||
|
@ -391,22 +246,17 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (!inputLocations[i])
|
||||
builder.addVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
|
||||
builder.AddVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
|
||||
}
|
||||
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR);
|
||||
// builder.addDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH);
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
|
||||
// builder.addDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
|
||||
// builder.addDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
|
||||
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
|
||||
// builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
|
||||
builder.addDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||
|
||||
// Note: the actual values are ignored since we use dynamic viewport+scissor states
|
||||
builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f);
|
||||
builder.setScissor(0, 0, 320, 200);
|
||||
builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f);
|
||||
builder.Scissor(0, 0, 320, 200);
|
||||
|
||||
static const VkPrimitiveTopology vktopology[] = {
|
||||
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
|
||||
|
@ -419,26 +269,130 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
static const VkStencilOp op2vk[] = { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_DECREMENT_AND_CLAMP };
|
||||
static const VkCompareOp depthfunc2vk[] = { VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS };
|
||||
|
||||
builder.setTopology(vktopology[key.DrawType]);
|
||||
builder.setDepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest);
|
||||
builder.setDepthFunc(depthfunc2vk[key.DepthFunc]);
|
||||
builder.Topology(vktopology[key.DrawType]);
|
||||
builder.DepthStencilEnable(key.DepthTest, key.DepthWrite, key.StencilTest);
|
||||
builder.DepthFunc(depthfunc2vk[key.DepthFunc]);
|
||||
if (fb->device->UsedDeviceFeatures.depthClamp)
|
||||
builder.setDepthClampEnable(key.DepthClamp);
|
||||
builder.setDepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f);
|
||||
builder.DepthClampEnable(key.DepthClamp);
|
||||
builder.DepthBias(key.DepthBias, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
// Note: CCW and CW is intentionally swapped here because the vulkan and opengl coordinate systems differ.
|
||||
// main.vp addresses this by patching up gl_Position.z, which has the side effect of flipping the sign of the front face calculations.
|
||||
builder.setCull(key.CullMode == Cull_None ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT, key.CullMode == Cull_CW ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE);
|
||||
builder.Cull(key.CullMode == Cull_None ? VK_CULL_MODE_NONE : VK_CULL_MODE_BACK_BIT, key.CullMode == Cull_CW ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE);
|
||||
|
||||
builder.setColorWriteMask((VkColorComponentFlags)key.ColorMask);
|
||||
builder.setStencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
|
||||
builder.setBlendMode(key.RenderStyle);
|
||||
builder.setSubpassColorAttachmentCount(PassKey.DrawBuffers);
|
||||
builder.setRasterizationSamples((VkSampleCountFlagBits)PassKey.Samples);
|
||||
builder.ColorWriteMask((VkColorComponentFlags)key.ColorMask);
|
||||
builder.Stencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
|
||||
builder.BlendMode(key.RenderStyle);
|
||||
builder.SubpassColorAttachmentCount(PassKey.DrawBuffers);
|
||||
builder.RasterizationSamples((VkSampleCountFlagBits)PassKey.Samples);
|
||||
|
||||
builder.setLayout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers));
|
||||
builder.setRenderPass(GetRenderPass(0));
|
||||
auto pipeline = builder.create(fb->device);
|
||||
pipeline->SetDebugName("VkRenderPassSetup.Pipeline");
|
||||
return pipeline;
|
||||
builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers));
|
||||
builder.RenderPass(GetRenderPass(0));
|
||||
builder.DebugName("VkRenderPassSetup.Pipeline");
|
||||
|
||||
return builder.Create(fb->device);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkPPRenderPassSetup::VkPPRenderPassSetup(VulkanFrameBuffer* fb, const VkPPRenderPassKey& key) : fb(fb)
|
||||
{
|
||||
CreateDescriptorLayout(key);
|
||||
CreatePipelineLayout(key);
|
||||
CreateRenderPass(key);
|
||||
CreatePipeline(key);
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey& key)
|
||||
{
|
||||
DescriptorSetLayoutBuilder builder;
|
||||
for (int i = 0; i < key.InputTextures; i++)
|
||||
builder.AddBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
if (key.ShadowMapBuffers)
|
||||
{
|
||||
builder.AddBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
builder.AddBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
builder.DebugName("VkPPRenderPassSetup.DescriptorLayout");
|
||||
DescriptorLayout = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreatePipelineLayout(const VkPPRenderPassKey& key)
|
||||
{
|
||||
PipelineLayoutBuilder builder;
|
||||
builder.AddSetLayout(DescriptorLayout.get());
|
||||
if (key.Uniforms > 0)
|
||||
builder.AddPushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, key.Uniforms);
|
||||
builder.DebugName("VkPPRenderPassSetup.PipelineLayout");
|
||||
PipelineLayout = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey& key)
|
||||
{
|
||||
GraphicsPipelineBuilder builder;
|
||||
builder.AddVertexShader(key.Shader->VertexShader.get());
|
||||
builder.AddFragmentShader(key.Shader->FragmentShader.get());
|
||||
|
||||
builder.AddVertexBufferBinding(0, sizeof(FFlatVertex));
|
||||
builder.AddVertexAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(FFlatVertex, x));
|
||||
builder.AddVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u));
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
|
||||
// Note: the actual values are ignored since we use dynamic viewport+scissor states
|
||||
builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f);
|
||||
builder.Scissor(0, 0, 320, 200);
|
||||
if (key.StencilTest)
|
||||
{
|
||||
builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||
builder.DepthStencilEnable(false, false, true);
|
||||
builder.Stencil(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0);
|
||||
}
|
||||
builder.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
|
||||
builder.BlendMode(key.BlendMode);
|
||||
builder.RasterizationSamples(key.Samples);
|
||||
builder.Layout(PipelineLayout.get());
|
||||
builder.RenderPass(RenderPass.get());
|
||||
builder.DebugName("VkPPRenderPassSetup.Pipeline");
|
||||
Pipeline = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey& key)
|
||||
{
|
||||
RenderPassBuilder builder;
|
||||
if (key.SwapChain)
|
||||
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
else
|
||||
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
if (key.StencilTest)
|
||||
{
|
||||
builder.AddDepthStencilAttachment(
|
||||
fb->GetBuffers()->SceneDepthStencilFormat, key.Samples,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
builder.AddSubpass();
|
||||
builder.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
if (key.StencilTest)
|
||||
{
|
||||
builder.AddSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
builder.AddExternalSubpassDependency(
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddExternalSubpassDependency(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
}
|
||||
|
||||
builder.DebugName("VkPPRenderPassSetup.RenderPass");
|
||||
RenderPass = builder.Create(fb->device);
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
#include "vulkan/system/vk_objects.h"
|
||||
#include "renderstyle.h"
|
||||
#include "hwrenderer/data/buffers.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
|
||||
class VKDataBuffer;
|
||||
class VulkanFrameBuffer;
|
||||
class VkPPShader;
|
||||
|
||||
class VkPipelineKey
|
||||
{
|
||||
|
@ -51,7 +53,7 @@ public:
|
|||
class VkRenderPassSetup
|
||||
{
|
||||
public:
|
||||
VkRenderPassSetup(const VkRenderPassKey &key);
|
||||
VkRenderPassSetup(VulkanFrameBuffer* fb, const VkRenderPassKey &key);
|
||||
|
||||
VulkanRenderPass *GetRenderPass(int clearTargets);
|
||||
VulkanPipeline *GetPipeline(const VkPipelineKey &key);
|
||||
|
@ -63,6 +65,8 @@ public:
|
|||
private:
|
||||
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);
|
||||
std::unique_ptr<VulkanPipeline> CreatePipeline(const VkPipelineKey &key);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
};
|
||||
|
||||
class VkVertexFormat
|
||||
|
@ -74,50 +78,64 @@ public:
|
|||
int UseVertexData;
|
||||
};
|
||||
|
||||
class VkPPRenderPassKey
|
||||
{
|
||||
public:
|
||||
VkPPShader* Shader;
|
||||
int Uniforms;
|
||||
int InputTextures;
|
||||
PPBlendMode BlendMode;
|
||||
VkFormat OutputFormat;
|
||||
int SwapChain;
|
||||
int ShadowMapBuffers;
|
||||
int StencilTest;
|
||||
VkSampleCountFlagBits Samples;
|
||||
|
||||
bool operator<(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
|
||||
bool operator==(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; }
|
||||
bool operator!=(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; }
|
||||
};
|
||||
|
||||
class VkPPRenderPassSetup
|
||||
{
|
||||
public:
|
||||
VkPPRenderPassSetup(VulkanFrameBuffer* fb, const VkPPRenderPassKey& key);
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> DescriptorLayout;
|
||||
std::unique_ptr<VulkanPipelineLayout> PipelineLayout;
|
||||
std::unique_ptr<VulkanRenderPass> RenderPass;
|
||||
std::unique_ptr<VulkanPipeline> Pipeline;
|
||||
|
||||
private:
|
||||
void CreateDescriptorLayout(const VkPPRenderPassKey& key);
|
||||
void CreatePipelineLayout(const VkPPRenderPassKey& key);
|
||||
void CreatePipeline(const VkPPRenderPassKey& key);
|
||||
void CreateRenderPass(const VkPPRenderPassKey& key);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
};
|
||||
|
||||
class VkRenderPassManager
|
||||
{
|
||||
public:
|
||||
VkRenderPassManager();
|
||||
VkRenderPassManager(VulkanFrameBuffer* fb);
|
||||
~VkRenderPassManager();
|
||||
|
||||
void Init();
|
||||
void RenderBuffersReset();
|
||||
void UpdateDynamicSet();
|
||||
void TextureSetPoolReset();
|
||||
|
||||
VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key);
|
||||
int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs);
|
||||
|
||||
VkVertexFormat *GetVertexFormat(int index);
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> AllocateTextureDescriptorSet(int numLayers);
|
||||
VulkanPipelineLayout* GetPipelineLayout(int numLayers);
|
||||
|
||||
VulkanDescriptorSet* GetNullTextureDescriptorSet();
|
||||
VulkanImageView* GetNullTextureView();
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> DynamicSetLayout;
|
||||
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> DynamicSet;
|
||||
VkPPRenderPassSetup* GetPPRenderPass(const VkPPRenderPassKey& key);
|
||||
|
||||
private:
|
||||
void CreateDynamicSetLayout();
|
||||
void CreateDescriptorPool();
|
||||
void CreateDynamicSet();
|
||||
void CreateNullTexture();
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
VulkanDescriptorSetLayout *GetTextureSetLayout(int numLayers);
|
||||
|
||||
int TextureDescriptorSetsLeft = 0;
|
||||
int TextureDescriptorsLeft = 0;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorPool>> TextureDescriptorPools;
|
||||
std::unique_ptr<VulkanDescriptorPool> DynamicDescriptorPool;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorSetLayout>> TextureSetLayouts;
|
||||
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;
|
||||
std::vector<std::unique_ptr<VulkanPipelineLayout>> PipelineLayouts;
|
||||
std::vector<VkVertexFormat> VertexFormats;
|
||||
|
||||
std::unique_ptr<VulkanImage> NullTexture;
|
||||
std::unique_ptr<VulkanImageView> NullTextureView;
|
||||
std::unique_ptr<VulkanDescriptorSet> NullTextureDescriptorSet;
|
||||
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> PPRenderPassSetup;
|
||||
};
|
||||
|
|
|
@ -23,8 +23,11 @@
|
|||
#include "vk_renderstate.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/system/vk_buffer.h"
|
||||
#include "vulkan/renderer/vk_renderpass.h"
|
||||
#include "vulkan/renderer/vk_renderbuffers.h"
|
||||
#include "vulkan/renderer/vk_descriptorset.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_hwtexture.h"
|
||||
|
||||
#include "hw_skydome.h"
|
||||
|
@ -39,7 +42,7 @@
|
|||
CVAR(Int, vk_submit_size, 1000, 0);
|
||||
EXTERN_CVAR(Bool, r_skipmats)
|
||||
|
||||
VkRenderState::VkRenderState()
|
||||
VkRenderState::VkRenderState(VulkanFrameBuffer* fb) : fb(fb), mStreamBufferWriter(fb), mMatrixBufferWriter(fb)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
@ -182,7 +185,7 @@ void VkRenderState::Apply(int dt)
|
|||
mApplyCount++;
|
||||
if (mApplyCount >= vk_submit_size)
|
||||
{
|
||||
GetVulkanFrameBuffer()->FlushCommands(false);
|
||||
fb->GetCommands()->FlushCommands(false);
|
||||
mApplyCount = 0;
|
||||
}
|
||||
|
||||
|
@ -195,7 +198,7 @@ void VkRenderState::Apply(int dt)
|
|||
ApplyDepthBias();
|
||||
ApplyPushConstants();
|
||||
ApplyVertexBuffers();
|
||||
ApplyDynamicSet();
|
||||
ApplyHWBufferSet();
|
||||
ApplyMaterial();
|
||||
mNeedApply = false;
|
||||
|
||||
|
@ -216,7 +219,7 @@ void VkRenderState::ApplyRenderPass(int dt)
|
|||
// Find a pipeline that matches our state
|
||||
VkPipelineKey pipelineKey;
|
||||
pipelineKey.DrawType = dt;
|
||||
pipelineKey.VertexFormat = static_cast<VKVertexBuffer*>(mVertexBuffer)->VertexFormat;
|
||||
pipelineKey.VertexFormat = static_cast<VkHardwareVertexBuffer*>(mVertexBuffer)->VertexFormat;
|
||||
pipelineKey.RenderStyle = mRenderStyle;
|
||||
pipelineKey.DepthTest = mDepthTest;
|
||||
pipelineKey.DepthWrite = mDepthTest && mDepthWrite;
|
||||
|
@ -251,7 +254,7 @@ void VkRenderState::ApplyRenderPass(int dt)
|
|||
|
||||
if (!inRenderPass)
|
||||
{
|
||||
mCommandBuffer = GetVulkanFrameBuffer()->GetDrawCommands();
|
||||
mCommandBuffer = fb->GetCommands()->GetDrawCommands();
|
||||
mScissorChanged = true;
|
||||
mViewportChanged = true;
|
||||
mStencilRefChanged = true;
|
||||
|
@ -333,10 +336,9 @@ void VkRenderState::ApplyViewport()
|
|||
|
||||
void VkRenderState::ApplyStreamData()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto passManager = fb->GetRenderPassManager();
|
||||
|
||||
mStreamData.useVertexData = passManager->GetVertexFormat(static_cast<VKVertexBuffer*>(mVertexBuffer)->VertexFormat)->UseVertexData;
|
||||
mStreamData.useVertexData = passManager->GetVertexFormat(static_cast<VkHardwareVertexBuffer*>(mVertexBuffer)->VertexFormat)->UseVertexData;
|
||||
|
||||
if (mMaterial.mMaterial && mMaterial.mMaterial->Source())
|
||||
mStreamData.timer = static_cast<float>((double)(screen->FrameTime - firstFrame) * (double)mMaterial.mMaterial->Source()->GetShaderSpeed() / 1000.);
|
||||
|
@ -391,7 +393,6 @@ void VkRenderState::ApplyPushConstants()
|
|||
mPushConstants.uLightIndex = mLightIndex;
|
||||
mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex();
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto passManager = fb->GetRenderPassManager();
|
||||
mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
|
||||
}
|
||||
|
@ -409,8 +410,8 @@ void VkRenderState::ApplyVertexBuffers()
|
|||
{
|
||||
if ((mVertexBuffer != mLastVertexBuffer || mVertexOffsets[0] != mLastVertexOffsets[0] || mVertexOffsets[1] != mLastVertexOffsets[1]) && mVertexBuffer)
|
||||
{
|
||||
auto vkbuf = static_cast<VKVertexBuffer*>(mVertexBuffer);
|
||||
const VkVertexFormat *format = GetVulkanFrameBuffer()->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat);
|
||||
auto vkbuf = static_cast<VkHardwareVertexBuffer*>(mVertexBuffer);
|
||||
const VkVertexFormat *format = fb->GetRenderPassManager()->GetVertexFormat(vkbuf->VertexFormat);
|
||||
VkBuffer vertexBuffers[2] = { vkbuf->mBuffer->buffer, vkbuf->mBuffer->buffer };
|
||||
VkDeviceSize offsets[] = { mVertexOffsets[0] * format->Stride, mVertexOffsets[1] * format->Stride };
|
||||
mCommandBuffer->bindVertexBuffers(0, 2, vertexBuffers, offsets);
|
||||
|
@ -421,7 +422,7 @@ void VkRenderState::ApplyVertexBuffers()
|
|||
|
||||
if (mIndexBuffer != mLastIndexBuffer && mIndexBuffer)
|
||||
{
|
||||
mCommandBuffer->bindIndexBuffer(static_cast<VKIndexBuffer*>(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
mCommandBuffer->bindIndexBuffer(static_cast<VkHardwareIndexBuffer*>(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
mLastIndexBuffer = mIndexBuffer;
|
||||
}
|
||||
}
|
||||
|
@ -430,29 +431,31 @@ void VkRenderState::ApplyMaterial()
|
|||
{
|
||||
if (mMaterial.mChanged)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto passManager = fb->GetRenderPassManager();
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
|
||||
if (mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) static_cast<FCanvasTexture*>(mMaterial.mMaterial->Source()->GetTexture())->NeedUpdate();
|
||||
|
||||
VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast<VkMaterial*>(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet();
|
||||
VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast<VkMaterial*>(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : descriptors->GetNullTextureDescriptorSet();
|
||||
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptorset);
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet());
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 2, descriptorset);
|
||||
mMaterial.mChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void VkRenderState::ApplyDynamicSet()
|
||||
void VkRenderState::ApplyHWBufferSet()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
uint32_t matrixOffset = mMatrixBufferWriter.Offset();
|
||||
uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset();
|
||||
if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset)
|
||||
{
|
||||
auto passManager = fb->GetRenderPassManager();
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
|
||||
uint32_t offsets[3] = { mViewpointOffset, matrixOffset, streamDataOffset };
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 3, offsets);
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet());
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptors->GetHWBufferDescriptorSet(), 3, offsets);
|
||||
|
||||
mLastViewpointOffset = mViewpointOffset;
|
||||
mLastMatricesOffset = matrixOffset;
|
||||
|
@ -462,7 +465,7 @@ void VkRenderState::ApplyDynamicSet()
|
|||
|
||||
void VkRenderState::WaitForStreamBuffers()
|
||||
{
|
||||
GetVulkanFrameBuffer()->WaitForCommands(false);
|
||||
fb->WaitForCommands(false);
|
||||
mApplyCount = 0;
|
||||
mStreamBufferWriter.Reset();
|
||||
mMatrixBufferWriter.Reset();
|
||||
|
@ -528,8 +531,6 @@ void VkRenderState::SetRenderTarget(VkTextureImage *image, VulkanImageView *dept
|
|||
|
||||
void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkRenderPassKey key = {};
|
||||
key.DrawBufferFormat = mRenderTarget.Format;
|
||||
key.Samples = mRenderTarget.Samples;
|
||||
|
@ -543,17 +544,17 @@ void VkRenderState::BeginRenderPass(VulkanCommandBuffer *cmdbuffer)
|
|||
{
|
||||
auto buffers = fb->GetBuffers();
|
||||
FramebufferBuilder builder;
|
||||
builder.setRenderPass(mPassSetup->GetRenderPass(0));
|
||||
builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
|
||||
builder.addAttachment(mRenderTarget.Image->View.get());
|
||||
builder.RenderPass(mPassSetup->GetRenderPass(0));
|
||||
builder.Size(mRenderTarget.Width, mRenderTarget.Height);
|
||||
builder.AddAttachment(mRenderTarget.Image->View.get());
|
||||
if (key.DrawBuffers > 1)
|
||||
builder.addAttachment(buffers->SceneFog.View.get());
|
||||
builder.AddAttachment(buffers->SceneFog.View.get());
|
||||
if (key.DrawBuffers > 2)
|
||||
builder.addAttachment(buffers->SceneNormal.View.get());
|
||||
builder.AddAttachment(buffers->SceneNormal.View.get());
|
||||
if (key.DepthStencil)
|
||||
builder.addAttachment(mRenderTarget.DepthStencil);
|
||||
framebuffer = builder.create(GetVulkanFrameBuffer()->device);
|
||||
framebuffer->SetDebugName("VkRenderPassSetup.Framebuffer");
|
||||
builder.AddAttachment(mRenderTarget.DepthStencil);
|
||||
builder.DebugName("VkRenderPassSetup.Framebuffer");
|
||||
framebuffer = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
// Only clear depth+stencil if the render target actually has that
|
||||
|
@ -583,7 +584,7 @@ void VkRenderStateMolten::Draw(int dt, int index, int count, bool apply)
|
|||
if (dt == DT_TriangleFan)
|
||||
{
|
||||
IIndexBuffer *oldIndexBuffer = mIndexBuffer;
|
||||
mIndexBuffer = GetVulkanFrameBuffer()->FanToTrisIndexBuffer.get();
|
||||
mIndexBuffer = fb->GetBufferManager()->FanToTrisIndexBuffer.get();
|
||||
|
||||
if (apply || mNeedApply)
|
||||
Apply(DT_Triangles);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_buffers.h"
|
||||
#include "vulkan/system/vk_hwbuffer.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/renderer/vk_renderpass.h"
|
||||
#include "vulkan/renderer/vk_streambuffer.h"
|
||||
|
@ -11,13 +11,14 @@
|
|||
#include "hw_renderstate.h"
|
||||
#include "hw_material.h"
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
class VkRenderPassSetup;
|
||||
class VkTextureImage;
|
||||
|
||||
class VkRenderState : public FRenderState
|
||||
{
|
||||
public:
|
||||
VkRenderState();
|
||||
VkRenderState(VulkanFrameBuffer* fb);
|
||||
virtual ~VkRenderState() = default;
|
||||
|
||||
// Draw commands
|
||||
|
@ -59,13 +60,15 @@ protected:
|
|||
void ApplyStreamData();
|
||||
void ApplyMatrices();
|
||||
void ApplyPushConstants();
|
||||
void ApplyDynamicSet();
|
||||
void ApplyHWBufferSet();
|
||||
void ApplyVertexBuffers();
|
||||
void ApplyMaterial();
|
||||
|
||||
void BeginRenderPass(VulkanCommandBuffer *cmdbuffer);
|
||||
void WaitForStreamBuffers();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
bool mDepthClamp = true;
|
||||
VulkanCommandBuffer *mCommandBuffer = nullptr;
|
||||
VkPipelineKey mPipelineKey = {};
|
||||
|
|
|
@ -23,37 +23,12 @@
|
|||
#include "vk_renderstate.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_buffer.h"
|
||||
#include "vulkan/renderer/vk_streambuffer.h"
|
||||
|
||||
VkStreamBuffer::VkStreamBuffer(size_t structSize, size_t count)
|
||||
VkStreamBufferWriter::VkStreamBufferWriter(VulkanFrameBuffer* fb)
|
||||
{
|
||||
mBlockSize = static_cast<uint32_t>((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment);
|
||||
|
||||
UniformBuffer = (VKDataBuffer*)GetVulkanFrameBuffer()->CreateDataBuffer(-1, false, false);
|
||||
UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent);
|
||||
}
|
||||
|
||||
VkStreamBuffer::~VkStreamBuffer()
|
||||
{
|
||||
delete UniformBuffer;
|
||||
}
|
||||
|
||||
uint32_t VkStreamBuffer::NextStreamDataBlock()
|
||||
{
|
||||
mStreamDataOffset += mBlockSize;
|
||||
if (mStreamDataOffset + (size_t)mBlockSize >= UniformBuffer->Size())
|
||||
{
|
||||
mStreamDataOffset = 0;
|
||||
return 0xffffffff;
|
||||
}
|
||||
return mStreamDataOffset;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkStreamBufferWriter::VkStreamBufferWriter()
|
||||
{
|
||||
mBuffer = GetVulkanFrameBuffer()->StreamBuffer;
|
||||
mBuffer = fb->GetBufferManager()->StreamBuffer.get();
|
||||
}
|
||||
|
||||
bool VkStreamBufferWriter::Write(const StreamData& data)
|
||||
|
@ -80,9 +55,9 @@ void VkStreamBufferWriter::Reset()
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkMatrixBufferWriter::VkMatrixBufferWriter()
|
||||
VkMatrixBufferWriter::VkMatrixBufferWriter(VulkanFrameBuffer* fb)
|
||||
{
|
||||
mBuffer = GetVulkanFrameBuffer()->MatrixBuffer;
|
||||
mBuffer = fb->GetBufferManager()->MatrixBuffer.get();
|
||||
mIdentityMatrix.loadIdentity();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_buffers.h"
|
||||
#include "vulkan/system/vk_hwbuffer.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
|
||||
class VkStreamBuffer;
|
||||
|
@ -10,7 +10,7 @@ class VkMatrixBuffer;
|
|||
class VkStreamBufferWriter
|
||||
{
|
||||
public:
|
||||
VkStreamBufferWriter();
|
||||
VkStreamBufferWriter(VulkanFrameBuffer* fb);
|
||||
|
||||
bool Write(const StreamData& data);
|
||||
void Reset();
|
||||
|
@ -27,7 +27,7 @@ private:
|
|||
class VkMatrixBufferWriter
|
||||
{
|
||||
public:
|
||||
VkMatrixBufferWriter();
|
||||
VkMatrixBufferWriter(VulkanFrameBuffer* fb);
|
||||
|
||||
bool Write(const VSMatrix& modelMatrix, bool modelMatrixEnabled, const VSMatrix& textureMatrix, bool textureMatrixEnabled);
|
||||
void Reset();
|
||||
|
@ -40,19 +40,3 @@ private:
|
|||
VSMatrix mIdentityMatrix;
|
||||
uint32_t mOffset = 0;
|
||||
};
|
||||
|
||||
class VkStreamBuffer
|
||||
{
|
||||
public:
|
||||
VkStreamBuffer(size_t structSize, size_t count);
|
||||
~VkStreamBuffer();
|
||||
|
||||
uint32_t NextStreamDataBlock();
|
||||
void Reset() { mStreamDataOffset = 0; }
|
||||
|
||||
VKDataBuffer* UniformBuffer = nullptr;
|
||||
|
||||
private:
|
||||
uint32_t mBlockSize = 0;
|
||||
uint32_t mStreamDataOffset = 0;
|
||||
};
|
||||
|
|
77
source/common/rendering/vulkan/shaders/vk_ppshader.cpp
Normal file
77
source/common/rendering/vulkan/shaders/vk_ppshader.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_ppshader.h"
|
||||
#include "vk_shader.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
VkPPShader::VkPPShader(VulkanFrameBuffer* fb, PPShader *shader) : fb(fb)
|
||||
{
|
||||
FString prolog;
|
||||
if (!shader->Uniforms.empty())
|
||||
prolog = UniformBlockDecl::Create("Uniforms", shader->Uniforms, -1);
|
||||
prolog += shader->Defines;
|
||||
|
||||
VertexShader = ShaderBuilder()
|
||||
.VertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version))
|
||||
.DebugName(shader->VertexShader.GetChars())
|
||||
.Create(shader->VertexShader.GetChars(), fb->device);
|
||||
|
||||
FragmentShader = ShaderBuilder()
|
||||
.FragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version))
|
||||
.DebugName(shader->FragmentShader.GetChars())
|
||||
.Create(shader->FragmentShader.GetChars(), fb->device);
|
||||
|
||||
fb->GetShaderManager()->AddVkPPShader(this);
|
||||
}
|
||||
|
||||
VkPPShader::~VkPPShader()
|
||||
{
|
||||
if (fb)
|
||||
fb->GetShaderManager()->RemoveVkPPShader(this);
|
||||
}
|
||||
|
||||
void VkPPShader::Reset()
|
||||
{
|
||||
if (fb)
|
||||
{
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(VertexShader));
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(FragmentShader));
|
||||
}
|
||||
}
|
||||
|
||||
FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
|
||||
{
|
||||
int lump = fileSystem.CheckNumForFullName(lumpName);
|
||||
if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars());
|
||||
FString code = fileSystem.ReadFile(lump).GetString().GetChars();
|
||||
|
||||
FString patchedCode;
|
||||
patchedCode.AppendFormat("#version %d\n", 450);
|
||||
patchedCode << defines;
|
||||
patchedCode << "#line 1\n";
|
||||
patchedCode << code;
|
||||
return patchedCode;
|
||||
}
|
26
source/common/rendering/vulkan/shaders/vk_ppshader.h
Normal file
26
source/common/rendering/vulkan/shaders/vk_ppshader.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include <list>
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkPPShader : public PPShaderBackend
|
||||
{
|
||||
public:
|
||||
VkPPShader(VulkanFrameBuffer* fb, PPShader *shader);
|
||||
~VkPPShader();
|
||||
|
||||
void Reset();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
std::list<VkPPShader*>::iterator it;
|
||||
|
||||
std::unique_ptr<VulkanShader> VertexShader;
|
||||
std::unique_ptr<VulkanShader> FragmentShader;
|
||||
|
||||
private:
|
||||
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
|
||||
};
|
|
@ -21,7 +21,9 @@
|
|||
*/
|
||||
|
||||
#include "vk_shader.h"
|
||||
#include "vk_ppshader.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "hw_shaderpatcher.h"
|
||||
#include "filesystem.h"
|
||||
#include "engineerrors.h"
|
||||
|
@ -111,7 +113,7 @@ bool VkShaderManager::CompileNextShader()
|
|||
return false;
|
||||
}
|
||||
|
||||
VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device)
|
||||
VkShaderManager::VkShaderManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
ShInitialize();
|
||||
CompileNextShader();
|
||||
|
@ -122,6 +124,12 @@ VkShaderManager::~VkShaderManager()
|
|||
ShFinalize();
|
||||
}
|
||||
|
||||
void VkShaderManager::Deinit()
|
||||
{
|
||||
while (!PPShaders.empty())
|
||||
RemoveVkPPShader(PPShaders.back());
|
||||
}
|
||||
|
||||
VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
|
||||
{
|
||||
if (compileIndex == -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
|
||||
|
@ -133,7 +141,8 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
|
|||
|
||||
VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
|
||||
{
|
||||
if (compileIndex != -1) return &mMaterialShaders[0][0];
|
||||
if (compileIndex != -1)
|
||||
return &mMaterialShaders[0][0];
|
||||
// indices 0-2 match the warping modes, 3 no texture, the following are custom
|
||||
if (!alphateston && eff < SHADER_NoTexture)
|
||||
{
|
||||
|
@ -148,8 +157,14 @@ VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassT
|
|||
|
||||
static const char *shaderBindings = R"(
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D ShadowMap;
|
||||
layout(set = 0, binding = 1) uniform sampler2DArray LightMap;
|
||||
#ifdef SUPPORTS_RAYTRACING
|
||||
layout(set = 0, binding = 2) uniform accelerationStructureEXT TopLevelAS;
|
||||
#endif
|
||||
|
||||
// This must match the HWViewpointUniforms struct
|
||||
layout(set = 0, binding = 0, std140) uniform ViewpointUBO {
|
||||
layout(set = 1, binding = 0, std140) uniform ViewpointUBO {
|
||||
mat4 ProjectionMatrix;
|
||||
mat4 ViewMatrix;
|
||||
mat4 NormalViewMatrix;
|
||||
|
@ -165,13 +180,7 @@ static const char *shaderBindings = R"(
|
|||
int uShadowmapFilter;
|
||||
};
|
||||
|
||||
// light buffers
|
||||
layout(set = 0, binding = 1, std430) buffer LightBufferSSO
|
||||
{
|
||||
vec4 lights[];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 2, std140) uniform MatricesUBO {
|
||||
layout(set = 1, binding = 1, std140) uniform MatricesUBO {
|
||||
mat4 ModelMatrix;
|
||||
mat4 NormalModelMatrix;
|
||||
mat4 TextureMatrix;
|
||||
|
@ -210,25 +219,28 @@ static const char *shaderBindings = R"(
|
|||
vec4 padding1, padding2, padding3;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3, std140) uniform StreamUBO {
|
||||
layout(set = 1, binding = 2, std140) uniform StreamUBO {
|
||||
StreamData data[MAX_STREAM_DATA];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 4) uniform sampler2D ShadowMap;
|
||||
layout(set = 0, binding = 5) uniform sampler2DArray LightMap;
|
||||
// light buffers
|
||||
layout(set = 1, binding = 3, std430) buffer LightBufferSSO
|
||||
{
|
||||
vec4 lights[];
|
||||
};
|
||||
|
||||
// textures
|
||||
layout(set = 1, binding = 0) uniform sampler2D tex;
|
||||
layout(set = 1, binding = 1) uniform sampler2D texture2;
|
||||
layout(set = 1, binding = 2) uniform sampler2D texture3;
|
||||
layout(set = 1, binding = 3) uniform sampler2D texture4;
|
||||
layout(set = 1, binding = 4) uniform sampler2D texture5;
|
||||
layout(set = 1, binding = 5) uniform sampler2D texture6;
|
||||
layout(set = 1, binding = 6) uniform sampler2D texture7;
|
||||
layout(set = 1, binding = 7) uniform sampler2D texture8;
|
||||
layout(set = 1, binding = 8) uniform sampler2D texture9;
|
||||
layout(set = 1, binding = 9) uniform sampler2D texture10;
|
||||
layout(set = 1, binding = 10) uniform sampler2D texture11;
|
||||
layout(set = 2, binding = 0) uniform sampler2D tex;
|
||||
layout(set = 2, binding = 1) uniform sampler2D texture2;
|
||||
layout(set = 2, binding = 2) uniform sampler2D texture3;
|
||||
layout(set = 2, binding = 3) uniform sampler2D texture4;
|
||||
layout(set = 2, binding = 4) uniform sampler2D texture5;
|
||||
layout(set = 2, binding = 5) uniform sampler2D texture6;
|
||||
layout(set = 2, binding = 6) uniform sampler2D texture7;
|
||||
layout(set = 2, binding = 7) uniform sampler2D texture8;
|
||||
layout(set = 2, binding = 8) uniform sampler2D texture9;
|
||||
layout(set = 2, binding = 9) uniform sampler2D texture10;
|
||||
layout(set = 2, binding = 10) uniform sampler2D texture11;
|
||||
|
||||
// This must match the PushConstants struct
|
||||
layout(push_constant) uniform PushConstants
|
||||
|
@ -325,18 +337,21 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
|
|||
code << "#define NPOT_EMULATION\n";
|
||||
#endif
|
||||
code << shaderBindings;
|
||||
if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
|
||||
if (!fb->device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
|
||||
code << "#line 1\n";
|
||||
code << LoadPrivateShaderLump(vert_lump).GetChars() << "\n";
|
||||
|
||||
ShaderBuilder builder;
|
||||
builder.setVertexShader(code);
|
||||
return builder.create(shadername.GetChars(), device);
|
||||
return ShaderBuilder()
|
||||
.VertexShader(code)
|
||||
.DebugName(shadername.GetChars())
|
||||
.Create(shadername.GetChars(), fb->device);
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass)
|
||||
{
|
||||
FString code = GetTargetGlslVersion();
|
||||
if (fb->RaytracingEnabled())
|
||||
code << "\n#define SUPPORTS_RAYTRACING\n";
|
||||
code << defines;
|
||||
code << "\n$placeholder$"; // here the code can later add more needed #defines.
|
||||
code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
|
||||
|
@ -346,7 +361,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
|||
code << shaderBindings;
|
||||
FString placeholder = "\n";
|
||||
|
||||
if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
|
||||
if (!fb->device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n";
|
||||
if (!alphatest) code << "#define NO_ALPHATEST\n";
|
||||
if (gbufferpass) code << "#define GBUFFER_PASS\n";
|
||||
|
||||
|
@ -418,14 +433,22 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
|||
code << LoadPrivateShaderLump(light_lump).GetChars();
|
||||
}
|
||||
|
||||
ShaderBuilder builder;
|
||||
builder.setFragmentShader(code);
|
||||
return builder.create(shadername.GetChars(), device);
|
||||
return ShaderBuilder()
|
||||
.FragmentShader(code)
|
||||
.DebugName(shadername.GetChars())
|
||||
.Create(shadername.GetChars(), fb->device);
|
||||
}
|
||||
|
||||
FString VkShaderManager::GetTargetGlslVersion()
|
||||
{
|
||||
return "#version 450 core\n";
|
||||
if (fb->device->ApiVersion == VK_API_VERSION_1_2)
|
||||
{
|
||||
return "#version 460\n#extension GL_EXT_ray_query : enable\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "#version 450 core\n";
|
||||
}
|
||||
}
|
||||
|
||||
FString VkShaderManager::LoadPublicShaderLump(const char *lumpname)
|
||||
|
@ -444,3 +467,22 @@ FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname)
|
|||
FileData data = fileSystem.ReadFile(lump);
|
||||
return data.GetString();
|
||||
}
|
||||
|
||||
VkPPShader* VkShaderManager::GetVkShader(PPShader* shader)
|
||||
{
|
||||
if (!shader->Backend)
|
||||
shader->Backend = std::make_unique<VkPPShader>(fb, shader);
|
||||
return static_cast<VkPPShader*>(shader->Backend.get());
|
||||
}
|
||||
|
||||
void VkShaderManager::AddVkPPShader(VkPPShader* shader)
|
||||
{
|
||||
shader->it = PPShaders.insert(PPShaders.end(), shader);
|
||||
}
|
||||
|
||||
void VkShaderManager::RemoveVkPPShader(VkPPShader* shader)
|
||||
{
|
||||
shader->Reset();
|
||||
shader->fb = nullptr;
|
||||
PPShaders.erase(shader->it);
|
||||
}
|
||||
|
|
|
@ -7,11 +7,15 @@
|
|||
#include "matrix.h"
|
||||
#include "name.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include <list>
|
||||
|
||||
#define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 8
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
class VulkanDevice;
|
||||
class VulkanShader;
|
||||
class VkPPShader;
|
||||
class PPShader;
|
||||
|
||||
struct MatricesUBO
|
||||
{
|
||||
|
@ -60,13 +64,20 @@ public:
|
|||
class VkShaderManager
|
||||
{
|
||||
public:
|
||||
VkShaderManager(VulkanDevice *device);
|
||||
VkShaderManager(VulkanFrameBuffer* fb);
|
||||
~VkShaderManager();
|
||||
|
||||
void Deinit();
|
||||
|
||||
VkShaderProgram *GetEffect(int effect, EPassType passType);
|
||||
VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType);
|
||||
bool CompileNextShader();
|
||||
|
||||
VkPPShader* GetVkShader(PPShader* shader);
|
||||
|
||||
void AddVkPPShader(VkPPShader* shader);
|
||||
void RemoveVkPPShader(VkPPShader* shader);
|
||||
|
||||
private:
|
||||
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines);
|
||||
std::unique_ptr<VulkanShader> LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass);
|
||||
|
@ -75,11 +86,13 @@ private:
|
|||
FString LoadPublicShaderLump(const char *lumpname);
|
||||
FString LoadPrivateShaderLump(const char *lumpname);
|
||||
|
||||
VulkanDevice *device;
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
std::vector<VkShaderProgram> mMaterialShaders[MAX_PASS_TYPES];
|
||||
std::vector<VkShaderProgram> mMaterialShadersNAT[MAX_PASS_TYPES];
|
||||
std::vector<VkShaderProgram> mEffectShaders[MAX_PASS_TYPES];
|
||||
uint8_t compilePass = 0, compileState = 0;
|
||||
int compileIndex = 0;
|
||||
|
||||
std::list<VkPPShader*> PPShaders;
|
||||
};
|
||||
|
|
133
source/common/rendering/vulkan/system/vk_buffer.cpp
Normal file
133
source/common/rendering/vulkan/system/vk_buffer.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_buffer.h"
|
||||
#include "vk_hwbuffer.h"
|
||||
#include "vulkan/renderer/vk_streambuffer.h"
|
||||
#include "hwrenderer/data/shaderuniforms.h"
|
||||
|
||||
VkBufferManager::VkBufferManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
VkBufferManager::~VkBufferManager()
|
||||
{
|
||||
}
|
||||
|
||||
void VkBufferManager::Init()
|
||||
{
|
||||
MatrixBuffer.reset(new VkStreamBuffer(this, sizeof(MatricesUBO), 50000));
|
||||
StreamBuffer.reset(new VkStreamBuffer(this, sizeof(StreamUBO), 300));
|
||||
|
||||
CreateFanToTrisIndexBuffer();
|
||||
}
|
||||
|
||||
void VkBufferManager::Deinit()
|
||||
{
|
||||
while (!Buffers.empty())
|
||||
RemoveBuffer(Buffers.back());
|
||||
}
|
||||
|
||||
void VkBufferManager::AddBuffer(VkHardwareBuffer* buffer)
|
||||
{
|
||||
buffer->it = Buffers.insert(Buffers.end(), buffer);
|
||||
}
|
||||
|
||||
void VkBufferManager::RemoveBuffer(VkHardwareBuffer* buffer)
|
||||
{
|
||||
buffer->Reset();
|
||||
buffer->fb = nullptr;
|
||||
Buffers.erase(buffer->it);
|
||||
|
||||
for (VkHardwareDataBuffer** knownbuf : { &ViewpointUBO, &LightBufferSSO, &LightNodes, &LightLines, &LightList })
|
||||
{
|
||||
if (buffer == *knownbuf) *knownbuf = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IVertexBuffer* VkBufferManager::CreateVertexBuffer()
|
||||
{
|
||||
return new VkHardwareVertexBuffer(fb);
|
||||
}
|
||||
|
||||
IIndexBuffer* VkBufferManager::CreateIndexBuffer()
|
||||
{
|
||||
return new VkHardwareIndexBuffer(fb);
|
||||
}
|
||||
|
||||
IDataBuffer* VkBufferManager::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize)
|
||||
{
|
||||
auto buffer = new VkHardwareDataBuffer(fb, bindingpoint, ssbo, needsresize);
|
||||
|
||||
switch (bindingpoint)
|
||||
{
|
||||
case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break;
|
||||
case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break;
|
||||
case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break;
|
||||
case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break;
|
||||
case LIGHTLIST_BINDINGPOINT: LightList = buffer; break;
|
||||
case POSTPROCESS_BINDINGPOINT: break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void VkBufferManager::CreateFanToTrisIndexBuffer()
|
||||
{
|
||||
TArray<uint32_t> data;
|
||||
for (int i = 2; i < 1000; i++)
|
||||
{
|
||||
data.Push(0);
|
||||
data.Push(i - 1);
|
||||
data.Push(i);
|
||||
}
|
||||
|
||||
FanToTrisIndexBuffer.reset(CreateIndexBuffer());
|
||||
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkStreamBuffer::VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count)
|
||||
{
|
||||
mBlockSize = static_cast<uint32_t>((structSize + screen->uniformblockalignment - 1) / screen->uniformblockalignment * screen->uniformblockalignment);
|
||||
|
||||
UniformBuffer = (VkHardwareDataBuffer*)buffers->CreateDataBuffer(-1, false, false);
|
||||
UniformBuffer->SetData(mBlockSize * count, nullptr, BufferUsageType::Persistent);
|
||||
}
|
||||
|
||||
VkStreamBuffer::~VkStreamBuffer()
|
||||
{
|
||||
delete UniformBuffer;
|
||||
}
|
||||
|
||||
uint32_t VkStreamBuffer::NextStreamDataBlock()
|
||||
{
|
||||
mStreamDataOffset += mBlockSize;
|
||||
if (mStreamDataOffset + (size_t)mBlockSize >= UniformBuffer->Size())
|
||||
{
|
||||
mStreamDataOffset = 0;
|
||||
return 0xffffffff;
|
||||
}
|
||||
return mStreamDataOffset;
|
||||
}
|
64
source/common/rendering/vulkan/system/vk_buffer.h
Normal file
64
source/common/rendering/vulkan/system/vk_buffer.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include <list>
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
class VkHardwareBuffer;
|
||||
class VkHardwareDataBuffer;
|
||||
class VkStreamBuffer;
|
||||
class IIndexBuffer;
|
||||
class IVertexBuffer;
|
||||
class IDataBuffer;
|
||||
|
||||
class VkBufferManager
|
||||
{
|
||||
public:
|
||||
VkBufferManager(VulkanFrameBuffer* fb);
|
||||
~VkBufferManager();
|
||||
|
||||
void Init();
|
||||
void Deinit();
|
||||
|
||||
IVertexBuffer* CreateVertexBuffer();
|
||||
IIndexBuffer* CreateIndexBuffer();
|
||||
IDataBuffer* CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize);
|
||||
|
||||
void AddBuffer(VkHardwareBuffer* buffer);
|
||||
void RemoveBuffer(VkHardwareBuffer* buffer);
|
||||
|
||||
VkHardwareDataBuffer* ViewpointUBO = nullptr;
|
||||
VkHardwareDataBuffer* LightBufferSSO = nullptr;
|
||||
VkHardwareDataBuffer* LightNodes = nullptr;
|
||||
VkHardwareDataBuffer* LightLines = nullptr;
|
||||
VkHardwareDataBuffer* LightList = nullptr;
|
||||
|
||||
std::unique_ptr<VkStreamBuffer> MatrixBuffer;
|
||||
std::unique_ptr<VkStreamBuffer> StreamBuffer;
|
||||
|
||||
std::unique_ptr<IIndexBuffer> FanToTrisIndexBuffer;
|
||||
|
||||
private:
|
||||
void CreateFanToTrisIndexBuffer();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
std::list<VkHardwareBuffer*> Buffers;
|
||||
};
|
||||
|
||||
class VkStreamBuffer
|
||||
{
|
||||
public:
|
||||
VkStreamBuffer(VkBufferManager* buffers, size_t structSize, size_t count);
|
||||
~VkStreamBuffer();
|
||||
|
||||
uint32_t NextStreamDataBlock();
|
||||
void Reset() { mStreamDataOffset = 0; }
|
||||
|
||||
VkHardwareDataBuffer* UniformBuffer = nullptr;
|
||||
|
||||
private:
|
||||
uint32_t mBlockSize = 0;
|
||||
uint32_t mStreamDataOffset = 0;
|
||||
};
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
268
source/common/rendering/vulkan/system/vk_commandbuffer.cpp
Normal file
268
source/common/rendering/vulkan/system/vk_commandbuffer.cpp
Normal file
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_commandbuffer.h"
|
||||
#include "vk_framebuffer.h"
|
||||
#include "vk_swapchain.h"
|
||||
#include "vk_builders.h"
|
||||
#include "vulkan/renderer/vk_renderstate.h"
|
||||
#include "vulkan/renderer/vk_postprocess.h"
|
||||
#include "hw_clock.h"
|
||||
#include "v_video.h"
|
||||
|
||||
extern int rendered_commandbuffers;
|
||||
int current_rendered_commandbuffers;
|
||||
|
||||
extern bool gpuStatActive;
|
||||
extern bool keepGpuStatActive;
|
||||
extern FString gpuStatOutput;
|
||||
|
||||
VkCommandBufferManager::VkCommandBufferManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
mCommandPool.reset(new VulkanCommandPool(fb->device, fb->device->graphicsFamily));
|
||||
|
||||
swapChain = std::make_unique<VulkanSwapChain>(fb->device);
|
||||
mSwapChainImageAvailableSemaphore.reset(new VulkanSemaphore(fb->device));
|
||||
mRenderFinishedSemaphore.reset(new VulkanSemaphore(fb->device));
|
||||
|
||||
for (auto& semaphore : mSubmitSemaphore)
|
||||
semaphore.reset(new VulkanSemaphore(fb->device));
|
||||
|
||||
for (auto& fence : mSubmitFence)
|
||||
fence.reset(new VulkanFence(fb->device));
|
||||
|
||||
for (int i = 0; i < maxConcurrentSubmitCount; i++)
|
||||
mSubmitWaitFences[i] = mSubmitFence[i]->fence;
|
||||
|
||||
if (fb->device->graphicsTimeQueries)
|
||||
{
|
||||
mTimestampQueryPool = QueryPoolBuilder()
|
||||
.QueryType(VK_QUERY_TYPE_TIMESTAMP, MaxTimestampQueries)
|
||||
.Create(fb->device);
|
||||
|
||||
GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, MaxTimestampQueries);
|
||||
}
|
||||
}
|
||||
|
||||
VkCommandBufferManager::~VkCommandBufferManager()
|
||||
{
|
||||
}
|
||||
|
||||
VulkanCommandBuffer* VkCommandBufferManager::GetTransferCommands()
|
||||
{
|
||||
if (!mTransferCommands)
|
||||
{
|
||||
mTransferCommands = mCommandPool->createBuffer();
|
||||
mTransferCommands->SetDebugName("VulkanFrameBuffer.mTransferCommands");
|
||||
mTransferCommands->begin();
|
||||
}
|
||||
return mTransferCommands.get();
|
||||
}
|
||||
|
||||
VulkanCommandBuffer* VkCommandBufferManager::GetDrawCommands()
|
||||
{
|
||||
if (!mDrawCommands)
|
||||
{
|
||||
mDrawCommands = mCommandPool->createBuffer();
|
||||
mDrawCommands->SetDebugName("VulkanFrameBuffer.mDrawCommands");
|
||||
mDrawCommands->begin();
|
||||
}
|
||||
return mDrawCommands.get();
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::BeginFrame()
|
||||
{
|
||||
if (mNextTimestampQuery > 0)
|
||||
{
|
||||
GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery);
|
||||
mNextTimestampQuery = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::FlushCommands(VulkanCommandBuffer** commands, size_t count, bool finish, bool lastsubmit)
|
||||
{
|
||||
int currentIndex = mNextSubmit % maxConcurrentSubmitCount;
|
||||
|
||||
if (mNextSubmit >= maxConcurrentSubmitCount)
|
||||
{
|
||||
vkWaitForFences(fb->device->device, 1, &mSubmitFence[currentIndex]->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(fb->device->device, 1, &mSubmitFence[currentIndex]->fence);
|
||||
}
|
||||
|
||||
QueueSubmit submit;
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
submit.AddCommandBuffer(commands[i]);
|
||||
|
||||
if (mNextSubmit > 0)
|
||||
submit.AddWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mSubmitSemaphore[(mNextSubmit - 1) % maxConcurrentSubmitCount].get());
|
||||
|
||||
if (finish && presentImageIndex != 0xffffffff)
|
||||
{
|
||||
submit.AddWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mSwapChainImageAvailableSemaphore.get());
|
||||
submit.AddSignal(mRenderFinishedSemaphore.get());
|
||||
}
|
||||
|
||||
if (!lastsubmit)
|
||||
submit.AddSignal(mSubmitSemaphore[currentIndex].get());
|
||||
|
||||
submit.Execute(fb->device, fb->device->graphicsQueue, mSubmitFence[currentIndex].get());
|
||||
mNextSubmit++;
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::FlushCommands(bool finish, bool lastsubmit, bool uploadOnly)
|
||||
{
|
||||
if (!uploadOnly)
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
|
||||
if ((!uploadOnly && mDrawCommands) || mTransferCommands)
|
||||
{
|
||||
VulkanCommandBuffer* commands[2];
|
||||
size_t count = 0;
|
||||
|
||||
if (mTransferCommands)
|
||||
{
|
||||
mTransferCommands->end();
|
||||
commands[count++] = mTransferCommands.get();
|
||||
TransferDeleteList->Add(std::move(mTransferCommands));
|
||||
}
|
||||
|
||||
if (!uploadOnly && mDrawCommands)
|
||||
{
|
||||
mDrawCommands->end();
|
||||
commands[count++] = mDrawCommands.get();
|
||||
DrawDeleteList->Add(std::move(mDrawCommands));
|
||||
}
|
||||
|
||||
FlushCommands(commands, count, finish, lastsubmit);
|
||||
|
||||
current_rendered_commandbuffers += (int)count;
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::WaitForCommands(bool finish, bool uploadOnly)
|
||||
{
|
||||
if (finish)
|
||||
{
|
||||
Finish.Reset();
|
||||
Finish.Clock();
|
||||
|
||||
presentImageIndex = swapChain->AcquireImage(fb->GetClientWidth(), fb->GetClientHeight(), fb->GetVSync(), mSwapChainImageAvailableSemaphore.get());
|
||||
if (presentImageIndex != 0xffffffff)
|
||||
fb->GetPostprocess()->DrawPresentTexture(fb->mOutputLetterbox, true, false);
|
||||
}
|
||||
|
||||
FlushCommands(finish, true, uploadOnly);
|
||||
|
||||
if (finish)
|
||||
{
|
||||
fb->FPSLimit();
|
||||
|
||||
if (presentImageIndex != 0xffffffff)
|
||||
swapChain->QueuePresent(presentImageIndex, mRenderFinishedSemaphore.get());
|
||||
}
|
||||
|
||||
int numWaitFences = min(mNextSubmit, (int)maxConcurrentSubmitCount);
|
||||
|
||||
if (numWaitFences > 0)
|
||||
{
|
||||
vkWaitForFences(fb->device->device, numWaitFences, mSubmitWaitFences, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(fb->device->device, numWaitFences, mSubmitWaitFences);
|
||||
}
|
||||
|
||||
DeleteFrameObjects(uploadOnly);
|
||||
mNextSubmit = 0;
|
||||
|
||||
if (finish)
|
||||
{
|
||||
Finish.Unclock();
|
||||
rendered_commandbuffers = current_rendered_commandbuffers;
|
||||
current_rendered_commandbuffers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::DeleteFrameObjects(bool uploadOnly)
|
||||
{
|
||||
TransferDeleteList = std::make_unique<DeleteList>();
|
||||
if (!uploadOnly)
|
||||
DrawDeleteList = std::make_unique<DeleteList>();
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::PushGroup(const FString& name)
|
||||
{
|
||||
if (!gpuStatActive)
|
||||
return;
|
||||
|
||||
if (mNextTimestampQuery < MaxTimestampQueries && fb->device->graphicsTimeQueries)
|
||||
{
|
||||
TimestampQuery q;
|
||||
q.name = name;
|
||||
q.startIndex = mNextTimestampQuery++;
|
||||
q.endIndex = 0;
|
||||
GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex);
|
||||
mGroupStack.push_back(timeElapsedQueries.size());
|
||||
timeElapsedQueries.push_back(q);
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::PopGroup()
|
||||
{
|
||||
if (!gpuStatActive || mGroupStack.empty())
|
||||
return;
|
||||
|
||||
TimestampQuery& q = timeElapsedQueries[mGroupStack.back()];
|
||||
mGroupStack.pop_back();
|
||||
|
||||
if (mNextTimestampQuery < MaxTimestampQueries && fb->device->graphicsTimeQueries)
|
||||
{
|
||||
q.endIndex = mNextTimestampQuery++;
|
||||
GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::UpdateGpuStats()
|
||||
{
|
||||
uint64_t timestamps[MaxTimestampQueries];
|
||||
if (mNextTimestampQuery > 0)
|
||||
mTimestampQueryPool->getResults(0, mNextTimestampQuery, sizeof(uint64_t) * mNextTimestampQuery, timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
|
||||
double timestampPeriod = fb->device->PhysicalDevice.Properties.limits.timestampPeriod;
|
||||
|
||||
gpuStatOutput = "";
|
||||
for (auto& q : timeElapsedQueries)
|
||||
{
|
||||
if (q.endIndex <= q.startIndex)
|
||||
continue;
|
||||
|
||||
int64_t timeElapsed = max(static_cast<int64_t>(timestamps[q.endIndex] - timestamps[q.startIndex]), (int64_t)0);
|
||||
double timeNS = timeElapsed * timestampPeriod;
|
||||
|
||||
FString out;
|
||||
out.Format("%s=%04.2f ms\n", q.name.GetChars(), timeNS / 1000000.0f);
|
||||
gpuStatOutput += out;
|
||||
}
|
||||
timeElapsedQueries.clear();
|
||||
mGroupStack.clear();
|
||||
|
||||
gpuStatActive = keepGpuStatActive;
|
||||
keepGpuStatActive = false;
|
||||
}
|
94
source/common/rendering/vulkan/system/vk_commandbuffer.h
Normal file
94
source/common/rendering/vulkan/system/vk_commandbuffer.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
#pragma once
|
||||
|
||||
#include "vk_device.h"
|
||||
#include "vk_objects.h"
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkCommandBufferManager
|
||||
{
|
||||
public:
|
||||
VkCommandBufferManager(VulkanFrameBuffer* fb);
|
||||
~VkCommandBufferManager();
|
||||
|
||||
void BeginFrame();
|
||||
|
||||
VulkanCommandBuffer* GetTransferCommands();
|
||||
VulkanCommandBuffer* GetDrawCommands();
|
||||
|
||||
void FlushCommands(bool finish, bool lastsubmit = false, bool uploadOnly = false);
|
||||
|
||||
void WaitForCommands(bool finish) { WaitForCommands(finish, false); }
|
||||
void WaitForCommands(bool finish, bool uploadOnly);
|
||||
|
||||
void PushGroup(const FString& name);
|
||||
void PopGroup();
|
||||
void UpdateGpuStats();
|
||||
|
||||
class DeleteList
|
||||
{
|
||||
public:
|
||||
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
|
||||
std::vector<std::unique_ptr<VulkanSampler>> Samplers;
|
||||
std::vector<std::unique_ptr<VulkanImage>> Images;
|
||||
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
|
||||
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
|
||||
std::vector<std::unique_ptr<VulkanAccelerationStructure>> AccelStructs;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
|
||||
std::vector<std::unique_ptr<VulkanShader>> Shaders;
|
||||
std::vector<std::unique_ptr<VulkanCommandBuffer>> CommandBuffers;
|
||||
size_t TotalSize = 0;
|
||||
|
||||
void Add(std::unique_ptr<VulkanBuffer> obj) { if (obj) { TotalSize += obj->size; Buffers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanSampler> obj) { if (obj) { Samplers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanImage> obj) { if (obj) { Images.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanImageView> obj) { if (obj) { ImageViews.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanFramebuffer> obj) { if (obj) { Framebuffers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanAccelerationStructure> obj) { if (obj) { AccelStructs.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanDescriptorPool> obj) { if (obj) { DescriptorPools.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanDescriptorSet> obj) { if (obj) { Descriptors.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanCommandBuffer> obj) { if (obj) { CommandBuffers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanShader> obj) { if (obj) { Shaders.push_back(std::move(obj)); } }
|
||||
};
|
||||
|
||||
std::unique_ptr<DeleteList> TransferDeleteList = std::make_unique<DeleteList>();
|
||||
std::unique_ptr<DeleteList> DrawDeleteList = std::make_unique<DeleteList>();
|
||||
|
||||
void DeleteFrameObjects(bool uploadOnly = false);
|
||||
|
||||
std::unique_ptr<VulkanSwapChain> swapChain;
|
||||
uint32_t presentImageIndex = 0xffffffff;
|
||||
|
||||
private:
|
||||
void FlushCommands(VulkanCommandBuffer** commands, size_t count, bool finish, bool lastsubmit);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
std::unique_ptr<VulkanCommandPool> mCommandPool;
|
||||
|
||||
std::unique_ptr<VulkanCommandBuffer> mTransferCommands;
|
||||
std::unique_ptr<VulkanCommandBuffer> mDrawCommands;
|
||||
|
||||
enum { maxConcurrentSubmitCount = 8 };
|
||||
std::unique_ptr<VulkanSemaphore> mSubmitSemaphore[maxConcurrentSubmitCount];
|
||||
std::unique_ptr<VulkanFence> mSubmitFence[maxConcurrentSubmitCount];
|
||||
VkFence mSubmitWaitFences[maxConcurrentSubmitCount];
|
||||
int mNextSubmit = 0;
|
||||
|
||||
std::unique_ptr<VulkanSemaphore> mSwapChainImageAvailableSemaphore;
|
||||
std::unique_ptr<VulkanSemaphore> mRenderFinishedSemaphore;
|
||||
|
||||
struct TimestampQuery
|
||||
{
|
||||
FString name;
|
||||
uint32_t startIndex;
|
||||
uint32_t endIndex;
|
||||
};
|
||||
|
||||
enum { MaxTimestampQueries = 100 };
|
||||
std::unique_ptr<VulkanQueryPool> mTimestampQueryPool;
|
||||
int mNextTimestampQuery = 0;
|
||||
std::vector<size_t> mGroupStack;
|
||||
std::vector<TimestampQuery> timeElapsedQueries;
|
||||
};
|
|
@ -216,8 +216,11 @@ bool VulkanDevice::SupportsDeviceExtension(const char *ext) const
|
|||
void VulkanDevice::CreateAllocator()
|
||||
{
|
||||
VmaAllocatorCreateInfo allocinfo = {};
|
||||
allocinfo.vulkanApiVersion = ApiVersion;
|
||||
if (SupportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME))
|
||||
allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
|
||||
allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
|
||||
if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||
allocinfo.physicalDevice = PhysicalDevice.Device;
|
||||
allocinfo.device = device;
|
||||
allocinfo.instance = instance;
|
||||
|
@ -245,14 +248,47 @@ void VulkanDevice::CreateDevice()
|
|||
queueCreateInfos.push_back(queueCreateInfo);
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures deviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES };
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR deviceAccelFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR };
|
||||
VkPhysicalDeviceRayQueryFeaturesKHR rayQueryFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR };
|
||||
|
||||
deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
|
||||
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||
deviceCreateInfo.pEnabledFeatures = &UsedDeviceFeatures;
|
||||
deviceCreateInfo.enabledExtensionCount = (uint32_t)EnabledDeviceExtensions.size();
|
||||
deviceCreateInfo.ppEnabledExtensionNames = EnabledDeviceExtensions.data();
|
||||
deviceCreateInfo.enabledLayerCount = 0;
|
||||
deviceFeatures2.features = UsedDeviceFeatures;
|
||||
deviceAddressFeatures.bufferDeviceAddress = true;
|
||||
deviceAccelFeatures.accelerationStructure = true;
|
||||
rayQueryFeatures.rayQuery = true;
|
||||
|
||||
void** next = const_cast<void**>(&deviceCreateInfo.pNext);
|
||||
if (SupportsDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
||||
{
|
||||
*next = &deviceFeatures2;
|
||||
next = &deviceFeatures2.pNext;
|
||||
}
|
||||
else // vulkan 1.0 specified features in a different way
|
||||
{
|
||||
deviceCreateInfo.pEnabledFeatures = &deviceFeatures2.features;
|
||||
}
|
||||
if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
{
|
||||
*next = &deviceAddressFeatures;
|
||||
next = &deviceAddressFeatures.pNext;
|
||||
}
|
||||
if (SupportsDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME))
|
||||
{
|
||||
*next = &deviceAccelFeatures;
|
||||
next = &deviceAccelFeatures.pNext;
|
||||
}
|
||||
if (SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
{
|
||||
*next = &rayQueryFeatures;
|
||||
next = &rayQueryFeatures.pNext;
|
||||
}
|
||||
|
||||
VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device);
|
||||
CheckVulkanError(result, "Could not create vulkan device");
|
||||
|
@ -306,23 +342,33 @@ void VulkanDevice::CreateInstance()
|
|||
}
|
||||
}
|
||||
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "GZDoom";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION);
|
||||
appInfo.pEngineName = "GZDoom";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||
// Try get the highest vulkan version we can get
|
||||
VkResult result = VK_ERROR_INITIALIZATION_FAILED;
|
||||
for (uint32_t apiVersion : { VK_API_VERSION_1_2, VK_API_VERSION_1_1, VK_API_VERSION_1_0 })
|
||||
{
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "GZDoom";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION);
|
||||
appInfo.pEngineName = "GZDoom";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION);
|
||||
appInfo.apiVersion = apiVersion;
|
||||
|
||||
VkInstanceCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size();
|
||||
createInfo.enabledLayerCount = (uint32_t)EnabledValidationLayers.size();
|
||||
createInfo.ppEnabledLayerNames = EnabledValidationLayers.data();
|
||||
createInfo.ppEnabledExtensionNames = EnabledExtensions.data();
|
||||
VkInstanceCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size();
|
||||
createInfo.enabledLayerCount = (uint32_t)EnabledValidationLayers.size();
|
||||
createInfo.ppEnabledLayerNames = EnabledValidationLayers.data();
|
||||
createInfo.ppEnabledExtensionNames = EnabledExtensions.data();
|
||||
|
||||
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
|
||||
result = vkCreateInstance(&createInfo, nullptr, &instance);
|
||||
if (result >= VK_SUCCESS)
|
||||
{
|
||||
ApiVersion = apiVersion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CheckVulkanError(result, "Could not create vulkan instance");
|
||||
|
||||
volkLoadInstance(instance);
|
||||
|
@ -359,14 +405,28 @@ VkBool32 VulkanDevice::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT mess
|
|||
|
||||
FString msg = callbackData->pMessage;
|
||||
|
||||
// For patent-pending reasons the validation layer apparently can't do this itself..
|
||||
for (uint32_t i = 0; i < callbackData->objectCount; i++)
|
||||
// Attempt to parse the string because the default formatting is totally unreadable and half of what it writes is totally useless!
|
||||
auto parts = msg.Split(" | ");
|
||||
if (parts.Size() == 3)
|
||||
{
|
||||
if (callbackData->pObjects[i].pObjectName)
|
||||
msg = parts[2];
|
||||
auto pos = msg.IndexOf(" The Vulkan spec states:");
|
||||
if (pos >= 0)
|
||||
msg = msg.Left(pos);
|
||||
|
||||
if (callbackData->objectCount > 0)
|
||||
{
|
||||
FString hexname;
|
||||
hexname.Format("0x%" PRIx64, callbackData->pObjects[i].objectHandle);
|
||||
msg.Substitute(hexname.GetChars(), callbackData->pObjects[i].pObjectName);
|
||||
msg += " (";
|
||||
for (uint32_t i = 0; i < callbackData->objectCount; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
msg += ", ";
|
||||
if (callbackData->pObjects[i].pObjectName)
|
||||
msg += callbackData->pObjects[i].pObjectName;
|
||||
else
|
||||
msg += "<noname>";
|
||||
}
|
||||
msg += ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,11 +60,22 @@ public:
|
|||
std::vector<const char *> EnabledExtensions;
|
||||
std::vector<const char *> OptionalExtensions = { VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME };
|
||||
std::vector<const char*> EnabledValidationLayers;
|
||||
uint32_t ApiVersion = {};
|
||||
|
||||
// Device setup
|
||||
VkPhysicalDeviceFeatures UsedDeviceFeatures = {};
|
||||
std::vector<const char *> EnabledDeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||
std::vector<const char *> OptionalDeviceExtensions = { VK_EXT_HDR_METADATA_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME };
|
||||
std::vector<const char *> OptionalDeviceExtensions =
|
||||
{
|
||||
VK_EXT_HDR_METADATA_EXTENSION_NAME,
|
||||
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
|
||||
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
||||
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
|
||||
VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,
|
||||
VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,
|
||||
VK_KHR_RAY_QUERY_EXTENSION_NAME
|
||||
};
|
||||
VulkanPhysicalDevice PhysicalDevice;
|
||||
bool DebugLayerActive = false;
|
||||
|
||||
|
@ -80,6 +91,8 @@ public:
|
|||
int presentFamily = -1;
|
||||
bool graphicsTimeQueries = false;
|
||||
|
||||
bool SupportsDeviceExtension(const char* ext) const;
|
||||
|
||||
private:
|
||||
void CreateInstance();
|
||||
void CreateSurface();
|
||||
|
@ -89,8 +102,6 @@ private:
|
|||
void CreateAllocator();
|
||||
void ReleaseResources();
|
||||
|
||||
bool SupportsDeviceExtension(const char *ext) const;
|
||||
|
||||
static bool CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f);
|
||||
|
||||
VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE;
|
||||
|
|
|
@ -43,17 +43,22 @@
|
|||
#include "hw_lightbuffer.h"
|
||||
|
||||
#include "vk_framebuffer.h"
|
||||
#include "vk_buffers.h"
|
||||
#include "vk_hwbuffer.h"
|
||||
#include "vulkan/renderer/vk_renderstate.h"
|
||||
#include "vulkan/renderer/vk_renderpass.h"
|
||||
#include "vulkan/renderer/vk_descriptorset.h"
|
||||
#include "vulkan/renderer/vk_streambuffer.h"
|
||||
#include "vulkan/renderer/vk_postprocess.h"
|
||||
#include "vulkan/renderer/vk_renderbuffers.h"
|
||||
#include "vulkan/renderer/vk_raytrace.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_samplers.h"
|
||||
#include "vulkan/textures/vk_hwtexture.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_swapchain.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/system/vk_buffer.h"
|
||||
#include "engineerrors.h"
|
||||
#include "c_dispatch.h"
|
||||
|
||||
|
@ -62,64 +67,49 @@ EXTERN_CVAR(Int, gl_tonemap)
|
|||
EXTERN_CVAR(Int, screenblocks)
|
||||
EXTERN_CVAR(Bool, cl_capfps)
|
||||
|
||||
extern int rendered_commandbuffers;
|
||||
int current_rendered_commandbuffers;
|
||||
|
||||
extern bool gpuStatActive;
|
||||
extern bool keepGpuStatActive;
|
||||
extern FString gpuStatOutput;
|
||||
|
||||
CCMD(vk_memstats)
|
||||
{
|
||||
VmaStats stats = {};
|
||||
vmaCalculateStats(GetVulkanFrameBuffer()->device->allocator, &stats);
|
||||
Printf("Allocated objects: %d, used bytes: %d MB\n", (int)stats.total.allocationCount, (int)stats.total.usedBytes / (1024 * 1024));
|
||||
Printf("Unused range count: %d, unused bytes: %d MB\n", (int)stats.total.unusedRangeCount, (int)stats.total.unusedBytes / (1024 * 1024));
|
||||
if (screen->IsVulkan())
|
||||
{
|
||||
VmaStats stats = {};
|
||||
vmaCalculateStats(static_cast<VulkanFrameBuffer*>(screen)->device->allocator, &stats);
|
||||
Printf("Allocated objects: %d, used bytes: %d MB\n", (int)stats.total.allocationCount, (int)stats.total.usedBytes / (1024 * 1024));
|
||||
Printf("Unused range count: %d, unused bytes: %d MB\n", (int)stats.total.unusedRangeCount, (int)stats.total.unusedBytes / (1024 * 1024));
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("Vulkan is not the current render device\n");
|
||||
}
|
||||
}
|
||||
|
||||
CVAR(Bool, vk_raytrace, false, 0/*CVAR_ARCHIVE | CVAR_GLOBALCONFIG*/)
|
||||
|
||||
VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevice *dev) :
|
||||
Super(hMonitor, fullscreen)
|
||||
{
|
||||
device = dev;
|
||||
|
||||
swapChain = std::make_unique<VulkanSwapChain>(device);
|
||||
mSwapChainImageAvailableSemaphore.reset(new VulkanSemaphore(device));
|
||||
mRenderFinishedSemaphore.reset(new VulkanSemaphore(device));
|
||||
|
||||
for (auto &semaphore : mSubmitSemaphore)
|
||||
semaphore.reset(new VulkanSemaphore(device));
|
||||
|
||||
for (auto &fence : mSubmitFence)
|
||||
fence.reset(new VulkanFence(device));
|
||||
|
||||
for (int i = 0; i < maxConcurrentSubmitCount; i++)
|
||||
mSubmitWaitFences[i] = mSubmitFence[i]->fence;
|
||||
}
|
||||
|
||||
VulkanFrameBuffer::~VulkanFrameBuffer()
|
||||
{
|
||||
vkDeviceWaitIdle(device->device); // make sure the GPU is no longer using any objects before RAII tears them down
|
||||
|
||||
// screen is already null at this point, but VkHardwareTexture::ResetAll needs it during clean up. Is there a better way we can do this?
|
||||
auto tmp = screen;
|
||||
screen = this;
|
||||
|
||||
// All descriptors must be destroyed before the descriptor pool in renderpass manager is destroyed
|
||||
VkHardwareTexture::ResetAll();
|
||||
VKBuffer::ResetAll();
|
||||
PPResource::ResetAll();
|
||||
|
||||
delete MatrixBuffer;
|
||||
delete StreamBuffer;
|
||||
delete mVertexData;
|
||||
delete mSkyData;
|
||||
delete mViewpoints;
|
||||
delete mLights;
|
||||
mShadowMap.Reset();
|
||||
|
||||
screen = tmp;
|
||||
if (mDescriptorSetManager)
|
||||
mDescriptorSetManager->Deinit();
|
||||
if (mTextureManager)
|
||||
mTextureManager->Deinit();
|
||||
if (mBufferManager)
|
||||
mBufferManager->Deinit();
|
||||
if (mShaderManager)
|
||||
mShaderManager->Deinit();
|
||||
|
||||
DeleteFrameObjects();
|
||||
mCommands->DeleteFrameObjects();
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::InitializeState()
|
||||
|
@ -145,43 +135,34 @@ void VulkanFrameBuffer::InitializeState()
|
|||
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
|
||||
maxuniformblock = device->PhysicalDevice.Properties.limits.maxUniformBufferRange;
|
||||
|
||||
mCommandPool.reset(new VulkanCommandPool(device, device->graphicsFamily));
|
||||
mCommands.reset(new VkCommandBufferManager(this));
|
||||
|
||||
mScreenBuffers.reset(new VkRenderBuffers());
|
||||
mSaveBuffers.reset(new VkRenderBuffers());
|
||||
mSamplerManager.reset(new VkSamplerManager(this));
|
||||
mTextureManager.reset(new VkTextureManager(this));
|
||||
mBufferManager.reset(new VkBufferManager(this));
|
||||
mBufferManager->Init();
|
||||
|
||||
mScreenBuffers.reset(new VkRenderBuffers(this));
|
||||
mSaveBuffers.reset(new VkRenderBuffers(this));
|
||||
mActiveRenderBuffers = mScreenBuffers.get();
|
||||
|
||||
mPostprocess.reset(new VkPostprocess());
|
||||
mRenderPassManager.reset(new VkRenderPassManager());
|
||||
mPostprocess.reset(new VkPostprocess(this));
|
||||
mDescriptorSetManager.reset(new VkDescriptorSetManager(this));
|
||||
mRenderPassManager.reset(new VkRenderPassManager(this));
|
||||
mRaytrace.reset(new VkRaytrace(this));
|
||||
|
||||
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
||||
mSkyData = new FSkyVertexBuffer;
|
||||
mViewpoints = new HWViewpointBuffer;
|
||||
mLights = new FLightBuffer();
|
||||
|
||||
CreateFanToTrisIndexBuffer();
|
||||
|
||||
// To do: move this to HW renderer interface maybe?
|
||||
MatrixBuffer = new VkStreamBuffer(sizeof(MatricesUBO), 50000);
|
||||
StreamBuffer = new VkStreamBuffer(sizeof(StreamUBO), 300);
|
||||
|
||||
mShaderManager.reset(new VkShaderManager(device));
|
||||
mSamplerManager.reset(new VkSamplerManager(device));
|
||||
mRenderPassManager->Init();
|
||||
mShaderManager.reset(new VkShaderManager(this));
|
||||
mDescriptorSetManager->Init();
|
||||
#ifdef __APPLE__
|
||||
mRenderState.reset(new VkRenderStateMolten());
|
||||
mRenderState.reset(new VkRenderStateMolten(this));
|
||||
#else
|
||||
mRenderState.reset(new VkRenderState());
|
||||
mRenderState.reset(new VkRenderState(this));
|
||||
#endif
|
||||
|
||||
if (device->graphicsTimeQueries)
|
||||
{
|
||||
QueryPoolBuilder querybuilder;
|
||||
querybuilder.setQueryType(VK_QUERY_TYPE_TIMESTAMP, MaxTimestampQueries);
|
||||
mTimestampQueryPool = querybuilder.create(device);
|
||||
|
||||
GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, MaxTimestampQueries);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::Update()
|
||||
|
@ -201,8 +182,8 @@ void VulkanFrameBuffer::Update()
|
|||
|
||||
Flush3D.Unclock();
|
||||
|
||||
WaitForCommands(true);
|
||||
UpdateGpuStats();
|
||||
mCommands->WaitForCommands(true);
|
||||
mCommands->UpdateGpuStats();
|
||||
|
||||
Super::Update();
|
||||
}
|
||||
|
@ -212,125 +193,6 @@ bool VulkanFrameBuffer::CompileNextShader()
|
|||
return mShaderManager->CompileNextShader();
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly)
|
||||
{
|
||||
FrameTextureUpload.Buffers.clear();
|
||||
FrameTextureUpload.TotalSize = 0;
|
||||
|
||||
if (!uploadOnly)
|
||||
{
|
||||
FrameDeleteList.Images.clear();
|
||||
FrameDeleteList.ImageViews.clear();
|
||||
FrameDeleteList.Framebuffers.clear();
|
||||
FrameDeleteList.Buffers.clear();
|
||||
FrameDeleteList.Descriptors.clear();
|
||||
FrameDeleteList.DescriptorPools.clear();
|
||||
FrameDeleteList.CommandBuffers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::FlushCommands(VulkanCommandBuffer **commands, size_t count, bool finish, bool lastsubmit)
|
||||
{
|
||||
int currentIndex = mNextSubmit % maxConcurrentSubmitCount;
|
||||
|
||||
if (mNextSubmit >= maxConcurrentSubmitCount)
|
||||
{
|
||||
vkWaitForFences(device->device, 1, &mSubmitFence[currentIndex]->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(device->device, 1, &mSubmitFence[currentIndex]->fence);
|
||||
}
|
||||
|
||||
QueueSubmit submit;
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
submit.addCommandBuffer(commands[i]);
|
||||
|
||||
if (mNextSubmit > 0)
|
||||
submit.addWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mSubmitSemaphore[(mNextSubmit - 1) % maxConcurrentSubmitCount].get());
|
||||
|
||||
if (finish && presentImageIndex != 0xffffffff)
|
||||
{
|
||||
submit.addWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mSwapChainImageAvailableSemaphore.get());
|
||||
submit.addSignal(mRenderFinishedSemaphore.get());
|
||||
}
|
||||
|
||||
if (!lastsubmit)
|
||||
submit.addSignal(mSubmitSemaphore[currentIndex].get());
|
||||
|
||||
submit.execute(device, device->graphicsQueue, mSubmitFence[currentIndex].get());
|
||||
mNextSubmit++;
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::FlushCommands(bool finish, bool lastsubmit, bool uploadOnly)
|
||||
{
|
||||
if (!uploadOnly)
|
||||
mRenderState->EndRenderPass();
|
||||
|
||||
if ((!uploadOnly && mDrawCommands) || mTransferCommands)
|
||||
{
|
||||
VulkanCommandBuffer *commands[2];
|
||||
size_t count = 0;
|
||||
|
||||
if (mTransferCommands)
|
||||
{
|
||||
mTransferCommands->end();
|
||||
commands[count++] = mTransferCommands.get();
|
||||
FrameDeleteList.CommandBuffers.push_back(std::move(mTransferCommands));
|
||||
}
|
||||
|
||||
if (!uploadOnly && mDrawCommands)
|
||||
{
|
||||
mDrawCommands->end();
|
||||
commands[count++] = mDrawCommands.get();
|
||||
FrameDeleteList.CommandBuffers.push_back(std::move(mDrawCommands));
|
||||
}
|
||||
|
||||
FlushCommands(commands, count, finish, lastsubmit);
|
||||
|
||||
current_rendered_commandbuffers += (int)count;
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::WaitForCommands(bool finish, bool uploadOnly)
|
||||
{
|
||||
if (finish)
|
||||
{
|
||||
Finish.Reset();
|
||||
Finish.Clock();
|
||||
|
||||
presentImageIndex = swapChain->AcquireImage(GetClientWidth(), GetClientHeight(), mSwapChainImageAvailableSemaphore.get());
|
||||
if (presentImageIndex != 0xffffffff)
|
||||
mPostprocess->DrawPresentTexture(mOutputLetterbox, true, false);
|
||||
}
|
||||
|
||||
FlushCommands(finish, true, uploadOnly);
|
||||
|
||||
if (finish)
|
||||
{
|
||||
FPSLimit();
|
||||
|
||||
if (presentImageIndex != 0xffffffff)
|
||||
swapChain->QueuePresent(presentImageIndex, mRenderFinishedSemaphore.get());
|
||||
}
|
||||
|
||||
int numWaitFences = min(mNextSubmit, (int)maxConcurrentSubmitCount);
|
||||
|
||||
if (numWaitFences > 0)
|
||||
{
|
||||
vkWaitForFences(device->device, numWaitFences, mSubmitWaitFences, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(device->device, numWaitFences, mSubmitWaitFences);
|
||||
}
|
||||
|
||||
DeleteFrameObjects(uploadOnly);
|
||||
mNextSubmit = 0;
|
||||
|
||||
if (finish)
|
||||
{
|
||||
Finish.Unclock();
|
||||
rendered_commandbuffers = current_rendered_commandbuffers;
|
||||
current_rendered_commandbuffers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function<void(IntRect &)> renderFunc)
|
||||
{
|
||||
auto BaseLayer = static_cast<VkHardwareTexture*>(tex->GetHardwareTexture(0, 0));
|
||||
|
@ -340,9 +202,9 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function<voi
|
|||
|
||||
mRenderState->EndRenderPass();
|
||||
|
||||
VkImageTransition barrier0;
|
||||
barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
barrier0.execute(GetDrawCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true)
|
||||
.Execute(mCommands->GetDrawCommands());
|
||||
|
||||
mRenderState->SetRenderTarget(image, depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
|
||||
|
||||
|
@ -355,9 +217,9 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function<voi
|
|||
|
||||
mRenderState->EndRenderPass();
|
||||
|
||||
VkImageTransition barrier1;
|
||||
barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||
barrier1.execute(GetDrawCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
|
||||
.Execute(mCommands->GetDrawCommands());
|
||||
|
||||
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
||||
|
||||
|
@ -376,11 +238,9 @@ const char* VulkanFrameBuffer::DeviceName() const
|
|||
return props.deviceName;
|
||||
}
|
||||
|
||||
|
||||
void VulkanFrameBuffer::SetVSync(bool vsync)
|
||||
{
|
||||
// This is handled in VulkanSwapChain::AcquireImage.
|
||||
cur_vsync = vsync;
|
||||
mVSync = vsync;
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
|
||||
|
@ -402,57 +262,42 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
|
|||
|
||||
IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels)
|
||||
{
|
||||
return new VkHardwareTexture(numchannels);
|
||||
return new VkHardwareTexture(this, numchannels);
|
||||
}
|
||||
|
||||
FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags)
|
||||
{
|
||||
return new VkMaterial(tex, scaleflags);
|
||||
return new VkMaterial(this, tex, scaleflags);
|
||||
}
|
||||
|
||||
IVertexBuffer *VulkanFrameBuffer::CreateVertexBuffer()
|
||||
{
|
||||
return new VKVertexBuffer();
|
||||
return GetBufferManager()->CreateVertexBuffer();
|
||||
}
|
||||
|
||||
IIndexBuffer *VulkanFrameBuffer::CreateIndexBuffer()
|
||||
{
|
||||
return new VKIndexBuffer();
|
||||
return GetBufferManager()->CreateIndexBuffer();
|
||||
}
|
||||
|
||||
IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize)
|
||||
{
|
||||
auto buffer = new VKDataBuffer(bindingpoint, ssbo, needsresize);
|
||||
|
||||
switch (bindingpoint)
|
||||
{
|
||||
case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break;
|
||||
case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break;
|
||||
case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break;
|
||||
case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break;
|
||||
case LIGHTLIST_BINDINGPOINT: LightList = buffer; break;
|
||||
case POSTPROCESS_BINDINGPOINT: break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
return GetBufferManager()->CreateDataBuffer(bindingpoint, ssbo, needsresize);
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::SetTextureFilterMode()
|
||||
{
|
||||
if (mSamplerManager)
|
||||
{
|
||||
// Destroy the texture descriptors as they used the old samplers
|
||||
VkMaterial::ResetAllDescriptors();
|
||||
|
||||
mSamplerManager->SetTextureFilterMode();
|
||||
mDescriptorSetManager->ResetHWTextureSets();
|
||||
mSamplerManager->ResetHWSamplers();
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::StartPrecaching()
|
||||
{
|
||||
// Destroy the texture descriptors to avoid problems with potentially stale textures.
|
||||
VkMaterial::ResetAllDescriptors();
|
||||
mDescriptorSetManager->ResetHWTextureSets();
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::BlurScene(float amount)
|
||||
|
@ -498,18 +343,21 @@ void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, uint8_t *data)
|
|||
VkTextureImage image;
|
||||
|
||||
// Convert from rgba16f to rgba8 using the GPU:
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
imgbuilder.setSize(w, h);
|
||||
image.Image = imgbuilder.create(device);
|
||||
image.Image = ImageBuilder()
|
||||
.Format(VK_FORMAT_R8G8B8A8_UNORM)
|
||||
.Usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
.Size(w, h)
|
||||
.DebugName("CopyScreenToBuffer")
|
||||
.Create(device);
|
||||
|
||||
GetPostprocess()->BlitCurrentToImage(&image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
// Staging buffer for download
|
||||
BufferBuilder bufbuilder;
|
||||
bufbuilder.setSize(w * h * 4);
|
||||
bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU);
|
||||
auto staging = bufbuilder.create(device);
|
||||
auto staging = BufferBuilder()
|
||||
.Size(w * h * 4)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU)
|
||||
.DebugName("CopyScreenToBuffer")
|
||||
.Create(device);
|
||||
|
||||
// Copy from image to buffer
|
||||
VkBufferImageCopy region = {};
|
||||
|
@ -518,10 +366,10 @@ void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, uint8_t *data)
|
|||
region.imageExtent.depth = 1;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
GetDrawCommands()->copyImageToBuffer(image.Image->image, image.Layout, staging->buffer, 1, ®ion);
|
||||
mCommands->GetDrawCommands()->copyImageToBuffer(image.Image->image, image.Layout, staging->buffer, 1, ®ion);
|
||||
|
||||
// Submit command buffers and wait for device to finish the work
|
||||
WaitForCommands(false);
|
||||
mCommands->WaitForCommands(false);
|
||||
|
||||
// Map and convert from rgba8 to rgb8
|
||||
uint8_t *dest = (uint8_t*)data;
|
||||
|
@ -547,7 +395,6 @@ void VulkanFrameBuffer::SetActiveRenderTarget()
|
|||
mPostprocess->SetActiveRenderTarget();
|
||||
}
|
||||
|
||||
|
||||
TArray<uint8_t> VulkanFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma)
|
||||
{
|
||||
int w = SCREENWIDTH;
|
||||
|
@ -572,178 +419,31 @@ TArray<uint8_t> VulkanFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &colo
|
|||
void VulkanFrameBuffer::BeginFrame()
|
||||
{
|
||||
SetViewportRects(nullptr);
|
||||
mCommands->BeginFrame();
|
||||
mTextureManager->BeginFrame();
|
||||
mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
||||
mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
||||
mRenderState->BeginFrame();
|
||||
mRenderPassManager->UpdateDynamicSet();
|
||||
|
||||
if (mNextTimestampQuery > 0)
|
||||
{
|
||||
GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery);
|
||||
mNextTimestampQuery = 0;
|
||||
}
|
||||
mDescriptorSetManager->BeginFrame();
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::InitLightmap(int LMTextureSize, int LMTextureCount, TArray<uint16_t>& LMTextureData)
|
||||
{
|
||||
if (LMTextureData.Size() > 0)
|
||||
{
|
||||
int w = LMTextureSize;
|
||||
int h = LMTextureSize;
|
||||
int count = LMTextureCount;
|
||||
int pixelsize = 8;
|
||||
auto& lightmap = mActiveRenderBuffers->Lightmap;
|
||||
|
||||
if (lightmap.Image)
|
||||
{
|
||||
FrameDeleteList.Images.push_back(std::move(lightmap.Image));
|
||||
FrameDeleteList.ImageViews.push_back(std::move(lightmap.View));
|
||||
lightmap.reset();
|
||||
}
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(w, h, 1, count);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
lightmap.Image = builder.create(device);
|
||||
lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
|
||||
viewbuilder.setImage(lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
lightmap.View = viewbuilder.create(device);
|
||||
lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
|
||||
|
||||
auto cmdbuffer = GetTransferCommands();
|
||||
|
||||
int totalSize = w * h * count * pixelsize;
|
||||
|
||||
BufferBuilder bufbuilder;
|
||||
bufbuilder.setSize(totalSize);
|
||||
bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
std::unique_ptr<VulkanBuffer> stagingBuffer = bufbuilder.create(device);
|
||||
stagingBuffer->SetDebugName("VkHardwareTexture.mStagingBuffer");
|
||||
|
||||
uint16_t one = 0x3c00; // half-float 1.0
|
||||
uint16_t* src = &LMTextureData[0];
|
||||
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
|
||||
for (int i = w * h * count; i > 0; i--)
|
||||
{
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = one;
|
||||
}
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, count);
|
||||
imageTransition.execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = count;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = w;
|
||||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count);
|
||||
barrier.execute(cmdbuffer);
|
||||
|
||||
FrameTextureUpload.Buffers.push_back(std::move(stagingBuffer));
|
||||
FrameTextureUpload.TotalSize += totalSize;
|
||||
|
||||
GetTextureManager()->SetLightmap(LMTextureSize, LMTextureCount, LMTextureData);
|
||||
LMTextureData.Reset(); // We no longer need this, release the memory
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::PushGroup(const FString &name)
|
||||
{
|
||||
if (!gpuStatActive)
|
||||
return;
|
||||
|
||||
if (mNextTimestampQuery < VulkanFrameBuffer::MaxTimestampQueries && device->graphicsTimeQueries)
|
||||
{
|
||||
TimestampQuery q;
|
||||
q.name = name;
|
||||
q.startIndex = mNextTimestampQuery++;
|
||||
q.endIndex = 0;
|
||||
GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex);
|
||||
mGroupStack.push_back(timeElapsedQueries.size());
|
||||
timeElapsedQueries.push_back(q);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::PopGroup()
|
||||
{
|
||||
if (!gpuStatActive || mGroupStack.empty())
|
||||
return;
|
||||
|
||||
TimestampQuery &q = timeElapsedQueries[mGroupStack.back()];
|
||||
mGroupStack.pop_back();
|
||||
|
||||
if (mNextTimestampQuery < VulkanFrameBuffer::MaxTimestampQueries && device->graphicsTimeQueries)
|
||||
{
|
||||
q.endIndex = mNextTimestampQuery++;
|
||||
GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::UpdateGpuStats()
|
||||
{
|
||||
uint64_t timestamps[MaxTimestampQueries];
|
||||
if (mNextTimestampQuery > 0)
|
||||
mTimestampQueryPool->getResults(0, mNextTimestampQuery, sizeof(uint64_t) * mNextTimestampQuery, timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
|
||||
double timestampPeriod = device->PhysicalDevice.Properties.limits.timestampPeriod;
|
||||
|
||||
gpuStatOutput = "";
|
||||
for (auto &q : timeElapsedQueries)
|
||||
{
|
||||
if (q.endIndex <= q.startIndex)
|
||||
continue;
|
||||
|
||||
int64_t timeElapsed = max(static_cast<int64_t>(timestamps[q.endIndex] - timestamps[q.startIndex]), (int64_t)0);
|
||||
double timeNS = timeElapsed * timestampPeriod;
|
||||
|
||||
FString out;
|
||||
out.Format("%s=%04.2f ms\n", q.name.GetChars(), timeNS / 1000000.0f);
|
||||
gpuStatOutput += out;
|
||||
}
|
||||
timeElapsedQueries.clear();
|
||||
mGroupStack.clear();
|
||||
|
||||
gpuStatActive = keepGpuStatActive;
|
||||
keepGpuStatActive = false;
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::Draw2D()
|
||||
{
|
||||
::Draw2D(twod, *mRenderState);
|
||||
}
|
||||
|
||||
VulkanCommandBuffer *VulkanFrameBuffer::GetTransferCommands()
|
||||
void VulkanFrameBuffer::WaitForCommands(bool finish)
|
||||
{
|
||||
if (!mTransferCommands)
|
||||
{
|
||||
mTransferCommands = mCommandPool->createBuffer();
|
||||
mTransferCommands->SetDebugName("VulkanFrameBuffer.mTransferCommands");
|
||||
mTransferCommands->begin();
|
||||
}
|
||||
return mTransferCommands.get();
|
||||
}
|
||||
|
||||
VulkanCommandBuffer *VulkanFrameBuffer::GetDrawCommands()
|
||||
{
|
||||
if (!mDrawCommands)
|
||||
{
|
||||
mDrawCommands = mCommandPool->createBuffer();
|
||||
mDrawCommands->SetDebugName("VulkanFrameBuffer.mDrawCommands");
|
||||
mDrawCommands->begin();
|
||||
}
|
||||
return mDrawCommands.get();
|
||||
mCommands->WaitForCommands(finish);
|
||||
}
|
||||
|
||||
unsigned int VulkanFrameBuffer::GetLightBufferBlockSize() const
|
||||
|
@ -787,18 +487,9 @@ void VulkanFrameBuffer::PrintStartupLog()
|
|||
Printf("Min. uniform buffer offset alignment: %" PRIu64 "\n", limits.minUniformBufferOffsetAlignment);
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::CreateFanToTrisIndexBuffer()
|
||||
void VulkanFrameBuffer::SetLevelMesh(hwrenderer::LevelMesh* mesh)
|
||||
{
|
||||
TArray<uint32_t> data;
|
||||
for (int i = 2; i < 1000; i++)
|
||||
{
|
||||
data.Push(0);
|
||||
data.Push(i - 1);
|
||||
data.Push(i);
|
||||
}
|
||||
|
||||
FanToTrisIndexBuffer.reset(CreateIndexBuffer());
|
||||
FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data(), BufferUsageType::Static);
|
||||
mRaytrace->SetLevelMesh(mesh);
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::UpdateShadowMap()
|
||||
|
@ -817,7 +508,6 @@ void VulkanFrameBuffer::ImageTransitionScene(bool unknown)
|
|||
mPostprocess->ImageTransitionScene(unknown);
|
||||
}
|
||||
|
||||
|
||||
FRenderState* VulkanFrameBuffer::RenderState()
|
||||
{
|
||||
return mRenderState.get();
|
||||
|
@ -832,3 +522,8 @@ void VulkanFrameBuffer::SetSceneRenderTarget(bool useSSAO)
|
|||
{
|
||||
mRenderState->SetRenderTarget(&GetBuffers()->SceneColor, GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
||||
}
|
||||
|
||||
bool VulkanFrameBuffer::RaytracingEnabled()
|
||||
{
|
||||
return vk_raytrace && device->SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,16 @@
|
|||
|
||||
struct FRenderViewpoint;
|
||||
class VkSamplerManager;
|
||||
class VkBufferManager;
|
||||
class VkTextureManager;
|
||||
class VkShaderManager;
|
||||
class VkCommandBufferManager;
|
||||
class VkDescriptorSetManager;
|
||||
class VkRenderPassManager;
|
||||
class VkRaytrace;
|
||||
class VkRenderState;
|
||||
class VkStreamBuffer;
|
||||
class VKDataBuffer;
|
||||
class VkHardwareDataBuffer;
|
||||
class VkHardwareTexture;
|
||||
class VkRenderBuffers;
|
||||
class VkPostprocess;
|
||||
|
@ -23,53 +28,22 @@ class VulkanFrameBuffer : public SystemBaseFrameBuffer
|
|||
|
||||
public:
|
||||
VulkanDevice *device;
|
||||
std::unique_ptr<VulkanSwapChain> swapChain;
|
||||
uint32_t presentImageIndex = 0xffffffff;
|
||||
bool cur_vsync;
|
||||
|
||||
VulkanCommandBuffer *GetTransferCommands();
|
||||
VulkanCommandBuffer *GetDrawCommands();
|
||||
VkCommandBufferManager* GetCommands() { return mCommands.get(); }
|
||||
VkShaderManager *GetShaderManager() { return mShaderManager.get(); }
|
||||
VkSamplerManager *GetSamplerManager() { return mSamplerManager.get(); }
|
||||
VkBufferManager* GetBufferManager() { return mBufferManager.get(); }
|
||||
VkTextureManager* GetTextureManager() { return mTextureManager.get(); }
|
||||
VkDescriptorSetManager* GetDescriptorSetManager() { return mDescriptorSetManager.get(); }
|
||||
VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); }
|
||||
VkRaytrace* GetRaytrace() { return mRaytrace.get(); }
|
||||
VkRenderState *GetRenderState() { return mRenderState.get(); }
|
||||
VkPostprocess *GetPostprocess() { return mPostprocess.get(); }
|
||||
VkRenderBuffers *GetBuffers() { return mActiveRenderBuffers; }
|
||||
FRenderState* RenderState() override;
|
||||
|
||||
void FlushCommands(bool finish, bool lastsubmit = false, bool uploadOnly = false);
|
||||
|
||||
unsigned int GetLightBufferBlockSize() const;
|
||||
|
||||
VKDataBuffer *ViewpointUBO = nullptr;
|
||||
VKDataBuffer *LightBufferSSO = nullptr;
|
||||
VkStreamBuffer *MatrixBuffer = nullptr;
|
||||
VkStreamBuffer *StreamBuffer = nullptr;
|
||||
|
||||
VKDataBuffer *LightNodes = nullptr;
|
||||
VKDataBuffer *LightLines = nullptr;
|
||||
VKDataBuffer *LightList = nullptr;
|
||||
|
||||
std::unique_ptr<IIndexBuffer> FanToTrisIndexBuffer;
|
||||
|
||||
class DeleteList
|
||||
{
|
||||
public:
|
||||
std::vector<std::unique_ptr<VulkanImage>> Images;
|
||||
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
|
||||
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
|
||||
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;
|
||||
std::vector<std::unique_ptr<VulkanCommandBuffer>> CommandBuffers;
|
||||
} FrameDeleteList;
|
||||
|
||||
struct
|
||||
{
|
||||
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
|
||||
size_t TotalSize = 0;
|
||||
} FrameTextureUpload;
|
||||
|
||||
VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevice *dev);
|
||||
~VulkanFrameBuffer();
|
||||
bool IsVulkan() override { return true; }
|
||||
|
@ -90,6 +64,7 @@ public:
|
|||
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||
void AmbientOccludeScene(float m5) override;
|
||||
void SetSceneRenderTarget(bool useSSAO) override;
|
||||
void SetLevelMesh(hwrenderer::LevelMesh* mesh) override;
|
||||
void UpdateShadowMap() override;
|
||||
void SetSaveBuffers(bool yes) override;
|
||||
void ImageTransitionScene(bool unknown) override;
|
||||
|
@ -106,62 +81,34 @@ public:
|
|||
|
||||
TArray<uint8_t> GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override;
|
||||
|
||||
bool GetVSync() { return mVSync; }
|
||||
void SetVSync(bool vsync) override;
|
||||
|
||||
void Draw2D() override;
|
||||
|
||||
void WaitForCommands(bool finish) override { WaitForCommands(finish, false); }
|
||||
void WaitForCommands(bool finish, bool uploadOnly);
|
||||
void WaitForCommands(bool finish) override;
|
||||
|
||||
void PushGroup(const FString &name);
|
||||
void PopGroup();
|
||||
void UpdateGpuStats();
|
||||
IntRect SetupTextureView(FCanvasTexture* tex);
|
||||
void FinishTextureView(FCanvasTexture* tex);
|
||||
bool RaytracingEnabled();
|
||||
|
||||
private:
|
||||
void RenderTextureView(FCanvasTexture* tex, std::function<void(IntRect &)> renderFunc) override;
|
||||
void PrintStartupLog();
|
||||
void CreateFanToTrisIndexBuffer();
|
||||
void CopyScreenToBuffer(int w, int h, uint8_t *data) override;
|
||||
void DeleteFrameObjects(bool uploadOnly = false);
|
||||
void FlushCommands(VulkanCommandBuffer **commands, size_t count, bool finish, bool lastsubmit);
|
||||
|
||||
std::unique_ptr<VkShaderManager> mShaderManager;
|
||||
std::unique_ptr<VkCommandBufferManager> mCommands;
|
||||
std::unique_ptr<VkBufferManager> mBufferManager;
|
||||
std::unique_ptr<VkSamplerManager> mSamplerManager;
|
||||
std::unique_ptr<VkTextureManager> mTextureManager;
|
||||
std::unique_ptr<VkShaderManager> mShaderManager;
|
||||
std::unique_ptr<VkRenderBuffers> mScreenBuffers;
|
||||
std::unique_ptr<VkRenderBuffers> mSaveBuffers;
|
||||
std::unique_ptr<VkPostprocess> mPostprocess;
|
||||
std::unique_ptr<VkDescriptorSetManager> mDescriptorSetManager;
|
||||
std::unique_ptr<VkRenderPassManager> mRenderPassManager;
|
||||
std::unique_ptr<VulkanCommandPool> mCommandPool;
|
||||
std::unique_ptr<VulkanCommandBuffer> mTransferCommands;
|
||||
std::unique_ptr<VkRaytrace> mRaytrace;
|
||||
std::unique_ptr<VkRenderState> mRenderState;
|
||||
|
||||
std::unique_ptr<VulkanCommandBuffer> mDrawCommands;
|
||||
|
||||
enum { maxConcurrentSubmitCount = 8};
|
||||
std::unique_ptr<VulkanSemaphore> mSubmitSemaphore[maxConcurrentSubmitCount];
|
||||
std::unique_ptr<VulkanFence> mSubmitFence[maxConcurrentSubmitCount];
|
||||
VkFence mSubmitWaitFences[maxConcurrentSubmitCount];
|
||||
int mNextSubmit = 0;
|
||||
|
||||
std::unique_ptr<VulkanSemaphore> mSwapChainImageAvailableSemaphore;
|
||||
std::unique_ptr<VulkanSemaphore> mRenderFinishedSemaphore;
|
||||
|
||||
VkRenderBuffers *mActiveRenderBuffers = nullptr;
|
||||
|
||||
struct TimestampQuery
|
||||
{
|
||||
FString name;
|
||||
uint32_t startIndex;
|
||||
uint32_t endIndex;
|
||||
};
|
||||
|
||||
enum { MaxTimestampQueries = 100 };
|
||||
std::unique_ptr<VulkanQueryPool> mTimestampQueryPool;
|
||||
int mNextTimestampQuery = 0;
|
||||
std::vector<size_t> mGroupStack;
|
||||
std::vector<TimestampQuery> timeElapsedQueries;
|
||||
bool mVSync = false;
|
||||
};
|
||||
|
||||
inline VulkanFrameBuffer *GetVulkanFrameBuffer() { return static_cast<VulkanFrameBuffer*>(screen); }
|
||||
|
|
|
@ -20,71 +20,54 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#include "vk_buffers.h"
|
||||
#include "vk_hwbuffer.h"
|
||||
#include "vk_builders.h"
|
||||
#include "vk_framebuffer.h"
|
||||
#include "vk_commandbuffer.h"
|
||||
#include "vk_buffer.h"
|
||||
#include "vulkan/renderer/vk_renderstate.h"
|
||||
#include "vulkan/renderer/vk_renderpass.h"
|
||||
#include "vulkan/renderer/vk_descriptorset.h"
|
||||
#include "engineerrors.h"
|
||||
|
||||
VKBuffer *VKBuffer::First = nullptr;
|
||||
|
||||
VKBuffer::VKBuffer()
|
||||
VkHardwareBuffer::VkHardwareBuffer(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
Next = First;
|
||||
First = this;
|
||||
if (Next) Next->Prev = this;
|
||||
fb->GetBufferManager()->AddBuffer(this);
|
||||
}
|
||||
|
||||
VKBuffer::~VKBuffer()
|
||||
VkHardwareBuffer::~VkHardwareBuffer()
|
||||
{
|
||||
if (Next) Next->Prev = Prev;
|
||||
if (Prev) Prev->Next = Next;
|
||||
else First = Next;
|
||||
if (fb)
|
||||
fb->GetBufferManager()->RemoveBuffer(this);
|
||||
}
|
||||
|
||||
if (mBuffer && map)
|
||||
mBuffer->Unmap();
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
void VkHardwareBuffer::Reset()
|
||||
{
|
||||
if (fb)
|
||||
{
|
||||
if (mBuffer && map)
|
||||
{
|
||||
mBuffer->Unmap();
|
||||
map = nullptr;
|
||||
}
|
||||
if (mBuffer)
|
||||
fb->FrameDeleteList.Buffers.push_back(std::move(mBuffer));
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(mBuffer));
|
||||
if (mStaging)
|
||||
fb->FrameDeleteList.Buffers.push_back(std::move(mStaging));
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(mStaging));
|
||||
}
|
||||
}
|
||||
|
||||
void VKBuffer::ResetAll()
|
||||
void VkHardwareBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
|
||||
{
|
||||
for (VKBuffer *cur = VKBuffer::First; cur; cur = cur->Next)
|
||||
cur->Reset();
|
||||
}
|
||||
|
||||
void VKBuffer::Reset()
|
||||
{
|
||||
if (mBuffer && map)
|
||||
mBuffer->Unmap();
|
||||
mBuffer.reset();
|
||||
mStaging.reset();
|
||||
}
|
||||
|
||||
void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
size_t bufsize = max(size, (size_t)16); // For supporting zero byte buffers
|
||||
|
||||
// If SetData is called multiple times we have to keep the old buffers alive as there might still be draw commands referencing them
|
||||
if (mBuffer)
|
||||
{
|
||||
fb->FrameDeleteList.Buffers.push_back(std::move(mBuffer));
|
||||
mBuffer = {};
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(mBuffer));
|
||||
}
|
||||
if (mStaging)
|
||||
{
|
||||
fb->FrameDeleteList.Buffers.push_back(std::move(mStaging));
|
||||
mStaging = {};
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(mStaging));
|
||||
}
|
||||
|
||||
if (usage == BufferUsageType::Static || usage == BufferUsageType::Stream)
|
||||
|
@ -93,15 +76,17 @@ void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
|
|||
|
||||
mPersistent = false;
|
||||
|
||||
BufferBuilder builder;
|
||||
builder.setUsage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | mBufferType, VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
builder.setSize(bufsize);
|
||||
mBuffer = builder.create(fb->device);
|
||||
mBuffer = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT | mBufferType, VMA_MEMORY_USAGE_GPU_ONLY)
|
||||
.Size(bufsize)
|
||||
.DebugName(usage == BufferUsageType::Static ? "VkHardwareBuffer.Static" : "VkHardwareBuffer.Stream")
|
||||
.Create(fb->device);
|
||||
|
||||
BufferBuilder builder2;
|
||||
builder2.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
builder2.setSize(bufsize);
|
||||
mStaging = builder2.create(fb->device);
|
||||
mStaging = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.Size(bufsize)
|
||||
.DebugName(usage == BufferUsageType::Static ? "VkHardwareBuffer.Staging.Static" : "VkHardwareBuffer.Staging.Stream")
|
||||
.Create(fb->device);
|
||||
|
||||
if (data)
|
||||
{
|
||||
|
@ -110,19 +95,20 @@ void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
|
|||
mStaging->Unmap();
|
||||
}
|
||||
|
||||
fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get());
|
||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get());
|
||||
}
|
||||
else if (usage == BufferUsageType::Persistent)
|
||||
{
|
||||
mPersistent = true;
|
||||
|
||||
BufferBuilder builder;
|
||||
builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
builder.setMemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
builder.setSize(bufsize);
|
||||
mBuffer = builder.create(fb->device);
|
||||
mBuffer = BufferBuilder()
|
||||
.Usage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
.MemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
.Size(bufsize)
|
||||
.DebugName("VkHardwareBuffer.Persistent")
|
||||
.Create(fb->device);
|
||||
|
||||
map = mBuffer->Map(0, bufsize);
|
||||
if (data)
|
||||
|
@ -132,13 +118,14 @@ void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
|
|||
{
|
||||
mPersistent = false;
|
||||
|
||||
BufferBuilder builder;
|
||||
builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, 0);
|
||||
builder.setMemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
builder.setSize(bufsize);
|
||||
mBuffer = builder.create(fb->device);
|
||||
mBuffer = BufferBuilder()
|
||||
.Usage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, 0)
|
||||
.MemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
.Size(bufsize)
|
||||
.DebugName("VkHardwareBuffer.Mappable")
|
||||
.Create(fb->device);
|
||||
|
||||
if (data)
|
||||
{
|
||||
|
@ -151,18 +138,17 @@ void VKBuffer::SetData(size_t size, const void *data, BufferUsageType usage)
|
|||
buffersize = size;
|
||||
}
|
||||
|
||||
void VKBuffer::SetSubData(size_t offset, size_t size, const void *data)
|
||||
void VkHardwareBuffer::SetSubData(size_t offset, size_t size, const void *data)
|
||||
{
|
||||
size = max(size, (size_t)16); // For supporting zero byte buffers
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
if (mStaging)
|
||||
{
|
||||
void *dst = mStaging->Map(offset, size);
|
||||
memcpy(dst, data, size);
|
||||
mStaging->Unmap();
|
||||
|
||||
fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get(), offset, offset, size);
|
||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get(), offset, offset, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -172,12 +158,10 @@ void VKBuffer::SetSubData(size_t offset, size_t size, const void *data)
|
|||
}
|
||||
}
|
||||
|
||||
void VKBuffer::Resize(size_t newsize)
|
||||
void VkHardwareBuffer::Resize(size_t newsize)
|
||||
{
|
||||
newsize = max(newsize, (size_t)16); // For supporting zero byte buffers
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
// Grab old buffer
|
||||
size_t oldsize = buffersize;
|
||||
std::unique_ptr<VulkanBuffer> oldBuffer = std::move(mBuffer);
|
||||
|
@ -185,33 +169,33 @@ void VKBuffer::Resize(size_t newsize)
|
|||
map = nullptr;
|
||||
|
||||
// Create new buffer
|
||||
BufferBuilder builder;
|
||||
builder.setUsage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
builder.setMemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
builder.setSize(newsize);
|
||||
mBuffer = builder.create(fb->device);
|
||||
mBuffer = BufferBuilder()
|
||||
.Usage(mBufferType, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
.MemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
.Size(newsize)
|
||||
.DebugName("VkHardwareBuffer.Resized")
|
||||
.Create(fb->device);
|
||||
buffersize = newsize;
|
||||
|
||||
// Transfer data from old to new
|
||||
fb->GetTransferCommands()->copyBuffer(oldBuffer.get(), mBuffer.get(), 0, 0, oldsize);
|
||||
fb->WaitForCommands(false);
|
||||
fb->GetCommands()->GetTransferCommands()->copyBuffer(oldBuffer.get(), mBuffer.get(), 0, 0, oldsize);
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(oldBuffer));
|
||||
fb->GetCommands()->WaitForCommands(false);
|
||||
fb->GetDescriptorSetManager()->UpdateHWBufferSet(); // Old buffer may be part of the bound descriptor set
|
||||
|
||||
// Fetch pointer to new buffer
|
||||
map = mBuffer->Map(0, newsize);
|
||||
|
||||
// Old buffer may be part of the dynamic set
|
||||
fb->GetRenderPassManager()->UpdateDynamicSet();
|
||||
}
|
||||
|
||||
void VKBuffer::Map()
|
||||
void VkHardwareBuffer::Map()
|
||||
{
|
||||
if (!mPersistent)
|
||||
map = mBuffer->Map(0, mBuffer->size);
|
||||
}
|
||||
|
||||
void VKBuffer::Unmap()
|
||||
void VkHardwareBuffer::Unmap()
|
||||
{
|
||||
if (!mPersistent)
|
||||
{
|
||||
|
@ -220,7 +204,7 @@ void VKBuffer::Unmap()
|
|||
}
|
||||
}
|
||||
|
||||
void *VKBuffer::Lock(unsigned int size)
|
||||
void *VkHardwareBuffer::Lock(unsigned int size)
|
||||
{
|
||||
size = max(size, (unsigned int)16); // For supporting zero byte buffers
|
||||
|
||||
|
@ -238,7 +222,7 @@ void *VKBuffer::Lock(unsigned int size)
|
|||
return map;
|
||||
}
|
||||
|
||||
void VKBuffer::Unlock()
|
||||
void VkHardwareBuffer::Unlock()
|
||||
{
|
||||
if (!mBuffer)
|
||||
{
|
||||
|
@ -255,15 +239,15 @@ void VKBuffer::Unlock()
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void VKVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs)
|
||||
void VkHardwareVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs)
|
||||
{
|
||||
VertexFormat = GetVulkanFrameBuffer()->GetRenderPassManager()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs);
|
||||
VertexFormat = fb->GetRenderPassManager()->GetVertexFormat(numBindingPoints, numAttributes, stride, attrs);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void VKDataBuffer::BindRange(FRenderState* state, size_t start, size_t length)
|
||||
void VkHardwareDataBuffer::BindRange(FRenderState* state, size_t start, size_t length)
|
||||
{
|
||||
static_cast<VkRenderState*>(state)->Bind(bindingpoint, (uint32_t)start);
|
||||
}
|
|
@ -3,20 +3,22 @@
|
|||
#include "hwrenderer/data/buffers.h"
|
||||
#include "vk_objects.h"
|
||||
#include "tarray.h"
|
||||
#include <list>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// silence bogus warning C4250: 'VKVertexBuffer': inherits 'VKBuffer::VKBuffer::SetData' via dominance
|
||||
// silence bogus warning C4250: 'VkHardwareVertexBuffer': inherits 'VkHardwareBuffer::VkHardwareBuffer::SetData' via dominance
|
||||
// According to internet infos, the warning is erroneously emitted in this case.
|
||||
#pragma warning(disable:4250)
|
||||
#endif
|
||||
|
||||
class VKBuffer : virtual public IBuffer
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkHardwareBuffer : virtual public IBuffer
|
||||
{
|
||||
public:
|
||||
VKBuffer();
|
||||
~VKBuffer();
|
||||
VkHardwareBuffer(VulkanFrameBuffer* fb);
|
||||
~VkHardwareBuffer();
|
||||
|
||||
static void ResetAll();
|
||||
void Reset();
|
||||
|
||||
void SetData(size_t size, const void *data, BufferUsageType usage) override;
|
||||
|
@ -29,37 +31,35 @@ public:
|
|||
void *Lock(unsigned int size) override;
|
||||
void Unlock() override;
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
std::list<VkHardwareBuffer*>::iterator it;
|
||||
|
||||
VkBufferUsageFlags mBufferType = 0;
|
||||
std::unique_ptr<VulkanBuffer> mBuffer;
|
||||
std::unique_ptr<VulkanBuffer> mStaging;
|
||||
bool mPersistent = false;
|
||||
TArray<uint8_t> mStaticUpload;
|
||||
|
||||
private:
|
||||
static VKBuffer *First;
|
||||
VKBuffer *Prev = nullptr;
|
||||
VKBuffer *Next = nullptr;
|
||||
};
|
||||
|
||||
class VKVertexBuffer : public IVertexBuffer, public VKBuffer
|
||||
class VkHardwareVertexBuffer : public IVertexBuffer, public VkHardwareBuffer
|
||||
{
|
||||
public:
|
||||
VKVertexBuffer() { mBufferType = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; }
|
||||
VkHardwareVertexBuffer(VulkanFrameBuffer* fb) : VkHardwareBuffer(fb) { mBufferType = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; }
|
||||
void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override;
|
||||
|
||||
int VertexFormat = -1;
|
||||
};
|
||||
|
||||
class VKIndexBuffer : public IIndexBuffer, public VKBuffer
|
||||
class VkHardwareIndexBuffer : public IIndexBuffer, public VkHardwareBuffer
|
||||
{
|
||||
public:
|
||||
VKIndexBuffer() { mBufferType = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; }
|
||||
VkHardwareIndexBuffer(VulkanFrameBuffer* fb) : VkHardwareBuffer(fb) { mBufferType = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; }
|
||||
};
|
||||
|
||||
class VKDataBuffer : public IDataBuffer, public VKBuffer
|
||||
class VkHardwareDataBuffer : public IDataBuffer, public VkHardwareBuffer
|
||||
{
|
||||
public:
|
||||
VKDataBuffer(int bindingpoint, bool ssbo, bool needresize) : bindingpoint(bindingpoint)
|
||||
VkHardwareDataBuffer(VulkanFrameBuffer* fb, int bindingpoint, bool ssbo, bool needresize) : VkHardwareBuffer(fb), bindingpoint(bindingpoint)
|
||||
{
|
||||
mBufferType = ssbo ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
if (needresize)
|
|
@ -44,7 +44,19 @@ public:
|
|||
VulkanBuffer(VulkanDevice *device, VkBuffer buffer, VmaAllocation allocation, size_t size);
|
||||
~VulkanBuffer();
|
||||
|
||||
void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER); }
|
||||
VkDeviceAddress GetDeviceAddress()
|
||||
{
|
||||
VkBufferDeviceAddressInfo info = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO };
|
||||
info.buffer = buffer;
|
||||
return vkGetBufferDeviceAddress(device->device, &info);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void SetDebugName(const char* name) { debugName = name; device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER); }
|
||||
std::string debugName;
|
||||
#else
|
||||
void SetDebugName(const char* name) { device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER); }
|
||||
#endif
|
||||
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
|
@ -174,7 +186,12 @@ public:
|
|||
VulkanDescriptorSet(VulkanDevice *device, VulkanDescriptorPool *pool, VkDescriptorSet set);
|
||||
~VulkanDescriptorSet();
|
||||
|
||||
void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)set, VK_OBJECT_TYPE_DESCRIPTOR_SET); }
|
||||
#ifdef _DEBUG
|
||||
void SetDebugName(const char* name) { debugName = name; device->SetDebugObjectName(name, (uint64_t)set, VK_OBJECT_TYPE_DESCRIPTOR_SET); }
|
||||
std::string debugName;
|
||||
#else
|
||||
void SetDebugName(const char* name) { device->SetDebugObjectName(name, (uint64_t)set, VK_OBJECT_TYPE_DESCRIPTOR_SET); }
|
||||
#endif
|
||||
|
||||
VulkanDevice *device;
|
||||
VulkanDescriptorPool *pool;
|
||||
|
@ -191,7 +208,12 @@ public:
|
|||
VulkanDescriptorPool(VulkanDevice *device, VkDescriptorPool pool);
|
||||
~VulkanDescriptorPool();
|
||||
|
||||
void SetDebugName(const char *name) { device->SetDebugObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL); }
|
||||
#ifdef _DEBUG
|
||||
void SetDebugName(const char* name) { debugName = name; device->SetDebugObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL); }
|
||||
std::string debugName;
|
||||
#else
|
||||
void SetDebugName(const char* name) { device->SetDebugObjectName(name, (uint64_t)pool, VK_OBJECT_TYPE_DESCRIPTOR_POOL); }
|
||||
#endif
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> tryAllocate(VulkanDescriptorSetLayout *layout);
|
||||
std::unique_ptr<VulkanDescriptorSet> allocate(VulkanDescriptorSetLayout *layout);
|
||||
|
@ -222,6 +244,29 @@ private:
|
|||
VulkanQueryPool &operator=(const VulkanQueryPool &) = delete;
|
||||
};
|
||||
|
||||
class VulkanAccelerationStructure
|
||||
{
|
||||
public:
|
||||
VulkanAccelerationStructure(VulkanDevice* device, VkAccelerationStructureKHR accelstruct);
|
||||
~VulkanAccelerationStructure();
|
||||
|
||||
VkDeviceAddress GetDeviceAddress()
|
||||
{
|
||||
VkAccelerationStructureDeviceAddressInfoKHR addressInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR };
|
||||
addressInfo.accelerationStructure = accelstruct;
|
||||
return vkGetAccelerationStructureDeviceAddressKHR(device->device, &addressInfo);
|
||||
}
|
||||
|
||||
void SetDebugName(const char* name) { device->SetDebugObjectName(name, (uint64_t)accelstruct, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR); }
|
||||
|
||||
VulkanDevice* device;
|
||||
VkAccelerationStructureKHR accelstruct;
|
||||
|
||||
private:
|
||||
VulkanAccelerationStructure(const VulkanAccelerationStructure&) = delete;
|
||||
VulkanAccelerationStructure& operator=(const VulkanAccelerationStructure&) = delete;
|
||||
};
|
||||
|
||||
class VulkanPipeline
|
||||
{
|
||||
public:
|
||||
|
@ -355,6 +400,10 @@ public:
|
|||
void endRenderPass();
|
||||
void executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
|
||||
|
||||
void buildAccelerationStructures(uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos);
|
||||
void traceRays(const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth);
|
||||
void writeAccelerationStructuresProperties(uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
|
||||
|
||||
void debugFullPipelineBarrier();
|
||||
|
||||
VkCommandBuffer buffer = nullptr;
|
||||
|
@ -879,6 +928,21 @@ inline void VulkanCommandBuffer::executeCommands(uint32_t commandBufferCount, co
|
|||
vkCmdExecuteCommands(buffer, commandBufferCount, pCommandBuffers);
|
||||
}
|
||||
|
||||
inline void VulkanCommandBuffer::buildAccelerationStructures(uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos)
|
||||
{
|
||||
vkCmdBuildAccelerationStructuresKHR(buffer, infoCount, pInfos, ppBuildRangeInfos);
|
||||
}
|
||||
|
||||
inline void VulkanCommandBuffer::traceRays(const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth)
|
||||
{
|
||||
vkCmdTraceRaysKHR(buffer, pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth);
|
||||
}
|
||||
|
||||
inline void VulkanCommandBuffer::writeAccelerationStructuresProperties(uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery)
|
||||
{
|
||||
vkCmdWriteAccelerationStructuresPropertiesKHR(buffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery);
|
||||
}
|
||||
|
||||
inline void VulkanCommandBuffer::SetDebugName(const char *name)
|
||||
{
|
||||
pool->device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_COMMAND_BUFFER);
|
||||
|
@ -1035,6 +1099,18 @@ inline VulkanSampler::~VulkanSampler()
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline VulkanAccelerationStructure::VulkanAccelerationStructure(VulkanDevice* device, VkAccelerationStructureKHR accelstruct)
|
||||
: device(device), accelstruct(accelstruct)
|
||||
{
|
||||
}
|
||||
|
||||
inline VulkanAccelerationStructure::~VulkanAccelerationStructure()
|
||||
{
|
||||
vkDestroyAccelerationStructureKHR(device->device, accelstruct, nullptr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline VulkanPipeline::VulkanPipeline(VulkanDevice *device, VkPipeline pipeline) : device(device), pipeline(pipeline)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -41,12 +41,11 @@ VulkanSwapChain::~VulkanSwapChain()
|
|||
ReleaseResources();
|
||||
}
|
||||
|
||||
uint32_t VulkanSwapChain::AcquireImage(int width, int height, VulkanSemaphore *semaphore, VulkanFence *fence)
|
||||
uint32_t VulkanSwapChain::AcquireImage(int width, int height, bool vsync, VulkanSemaphore *semaphore, VulkanFence *fence)
|
||||
{
|
||||
auto vsync = static_cast<VulkanFrameBuffer*>(screen)->cur_vsync;
|
||||
if (lastSwapWidth != width || lastSwapHeight != height || lastVsync != vsync || lastHdr != vk_hdr || !swapChain)
|
||||
{
|
||||
Recreate();
|
||||
Recreate(vsync);
|
||||
lastSwapWidth = width;
|
||||
lastSwapHeight = height;
|
||||
lastVsync = vsync;
|
||||
|
@ -77,7 +76,7 @@ uint32_t VulkanSwapChain::AcquireImage(int width, int height, VulkanSemaphore *s
|
|||
}
|
||||
else if (result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
Recreate();
|
||||
Recreate(vsync);
|
||||
}
|
||||
else if (result == VK_NOT_READY || result == VK_TIMEOUT)
|
||||
{
|
||||
|
@ -133,13 +132,13 @@ void VulkanSwapChain::QueuePresent(uint32_t imageIndex, VulkanSemaphore *semapho
|
|||
}
|
||||
}
|
||||
|
||||
void VulkanSwapChain::Recreate()
|
||||
void VulkanSwapChain::Recreate(bool vsync)
|
||||
{
|
||||
ReleaseViews();
|
||||
swapChainImages.clear();
|
||||
|
||||
VkSwapchainKHR oldSwapChain = swapChain;
|
||||
CreateSwapChain(oldSwapChain);
|
||||
CreateSwapChain(vsync, oldSwapChain);
|
||||
if (oldSwapChain)
|
||||
vkDestroySwapchainKHR(device->device, oldSwapChain, nullptr);
|
||||
|
||||
|
@ -150,10 +149,10 @@ void VulkanSwapChain::Recreate()
|
|||
}
|
||||
}
|
||||
|
||||
bool VulkanSwapChain::CreateSwapChain(VkSwapchainKHR oldSwapChain)
|
||||
bool VulkanSwapChain::CreateSwapChain(bool vsync, VkSwapchainKHR oldSwapChain)
|
||||
{
|
||||
SelectFormat();
|
||||
SelectPresentMode();
|
||||
SelectPresentMode(vsync);
|
||||
|
||||
int width, height;
|
||||
I_GetVulkanDrawableSize(&width, &height);
|
||||
|
@ -301,7 +300,7 @@ void VulkanSwapChain::SelectFormat()
|
|||
swapChainFormat = surfaceFormats.front();
|
||||
}
|
||||
|
||||
void VulkanSwapChain::SelectPresentMode()
|
||||
void VulkanSwapChain::SelectPresentMode(bool vsync)
|
||||
{
|
||||
std::vector<VkPresentModeKHR> presentModes = GetPresentModes();
|
||||
|
||||
|
@ -309,7 +308,6 @@ void VulkanSwapChain::SelectPresentMode()
|
|||
VulkanError("No surface present modes supported");
|
||||
|
||||
swapChainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
auto vsync = static_cast<VulkanFrameBuffer*>(screen)->cur_vsync;
|
||||
if (vsync)
|
||||
{
|
||||
bool supportsFifoRelaxed = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_FIFO_RELAXED_KHR) != presentModes.end();
|
||||
|
|
|
@ -12,11 +12,9 @@ public:
|
|||
VulkanSwapChain(VulkanDevice *device);
|
||||
~VulkanSwapChain();
|
||||
|
||||
uint32_t AcquireImage(int width, int height, VulkanSemaphore *semaphore = nullptr, VulkanFence *fence = nullptr);
|
||||
uint32_t AcquireImage(int width, int height, bool vsync, VulkanSemaphore *semaphore = nullptr, VulkanFence *fence = nullptr);
|
||||
void QueuePresent(uint32_t imageIndex, VulkanSemaphore *semaphore = nullptr);
|
||||
|
||||
void Recreate();
|
||||
|
||||
bool IsHdrModeActive() const;
|
||||
|
||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||
|
@ -30,9 +28,10 @@ public:
|
|||
VkExtent2D actualExtent;
|
||||
|
||||
private:
|
||||
void Recreate(bool vsync);
|
||||
void SelectFormat();
|
||||
void SelectPresentMode();
|
||||
bool CreateSwapChain(VkSwapchainKHR oldSwapChain = VK_NULL_HANDLE);
|
||||
void SelectPresentMode(bool vsync);
|
||||
bool CreateSwapChain(bool vsync, VkSwapchainKHR oldSwapChain = VK_NULL_HANDLE);
|
||||
void CreateViews();
|
||||
void GetImages();
|
||||
void ReleaseResources();
|
||||
|
|
|
@ -28,41 +28,30 @@
|
|||
#include "vulkan/system/vk_objects.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/textures/vk_samplers.h"
|
||||
#include "vulkan/renderer/vk_renderpass.h"
|
||||
#include "vulkan/textures/vk_renderbuffers.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "vulkan/renderer/vk_descriptorset.h"
|
||||
#include "vulkan/renderer/vk_postprocess.h"
|
||||
#include "vulkan/renderer/vk_renderbuffers.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vk_hwtexture.h"
|
||||
|
||||
VkHardwareTexture *VkHardwareTexture::First = nullptr;
|
||||
|
||||
VkHardwareTexture::VkHardwareTexture(int numchannels)
|
||||
VkHardwareTexture::VkHardwareTexture(VulkanFrameBuffer* fb, int numchannels) : fb(fb)
|
||||
{
|
||||
mTexelsize = numchannels;
|
||||
Next = First;
|
||||
First = this;
|
||||
if (Next) Next->Prev = this;
|
||||
fb->GetTextureManager()->AddTexture(this);
|
||||
}
|
||||
|
||||
VkHardwareTexture::~VkHardwareTexture()
|
||||
{
|
||||
if (Next) Next->Prev = Prev;
|
||||
if (Prev) Prev->Next = Next;
|
||||
else First = Next;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void VkHardwareTexture::ResetAll()
|
||||
{
|
||||
for (VkHardwareTexture *cur = VkHardwareTexture::First; cur; cur = cur->Next)
|
||||
cur->Reset();
|
||||
if (fb)
|
||||
fb->GetTextureManager()->RemoveTexture(this);
|
||||
}
|
||||
|
||||
void VkHardwareTexture::Reset()
|
||||
{
|
||||
if (auto fb = GetVulkanFrameBuffer())
|
||||
if (fb)
|
||||
{
|
||||
if (mappedSWFB)
|
||||
{
|
||||
|
@ -70,15 +59,8 @@ void VkHardwareTexture::Reset()
|
|||
mappedSWFB = nullptr;
|
||||
}
|
||||
|
||||
auto &deleteList = fb->FrameDeleteList;
|
||||
if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
|
||||
if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View));
|
||||
for (auto &it : mImage.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
|
||||
if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
|
||||
if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View));
|
||||
for (auto &it : mDepthStencil.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second));
|
||||
mImage.reset();
|
||||
mDepthStencil.reset();
|
||||
mImage.Reset(fb);
|
||||
mDepthStencil.Reset(fb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,29 +77,28 @@ VkTextureImage *VkHardwareTexture::GetDepthStencil(FTexture *tex)
|
|||
{
|
||||
if (!mDepthStencil.View)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkFormat format = fb->GetBuffers()->SceneDepthStencilFormat;
|
||||
int w = tex->GetWidth();
|
||||
int h = tex->GetHeight();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(w, h);
|
||||
builder.setSamples(VK_SAMPLE_COUNT_1_BIT);
|
||||
builder.setFormat(format);
|
||||
builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
||||
mDepthStencil.Image = builder.create(fb->device);
|
||||
mDepthStencil.Image->SetDebugName("VkHardwareTexture.DepthStencil");
|
||||
mDepthStencil.Image = ImageBuilder()
|
||||
.Size(w, h)
|
||||
.Samples(VK_SAMPLE_COUNT_1_BIT)
|
||||
.Format(format)
|
||||
.Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
.DebugName("VkHardwareTexture.DepthStencil")
|
||||
.Create(fb->device);
|
||||
|
||||
mDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(mDepthStencil.Image.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
mDepthStencil.View = viewbuilder.create(fb->device);
|
||||
mDepthStencil.View->SetDebugName("VkHardwareTexture.DepthStencilView");
|
||||
mDepthStencil.View = ImageViewBuilder()
|
||||
.Image(mDepthStencil.Image.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
.DebugName("VkHardwareTexture.DepthStencilView")
|
||||
.Create(fb->device);
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&mDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true);
|
||||
barrier.execute(fb->GetTransferCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&mDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
}
|
||||
return &mDepthStencil;
|
||||
}
|
||||
|
@ -132,29 +113,25 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
|||
}
|
||||
else
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
int w = tex->GetWidth();
|
||||
int h = tex->GetHeight();
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(w, h);
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
mImage.Image = imgbuilder.create(fb->device);
|
||||
mImage.Image->SetDebugName("VkHardwareTexture.mImage");
|
||||
mImage.Image = ImageBuilder()
|
||||
.Format(format)
|
||||
.Size(w, h)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkHardwareTexture.mImage")
|
||||
.Create(fb->device);
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(mImage.Image.get(), format);
|
||||
mImage.View = viewbuilder.create(fb->device);
|
||||
mImage.View->SetDebugName("VkHardwareTexture.mImageView");
|
||||
mImage.View = ImageViewBuilder()
|
||||
.Image(mImage.Image.get(), format)
|
||||
.DebugName("VkHardwareTexture.mImageView")
|
||||
.Create(fb->device);
|
||||
|
||||
auto cmdbuffer = fb->GetTransferCommands();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
|
||||
imageTransition.execute(cmdbuffer);
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,37 +140,35 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
if (w <= 0 || h <= 0)
|
||||
throw CVulkanError("Trying to create zero size texture");
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
int totalSize = w * h * pixelsize;
|
||||
|
||||
BufferBuilder bufbuilder;
|
||||
bufbuilder.setSize(totalSize);
|
||||
bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
std::unique_ptr<VulkanBuffer> stagingBuffer = bufbuilder.create(fb->device);
|
||||
stagingBuffer->SetDebugName("VkHardwareTexture.mStagingBuffer");
|
||||
auto stagingBuffer = BufferBuilder()
|
||||
.Size(totalSize)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("VkHardwareTexture.mStagingBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
uint8_t *data = (uint8_t*)stagingBuffer->Map(0, totalSize);
|
||||
memcpy(data, pixels, totalSize);
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(w, h, !mipmap ? 1 : GetMipLevels(w, h));
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
mImage.Image = imgbuilder.create(fb->device);
|
||||
mImage.Image->SetDebugName("VkHardwareTexture.mImage");
|
||||
mImage.Image = ImageBuilder()
|
||||
.Format(format)
|
||||
.Size(w, h, !mipmap ? 1 : GetMipLevels(w, h))
|
||||
.Usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkHardwareTexture.mImage")
|
||||
.Create(fb->device);
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(mImage.Image.get(), format);
|
||||
mImage.View = viewbuilder.create(fb->device);
|
||||
mImage.View->SetDebugName("VkHardwareTexture.mImageView");
|
||||
mImage.View = ImageViewBuilder()
|
||||
.Image(mImage.Image.get(), format)
|
||||
.DebugName("VkHardwareTexture.mImageView")
|
||||
.Create(fb->device);
|
||||
|
||||
auto cmdbuffer = fb->GetTransferCommands();
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||
imageTransition.execute(cmdbuffer);
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
@ -203,14 +178,12 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
|
|||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
fb->FrameTextureUpload.Buffers.push_back(std::move(stagingBuffer));
|
||||
|
||||
if (mipmap) mImage.GenerateMipmaps(cmdbuffer);
|
||||
|
||||
// If we queued more than 64 MB of data already: wait until the uploads finish before continuing
|
||||
fb->FrameTextureUpload.TotalSize += totalSize;
|
||||
if (fb->FrameTextureUpload.TotalSize > 64 * 1024 * 1024)
|
||||
fb->WaitForCommands(false, true);
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
if (fb->GetCommands()->TransferDeleteList->TotalSize > 64 * 1024 * 1024)
|
||||
fb->GetCommands()->WaitForCommands(false, true);
|
||||
}
|
||||
|
||||
int VkHardwareTexture::GetMipLevels(int w, int h)
|
||||
|
@ -234,33 +207,30 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
|||
|
||||
if (!mImage.Image)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkFormat format = texelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM;
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
VkDeviceSize allocatedBytes = 0;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(w, h);
|
||||
imgbuilder.setLinearTiling();
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
|
||||
imgbuilder.setMemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
mImage.Image = imgbuilder.create(fb->device, &allocatedBytes);
|
||||
mImage.Image->SetDebugName("VkHardwareTexture.mImage");
|
||||
mImage.Image = ImageBuilder()
|
||||
.Format(format)
|
||||
.Size(w, h)
|
||||
.LinearTiling()
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
.MemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
.DebugName("VkHardwareTexture.mImage")
|
||||
.Create(fb->device, &allocatedBytes);
|
||||
|
||||
mTexelsize = texelsize;
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(mImage.Image.get(), format);
|
||||
mImage.View = viewbuilder.create(fb->device);
|
||||
mImage.View->SetDebugName("VkHardwareTexture.mImageView");
|
||||
mImage.View = ImageViewBuilder()
|
||||
.Image(mImage.Image.get(), format)
|
||||
.DebugName("VkHardwareTexture.mImageView")
|
||||
.Create(fb->device);
|
||||
|
||||
auto cmdbuffer = fb->GetTransferCommands();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_GENERAL, true);
|
||||
imageTransition.execute(cmdbuffer);
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_GENERAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
|
||||
bufferpitch = int(allocatedBytes / h / texelsize);
|
||||
}
|
||||
|
@ -283,22 +253,21 @@ unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int
|
|||
|
||||
void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(w, h);
|
||||
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
mImage.Image = imgbuilder.create(fb->device);
|
||||
mImage.Image->SetDebugName(name);
|
||||
mImage.Image = ImageBuilder()
|
||||
.Format(format)
|
||||
.Size(w, h)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY)
|
||||
.DebugName(name)
|
||||
.Create(fb->device);
|
||||
|
||||
mTexelsize = 4;
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setImage(mImage.Image.get(), format);
|
||||
mImage.View = viewbuilder.create(fb->device);
|
||||
mImage.View->SetDebugName(name);
|
||||
mImage.View = ImageViewBuilder()
|
||||
.Image(mImage.Image.get(), format)
|
||||
.DebugName(name)
|
||||
.Create(fb->device);
|
||||
|
||||
if (fb->GetBuffers()->GetWidth() > 0 && fb->GetBuffers()->GetHeight() > 0)
|
||||
{
|
||||
|
@ -309,9 +278,9 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
|
|||
// hwrenderer asked image data from a frame buffer that was never written into. Let's give it that..
|
||||
// (ideally the hwrenderer wouldn't do this, but the calling code is too complex for me to fix)
|
||||
|
||||
VkImageTransition transition0;
|
||||
transition0.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||
transition0.execute(fb->GetTransferCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
|
||||
VkImageSubresourceRange range = {};
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
@ -323,56 +292,38 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
|
|||
value.float32[1] = 0.0f;
|
||||
value.float32[2] = 0.0f;
|
||||
value.float32[3] = 1.0f;
|
||||
fb->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range);
|
||||
fb->GetCommands()->GetTransferCommands()->clearColorImage(mImage.Image->image, mImage.Layout, &value, 1, &range);
|
||||
|
||||
VkImageTransition transition1;
|
||||
transition1.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||
transition1.execute(fb->GetTransferCommands());
|
||||
VkImageTransition()
|
||||
.AddImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkMaterial* VkMaterial::First = nullptr;
|
||||
|
||||
VkMaterial::VkMaterial(FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags)
|
||||
VkMaterial::VkMaterial(VulkanFrameBuffer* fb, FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags), fb(fb)
|
||||
{
|
||||
Next = First;
|
||||
First = this;
|
||||
if (Next) Next->Prev = this;
|
||||
fb->GetDescriptorSetManager()->AddMaterial(this);
|
||||
}
|
||||
|
||||
VkMaterial::~VkMaterial()
|
||||
{
|
||||
if (Next) Next->Prev = Prev;
|
||||
if (Prev) Prev->Next = Next;
|
||||
else First = Next;
|
||||
|
||||
DeleteDescriptors();
|
||||
if (fb)
|
||||
fb->GetDescriptorSetManager()->RemoveMaterial(this);
|
||||
}
|
||||
|
||||
void VkMaterial::DeleteDescriptors()
|
||||
{
|
||||
if (auto fb = GetVulkanFrameBuffer())
|
||||
if (fb)
|
||||
{
|
||||
auto& deleteList = fb->FrameDeleteList;
|
||||
|
||||
auto deleteList = fb->GetCommands()->DrawDeleteList.get();
|
||||
for (auto& it : mDescriptorSets)
|
||||
{
|
||||
deleteList.Descriptors.push_back(std::move(it.descriptor));
|
||||
deleteList->Add(std::move(it.descriptor));
|
||||
}
|
||||
mDescriptorSets.clear();
|
||||
}
|
||||
|
||||
mDescriptorSets.clear();
|
||||
}
|
||||
|
||||
void VkMaterial::ResetAllDescriptors()
|
||||
{
|
||||
for (VkMaterial* cur = First; cur; cur = cur->Next)
|
||||
cur->DeleteDescriptors();
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
if (fb)
|
||||
fb->GetRenderPassManager()->TextureSetPoolReset();
|
||||
}
|
||||
|
||||
VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
||||
|
@ -391,8 +342,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
|
||||
int numLayers = NumLayers();
|
||||
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
auto descriptor = fb->GetRenderPassManager()->AllocateTextureDescriptorSet(max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS));
|
||||
auto descriptor = fb->GetDescriptorSetManager()->AllocateTextureDescriptorSet(max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS));
|
||||
|
||||
descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets");
|
||||
|
||||
|
@ -402,7 +352,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
MaterialLayerInfo *layer;
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &layer));
|
||||
auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags);
|
||||
update.addCombinedImageSampler(descriptor.get(), 0, systeximage->View.get(), sampler, systeximage->Layout);
|
||||
update.AddCombinedImageSampler(descriptor.get(), 0, systeximage->View.get(), sampler, systeximage->Layout);
|
||||
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
{
|
||||
|
@ -410,7 +360,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags);
|
||||
update.addCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -419,18 +369,18 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
|||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, translation, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags);
|
||||
update.addCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, syslayerimage->View.get(), sampler, syslayerimage->Layout);
|
||||
}
|
||||
numLayers = 3;
|
||||
}
|
||||
|
||||
auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView();
|
||||
auto dummyImage = fb->GetTextureManager()->GetNullTextureView();
|
||||
for (int i = numLayers; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++)
|
||||
{
|
||||
update.addCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.AddCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
update.updateSets(fb->device);
|
||||
update.Execute(fb->device);
|
||||
mDescriptorSets.emplace_back(clampmode, translationp, std::move(descriptor));
|
||||
return mDescriptorSets.back().descriptor.get();
|
||||
}
|
||||
|
|
|
@ -12,22 +12,23 @@
|
|||
#include "volk/volk.h"
|
||||
#include "vk_imagetransition.h"
|
||||
#include "hw_material.h"
|
||||
#include <list>
|
||||
|
||||
struct FMaterialState;
|
||||
class VulkanDescriptorSet;
|
||||
class VulkanImage;
|
||||
class VulkanImageView;
|
||||
class VulkanBuffer;
|
||||
class VulkanFrameBuffer;
|
||||
class FGameTexture;
|
||||
|
||||
class VkHardwareTexture : public IHardwareTexture
|
||||
{
|
||||
friend class VkMaterial;
|
||||
public:
|
||||
VkHardwareTexture(int numchannels);
|
||||
VkHardwareTexture(VulkanFrameBuffer* fb, int numchannels);
|
||||
~VkHardwareTexture();
|
||||
|
||||
static void ResetAll();
|
||||
void Reset();
|
||||
|
||||
// Software renderer stuff
|
||||
|
@ -41,6 +42,8 @@ public:
|
|||
VkTextureImage *GetImage(FTexture *tex, int translation, int flags);
|
||||
VkTextureImage *GetDepthStencil(FTexture *tex);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
std::list<VkHardwareTexture*>::iterator it;
|
||||
|
||||
private:
|
||||
void CreateImage(FTexture *tex, int translation, int flags);
|
||||
|
@ -48,10 +51,6 @@ private:
|
|||
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap);
|
||||
static int GetMipLevels(int w, int h);
|
||||
|
||||
static VkHardwareTexture *First;
|
||||
VkHardwareTexture *Prev = nullptr;
|
||||
VkHardwareTexture *Next = nullptr;
|
||||
|
||||
VkTextureImage mImage;
|
||||
int mTexelsize = 4;
|
||||
|
||||
|
@ -60,13 +59,20 @@ private:
|
|||
uint8_t* mappedSWFB = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class VkMaterial : public FMaterial
|
||||
{
|
||||
static VkMaterial* First;
|
||||
VkMaterial* Prev = nullptr;
|
||||
VkMaterial* Next = nullptr;
|
||||
public:
|
||||
VkMaterial(VulkanFrameBuffer* fb, FGameTexture* tex, int scaleflags);
|
||||
~VkMaterial();
|
||||
|
||||
VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state);
|
||||
|
||||
void DeleteDescriptors() override;
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
std::list<VkMaterial*>::iterator it;
|
||||
|
||||
private:
|
||||
struct DescriptorEntry
|
||||
{
|
||||
int clampmode;
|
||||
|
@ -82,12 +88,4 @@ class VkMaterial : public FMaterial
|
|||
};
|
||||
|
||||
std::vector<DescriptorEntry> mDescriptorSets;
|
||||
|
||||
public:
|
||||
VkMaterial(FGameTexture *tex, int scaleflags);
|
||||
~VkMaterial();
|
||||
VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state);
|
||||
void DeleteDescriptors() override;
|
||||
static void ResetAllDescriptors();
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
#include "vk_imagetransition.h"
|
||||
|
||||
void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel, int levelCount)
|
||||
VkImageTransition& VkImageTransition::AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel, int levelCount)
|
||||
{
|
||||
if (image->Layout == targetLayout)
|
||||
return;
|
||||
return *this;
|
||||
|
||||
VkAccessFlags srcAccess = 0;
|
||||
VkAccessFlags dstAccess = 0;
|
||||
|
@ -91,15 +91,16 @@ void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayo
|
|||
I_FatalError("Unimplemented dst image layout transition\n");
|
||||
}
|
||||
|
||||
barrier.addImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask, baseMipLevel, levelCount);
|
||||
barrier.AddImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask, baseMipLevel, levelCount);
|
||||
needbarrier = true;
|
||||
image->Layout = targetLayout;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void VkImageTransition::execute(VulkanCommandBuffer *cmdbuffer)
|
||||
void VkImageTransition::Execute(VulkanCommandBuffer *cmdbuffer)
|
||||
{
|
||||
if (needbarrier)
|
||||
barrier.execute(cmdbuffer, srcStageMask, dstStageMask);
|
||||
barrier.Execute(cmdbuffer, srcStageMask, dstStageMask);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -111,10 +112,10 @@ void VkTextureImage::GenerateMipmaps(VulkanCommandBuffer *cmdbuffer)
|
|||
int i;
|
||||
for (i = 1; mipWidth > 1 || mipHeight > 1; i++)
|
||||
{
|
||||
PipelineBarrier barrier0;
|
||||
barrier0.addImage(Image.get(), Layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1);
|
||||
barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i);
|
||||
barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
PipelineBarrier()
|
||||
.AddImage(Image.get(), Layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1)
|
||||
.AddImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
Layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
int nextWidth = max(mipWidth >> 1, 1);
|
||||
|
@ -135,17 +136,17 @@ void VkTextureImage::GenerateMipmaps(VulkanCommandBuffer *cmdbuffer)
|
|||
blit.dstSubresource.layerCount = 1;
|
||||
cmdbuffer->blitImage(Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
|
||||
|
||||
PipelineBarrier barrier1;
|
||||
barrier1.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1);
|
||||
barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
PipelineBarrier()
|
||||
.AddImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
mipWidth = nextWidth;
|
||||
mipHeight = nextHeight;
|
||||
}
|
||||
|
||||
PipelineBarrier barrier2;
|
||||
barrier2.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1);
|
||||
barrier2.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
PipelineBarrier()
|
||||
.AddImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
|
|
@ -3,20 +3,25 @@
|
|||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/renderer/vk_renderpass.h"
|
||||
|
||||
class VkTextureImage
|
||||
{
|
||||
public:
|
||||
void reset()
|
||||
void Reset(VulkanFrameBuffer* fb)
|
||||
{
|
||||
AspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
Layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
PPFramebuffer.reset();
|
||||
auto deletelist = fb->GetCommands()->DrawDeleteList.get();
|
||||
deletelist->Add(std::move(PPFramebuffer));
|
||||
for (auto &it : RSFramebuffers)
|
||||
deletelist->Add(std::move(it.second));
|
||||
RSFramebuffers.clear();
|
||||
DepthOnlyView.reset();
|
||||
View.reset();
|
||||
Image.reset();
|
||||
deletelist->Add(std::move(DepthOnlyView));
|
||||
deletelist->Add(std::move(View));
|
||||
deletelist->Add(std::move(Image));
|
||||
}
|
||||
|
||||
void GenerateMipmaps(VulkanCommandBuffer *cmdbuffer);
|
||||
|
@ -33,8 +38,8 @@ public:
|
|||
class VkImageTransition
|
||||
{
|
||||
public:
|
||||
void addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel = 0, int levelCount = 1);
|
||||
void execute(VulkanCommandBuffer *cmdbuffer);
|
||||
VkImageTransition& AddImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout, int baseMipLevel = 0, int levelCount = 1);
|
||||
void Execute(VulkanCommandBuffer *cmdbuffer);
|
||||
|
||||
private:
|
||||
PipelineBarrier barrier;
|
||||
|
|
114
source/common/rendering/vulkan/textures/vk_pptexture.cpp
Normal file
114
source/common/rendering/vulkan/textures/vk_pptexture.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_pptexture.h"
|
||||
#include "vk_texture.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
|
||||
VkPPTexture::VkPPTexture(VulkanFrameBuffer* fb, PPTexture *texture) : fb(fb)
|
||||
{
|
||||
VkFormat format;
|
||||
int pixelsize;
|
||||
switch (texture->Format)
|
||||
{
|
||||
default:
|
||||
case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break;
|
||||
case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break;
|
||||
case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break;
|
||||
case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break;
|
||||
case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break;
|
||||
}
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
imgbuilder.Format(format);
|
||||
imgbuilder.Size(texture->Width, texture->Height);
|
||||
if (texture->Data)
|
||||
imgbuilder.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
else
|
||||
imgbuilder.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
imgbuilder.DebugName("VkPPTexture");
|
||||
if (!imgbuilder.IsFormatSupported(fb->device))
|
||||
I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n");
|
||||
TexImage.Image = imgbuilder.Create(fb->device);
|
||||
Format = format;
|
||||
|
||||
TexImage.View = ImageViewBuilder()
|
||||
.Image(TexImage.Image.get(), format)
|
||||
.DebugName("VkPPTextureView")
|
||||
.Create(fb->device);
|
||||
|
||||
if (texture->Data)
|
||||
{
|
||||
size_t totalsize = texture->Width * texture->Height * pixelsize;
|
||||
|
||||
Staging = BufferBuilder()
|
||||
.Size(totalsize)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("VkPPTextureStaging")
|
||||
.Create(fb->device);
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
|
||||
void *data = Staging->Map(0, totalsize);
|
||||
memcpy(data, texture->Data.get(), totalsize);
|
||||
Staging->Unmap();
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = texture->Width;
|
||||
region.imageExtent.height = texture->Height;
|
||||
fb->GetCommands()->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
}
|
||||
else
|
||||
{
|
||||
VkImageTransition()
|
||||
.AddImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands());
|
||||
}
|
||||
|
||||
fb->GetTextureManager()->AddPPTexture(this);
|
||||
}
|
||||
|
||||
VkPPTexture::~VkPPTexture()
|
||||
{
|
||||
if (fb)
|
||||
fb->GetTextureManager()->RemovePPTexture(this);
|
||||
}
|
||||
|
||||
void VkPPTexture::Reset()
|
||||
{
|
||||
if (fb)
|
||||
{
|
||||
TexImage.Reset(fb);
|
||||
if (Staging)
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(Staging));
|
||||
}
|
||||
}
|
25
source/common/rendering/vulkan/textures/vk_pptexture.h
Normal file
25
source/common/rendering/vulkan/textures/vk_pptexture.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include "vulkan/textures/vk_imagetransition.h"
|
||||
#include <list>
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
|
||||
class VkPPTexture : public PPTextureBackend
|
||||
{
|
||||
public:
|
||||
VkPPTexture(VulkanFrameBuffer* fb, PPTexture *texture);
|
||||
~VkPPTexture();
|
||||
|
||||
void Reset();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
std::list<VkPPTexture*>::iterator it;
|
||||
|
||||
VkTextureImage TexImage;
|
||||
std::unique_ptr<VulkanBuffer> Staging;
|
||||
VkFormat Format;
|
||||
};
|
263
source/common/rendering/vulkan/textures/vk_renderbuffers.cpp
Normal file
263
source/common/rendering/vulkan/textures/vk_renderbuffers.cpp
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_renderbuffers.h"
|
||||
#include "vulkan/renderer/vk_postprocess.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "vulkan/shaders/vk_shader.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vulkan/system/vk_swapchain.h"
|
||||
#include "hw_cvars.h"
|
||||
|
||||
VkRenderBuffers::VkRenderBuffers(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
VkRenderBuffers::~VkRenderBuffers()
|
||||
{
|
||||
}
|
||||
|
||||
VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount()
|
||||
{
|
||||
const auto &limits = fb->device->PhysicalDevice.Properties.limits;
|
||||
VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts;
|
||||
|
||||
int requestedSamples = clamp((int)gl_multisample, 0, 64);
|
||||
|
||||
int samples = 1;
|
||||
VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT;
|
||||
VkSampleCountFlags best = bit;
|
||||
while (samples <= requestedSamples)
|
||||
{
|
||||
if (deviceSampleCounts & bit)
|
||||
{
|
||||
best = bit;
|
||||
}
|
||||
samples <<= 1;
|
||||
bit <<= 1;
|
||||
}
|
||||
return (VkSampleCountFlagBits)best;
|
||||
}
|
||||
|
||||
void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int sceneHeight)
|
||||
{
|
||||
VkSampleCountFlagBits samples = GetBestSampleCount();
|
||||
|
||||
if (width != mWidth || height != mHeight || mSamples != samples)
|
||||
{
|
||||
fb->GetCommands()->WaitForCommands(false);
|
||||
fb->GetRenderPassManager()->RenderBuffersReset();
|
||||
}
|
||||
|
||||
if (width != mWidth || height != mHeight)
|
||||
CreatePipeline(width, height);
|
||||
|
||||
if (width != mWidth || height != mHeight || mSamples != samples)
|
||||
CreateScene(width, height, samples);
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mSamples = samples;
|
||||
mSceneWidth = sceneWidth;
|
||||
mSceneHeight = sceneHeight;
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreatePipeline(int width, int height)
|
||||
{
|
||||
for (int i = 0; i < NumPipelineImages; i++)
|
||||
{
|
||||
PipelineImage[i].Reset(fb);
|
||||
}
|
||||
|
||||
VkImageTransition barrier;
|
||||
for (int i = 0; i < NumPipelineImages; i++)
|
||||
{
|
||||
PipelineImage[i].Image = ImageBuilder()
|
||||
.Size(width, height)
|
||||
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
.DebugName("VkRenderBuffers.PipelineImage")
|
||||
.Create(fb->device);
|
||||
|
||||
PipelineImage[i].View = ImageViewBuilder()
|
||||
.Image(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||
.DebugName("VkRenderBuffers.PipelineView")
|
||||
.Create(fb->device);
|
||||
|
||||
barrier.AddImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||
}
|
||||
barrier.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
SceneColor.Reset(fb);
|
||||
SceneDepthStencil.Reset(fb);
|
||||
SceneNormal.Reset(fb);
|
||||
SceneFog.Reset(fb);
|
||||
|
||||
CreateSceneColor(width, height, samples);
|
||||
CreateSceneDepthStencil(width, height, samples);
|
||||
CreateSceneNormal(width, height, samples);
|
||||
CreateSceneFog(width, height, samples);
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true)
|
||||
.AddImage(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true)
|
||||
.AddImage(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true)
|
||||
.AddImage(&SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
SceneColor.Image = ImageBuilder()
|
||||
.Size(width, height)
|
||||
.Samples(samples)
|
||||
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
|
||||
.DebugName("VkRenderBuffers.SceneColor")
|
||||
.Create(fb->device);
|
||||
|
||||
SceneColor.View = ImageViewBuilder()
|
||||
.Image(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||
.DebugName("VkRenderBuffers.SceneColorView")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
ImageBuilder builder;
|
||||
builder.Size(width, height);
|
||||
builder.Samples(samples);
|
||||
builder.Format(SceneDepthStencilFormat);
|
||||
builder.Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
if (!builder.IsFormatSupported(fb->device))
|
||||
{
|
||||
SceneDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
builder.Format(SceneDepthStencilFormat);
|
||||
if (!builder.IsFormatSupported(fb->device))
|
||||
{
|
||||
I_FatalError("This device does not support any of the required depth stencil image formats.");
|
||||
}
|
||||
}
|
||||
builder.DebugName("VkRenderBuffers.SceneDepthStencil");
|
||||
|
||||
SceneDepthStencil.Image = builder.Create(fb->device);
|
||||
SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
SceneDepthStencil.View = ImageViewBuilder()
|
||||
.Image(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
.DebugName("VkRenderBuffers.SceneDepthStencilView")
|
||||
.Create(fb->device);
|
||||
|
||||
SceneDepthStencil.DepthOnlyView = ImageViewBuilder()
|
||||
.Image(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
.DebugName("VkRenderBuffers.SceneDepthView")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
SceneFog.Image = ImageBuilder()
|
||||
.Size(width, height)
|
||||
.Samples(samples)
|
||||
.Format(VK_FORMAT_R8G8B8A8_UNORM)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkRenderBuffers.SceneFog")
|
||||
.Create(fb->device);
|
||||
|
||||
SceneFog.View = ImageViewBuilder()
|
||||
.Image(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM)
|
||||
.DebugName("VkRenderBuffers.SceneFogView")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples)
|
||||
{
|
||||
ImageBuilder builder;
|
||||
builder.Size(width, height);
|
||||
builder.Samples(samples);
|
||||
builder.Format(SceneNormalFormat);
|
||||
builder.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
if (!builder.IsFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
|
||||
{
|
||||
SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
builder.Format(SceneNormalFormat);
|
||||
}
|
||||
builder.DebugName("VkRenderBuffers.SceneNormal");
|
||||
|
||||
SceneNormal.Image = builder.Create(fb->device);
|
||||
|
||||
SceneNormal.View = ImageViewBuilder()
|
||||
.Image(SceneNormal.Image.get(), SceneNormalFormat)
|
||||
.DebugName("VkRenderBuffers.SceneNormalView")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, bool stencilTest, int& framebufferWidth, int& framebufferHeight)
|
||||
{
|
||||
VkTextureImage* tex = fb->GetTextureManager()->GetTexture(output.Type, output.Texture);
|
||||
|
||||
VkImageView view;
|
||||
std::unique_ptr<VulkanFramebuffer>* framebufferptr = nullptr;
|
||||
int w, h;
|
||||
if (tex)
|
||||
{
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture);
|
||||
if (stencilTest)
|
||||
imageTransition.AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false);
|
||||
imageTransition.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
|
||||
view = tex->View->view;
|
||||
w = tex->Image->width;
|
||||
h = tex->Image->height;
|
||||
framebufferptr = &tex->PPFramebuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
view = fb->GetCommands()->swapChain->swapChainImageViews[fb->GetCommands()->presentImageIndex];
|
||||
framebufferptr = &fb->GetCommands()->swapChain->framebuffers[fb->GetCommands()->presentImageIndex];
|
||||
w = fb->GetCommands()->swapChain->actualExtent.width;
|
||||
h = fb->GetCommands()->swapChain->actualExtent.height;
|
||||
}
|
||||
|
||||
auto& framebuffer = *framebufferptr;
|
||||
if (!framebuffer)
|
||||
{
|
||||
FramebufferBuilder builder;
|
||||
builder.RenderPass(passSetup->RenderPass.get());
|
||||
builder.Size(w, h);
|
||||
builder.AddAttachment(view);
|
||||
if (stencilTest)
|
||||
builder.AddAttachment(fb->GetBuffers()->SceneDepthStencil.View.get());
|
||||
builder.DebugName("PPOutputFB");
|
||||
framebuffer = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
framebufferWidth = w;
|
||||
framebufferHeight = h;
|
||||
return framebuffer.get();
|
||||
}
|
|
@ -4,10 +4,14 @@
|
|||
#include "vulkan/system/vk_objects.h"
|
||||
#include "vulkan/textures/vk_imagetransition.h"
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
class VkPPRenderPassSetup;
|
||||
class PPOutput;
|
||||
|
||||
class VkRenderBuffers
|
||||
{
|
||||
public:
|
||||
VkRenderBuffers();
|
||||
VkRenderBuffers(VulkanFrameBuffer* fb);
|
||||
~VkRenderBuffers();
|
||||
|
||||
void BeginFrame(int width, int height, int sceneWidth, int sceneHeight);
|
||||
|
@ -29,11 +33,7 @@ public:
|
|||
static const int NumPipelineImages = 2;
|
||||
VkTextureImage PipelineImage[NumPipelineImages];
|
||||
|
||||
VkTextureImage Shadowmap;
|
||||
std::unique_ptr<VulkanSampler> ShadowmapSampler;
|
||||
|
||||
VkTextureImage Lightmap;
|
||||
std::unique_ptr<VulkanSampler> LightmapSampler;
|
||||
VulkanFramebuffer* GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, bool stencilTest, int& framebufferWidth, int& framebufferHeight);
|
||||
|
||||
private:
|
||||
void CreatePipeline(int width, int height);
|
||||
|
@ -42,10 +42,10 @@ private:
|
|||
void CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateShadowmap();
|
||||
void CreateLightmapSampler();
|
||||
VkSampleCountFlagBits GetBestSampleCount();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
int mWidth = 0;
|
||||
int mHeight = 0;
|
||||
int mSceneWidth = 0;
|
|
@ -23,13 +23,15 @@
|
|||
#include "volk/volk.h"
|
||||
#include "c_cvars.h"
|
||||
#include "v_video.h"
|
||||
|
||||
#include "hw_cvars.h"
|
||||
#include "vulkan/system/vk_device.h"
|
||||
#include "vulkan/system/vk_builders.h"
|
||||
#include "vulkan/system/vk_framebuffer.h"
|
||||
#include "vulkan/system/vk_commandbuffer.h"
|
||||
#include "vk_samplers.h"
|
||||
#include "hw_material.h"
|
||||
#include "i_interface.h"
|
||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||
|
||||
struct VkTexFilter
|
||||
{
|
||||
|
@ -37,16 +39,17 @@ struct VkTexFilter
|
|||
VkFilter magFilter;
|
||||
VkSamplerMipmapMode mipfilter;
|
||||
bool mipmapping;
|
||||
} ;
|
||||
};
|
||||
|
||||
VkTexFilter TexFilter[]={
|
||||
static VkTexFilter TexFilter[] =
|
||||
{
|
||||
{VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, false},
|
||||
{VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, true},
|
||||
{VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, false},
|
||||
{VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, true},
|
||||
{VK_FILTER_LINEAR, VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_LINEAR, true},
|
||||
{VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR, true},
|
||||
{VK_FILTER_LINEAR, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR, true},
|
||||
{VK_FILTER_LINEAR, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR, true}
|
||||
};
|
||||
|
||||
struct VkTexClamp
|
||||
|
@ -55,89 +58,132 @@ struct VkTexClamp
|
|||
VkSamplerAddressMode clamp_v;
|
||||
};
|
||||
|
||||
VkTexClamp TexClamp[] ={
|
||||
static VkTexClamp TexClamp[] =
|
||||
{
|
||||
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT },
|
||||
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT },
|
||||
{ VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE },
|
||||
{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE },
|
||||
};
|
||||
|
||||
VkSamplerManager::VkSamplerManager(VulkanDevice *dev)
|
||||
VkSamplerManager::VkSamplerManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
vDevice = dev;
|
||||
Create();
|
||||
CreateHWSamplers();
|
||||
CreateShadowmapSampler();
|
||||
CreateLightmapSampler();
|
||||
}
|
||||
|
||||
VkSamplerManager::~VkSamplerManager()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void VkSamplerManager::SetTextureFilterMode()
|
||||
void VkSamplerManager::ResetHWSamplers()
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
DeleteHWSamplers();
|
||||
CreateHWSamplers();
|
||||
}
|
||||
|
||||
void VkSamplerManager::Create()
|
||||
void VkSamplerManager::CreateHWSamplers()
|
||||
{
|
||||
int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter()? 0 : gl_texture_filter;
|
||||
|
||||
for (int i = CLAMP_NONE; i <= CLAMP_XY; i++)
|
||||
{
|
||||
SamplerBuilder builder;
|
||||
builder.setMagFilter(TexFilter[filter].magFilter);
|
||||
builder.setMinFilter(TexFilter[filter].minFilter);
|
||||
builder.setAddressMode(TexClamp[i].clamp_u, TexClamp[i].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||
builder.setMipmapMode(TexFilter[filter].mipfilter);
|
||||
builder.MagFilter(TexFilter[filter].magFilter);
|
||||
builder.MinFilter(TexFilter[filter].minFilter);
|
||||
builder.AddressMode(TexClamp[i].clamp_u, TexClamp[i].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||
builder.MipmapMode(TexFilter[filter].mipfilter);
|
||||
if (TexFilter[filter].mipmapping)
|
||||
{
|
||||
builder.setAnisotropy(gl_texture_filter_anisotropic);
|
||||
builder.setMaxLod(100.0f); // According to the spec this value is clamped so something high makes it usable for all textures.
|
||||
builder.Anisotropy(gl_texture_filter_anisotropic);
|
||||
builder.MaxLod(100.0f); // According to the spec this value is clamped so something high makes it usable for all textures.
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.setMaxLod(0.25f);
|
||||
builder.MaxLod(0.25f);
|
||||
}
|
||||
mSamplers[i] = builder.create(vDevice);
|
||||
mSamplers[i]->SetDebugName("VkSamplerManager.mSamplers");
|
||||
}
|
||||
{
|
||||
SamplerBuilder builder;
|
||||
builder.setMagFilter(TexFilter[filter].magFilter);
|
||||
builder.setMinFilter(TexFilter[filter].magFilter);
|
||||
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
builder.setMaxLod(0.25f);
|
||||
mSamplers[CLAMP_XY_NOMIP] = builder.create(vDevice);
|
||||
mSamplers[CLAMP_XY_NOMIP]->SetDebugName("VkSamplerManager.mSamplers");
|
||||
builder.DebugName("VkSamplerManager.mSamplers");
|
||||
mSamplers[i] = builder.Create(fb->device);
|
||||
}
|
||||
|
||||
mSamplers[CLAMP_XY_NOMIP] = SamplerBuilder()
|
||||
.MagFilter(TexFilter[filter].magFilter)
|
||||
.MinFilter(TexFilter[filter].magFilter)
|
||||
.AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT)
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST)
|
||||
.MaxLod(0.25f)
|
||||
.DebugName("VkSamplerManager.mSamplers")
|
||||
.Create(fb->device);
|
||||
|
||||
for (int i = CLAMP_NOFILTER; i <= CLAMP_NOFILTER_XY; i++)
|
||||
{
|
||||
SamplerBuilder builder;
|
||||
builder.setMagFilter(VK_FILTER_NEAREST);
|
||||
builder.setMinFilter(VK_FILTER_NEAREST);
|
||||
builder.setAddressMode(TexClamp[i - CLAMP_NOFILTER].clamp_u, TexClamp[i - CLAMP_NOFILTER].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
builder.setMaxLod(0.25f);
|
||||
mSamplers[i] = builder.create(vDevice);
|
||||
mSamplers[i]->SetDebugName("VkSamplerManager.mSamplers");
|
||||
mSamplers[i] = SamplerBuilder()
|
||||
.MagFilter(VK_FILTER_NEAREST)
|
||||
.MinFilter(VK_FILTER_NEAREST)
|
||||
.AddressMode(TexClamp[i - CLAMP_NOFILTER].clamp_u, TexClamp[i - CLAMP_NOFILTER].clamp_v, VK_SAMPLER_ADDRESS_MODE_REPEAT)
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST)
|
||||
.MaxLod(0.25f)
|
||||
.DebugName("VkSamplerManager.mSamplers")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
// CAMTEX is repeating with texture filter and no mipmap
|
||||
mSamplers[CLAMP_CAMTEX] = SamplerBuilder()
|
||||
.MagFilter(TexFilter[filter].magFilter)
|
||||
.MinFilter(TexFilter[filter].magFilter)
|
||||
.AddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT)
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST)
|
||||
.MaxLod(0.25f)
|
||||
.DebugName("VkSamplerManager.mSamplers")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkSamplerManager::DeleteHWSamplers()
|
||||
{
|
||||
for (auto& sampler : mSamplers)
|
||||
{
|
||||
SamplerBuilder builder;
|
||||
builder.setMagFilter(TexFilter[filter].magFilter);
|
||||
builder.setMinFilter(TexFilter[filter].magFilter);
|
||||
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT);
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
builder.setMaxLod(0.25f);
|
||||
mSamplers[CLAMP_CAMTEX] = builder.create(vDevice);
|
||||
mSamplers[CLAMP_CAMTEX]->SetDebugName("VkSamplerManager.mSamplers");
|
||||
if (sampler)
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(sampler));
|
||||
}
|
||||
}
|
||||
|
||||
void VkSamplerManager::Destroy()
|
||||
VulkanSampler* VkSamplerManager::Get(PPFilterMode filter, PPWrapMode wrap)
|
||||
{
|
||||
for (int i = 0; i < NUMSAMPLERS; i++)
|
||||
mSamplers[i].reset();
|
||||
int index = (((int)filter) << 1) | (int)wrap;
|
||||
auto& sampler = mPPSamplers[index];
|
||||
if (sampler)
|
||||
return sampler.get();
|
||||
|
||||
sampler = SamplerBuilder()
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST)
|
||||
.MinFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR)
|
||||
.MagFilter(filter == PPFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR)
|
||||
.AddressMode(wrap == PPWrapMode::Clamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT)
|
||||
.DebugName("VkPostprocess.mSamplers")
|
||||
.Create(fb->device);
|
||||
|
||||
return sampler.get();
|
||||
}
|
||||
|
||||
void VkSamplerManager::CreateShadowmapSampler()
|
||||
{
|
||||
ShadowmapSampler = SamplerBuilder()
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST)
|
||||
.MinFilter(VK_FILTER_NEAREST)
|
||||
.MagFilter(VK_FILTER_NEAREST)
|
||||
.AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
|
||||
.DebugName("VkRenderBuffers.ShadowmapSampler")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
||||
void VkSamplerManager::CreateLightmapSampler()
|
||||
{
|
||||
LightmapSampler = SamplerBuilder()
|
||||
.MipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR)
|
||||
.MinFilter(VK_FILTER_LINEAR)
|
||||
.MagFilter(VK_FILTER_LINEAR)
|
||||
.AddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
|
||||
.DebugName("VkRenderBuffers.LightmapSampler")
|
||||
.Create(fb->device);
|
||||
}
|
||||
|
|
|
@ -1,32 +1,34 @@
|
|||
#ifndef __VK_SAMPLERS_H
|
||||
#define __VK_SAMPLERS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include <array>
|
||||
|
||||
class VulkanDevice;
|
||||
class VulkanFrameBuffer;
|
||||
enum class PPFilterMode;
|
||||
enum class PPWrapMode;
|
||||
|
||||
class VkSamplerManager
|
||||
{
|
||||
VulkanDevice *vDevice;
|
||||
std::unique_ptr<VulkanSampler> mSamplers[NUMSAMPLERS];
|
||||
|
||||
//void UnbindAll();
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
|
||||
public:
|
||||
|
||||
VkSamplerManager(VulkanDevice *dev);
|
||||
VkSamplerManager(VulkanFrameBuffer* fb);
|
||||
~VkSamplerManager();
|
||||
|
||||
//uint8_t Bind(int texunit, int num, int lastval);
|
||||
void SetTextureFilterMode();
|
||||
void ResetHWSamplers();
|
||||
|
||||
VulkanSampler *Get(int no) const { return mSamplers[no].get(); }
|
||||
VulkanSampler* Get(PPFilterMode filter, PPWrapMode wrap);
|
||||
|
||||
std::unique_ptr<VulkanSampler> ShadowmapSampler;
|
||||
std::unique_ptr<VulkanSampler> LightmapSampler;
|
||||
|
||||
private:
|
||||
void CreateHWSamplers();
|
||||
void DeleteHWSamplers();
|
||||
void CreateShadowmapSampler();
|
||||
void CreateLightmapSampler();
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
std::array<std::unique_ptr<VulkanSampler>, NUMSAMPLERS> mSamplers;
|
||||
std::array<std::unique_ptr<VulkanSampler>, 4> mPPSamplers;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
253
source/common/rendering/vulkan/textures/vk_texture.cpp
Normal file
253
source/common/rendering/vulkan/textures/vk_texture.cpp
Normal file
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_texture.h"
|
||||
#include "vk_hwtexture.h"
|
||||
#include "vk_pptexture.h"
|
||||
#include "vk_renderbuffers.h"
|
||||
#include "vulkan/renderer/vk_postprocess.h"
|
||||
#include "hw_cvars.h"
|
||||
|
||||
VkTextureManager::VkTextureManager(VulkanFrameBuffer* fb) : fb(fb)
|
||||
{
|
||||
CreateNullTexture();
|
||||
CreateShadowmap();
|
||||
CreateLightmap();
|
||||
}
|
||||
|
||||
VkTextureManager::~VkTextureManager()
|
||||
{
|
||||
while (!Textures.empty())
|
||||
RemoveTexture(Textures.back());
|
||||
while (!PPTextures.empty())
|
||||
RemovePPTexture(PPTextures.back());
|
||||
}
|
||||
|
||||
void VkTextureManager::Deinit()
|
||||
{
|
||||
while (!Textures.empty())
|
||||
RemoveTexture(Textures.back());
|
||||
while (!PPTextures.empty())
|
||||
RemovePPTexture(PPTextures.back());
|
||||
}
|
||||
|
||||
void VkTextureManager::BeginFrame()
|
||||
{
|
||||
if (!Shadowmap.Image || Shadowmap.Image->width != gl_shadowmap_quality)
|
||||
{
|
||||
Shadowmap.Reset(fb);
|
||||
CreateShadowmap();
|
||||
}
|
||||
}
|
||||
|
||||
void VkTextureManager::AddTexture(VkHardwareTexture* texture)
|
||||
{
|
||||
texture->it = Textures.insert(Textures.end(), texture);
|
||||
}
|
||||
|
||||
void VkTextureManager::RemoveTexture(VkHardwareTexture* texture)
|
||||
{
|
||||
texture->Reset();
|
||||
texture->fb = nullptr;
|
||||
Textures.erase(texture->it);
|
||||
}
|
||||
|
||||
void VkTextureManager::AddPPTexture(VkPPTexture* texture)
|
||||
{
|
||||
texture->it = PPTextures.insert(PPTextures.end(), texture);
|
||||
}
|
||||
|
||||
void VkTextureManager::RemovePPTexture(VkPPTexture* texture)
|
||||
{
|
||||
texture->Reset();
|
||||
texture->fb = nullptr;
|
||||
PPTextures.erase(texture->it);
|
||||
}
|
||||
|
||||
VkTextureImage* VkTextureManager::GetTexture(const PPTextureType& type, PPTexture* pptexture)
|
||||
{
|
||||
if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture)
|
||||
{
|
||||
int idx = fb->GetPostprocess()->GetCurrentPipelineImage();
|
||||
if (type == PPTextureType::NextPipelineTexture)
|
||||
idx = (idx + 1) % VkRenderBuffers::NumPipelineImages;
|
||||
|
||||
return &fb->GetBuffers()->PipelineImage[idx];
|
||||
}
|
||||
else if (type == PPTextureType::PPTexture)
|
||||
{
|
||||
auto vktex = GetVkTexture(pptexture);
|
||||
return &vktex->TexImage;
|
||||
}
|
||||
else if (type == PPTextureType::SceneColor)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneColor;
|
||||
}
|
||||
else if (type == PPTextureType::SceneNormal)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneNormal;
|
||||
}
|
||||
else if (type == PPTextureType::SceneFog)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneFog;
|
||||
}
|
||||
else if (type == PPTextureType::SceneDepth)
|
||||
{
|
||||
return &fb->GetBuffers()->SceneDepthStencil;
|
||||
}
|
||||
else if (type == PPTextureType::ShadowMap)
|
||||
{
|
||||
return &Shadowmap;
|
||||
}
|
||||
else if (type == PPTextureType::SwapChain)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VkFormat VkTextureManager::GetTextureFormat(PPTexture* texture)
|
||||
{
|
||||
return GetVkTexture(texture)->Format;
|
||||
}
|
||||
|
||||
VkPPTexture* VkTextureManager::GetVkTexture(PPTexture* texture)
|
||||
{
|
||||
if (!texture->Backend)
|
||||
texture->Backend = std::make_unique<VkPPTexture>(fb, texture);
|
||||
return static_cast<VkPPTexture*>(texture->Backend.get());
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateNullTexture()
|
||||
{
|
||||
NullTexture = ImageBuilder()
|
||||
.Format(VK_FORMAT_R8G8B8A8_UNORM)
|
||||
.Size(1, 1)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkDescriptorSetManager.NullTexture")
|
||||
.Create(fb->device);
|
||||
|
||||
NullTextureView = ImageViewBuilder()
|
||||
.Image(NullTexture.get(), VK_FORMAT_R8G8B8A8_UNORM)
|
||||
.DebugName("VkDescriptorSetManager.NullTextureView")
|
||||
.Create(fb->device);
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(NullTexture.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateShadowmap()
|
||||
{
|
||||
Shadowmap.Image = ImageBuilder()
|
||||
.Size(gl_shadowmap_quality, 1024)
|
||||
.Format(VK_FORMAT_R32_SFLOAT)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.DebugName("VkRenderBuffers.Shadowmap")
|
||||
.Create(fb->device);
|
||||
|
||||
Shadowmap.View = ImageViewBuilder()
|
||||
.Image(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT)
|
||||
.DebugName("VkRenderBuffers.ShadowmapView")
|
||||
.Create(fb->device);
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true)
|
||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateLightmap()
|
||||
{
|
||||
TArray<uint16_t> data;
|
||||
data.Push(0);
|
||||
data.Push(0);
|
||||
data.Push(0);
|
||||
data.Push(0x3c00); // half-float 1.0
|
||||
SetLightmap(1, 1, data);
|
||||
}
|
||||
|
||||
void VkTextureManager::SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData)
|
||||
{
|
||||
int w = LMTextureSize;
|
||||
int h = LMTextureSize;
|
||||
int count = LMTextureCount;
|
||||
int pixelsize = 8;
|
||||
|
||||
Lightmap.Reset(fb);
|
||||
|
||||
Lightmap.Image = ImageBuilder()
|
||||
.Size(w, h, 1, count)
|
||||
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
.DebugName("VkRenderBuffers.Lightmap")
|
||||
.Create(fb->device);
|
||||
|
||||
Lightmap.View = ImageViewBuilder()
|
||||
.Type(VK_IMAGE_VIEW_TYPE_2D_ARRAY)
|
||||
.Image(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT)
|
||||
.DebugName("VkRenderBuffers.LightmapView")
|
||||
.Create(fb->device);
|
||||
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
int totalSize = w * h * count * pixelsize;
|
||||
|
||||
auto stagingBuffer = BufferBuilder()
|
||||
.Size(totalSize)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("VkHardwareTexture.mStagingBuffer")
|
||||
.Create(fb->device);
|
||||
|
||||
uint16_t one = 0x3c00; // half-float 1.0
|
||||
const uint16_t* src = LMTextureData.Data();
|
||||
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
|
||||
for (int i = w * h * count; i > 0; i--)
|
||||
{
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = one;
|
||||
}
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, count)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = count;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageExtent.width = w;
|
||||
region.imageExtent.height = h;
|
||||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageTransition()
|
||||
.AddImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, count)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
}
|
57
source/common/rendering/vulkan/textures/vk_texture.h
Normal file
57
source/common/rendering/vulkan/textures/vk_texture.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "vulkan/system/vk_objects.h"
|
||||
#include "vulkan/textures/vk_imagetransition.h"
|
||||
#include <list>
|
||||
|
||||
class VulkanFrameBuffer;
|
||||
class VkHardwareTexture;
|
||||
class VkMaterial;
|
||||
class VkPPTexture;
|
||||
class VkTextureImage;
|
||||
enum class PPTextureType;
|
||||
class PPTexture;
|
||||
|
||||
class VkTextureManager
|
||||
{
|
||||
public:
|
||||
VkTextureManager(VulkanFrameBuffer* fb);
|
||||
~VkTextureManager();
|
||||
|
||||
void Deinit();
|
||||
|
||||
void BeginFrame();
|
||||
|
||||
void SetLightmap(int LMTextureSize, int LMTextureCount, const TArray<uint16_t>& LMTextureData);
|
||||
|
||||
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
||||
VkFormat GetTextureFormat(PPTexture* texture);
|
||||
|
||||
void AddTexture(VkHardwareTexture* texture);
|
||||
void RemoveTexture(VkHardwareTexture* texture);
|
||||
|
||||
void AddPPTexture(VkPPTexture* texture);
|
||||
void RemovePPTexture(VkPPTexture* texture);
|
||||
|
||||
VulkanImage* GetNullTexture() { return NullTexture.get(); }
|
||||
VulkanImageView* GetNullTextureView() { return NullTextureView.get(); }
|
||||
|
||||
VkTextureImage Shadowmap;
|
||||
VkTextureImage Lightmap;
|
||||
|
||||
private:
|
||||
void CreateNullTexture();
|
||||
void CreateShadowmap();
|
||||
void CreateLightmap();
|
||||
|
||||
VkPPTexture* GetVkTexture(PPTexture* texture);
|
||||
|
||||
VulkanFrameBuffer* fb = nullptr;
|
||||
|
||||
std::list<VkHardwareTexture*> Textures;
|
||||
std::list<VkPPTexture*> PPTextures;
|
||||
|
||||
std::unique_ptr<VulkanImage> NullTexture;
|
||||
std::unique_ptr<VulkanImageView> NullTextureView;
|
||||
};
|
File diff suppressed because it is too large
Load diff
|
@ -6,6 +6,7 @@
|
|||
*
|
||||
* This library is distributed under the MIT License. See notice at the end of this file.
|
||||
*/
|
||||
/* clang-format off */
|
||||
#ifndef VOLK_H_
|
||||
#define VOLK_H_
|
||||
|
||||
|
@ -13,16 +14,49 @@
|
|||
# error To use volk, you need to define VK_NO_PROTOTYPES before including vulkan.h
|
||||
#endif
|
||||
|
||||
/* VOLK_GENERATE_VERSION */
|
||||
#define VOLK_HEADER_VERSION 102
|
||||
/* VOLK_GENERATE_VERSION */
|
||||
/* VOLK_GENERATE_VERSION_DEFINE */
|
||||
#define VOLK_HEADER_VERSION 190
|
||||
/* VOLK_GENERATE_VERSION_DEFINE */
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
# define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
|
||||
#ifndef VULKAN_H_
|
||||
# include <vulkan/vulkan.h>
|
||||
# ifdef VOLK_VULKAN_H_PATH
|
||||
# include VOLK_VULKAN_H_PATH
|
||||
# elif defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
# include <vulkan/vk_platform.h>
|
||||
# include <vulkan/vulkan_core.h>
|
||||
|
||||
/* When VK_USE_PLATFORM_WIN32_KHR is defined, instead of including vulkan.h directly, we include individual parts of the SDK
|
||||
* This is necessary to avoid including <windows.h> which is very heavy - it takes 200ms to parse without WIN32_LEAN_AND_MEAN
|
||||
* and 100ms to parse with it. vulkan_win32.h only needs a few symbols that are easy to redefine ourselves.
|
||||
*/
|
||||
typedef unsigned long DWORD;
|
||||
typedef const wchar_t* LPCWSTR;
|
||||
typedef void* HANDLE;
|
||||
typedef struct HINSTANCE__* HINSTANCE;
|
||||
typedef struct HWND__* HWND;
|
||||
typedef struct HMONITOR__* HMONITOR;
|
||||
typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;
|
||||
|
||||
# include <vulkan/vulkan_win32.h>
|
||||
|
||||
# ifdef VK_ENABLE_BETA_EXTENSIONS
|
||||
# include <vulkan/vulkan_beta.h>
|
||||
# endif
|
||||
# else
|
||||
# include <vulkan/vulkan.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Disable several extensions on earlier SDKs because later SDKs introduce a backwards incompatible change to function signatures */
|
||||
#if VK_HEADER_VERSION < 140
|
||||
# undef VK_NVX_image_view_handle
|
||||
#endif
|
||||
#if VK_HEADER_VERSION < 184
|
||||
# undef VK_HUAWEI_subpass_shading
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -59,6 +93,12 @@ uint32_t volkGetInstanceVersion(void);
|
|||
*/
|
||||
void volkLoadInstance(VkInstance instance);
|
||||
|
||||
/**
|
||||
* Load global function pointers using application-created VkInstance; call this function after creating the Vulkan instance.
|
||||
* Skips loading device-based function pointers, requires usage of volkLoadDevice afterwards.
|
||||
*/
|
||||
void volkLoadInstanceOnly(VkInstance instance);
|
||||
|
||||
/**
|
||||
* Load global function pointers using application-created VkDevice; call this function after creating the Vulkan device.
|
||||
*
|
||||
|
@ -66,6 +106,18 @@ void volkLoadInstance(VkInstance instance);
|
|||
*/
|
||||
void volkLoadDevice(VkDevice device);
|
||||
|
||||
/**
|
||||
* Return last VkInstance for which global function pointers have been loaded via volkLoadInstance(),
|
||||
* or VK_NULL_HANDLE if volkLoadInstance() has not been called.
|
||||
*/
|
||||
VkInstance volkGetLoadedInstance(void);
|
||||
|
||||
/**
|
||||
* Return last VkDevice for which global function pointers have been loaded via volkLoadDevice(),
|
||||
* or VK_NULL_HANDLE if volkLoadDevice() has not been called.
|
||||
*/
|
||||
VkDevice volkGetLoadedDevice(void);
|
||||
|
||||
/**
|
||||
* Load function pointers using application-created VkDevice into a table.
|
||||
* Application should use function pointers from that table instead of using global function pointers.
|
||||
|
@ -218,9 +270,27 @@ struct VolkDeviceTable
|
|||
PFN_vkTrimCommandPool vkTrimCommandPool;
|
||||
PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate;
|
||||
#endif /* defined(VK_VERSION_1_1) */
|
||||
#if defined(VK_VERSION_1_2)
|
||||
PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2;
|
||||
PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount;
|
||||
PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount;
|
||||
PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2;
|
||||
PFN_vkCmdNextSubpass2 vkCmdNextSubpass2;
|
||||
PFN_vkCreateRenderPass2 vkCreateRenderPass2;
|
||||
PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress;
|
||||
PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress;
|
||||
PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress;
|
||||
PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue;
|
||||
PFN_vkResetQueryPool vkResetQueryPool;
|
||||
PFN_vkSignalSemaphore vkSignalSemaphore;
|
||||
PFN_vkWaitSemaphores vkWaitSemaphores;
|
||||
#endif /* defined(VK_VERSION_1_2) */
|
||||
#if defined(VK_AMD_buffer_marker)
|
||||
PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD;
|
||||
#endif /* defined(VK_AMD_buffer_marker) */
|
||||
#if defined(VK_AMD_display_native_hdr)
|
||||
PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD;
|
||||
#endif /* defined(VK_AMD_display_native_hdr) */
|
||||
#if defined(VK_AMD_draw_indirect_count)
|
||||
PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD;
|
||||
PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD;
|
||||
|
@ -238,6 +308,9 @@ struct VolkDeviceTable
|
|||
#if defined(VK_EXT_calibrated_timestamps)
|
||||
PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT;
|
||||
#endif /* defined(VK_EXT_calibrated_timestamps) */
|
||||
#if defined(VK_EXT_color_write_enable)
|
||||
PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT;
|
||||
#endif /* defined(VK_EXT_color_write_enable) */
|
||||
#if defined(VK_EXT_conditional_rendering)
|
||||
PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT;
|
||||
PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT;
|
||||
|
@ -249,16 +322,6 @@ struct VolkDeviceTable
|
|||
PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT;
|
||||
PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT;
|
||||
#endif /* defined(VK_EXT_debug_marker) */
|
||||
#if defined(VK_EXT_debug_utils)
|
||||
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
|
||||
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
|
||||
PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
|
||||
PFN_vkQueueBeginDebugUtilsLabelEXT vkQueueBeginDebugUtilsLabelEXT;
|
||||
PFN_vkQueueEndDebugUtilsLabelEXT vkQueueEndDebugUtilsLabelEXT;
|
||||
PFN_vkQueueInsertDebugUtilsLabelEXT vkQueueInsertDebugUtilsLabelEXT;
|
||||
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
|
||||
PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
|
||||
#endif /* defined(VK_EXT_debug_utils) */
|
||||
#if defined(VK_EXT_discard_rectangles)
|
||||
PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT;
|
||||
#endif /* defined(VK_EXT_discard_rectangles) */
|
||||
|
@ -268,15 +331,56 @@ struct VolkDeviceTable
|
|||
PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT;
|
||||
PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT;
|
||||
#endif /* defined(VK_EXT_display_control) */
|
||||
#if defined(VK_EXT_extended_dynamic_state)
|
||||
PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT;
|
||||
PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT;
|
||||
PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT;
|
||||
PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT;
|
||||
PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT;
|
||||
PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT;
|
||||
PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT;
|
||||
PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT;
|
||||
PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT;
|
||||
PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT;
|
||||
PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT;
|
||||
PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT;
|
||||
#endif /* defined(VK_EXT_extended_dynamic_state) */
|
||||
#if defined(VK_EXT_extended_dynamic_state2)
|
||||
PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT;
|
||||
PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT;
|
||||
PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT;
|
||||
PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT;
|
||||
PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT;
|
||||
#endif /* defined(VK_EXT_extended_dynamic_state2) */
|
||||
#if defined(VK_EXT_external_memory_host)
|
||||
PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT;
|
||||
#endif /* defined(VK_EXT_external_memory_host) */
|
||||
#if defined(VK_EXT_full_screen_exclusive)
|
||||
PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT;
|
||||
PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT;
|
||||
#endif /* defined(VK_EXT_full_screen_exclusive) */
|
||||
#if defined(VK_EXT_hdr_metadata)
|
||||
PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT;
|
||||
#endif /* defined(VK_EXT_hdr_metadata) */
|
||||
#if defined(VK_EXT_host_query_reset)
|
||||
PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
|
||||
#endif /* defined(VK_EXT_host_query_reset) */
|
||||
#if defined(VK_EXT_image_drm_format_modifier)
|
||||
PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT;
|
||||
#endif /* defined(VK_EXT_image_drm_format_modifier) */
|
||||
#if defined(VK_EXT_line_rasterization)
|
||||
PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT;
|
||||
#endif /* defined(VK_EXT_line_rasterization) */
|
||||
#if defined(VK_EXT_multi_draw)
|
||||
PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT;
|
||||
PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT;
|
||||
#endif /* defined(VK_EXT_multi_draw) */
|
||||
#if defined(VK_EXT_private_data)
|
||||
PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT;
|
||||
PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
|
||||
PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT;
|
||||
PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT;
|
||||
#endif /* defined(VK_EXT_private_data) */
|
||||
#if defined(VK_EXT_sample_locations)
|
||||
PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT;
|
||||
#endif /* defined(VK_EXT_sample_locations) */
|
||||
|
@ -294,20 +398,87 @@ struct VolkDeviceTable
|
|||
PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT;
|
||||
PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT;
|
||||
#endif /* defined(VK_EXT_validation_cache) */
|
||||
#if defined(VK_EXT_vertex_input_dynamic_state)
|
||||
PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT;
|
||||
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
|
||||
#if defined(VK_FUCHSIA_external_memory)
|
||||
PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA;
|
||||
PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA;
|
||||
#endif /* defined(VK_FUCHSIA_external_memory) */
|
||||
#if defined(VK_FUCHSIA_external_semaphore)
|
||||
PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA;
|
||||
PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA;
|
||||
#endif /* defined(VK_FUCHSIA_external_semaphore) */
|
||||
#if defined(VK_GOOGLE_display_timing)
|
||||
PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;
|
||||
PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE;
|
||||
#endif /* defined(VK_GOOGLE_display_timing) */
|
||||
#if defined(VK_HUAWEI_invocation_mask)
|
||||
PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI;
|
||||
#endif /* defined(VK_HUAWEI_invocation_mask) */
|
||||
#if defined(VK_HUAWEI_subpass_shading)
|
||||
PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI;
|
||||
PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI;
|
||||
#endif /* defined(VK_HUAWEI_subpass_shading) */
|
||||
#if defined(VK_INTEL_performance_query)
|
||||
PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL;
|
||||
PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL;
|
||||
PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL;
|
||||
PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL;
|
||||
PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL;
|
||||
PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL;
|
||||
PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL;
|
||||
PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL;
|
||||
PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL;
|
||||
#endif /* defined(VK_INTEL_performance_query) */
|
||||
#if defined(VK_KHR_acceleration_structure)
|
||||
PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
|
||||
PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR;
|
||||
PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
|
||||
PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR;
|
||||
PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR;
|
||||
PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR;
|
||||
PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR;
|
||||
PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR;
|
||||
PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR;
|
||||
PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR;
|
||||
PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
|
||||
PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
|
||||
PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
|
||||
PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
|
||||
PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR;
|
||||
PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR;
|
||||
#endif /* defined(VK_KHR_acceleration_structure) */
|
||||
#if defined(VK_KHR_bind_memory2)
|
||||
PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR;
|
||||
PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
|
||||
#endif /* defined(VK_KHR_bind_memory2) */
|
||||
#if defined(VK_KHR_buffer_device_address)
|
||||
PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
|
||||
PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR;
|
||||
PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR;
|
||||
#endif /* defined(VK_KHR_buffer_device_address) */
|
||||
#if defined(VK_KHR_copy_commands2)
|
||||
PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR;
|
||||
PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR;
|
||||
PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR;
|
||||
PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR;
|
||||
PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR;
|
||||
PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR;
|
||||
#endif /* defined(VK_KHR_copy_commands2) */
|
||||
#if defined(VK_KHR_create_renderpass2)
|
||||
PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR;
|
||||
PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR;
|
||||
PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR;
|
||||
PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR;
|
||||
#endif /* defined(VK_KHR_create_renderpass2) */
|
||||
#if defined(VK_KHR_deferred_host_operations)
|
||||
PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR;
|
||||
PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR;
|
||||
PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR;
|
||||
PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR;
|
||||
PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR;
|
||||
#endif /* defined(VK_KHR_deferred_host_operations) */
|
||||
#if defined(VK_KHR_descriptor_update_template)
|
||||
PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
|
||||
PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
|
||||
|
@ -349,6 +520,9 @@ struct VolkDeviceTable
|
|||
PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR;
|
||||
PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR;
|
||||
#endif /* defined(VK_KHR_external_semaphore_win32) */
|
||||
#if defined(VK_KHR_fragment_shading_rate)
|
||||
PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR;
|
||||
#endif /* defined(VK_KHR_fragment_shading_rate) */
|
||||
#if defined(VK_KHR_get_memory_requirements2)
|
||||
PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
|
||||
PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
|
||||
|
@ -360,9 +534,30 @@ struct VolkDeviceTable
|
|||
#if defined(VK_KHR_maintenance3)
|
||||
PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR;
|
||||
#endif /* defined(VK_KHR_maintenance3) */
|
||||
#if defined(VK_KHR_performance_query)
|
||||
PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR;
|
||||
PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR;
|
||||
#endif /* defined(VK_KHR_performance_query) */
|
||||
#if defined(VK_KHR_pipeline_executable_properties)
|
||||
PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR;
|
||||
PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR;
|
||||
PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR;
|
||||
#endif /* defined(VK_KHR_pipeline_executable_properties) */
|
||||
#if defined(VK_KHR_present_wait)
|
||||
PFN_vkWaitForPresentKHR vkWaitForPresentKHR;
|
||||
#endif /* defined(VK_KHR_present_wait) */
|
||||
#if defined(VK_KHR_push_descriptor)
|
||||
PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR;
|
||||
#endif /* defined(VK_KHR_push_descriptor) */
|
||||
#if defined(VK_KHR_ray_tracing_pipeline)
|
||||
PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR;
|
||||
PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR;
|
||||
PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
|
||||
PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
|
||||
PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR;
|
||||
PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
|
||||
PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR;
|
||||
#endif /* defined(VK_KHR_ray_tracing_pipeline) */
|
||||
#if defined(VK_KHR_sampler_ycbcr_conversion)
|
||||
PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
|
||||
PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
|
||||
|
@ -377,17 +572,52 @@ struct VolkDeviceTable
|
|||
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
|
||||
PFN_vkQueuePresentKHR vkQueuePresentKHR;
|
||||
#endif /* defined(VK_KHR_swapchain) */
|
||||
#if defined(VK_NVX_device_generated_commands)
|
||||
PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX;
|
||||
PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX;
|
||||
PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX;
|
||||
PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX;
|
||||
PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX;
|
||||
PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX;
|
||||
PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX;
|
||||
PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX;
|
||||
#endif /* defined(VK_NVX_device_generated_commands) */
|
||||
#if defined(VK_KHR_synchronization2)
|
||||
PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR;
|
||||
PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR;
|
||||
PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR;
|
||||
PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR;
|
||||
PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR;
|
||||
PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR;
|
||||
#endif /* defined(VK_KHR_synchronization2) */
|
||||
#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker)
|
||||
PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD;
|
||||
#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */
|
||||
#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints)
|
||||
PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV;
|
||||
#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */
|
||||
#if defined(VK_KHR_timeline_semaphore)
|
||||
PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR;
|
||||
PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR;
|
||||
PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR;
|
||||
#endif /* defined(VK_KHR_timeline_semaphore) */
|
||||
#if defined(VK_KHR_video_decode_queue)
|
||||
PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR;
|
||||
#endif /* defined(VK_KHR_video_decode_queue) */
|
||||
#if defined(VK_KHR_video_encode_queue)
|
||||
PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR;
|
||||
#endif /* defined(VK_KHR_video_encode_queue) */
|
||||
#if defined(VK_KHR_video_queue)
|
||||
PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR;
|
||||
PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR;
|
||||
PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR;
|
||||
PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR;
|
||||
PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR;
|
||||
PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR;
|
||||
PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR;
|
||||
PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR;
|
||||
PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR;
|
||||
PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR;
|
||||
#endif /* defined(VK_KHR_video_queue) */
|
||||
#if defined(VK_NVX_binary_import)
|
||||
PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX;
|
||||
PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX;
|
||||
PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX;
|
||||
PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX;
|
||||
PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX;
|
||||
#endif /* defined(VK_NVX_binary_import) */
|
||||
#if defined(VK_NVX_image_view_handle)
|
||||
PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX;
|
||||
PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX;
|
||||
#endif /* defined(VK_NVX_image_view_handle) */
|
||||
#if defined(VK_NV_clip_space_w_scaling)
|
||||
|
@ -397,9 +627,23 @@ struct VolkDeviceTable
|
|||
PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV;
|
||||
PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV;
|
||||
#endif /* defined(VK_NV_device_diagnostic_checkpoints) */
|
||||
#if defined(VK_NV_device_generated_commands)
|
||||
PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV;
|
||||
PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV;
|
||||
PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV;
|
||||
PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV;
|
||||
PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV;
|
||||
PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV;
|
||||
#endif /* defined(VK_NV_device_generated_commands) */
|
||||
#if defined(VK_NV_external_memory_rdma)
|
||||
PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV;
|
||||
#endif /* defined(VK_NV_external_memory_rdma) */
|
||||
#if defined(VK_NV_external_memory_win32)
|
||||
PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV;
|
||||
#endif /* defined(VK_NV_external_memory_win32) */
|
||||
#if defined(VK_NV_fragment_shading_rate_enums)
|
||||
PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV;
|
||||
#endif /* defined(VK_NV_fragment_shading_rate_enums) */
|
||||
#if defined(VK_NV_mesh_shader)
|
||||
PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV;
|
||||
PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV;
|
||||
|
@ -427,9 +671,12 @@ struct VolkDeviceTable
|
|||
PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV;
|
||||
PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV;
|
||||
#endif /* defined(VK_NV_shading_rate_image) */
|
||||
#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1))
|
||||
#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1))
|
||||
PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT;
|
||||
#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */
|
||||
#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template))
|
||||
PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR;
|
||||
#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) */
|
||||
#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */
|
||||
#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1))
|
||||
PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR;
|
||||
PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR;
|
||||
|
@ -610,9 +857,27 @@ extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 vkGetPhysicalDeviceSp
|
|||
extern PFN_vkTrimCommandPool vkTrimCommandPool;
|
||||
extern PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate;
|
||||
#endif /* defined(VK_VERSION_1_1) */
|
||||
#if defined(VK_VERSION_1_2)
|
||||
extern PFN_vkCmdBeginRenderPass2 vkCmdBeginRenderPass2;
|
||||
extern PFN_vkCmdDrawIndexedIndirectCount vkCmdDrawIndexedIndirectCount;
|
||||
extern PFN_vkCmdDrawIndirectCount vkCmdDrawIndirectCount;
|
||||
extern PFN_vkCmdEndRenderPass2 vkCmdEndRenderPass2;
|
||||
extern PFN_vkCmdNextSubpass2 vkCmdNextSubpass2;
|
||||
extern PFN_vkCreateRenderPass2 vkCreateRenderPass2;
|
||||
extern PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress;
|
||||
extern PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress;
|
||||
extern PFN_vkGetDeviceMemoryOpaqueCaptureAddress vkGetDeviceMemoryOpaqueCaptureAddress;
|
||||
extern PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue;
|
||||
extern PFN_vkResetQueryPool vkResetQueryPool;
|
||||
extern PFN_vkSignalSemaphore vkSignalSemaphore;
|
||||
extern PFN_vkWaitSemaphores vkWaitSemaphores;
|
||||
#endif /* defined(VK_VERSION_1_2) */
|
||||
#if defined(VK_AMD_buffer_marker)
|
||||
extern PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD;
|
||||
#endif /* defined(VK_AMD_buffer_marker) */
|
||||
#if defined(VK_AMD_display_native_hdr)
|
||||
extern PFN_vkSetLocalDimmingAMD vkSetLocalDimmingAMD;
|
||||
#endif /* defined(VK_AMD_display_native_hdr) */
|
||||
#if defined(VK_AMD_draw_indirect_count)
|
||||
extern PFN_vkCmdDrawIndexedIndirectCountAMD vkCmdDrawIndexedIndirectCountAMD;
|
||||
extern PFN_vkCmdDrawIndirectCountAMD vkCmdDrawIndirectCountAMD;
|
||||
|
@ -624,6 +889,10 @@ extern PFN_vkGetShaderInfoAMD vkGetShaderInfoAMD;
|
|||
extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID;
|
||||
extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID;
|
||||
#endif /* defined(VK_ANDROID_external_memory_android_hardware_buffer) */
|
||||
#if defined(VK_EXT_acquire_drm_display)
|
||||
extern PFN_vkAcquireDrmDisplayEXT vkAcquireDrmDisplayEXT;
|
||||
extern PFN_vkGetDrmDisplayEXT vkGetDrmDisplayEXT;
|
||||
#endif /* defined(VK_EXT_acquire_drm_display) */
|
||||
#if defined(VK_EXT_acquire_xlib_display)
|
||||
extern PFN_vkAcquireXlibDisplayEXT vkAcquireXlibDisplayEXT;
|
||||
extern PFN_vkGetRandROutputDisplayEXT vkGetRandROutputDisplayEXT;
|
||||
|
@ -635,6 +904,9 @@ extern PFN_vkGetBufferDeviceAddressEXT vkGetBufferDeviceAddressEXT;
|
|||
extern PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT;
|
||||
extern PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT;
|
||||
#endif /* defined(VK_EXT_calibrated_timestamps) */
|
||||
#if defined(VK_EXT_color_write_enable)
|
||||
extern PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT;
|
||||
#endif /* defined(VK_EXT_color_write_enable) */
|
||||
#if defined(VK_EXT_conditional_rendering)
|
||||
extern PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT;
|
||||
extern PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT;
|
||||
|
@ -667,6 +939,10 @@ extern PFN_vkSubmitDebugUtilsMessageEXT vkSubmitDebugUtilsMessageEXT;
|
|||
#if defined(VK_EXT_direct_mode_display)
|
||||
extern PFN_vkReleaseDisplayEXT vkReleaseDisplayEXT;
|
||||
#endif /* defined(VK_EXT_direct_mode_display) */
|
||||
#if defined(VK_EXT_directfb_surface)
|
||||
extern PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT;
|
||||
extern PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT vkGetPhysicalDeviceDirectFBPresentationSupportEXT;
|
||||
#endif /* defined(VK_EXT_directfb_surface) */
|
||||
#if defined(VK_EXT_discard_rectangles)
|
||||
extern PFN_vkCmdSetDiscardRectangleEXT vkCmdSetDiscardRectangleEXT;
|
||||
#endif /* defined(VK_EXT_discard_rectangles) */
|
||||
|
@ -679,22 +955,70 @@ extern PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT;
|
|||
#if defined(VK_EXT_display_surface_counter)
|
||||
extern PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
|
||||
#endif /* defined(VK_EXT_display_surface_counter) */
|
||||
#if defined(VK_EXT_extended_dynamic_state)
|
||||
extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT;
|
||||
extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT;
|
||||
extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT;
|
||||
extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT;
|
||||
extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT;
|
||||
extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT;
|
||||
extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT;
|
||||
extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT;
|
||||
extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT;
|
||||
extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT;
|
||||
extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT;
|
||||
extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT;
|
||||
#endif /* defined(VK_EXT_extended_dynamic_state) */
|
||||
#if defined(VK_EXT_extended_dynamic_state2)
|
||||
extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT;
|
||||
extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT;
|
||||
extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT;
|
||||
extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT;
|
||||
extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT;
|
||||
#endif /* defined(VK_EXT_extended_dynamic_state2) */
|
||||
#if defined(VK_EXT_external_memory_host)
|
||||
extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT;
|
||||
#endif /* defined(VK_EXT_external_memory_host) */
|
||||
#if defined(VK_EXT_full_screen_exclusive)
|
||||
extern PFN_vkAcquireFullScreenExclusiveModeEXT vkAcquireFullScreenExclusiveModeEXT;
|
||||
extern PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT vkGetPhysicalDeviceSurfacePresentModes2EXT;
|
||||
extern PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT;
|
||||
#endif /* defined(VK_EXT_full_screen_exclusive) */
|
||||
#if defined(VK_EXT_hdr_metadata)
|
||||
extern PFN_vkSetHdrMetadataEXT vkSetHdrMetadataEXT;
|
||||
#endif /* defined(VK_EXT_hdr_metadata) */
|
||||
#if defined(VK_EXT_headless_surface)
|
||||
extern PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT;
|
||||
#endif /* defined(VK_EXT_headless_surface) */
|
||||
#if defined(VK_EXT_host_query_reset)
|
||||
extern PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
|
||||
#endif /* defined(VK_EXT_host_query_reset) */
|
||||
#if defined(VK_EXT_image_drm_format_modifier)
|
||||
extern PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT;
|
||||
#endif /* defined(VK_EXT_image_drm_format_modifier) */
|
||||
#if defined(VK_EXT_line_rasterization)
|
||||
extern PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT;
|
||||
#endif /* defined(VK_EXT_line_rasterization) */
|
||||
#if defined(VK_EXT_metal_surface)
|
||||
extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
|
||||
#endif /* defined(VK_EXT_metal_surface) */
|
||||
#if defined(VK_EXT_multi_draw)
|
||||
extern PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT;
|
||||
extern PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT;
|
||||
#endif /* defined(VK_EXT_multi_draw) */
|
||||
#if defined(VK_EXT_private_data)
|
||||
extern PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT;
|
||||
extern PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
|
||||
extern PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT;
|
||||
extern PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT;
|
||||
#endif /* defined(VK_EXT_private_data) */
|
||||
#if defined(VK_EXT_sample_locations)
|
||||
extern PFN_vkCmdSetSampleLocationsEXT vkCmdSetSampleLocationsEXT;
|
||||
extern PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT;
|
||||
#endif /* defined(VK_EXT_sample_locations) */
|
||||
#if defined(VK_EXT_tooling_info)
|
||||
extern PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT;
|
||||
#endif /* defined(VK_EXT_tooling_info) */
|
||||
#if defined(VK_EXT_transform_feedback)
|
||||
extern PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT;
|
||||
extern PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT;
|
||||
|
@ -709,13 +1033,63 @@ extern PFN_vkDestroyValidationCacheEXT vkDestroyValidationCacheEXT;
|
|||
extern PFN_vkGetValidationCacheDataEXT vkGetValidationCacheDataEXT;
|
||||
extern PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT;
|
||||
#endif /* defined(VK_EXT_validation_cache) */
|
||||
#if defined(VK_EXT_vertex_input_dynamic_state)
|
||||
extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT;
|
||||
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
|
||||
#if defined(VK_FUCHSIA_external_memory)
|
||||
extern PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA;
|
||||
extern PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA;
|
||||
#endif /* defined(VK_FUCHSIA_external_memory) */
|
||||
#if defined(VK_FUCHSIA_external_semaphore)
|
||||
extern PFN_vkGetSemaphoreZirconHandleFUCHSIA vkGetSemaphoreZirconHandleFUCHSIA;
|
||||
extern PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA;
|
||||
#endif /* defined(VK_FUCHSIA_external_semaphore) */
|
||||
#if defined(VK_FUCHSIA_imagepipe_surface)
|
||||
extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA;
|
||||
#endif /* defined(VK_FUCHSIA_imagepipe_surface) */
|
||||
#if defined(VK_GGP_stream_descriptor_surface)
|
||||
extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP;
|
||||
#endif /* defined(VK_GGP_stream_descriptor_surface) */
|
||||
#if defined(VK_GOOGLE_display_timing)
|
||||
extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;
|
||||
extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE;
|
||||
#endif /* defined(VK_GOOGLE_display_timing) */
|
||||
#if defined(VK_HUAWEI_invocation_mask)
|
||||
extern PFN_vkCmdBindInvocationMaskHUAWEI vkCmdBindInvocationMaskHUAWEI;
|
||||
#endif /* defined(VK_HUAWEI_invocation_mask) */
|
||||
#if defined(VK_HUAWEI_subpass_shading)
|
||||
extern PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI;
|
||||
extern PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI;
|
||||
#endif /* defined(VK_HUAWEI_subpass_shading) */
|
||||
#if defined(VK_INTEL_performance_query)
|
||||
extern PFN_vkAcquirePerformanceConfigurationINTEL vkAcquirePerformanceConfigurationINTEL;
|
||||
extern PFN_vkCmdSetPerformanceMarkerINTEL vkCmdSetPerformanceMarkerINTEL;
|
||||
extern PFN_vkCmdSetPerformanceOverrideINTEL vkCmdSetPerformanceOverrideINTEL;
|
||||
extern PFN_vkCmdSetPerformanceStreamMarkerINTEL vkCmdSetPerformanceStreamMarkerINTEL;
|
||||
extern PFN_vkGetPerformanceParameterINTEL vkGetPerformanceParameterINTEL;
|
||||
extern PFN_vkInitializePerformanceApiINTEL vkInitializePerformanceApiINTEL;
|
||||
extern PFN_vkQueueSetPerformanceConfigurationINTEL vkQueueSetPerformanceConfigurationINTEL;
|
||||
extern PFN_vkReleasePerformanceConfigurationINTEL vkReleasePerformanceConfigurationINTEL;
|
||||
extern PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL;
|
||||
#endif /* defined(VK_INTEL_performance_query) */
|
||||
#if defined(VK_KHR_acceleration_structure)
|
||||
extern PFN_vkBuildAccelerationStructuresKHR vkBuildAccelerationStructuresKHR;
|
||||
extern PFN_vkCmdBuildAccelerationStructuresIndirectKHR vkCmdBuildAccelerationStructuresIndirectKHR;
|
||||
extern PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR;
|
||||
extern PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR;
|
||||
extern PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR;
|
||||
extern PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR;
|
||||
extern PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR;
|
||||
extern PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR;
|
||||
extern PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR;
|
||||
extern PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR;
|
||||
extern PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR;
|
||||
extern PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR;
|
||||
extern PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR;
|
||||
extern PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR;
|
||||
extern PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR;
|
||||
extern PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR;
|
||||
#endif /* defined(VK_KHR_acceleration_structure) */
|
||||
#if defined(VK_KHR_android_surface)
|
||||
extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
|
||||
#endif /* defined(VK_KHR_android_surface) */
|
||||
|
@ -723,12 +1097,32 @@ extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
|
|||
extern PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR;
|
||||
extern PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
|
||||
#endif /* defined(VK_KHR_bind_memory2) */
|
||||
#if defined(VK_KHR_buffer_device_address)
|
||||
extern PFN_vkGetBufferDeviceAddressKHR vkGetBufferDeviceAddressKHR;
|
||||
extern PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR;
|
||||
extern PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR vkGetDeviceMemoryOpaqueCaptureAddressKHR;
|
||||
#endif /* defined(VK_KHR_buffer_device_address) */
|
||||
#if defined(VK_KHR_copy_commands2)
|
||||
extern PFN_vkCmdBlitImage2KHR vkCmdBlitImage2KHR;
|
||||
extern PFN_vkCmdCopyBuffer2KHR vkCmdCopyBuffer2KHR;
|
||||
extern PFN_vkCmdCopyBufferToImage2KHR vkCmdCopyBufferToImage2KHR;
|
||||
extern PFN_vkCmdCopyImage2KHR vkCmdCopyImage2KHR;
|
||||
extern PFN_vkCmdCopyImageToBuffer2KHR vkCmdCopyImageToBuffer2KHR;
|
||||
extern PFN_vkCmdResolveImage2KHR vkCmdResolveImage2KHR;
|
||||
#endif /* defined(VK_KHR_copy_commands2) */
|
||||
#if defined(VK_KHR_create_renderpass2)
|
||||
extern PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR;
|
||||
extern PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR;
|
||||
extern PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR;
|
||||
extern PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR;
|
||||
#endif /* defined(VK_KHR_create_renderpass2) */
|
||||
#if defined(VK_KHR_deferred_host_operations)
|
||||
extern PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR;
|
||||
extern PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR;
|
||||
extern PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR;
|
||||
extern PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR;
|
||||
extern PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR;
|
||||
#endif /* defined(VK_KHR_deferred_host_operations) */
|
||||
#if defined(VK_KHR_descriptor_update_template)
|
||||
extern PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
|
||||
extern PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
|
||||
|
@ -791,6 +1185,10 @@ extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
|
|||
extern PFN_vkGetSemaphoreWin32HandleKHR vkGetSemaphoreWin32HandleKHR;
|
||||
extern PFN_vkImportSemaphoreWin32HandleKHR vkImportSemaphoreWin32HandleKHR;
|
||||
#endif /* defined(VK_KHR_external_semaphore_win32) */
|
||||
#if defined(VK_KHR_fragment_shading_rate)
|
||||
extern PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR;
|
||||
extern PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR;
|
||||
#endif /* defined(VK_KHR_fragment_shading_rate) */
|
||||
#if defined(VK_KHR_get_display_properties2)
|
||||
extern PFN_vkGetDisplayModeProperties2KHR vkGetDisplayModeProperties2KHR;
|
||||
extern PFN_vkGetDisplayPlaneCapabilities2KHR vkGetDisplayPlaneCapabilities2KHR;
|
||||
|
@ -821,9 +1219,32 @@ extern PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR;
|
|||
#if defined(VK_KHR_maintenance3)
|
||||
extern PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR;
|
||||
#endif /* defined(VK_KHR_maintenance3) */
|
||||
#if defined(VK_KHR_performance_query)
|
||||
extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR;
|
||||
extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
|
||||
extern PFN_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR;
|
||||
extern PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR;
|
||||
#endif /* defined(VK_KHR_performance_query) */
|
||||
#if defined(VK_KHR_pipeline_executable_properties)
|
||||
extern PFN_vkGetPipelineExecutableInternalRepresentationsKHR vkGetPipelineExecutableInternalRepresentationsKHR;
|
||||
extern PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR;
|
||||
extern PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR;
|
||||
#endif /* defined(VK_KHR_pipeline_executable_properties) */
|
||||
#if defined(VK_KHR_present_wait)
|
||||
extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR;
|
||||
#endif /* defined(VK_KHR_present_wait) */
|
||||
#if defined(VK_KHR_push_descriptor)
|
||||
extern PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR;
|
||||
#endif /* defined(VK_KHR_push_descriptor) */
|
||||
#if defined(VK_KHR_ray_tracing_pipeline)
|
||||
extern PFN_vkCmdSetRayTracingPipelineStackSizeKHR vkCmdSetRayTracingPipelineStackSizeKHR;
|
||||
extern PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR;
|
||||
extern PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
|
||||
extern PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
|
||||
extern PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR;
|
||||
extern PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
|
||||
extern PFN_vkGetRayTracingShaderGroupStackSizeKHR vkGetRayTracingShaderGroupStackSizeKHR;
|
||||
#endif /* defined(VK_KHR_ray_tracing_pipeline) */
|
||||
#if defined(VK_KHR_sampler_ycbcr_conversion)
|
||||
extern PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
|
||||
extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
|
||||
|
@ -845,6 +1266,45 @@ extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
|
|||
extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
|
||||
extern PFN_vkQueuePresentKHR vkQueuePresentKHR;
|
||||
#endif /* defined(VK_KHR_swapchain) */
|
||||
#if defined(VK_KHR_synchronization2)
|
||||
extern PFN_vkCmdPipelineBarrier2KHR vkCmdPipelineBarrier2KHR;
|
||||
extern PFN_vkCmdResetEvent2KHR vkCmdResetEvent2KHR;
|
||||
extern PFN_vkCmdSetEvent2KHR vkCmdSetEvent2KHR;
|
||||
extern PFN_vkCmdWaitEvents2KHR vkCmdWaitEvents2KHR;
|
||||
extern PFN_vkCmdWriteTimestamp2KHR vkCmdWriteTimestamp2KHR;
|
||||
extern PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR;
|
||||
#endif /* defined(VK_KHR_synchronization2) */
|
||||
#if defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker)
|
||||
extern PFN_vkCmdWriteBufferMarker2AMD vkCmdWriteBufferMarker2AMD;
|
||||
#endif /* defined(VK_KHR_synchronization2) && defined(VK_AMD_buffer_marker) */
|
||||
#if defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints)
|
||||
extern PFN_vkGetQueueCheckpointData2NV vkGetQueueCheckpointData2NV;
|
||||
#endif /* defined(VK_KHR_synchronization2) && defined(VK_NV_device_diagnostic_checkpoints) */
|
||||
#if defined(VK_KHR_timeline_semaphore)
|
||||
extern PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR;
|
||||
extern PFN_vkSignalSemaphoreKHR vkSignalSemaphoreKHR;
|
||||
extern PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR;
|
||||
#endif /* defined(VK_KHR_timeline_semaphore) */
|
||||
#if defined(VK_KHR_video_decode_queue)
|
||||
extern PFN_vkCmdDecodeVideoKHR vkCmdDecodeVideoKHR;
|
||||
#endif /* defined(VK_KHR_video_decode_queue) */
|
||||
#if defined(VK_KHR_video_encode_queue)
|
||||
extern PFN_vkCmdEncodeVideoKHR vkCmdEncodeVideoKHR;
|
||||
#endif /* defined(VK_KHR_video_encode_queue) */
|
||||
#if defined(VK_KHR_video_queue)
|
||||
extern PFN_vkBindVideoSessionMemoryKHR vkBindVideoSessionMemoryKHR;
|
||||
extern PFN_vkCmdBeginVideoCodingKHR vkCmdBeginVideoCodingKHR;
|
||||
extern PFN_vkCmdControlVideoCodingKHR vkCmdControlVideoCodingKHR;
|
||||
extern PFN_vkCmdEndVideoCodingKHR vkCmdEndVideoCodingKHR;
|
||||
extern PFN_vkCreateVideoSessionKHR vkCreateVideoSessionKHR;
|
||||
extern PFN_vkCreateVideoSessionParametersKHR vkCreateVideoSessionParametersKHR;
|
||||
extern PFN_vkDestroyVideoSessionKHR vkDestroyVideoSessionKHR;
|
||||
extern PFN_vkDestroyVideoSessionParametersKHR vkDestroyVideoSessionParametersKHR;
|
||||
extern PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR;
|
||||
extern PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR;
|
||||
extern PFN_vkGetVideoSessionMemoryRequirementsKHR vkGetVideoSessionMemoryRequirementsKHR;
|
||||
extern PFN_vkUpdateVideoSessionParametersKHR vkUpdateVideoSessionParametersKHR;
|
||||
#endif /* defined(VK_KHR_video_queue) */
|
||||
#if defined(VK_KHR_wayland_surface)
|
||||
extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
|
||||
extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR;
|
||||
|
@ -870,36 +1330,54 @@ extern PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
|
|||
#if defined(VK_NN_vi_surface)
|
||||
extern PFN_vkCreateViSurfaceNN vkCreateViSurfaceNN;
|
||||
#endif /* defined(VK_NN_vi_surface) */
|
||||
#if defined(VK_NVX_device_generated_commands)
|
||||
extern PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX;
|
||||
extern PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX;
|
||||
extern PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX;
|
||||
extern PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX;
|
||||
extern PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX;
|
||||
extern PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX;
|
||||
extern PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX;
|
||||
extern PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX;
|
||||
extern PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX;
|
||||
#endif /* defined(VK_NVX_device_generated_commands) */
|
||||
#if defined(VK_NVX_binary_import)
|
||||
extern PFN_vkCmdCuLaunchKernelNVX vkCmdCuLaunchKernelNVX;
|
||||
extern PFN_vkCreateCuFunctionNVX vkCreateCuFunctionNVX;
|
||||
extern PFN_vkCreateCuModuleNVX vkCreateCuModuleNVX;
|
||||
extern PFN_vkDestroyCuFunctionNVX vkDestroyCuFunctionNVX;
|
||||
extern PFN_vkDestroyCuModuleNVX vkDestroyCuModuleNVX;
|
||||
#endif /* defined(VK_NVX_binary_import) */
|
||||
#if defined(VK_NVX_image_view_handle)
|
||||
extern PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX;
|
||||
extern PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX;
|
||||
#endif /* defined(VK_NVX_image_view_handle) */
|
||||
#if defined(VK_NV_acquire_winrt_display)
|
||||
extern PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV;
|
||||
extern PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV;
|
||||
#endif /* defined(VK_NV_acquire_winrt_display) */
|
||||
#if defined(VK_NV_clip_space_w_scaling)
|
||||
extern PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV;
|
||||
#endif /* defined(VK_NV_clip_space_w_scaling) */
|
||||
#if defined(VK_NV_cooperative_matrix)
|
||||
extern PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV vkGetPhysicalDeviceCooperativeMatrixPropertiesNV;
|
||||
#endif /* defined(VK_NV_cooperative_matrix) */
|
||||
#if defined(VK_NV_coverage_reduction_mode)
|
||||
extern PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
|
||||
#endif /* defined(VK_NV_coverage_reduction_mode) */
|
||||
#if defined(VK_NV_device_diagnostic_checkpoints)
|
||||
extern PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV;
|
||||
extern PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV;
|
||||
#endif /* defined(VK_NV_device_diagnostic_checkpoints) */
|
||||
#if defined(VK_NV_device_generated_commands)
|
||||
extern PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV;
|
||||
extern PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV;
|
||||
extern PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV;
|
||||
extern PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV;
|
||||
extern PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV;
|
||||
extern PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV;
|
||||
#endif /* defined(VK_NV_device_generated_commands) */
|
||||
#if defined(VK_NV_external_memory_capabilities)
|
||||
extern PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV vkGetPhysicalDeviceExternalImageFormatPropertiesNV;
|
||||
#endif /* defined(VK_NV_external_memory_capabilities) */
|
||||
#if defined(VK_NV_external_memory_rdma)
|
||||
extern PFN_vkGetMemoryRemoteAddressNV vkGetMemoryRemoteAddressNV;
|
||||
#endif /* defined(VK_NV_external_memory_rdma) */
|
||||
#if defined(VK_NV_external_memory_win32)
|
||||
extern PFN_vkGetMemoryWin32HandleNV vkGetMemoryWin32HandleNV;
|
||||
#endif /* defined(VK_NV_external_memory_win32) */
|
||||
#if defined(VK_NV_fragment_shading_rate_enums)
|
||||
extern PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV;
|
||||
#endif /* defined(VK_NV_fragment_shading_rate_enums) */
|
||||
#if defined(VK_NV_mesh_shader)
|
||||
extern PFN_vkCmdDrawMeshTasksIndirectCountNV vkCmdDrawMeshTasksIndirectCountNV;
|
||||
extern PFN_vkCmdDrawMeshTasksIndirectNV vkCmdDrawMeshTasksIndirectNV;
|
||||
|
@ -927,9 +1405,16 @@ extern PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV;
|
|||
extern PFN_vkCmdSetCoarseSampleOrderNV vkCmdSetCoarseSampleOrderNV;
|
||||
extern PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV;
|
||||
#endif /* defined(VK_NV_shading_rate_image) */
|
||||
#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1))
|
||||
#if defined(VK_QNX_screen_surface)
|
||||
extern PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX;
|
||||
extern PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX vkGetPhysicalDeviceScreenPresentationSupportQNX;
|
||||
#endif /* defined(VK_QNX_screen_surface) */
|
||||
#if (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1))
|
||||
extern PFN_vkGetDeviceGroupSurfacePresentModes2EXT vkGetDeviceGroupSurfacePresentModes2EXT;
|
||||
#endif /* (defined(VK_EXT_full_screen_exclusive) && defined(VK_KHR_device_group)) || (defined(VK_EXT_full_screen_exclusive) && defined(VK_VERSION_1_1)) */
|
||||
#if (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template))
|
||||
extern PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR;
|
||||
#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) */
|
||||
#endif /* (defined(VK_KHR_descriptor_update_template) && defined(VK_KHR_push_descriptor)) || (defined(VK_KHR_push_descriptor) && defined(VK_VERSION_1_1)) || (defined(VK_KHR_push_descriptor) && defined(VK_KHR_descriptor_update_template)) */
|
||||
#if (defined(VK_KHR_device_group) && defined(VK_KHR_surface)) || (defined(VK_KHR_swapchain) && defined(VK_VERSION_1_1))
|
||||
extern PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR;
|
||||
extern PFN_vkGetDeviceGroupSurfacePresentModesKHR vkGetDeviceGroupSurfacePresentModesKHR;
|
||||
|
@ -946,6 +1431,14 @@ extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef VOLK_IMPLEMENTATION
|
||||
#undef VOLK_IMPLEMENTATION
|
||||
// Prevent tools like dependency checkers that don't evaluate
|
||||
// macros from detecting a cyclic dependency.
|
||||
#define VOLK_SOURCE "volk.c"
|
||||
#include VOLK_SOURCE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copyright (c) 2018-2019 Arseny Kapoulkine
|
||||
*
|
||||
|
@ -967,3 +1460,4 @@ extern PFN_vkAcquireNextImage2KHR vkAcquireNextImage2KHR;
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
/* clang-format on */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue