Skip to content

Commit

Permalink
- fix vulkan crash when there are no textures in player's view
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed Feb 15, 2020
1 parent c485256 commit 08e86b5
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
39 changes: 39 additions & 0 deletions src/rendering/vulkan/renderer/vk_renderpass.cpp
Expand Up @@ -23,6 +23,7 @@
#include "vk_renderpass.h"
#include "vk_renderbuffers.h"
#include "vk_renderstate.h"
#include "vulkan/textures/vk_samplers.h"
#include "vulkan/shaders/vk_shader.h"
#include "vulkan/system/vk_builders.h"
#include "vulkan/system/vk_framebuffer.h"
Expand All @@ -45,6 +46,7 @@ void VkRenderPassManager::Init()
CreateDynamicSetLayout();
CreateDescriptorPool();
CreateDynamicSet();
CreateNullTexture();
}

void VkRenderPassManager::RenderBuffersReset()
Expand All @@ -63,6 +65,7 @@ void VkRenderPassManager::TextureSetPoolReset()
deleteList.DescriptorPools.push_back(std::move(desc));
}
}
NullTextureDescriptorSet.reset();
TextureDescriptorPools.clear();
TextureDescriptorSetsLeft = 0;
TextureDescriptorsLeft = 0;
Expand Down Expand Up @@ -187,6 +190,42 @@ void VkRenderPassManager::CreateDynamicSet()
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(1);

auto fb = GetVulkanFrameBuffer();
WriteDescriptors update;
update.addCombinedImageSampler(NullTextureDescriptorSet.get(), 0, NullTextureView.get(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
update.updateSets(fb->device);
}

return NullTextureDescriptorSet.get();
}

void VkRenderPassManager::UpdateDynamicSet()
{
auto fb = GetVulkanFrameBuffer();
Expand Down
7 changes: 7 additions & 0 deletions src/rendering/vulkan/renderer/vk_renderpass.h
Expand Up @@ -93,6 +93,8 @@ class VkRenderPassManager
std::unique_ptr<VulkanDescriptorSet> AllocateTextureDescriptorSet(int numLayers);
VulkanPipelineLayout* GetPipelineLayout(int numLayers);

VulkanDescriptorSet* GetNullTextureDescriptorSet();

std::unique_ptr<VulkanDescriptorSetLayout> DynamicSetLayout;
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;

Expand All @@ -102,6 +104,7 @@ class VkRenderPassManager
void CreateDynamicSetLayout();
void CreateDescriptorPool();
void CreateDynamicSet();
void CreateNullTexture();

VulkanDescriptorSetLayout *GetTextureSetLayout(int numLayers);

Expand All @@ -112,4 +115,8 @@ class VkRenderPassManager
std::vector<std::unique_ptr<VulkanDescriptorSetLayout>> TextureSetLayouts;
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;
};
17 changes: 8 additions & 9 deletions src/rendering/vulkan/renderer/vk_renderstate.cpp
Expand Up @@ -228,7 +228,7 @@ void VkRenderState::ApplyRenderPass(int dt)
pipelineKey.StencilPassOp = mStencilOp;
pipelineKey.ColorMask = mColorMask;
pipelineKey.CullMode = mCullMode;
pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 0;
pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 1; // Always force minimum 1 texture as the shader requires it
if (mSpecialEffect > EFF_NONE)
{
pipelineKey.SpecialEffect = mSpecialEffect;
Expand Down Expand Up @@ -423,16 +423,15 @@ void VkRenderState::ApplyVertexBuffers()

void VkRenderState::ApplyMaterial()
{
if (mMaterial.mChanged && mMaterial.mMaterial)
if (mMaterial.mChanged)
{
auto base = static_cast<VkHardwareTexture*>(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation));
if (base)
{
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, base->GetDescriptorSet(mMaterial));
}
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();

VkHardwareTexture* base = mMaterial.mMaterial ? static_cast<VkHardwareTexture*>(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)) : nullptr;
VulkanDescriptorSet* descriptorset = base ? base->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet();

mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptorset);
mMaterial.mChanged = false;
}
}
Expand Down

0 comments on commit 08e86b5

Please sign in to comment.