Add support for rendering into 3d textures on Vulkan

#136
This commit is contained in:
Wojtek Figat
2021-05-18 11:40:38 +02:00
parent 5a7efe9019
commit 9cba6bad6d
10 changed files with 89 additions and 102 deletions

View File

@@ -145,6 +145,11 @@ MaterialShader* MaterialShader::CreateDummy(MemoryReadStream& shaderCacheStream,
return material; return material;
} }
GPUShader* MaterialShader::GetShader() const
{
return _shader;
}
const MaterialInfo& MaterialShader::GetInfo() const const MaterialInfo& MaterialShader::GetInfo() const
{ {
return _info; return _info;

View File

@@ -100,6 +100,8 @@ public:
/// <returns>The created and loaded material or null if failed.</returns> /// <returns>The created and loaded material or null if failed.</returns>
static MaterialShader* CreateDummy(MemoryReadStream& shaderCacheStream, const MaterialInfo& info); static MaterialShader* CreateDummy(MemoryReadStream& shaderCacheStream, const MaterialInfo& info);
GPUShader* GetShader() const;
/// <summary> /// <summary>
/// Clears the loaded data. /// Clears the loaded data.
/// </summary> /// </summary>

View File

@@ -82,6 +82,9 @@ bool GPUShader::Create(MemoryReadStream& stream)
int32 shadersCount; int32 shadersCount;
stream.ReadInt32(&shadersCount); stream.ReadInt32(&shadersCount);
GPUShaderProgramInitializer initializer; GPUShaderProgramInitializer initializer;
#if !BUILD_RELEASE
initializer.Owner = this;
#endif
for (int32 i = 0; i < shadersCount; i++) for (int32 i = 0; i < shadersCount; i++)
{ {
const ShaderStage type = static_cast<ShaderStage>(stream.ReadByte()); const ShaderStage type = static_cast<ShaderStage>(stream.ReadByte());

View File

@@ -6,6 +6,8 @@
#include "Engine/Core/Types/String.h" #include "Engine/Core/Types/String.h"
#include "Config.h" #include "Config.h"
class GPUShader;
/// <summary> /// <summary>
/// The shader program metadata container. Contains description about resources used by the shader. /// The shader program metadata container. Contains description about resources used by the shader.
/// </summary> /// </summary>
@@ -37,6 +39,9 @@ struct GPUShaderProgramInitializer
StringAnsi Name; StringAnsi Name;
ShaderBindings Bindings; ShaderBindings Bindings;
ShaderFlags Flags; ShaderFlags Flags;
#if !BUILD_RELEASE
GPUShader* Owner;
#endif
}; };
/// <summary> /// <summary>
@@ -49,12 +54,18 @@ protected:
StringAnsi _name; StringAnsi _name;
ShaderBindings _bindings; ShaderBindings _bindings;
ShaderFlags _flags; ShaderFlags _flags;
#if !BUILD_RELEASE
GPUShader* _owner;
#endif
void Init(const GPUShaderProgramInitializer& initializer) void Init(const GPUShaderProgramInitializer& initializer)
{ {
_name = initializer.Name; _name = initializer.Name;
_bindings = initializer.Bindings; _bindings = initializer.Bindings;
_flags = initializer.Flags; _flags = initializer.Flags;
#if !BUILD_RELEASE
_owner = initializer.Owner;
#endif
} }
public: public:
@@ -69,9 +80,8 @@ public:
public: public:
/// <summary> /// <summary>
/// Gets name of the shader program /// Gets name of the shader program.
/// </summary> /// </summary>
/// <returns>Name</returns>
FORCE_INLINE const StringAnsi& GetName() const FORCE_INLINE const StringAnsi& GetName() const
{ {
return _name; return _name;
@@ -80,7 +90,6 @@ public:
/// <summary> /// <summary>
/// Gets the shader resource bindings. /// Gets the shader resource bindings.
/// </summary> /// </summary>
/// <returns>The bindings.</returns>
FORCE_INLINE const ShaderBindings& GetBindings() const FORCE_INLINE const ShaderBindings& GetBindings() const
{ {
return _bindings; return _bindings;
@@ -89,7 +98,6 @@ public:
/// <summary> /// <summary>
/// Gets the shader flags. /// Gets the shader flags.
/// </summary> /// </summary>
/// <returns>The flags.</returns>
FORCE_INLINE ShaderFlags GetFlags() const FORCE_INLINE ShaderFlags GetFlags() const
{ {
return _flags; return _flags;
@@ -98,21 +106,18 @@ public:
public: public:
/// <summary> /// <summary>
/// Gets shader program stage type /// Gets shader program stage type.
/// </summary> /// </summary>
/// <returns>Shader Stage type</returns>
virtual ShaderStage GetStage() const = 0; virtual ShaderStage GetStage() const = 0;
/// <summary> /// <summary>
/// Gets buffer handle (platform dependent) /// Gets buffer handle (platform dependent).
/// </summary> /// </summary>
/// <returns>Handle</returns>
virtual void* GetBufferHandle() const = 0; virtual void* GetBufferHandle() const = 0;
/// <summary> /// <summary>
/// Gets buffer size (in bytes) /// Gets buffer size (in bytes).
/// </summary> /// </summary>
/// <returns>Size of the buffer in bytes</returns>
virtual uint32 GetBufferSize() const = 0; virtual uint32 GetBufferSize() const = 0;
}; };
@@ -124,15 +129,13 @@ class GPUShaderProgramVS : public GPUShaderProgram
public: public:
/// <summary> /// <summary>
/// Gets input layout description handle (platform dependent) /// Gets input layout description handle (platform dependent).
/// </summary> /// </summary>
/// <returns>Input layout</returns>
virtual void* GetInputLayout() const = 0; virtual void* GetInputLayout() const = 0;
/// <summary> /// <summary>
/// Gets input layout description size (in bytes) /// Gets input layout description size (in bytes).
/// </summary> /// </summary>
/// <returns>Input layout description size in bytes</returns>
virtual byte GetInputLayoutSize() const = 0; virtual byte GetInputLayoutSize() const = 0;
public: public:

View File

@@ -346,7 +346,6 @@ void GPUContextVulkan::BeginRenderPass()
{ {
layout.RTVsFormats[i] = handle->GetFormat(); layout.RTVsFormats[i] = handle->GetFormat();
framebufferKey.Attachments[i] = handle->GetFramebufferView(); framebufferKey.Attachments[i] = handle->GetFramebufferView();
AddImageBarrier(handle, handle->LayoutRTV); AddImageBarrier(handle, handle->LayoutRTV);
} }
else else
@@ -355,36 +354,31 @@ void GPUContextVulkan::BeginRenderPass()
framebufferKey.Attachments[i] = VK_NULL_HANDLE; framebufferKey.Attachments[i] = VK_NULL_HANDLE;
} }
} }
GPUTextureViewVulkan* handle;
if (_rtDepth) if (_rtDepth)
{ {
auto handle = _rtDepth; handle = _rtDepth;
layout.MSAA = handle->GetMSAA();
layout.Extent = handle->Extent;
layout.ReadDepth = true; // TODO: use proper depthStencilAccess flags layout.ReadDepth = true; // TODO: use proper depthStencilAccess flags
layout.WriteDepth = handle->LayoutRTV == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // TODO: do it in a proper way layout.WriteDepth = handle->LayoutRTV == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // TODO: do it in a proper way
framebufferKey.AttachmentCount++; framebufferKey.AttachmentCount++;
framebufferKey.Attachments[_rtCount] = handle->GetFramebufferView(); framebufferKey.Attachments[_rtCount] = handle->GetFramebufferView();
AddImageBarrier(handle, handle->LayoutRTV); AddImageBarrier(handle, handle->LayoutRTV);
} }
else if (_rtHandles[0])
{
layout.MSAA = _rtHandles[0]->GetMSAA();
layout.Extent = _rtHandles[0]->Extent;
layout.ReadDepth = false;
layout.WriteDepth = false;
}
else else
{ {
// No depth or render target binded? handle = _rtHandles[0];
CRASH; layout.ReadDepth = false;
layout.WriteDepth = false;
} }
layout.MSAA = handle->GetMSAA();
layout.Extent.width = handle->Extent.width;
layout.Extent.height = handle->Extent.height;
layout.Layers = handle->Layers;
// Get or create objects // Get or create objects
auto renderPass = _device->GetOrCreateRenderPass(layout); auto renderPass = _device->GetOrCreateRenderPass(layout);
framebufferKey.RenderPass = renderPass; framebufferKey.RenderPass = renderPass;
uint32 layers = 1; // TODO: support rendering to many layers (eg. texture array) auto framebuffer = _device->GetOrCreateFramebuffer(framebufferKey, layout.Extent, layout.Layers);
auto framebuffer = _device->GetOrCreateFramebuffer(framebufferKey, layout.Extent, layers);
_renderPass = renderPass; _renderPass = renderPass;
FlushBarriers(); FlushBarriers();
@@ -519,7 +513,7 @@ void GPUContextVulkan::UpdateDescriptorSets(const SpirvShaderDescriptorInfo& des
} }
default: default:
// Unknown or invalid descriptor type // Unknown or invalid descriptor type
CRASH; CRASH;
break; break;
} }
} }

View File

@@ -61,7 +61,6 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT m
if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
{ {
msgPrefix = TEXT("ERROR"); msgPrefix = TEXT("ERROR");
if (!StringUtils::Compare(layerPrefix, "SC")) if (!StringUtils::Compare(layerPrefix, "SC"))
{ {
if (msgCode == 3) if (msgCode == 3)
@@ -79,7 +78,6 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT m
else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
{ {
msgPrefix = TEXT("WARN"); msgPrefix = TEXT("WARN");
if (!StringUtils::Compare(layerPrefix, "SC")) if (!StringUtils::Compare(layerPrefix, "SC"))
{ {
if (msgCode == 2) if (msgCode == 2)
@@ -92,7 +90,6 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT m
else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
{ {
msgPrefix = TEXT("PERF"); msgPrefix = TEXT("PERF");
if (!StringUtils::Compare(layerPrefix, "SC")) if (!StringUtils::Compare(layerPrefix, "SC"))
{ {
if (msgCode == 2) if (msgCode == 2)
@@ -118,14 +115,8 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT m
{ {
msgPrefix = TEXT("DEBUG"); msgPrefix = TEXT("DEBUG");
} }
else
{
CRASH;
}
// Send info
LOG(Info, "[Vulkan] {0}:{1}:{2} {3}", msgPrefix, String(layerPrefix), msgCode, String(msg)); LOG(Info, "[Vulkan] {0}:{1}:{2} {3}", msgPrefix, String(layerPrefix), msgCode, String(msg));
return VK_FALSE; return VK_FALSE;
} }
@@ -147,6 +138,9 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever
case 5: // SPIR-V module not valid: MemoryBarrier: Vulkan specification requires Memory Semantics to have one of the following bits set: Acquire, Release, AcquireRelease or SequentiallyConsistent case 5: // SPIR-V module not valid: MemoryBarrier: Vulkan specification requires Memory Semantics to have one of the following bits set: Acquire, Release, AcquireRelease or SequentiallyConsistent
case -1666394502: // After query pool creation, each query must be reset before it is used. Queries must also be reset between uses. case -1666394502: // After query pool creation, each query must be reset before it is used. Queries must also be reset between uses.
case 602160055: // Attachment 4 not written by fragment shader; undefined values will be written to attachment. TODO: investigate it for PS_GBuffer shader from Deferred material with USE_LIGHTMAP=1 case 602160055: // Attachment 4 not written by fragment shader; undefined values will be written to attachment. TODO: investigate it for PS_GBuffer shader from Deferred material with USE_LIGHTMAP=1
case 7060244: // Image Operand Offset can only be used with OpImage*Gather operations
case -1539028524: // SortedIndices is null so Vulkan backend sets it to default R32_SFLOAT format which is not good for UINT format of the buffer
case -1810835948: // SortedIndices is null so Vulkan backend sets it to default R32_SFLOAT format which is not good for UINT format of the buffer
return VK_FALSE; return VK_FALSE;
} }
break; break;
@@ -214,15 +208,10 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever
type = TEXT("Perf"); type = TEXT("Perf");
} }
// Send info
if (callbackData->pMessageIdName) if (callbackData->pMessageIdName)
{
LOG(Info, "[Vulkan] {0} {1}:{2}({3}) {4}", type, severity, callbackData->messageIdNumber, String(callbackData->pMessageIdName), String(callbackData->pMessage)); LOG(Info, "[Vulkan] {0} {1}:{2}({3}) {4}", type, severity, callbackData->messageIdNumber, String(callbackData->pMessageIdName), String(callbackData->pMessage));
}
else else
{
LOG(Info, "[Vulkan] {0} {1}:{2} {3}", type, severity, callbackData->messageIdNumber, String(callbackData->pMessage)); LOG(Info, "[Vulkan] {0} {1}:{2} {3}", type, severity, callbackData->messageIdNumber, String(callbackData->pMessage));
}
return VK_FALSE; return VK_FALSE;
} }
@@ -440,10 +429,11 @@ uint32 GetHash(const RenderTargetLayoutVulkan& key)
CombineHash(hash, (uint32)key.WriteDepth); CombineHash(hash, (uint32)key.WriteDepth);
CombineHash(hash, (uint32)key.DepthFormat * 93473262); CombineHash(hash, (uint32)key.DepthFormat * 93473262);
CombineHash(hash, key.RTsCount * 136); CombineHash(hash, key.RTsCount * 136);
CombineHash(hash, key.Extent.width);
CombineHash(hash, key.Extent.height);
CombineHash(hash, key.Layers);
for (int32 i = 0; i < ARRAY_COUNT(key.RTVsFormats); i++) for (int32 i = 0; i < ARRAY_COUNT(key.RTVsFormats); i++)
{
CombineHash(hash, (uint32)key.RTVsFormats[i]); CombineHash(hash, (uint32)key.RTVsFormats[i]);
}
return hash; return hash;
} }
@@ -452,13 +442,11 @@ uint32 GetHash(const FramebufferVulkan::Key& key)
uint32 hash = (int32)(intptr)key.RenderPass; uint32 hash = (int32)(intptr)key.RenderPass;
CombineHash(hash, (uint32)key.AttachmentCount * 136); CombineHash(hash, (uint32)key.AttachmentCount * 136);
for (int32 i = 0; i < ARRAY_COUNT(key.Attachments); i++) for (int32 i = 0; i < ARRAY_COUNT(key.Attachments); i++)
{
CombineHash(hash, (uint32)(intptr)key.Attachments[i]); CombineHash(hash, (uint32)(intptr)key.Attachments[i]);
}
return hash; return hash;
} }
FramebufferVulkan::FramebufferVulkan(GPUDeviceVulkan* device, Key& key, VkExtent3D& extent, uint32 layers) FramebufferVulkan::FramebufferVulkan(GPUDeviceVulkan* device, Key& key, VkExtent2D& extent, uint32 layers)
: _device(device) : _device(device)
, _handle(VK_NULL_HANDLE) , _handle(VK_NULL_HANDLE)
, Extent(extent) , Extent(extent)
@@ -1271,33 +1259,23 @@ GPUDeviceVulkan::~GPUDeviceVulkan()
RenderPassVulkan* GPUDeviceVulkan::GetOrCreateRenderPass(RenderTargetLayoutVulkan& layout) RenderPassVulkan* GPUDeviceVulkan::GetOrCreateRenderPass(RenderTargetLayoutVulkan& layout)
{ {
// Try reuse cached version
RenderPassVulkan* renderPass; RenderPassVulkan* renderPass;
if (_renderPasses.TryGet(layout, renderPass)) if (_renderPasses.TryGet(layout, renderPass))
{
return renderPass; return renderPass;
}
PROFILE_CPU_NAMED("Create Render Pass"); PROFILE_CPU_NAMED("Create Render Pass");
// Create object and cache it
renderPass = New<RenderPassVulkan>(this, layout); renderPass = New<RenderPassVulkan>(this, layout);
_renderPasses.Add(layout, renderPass); _renderPasses.Add(layout, renderPass);
return renderPass; return renderPass;
} }
FramebufferVulkan* GPUDeviceVulkan::GetOrCreateFramebuffer(FramebufferVulkan::Key& key, VkExtent3D& extent, uint32 layers) FramebufferVulkan* GPUDeviceVulkan::GetOrCreateFramebuffer(FramebufferVulkan::Key& key, VkExtent2D& extent, uint32 layers)
{ {
// Try reuse cached version
FramebufferVulkan* framebuffer; FramebufferVulkan* framebuffer;
if (_framebuffers.TryGet(key, framebuffer)) if (_framebuffers.TryGet(key, framebuffer))
{
return framebuffer; return framebuffer;
}
PROFILE_CPU_NAMED("Create Framebuffer"); PROFILE_CPU_NAMED("Create Framebuffer");
// Create object and cache it
framebuffer = New<FramebufferVulkan>(this, key, extent, layers); framebuffer = New<FramebufferVulkan>(this, key, extent, layers);
_framebuffers.Add(key, framebuffer); _framebuffers.Add(key, framebuffer);
return framebuffer; return framebuffer;
@@ -1305,16 +1283,11 @@ FramebufferVulkan* GPUDeviceVulkan::GetOrCreateFramebuffer(FramebufferVulkan::Ke
PipelineLayoutVulkan* GPUDeviceVulkan::GetOrCreateLayout(DescriptorSetLayoutInfoVulkan& key) PipelineLayoutVulkan* GPUDeviceVulkan::GetOrCreateLayout(DescriptorSetLayoutInfoVulkan& key)
{ {
// Try reuse cached version
PipelineLayoutVulkan* layout; PipelineLayoutVulkan* layout;
if (_layouts.TryGet(key, layout)) if (_layouts.TryGet(key, layout))
{
return layout; return layout;
}
PROFILE_CPU_NAMED("Create Pipeline Layout"); PROFILE_CPU_NAMED("Create Pipeline Layout");
// Create object and cache it
layout = New<PipelineLayoutVulkan>(this, key); layout = New<PipelineLayoutVulkan>(this, key);
_layouts.Add(key, layout); _layouts.Add(key, layout);
return layout; return layout;
@@ -1698,7 +1671,11 @@ bool GPUDeviceVulkan::Init()
auto& limits = Limits; auto& limits = Limits;
limits.HasCompute = GetShaderProfile() == ShaderProfile::Vulkan_SM5 && PhysicalDeviceLimits.maxComputeWorkGroupCount[0] >= GPU_MAX_CS_DISPATCH_THREAD_GROUPS && PhysicalDeviceLimits.maxComputeWorkGroupCount[1] >= GPU_MAX_CS_DISPATCH_THREAD_GROUPS; limits.HasCompute = GetShaderProfile() == ShaderProfile::Vulkan_SM5 && PhysicalDeviceLimits.maxComputeWorkGroupCount[0] >= GPU_MAX_CS_DISPATCH_THREAD_GROUPS && PhysicalDeviceLimits.maxComputeWorkGroupCount[1] >= GPU_MAX_CS_DISPATCH_THREAD_GROUPS;
limits.HasTessellation = !!PhysicalDeviceFeatures.tessellationShader && PhysicalDeviceLimits.maxBoundDescriptorSets > (uint32_t)DescriptorSet::Domain; limits.HasTessellation = !!PhysicalDeviceFeatures.tessellationShader && PhysicalDeviceLimits.maxBoundDescriptorSets > (uint32_t)DescriptorSet::Domain;
limits.HasGeometryShaders = false; // TODO: add geometry shaders support for Vulkan #if PLATFORM_ANDROID
limits.HasGeometryShaders = false; // Don't even try GS on mobile
#else
limits.HasGeometryShaders = !!PhysicalDeviceFeatures.geometryShader;
#endif
limits.HasInstancing = true; limits.HasInstancing = true;
limits.HasVolumeTextureRendering = true; limits.HasVolumeTextureRendering = true;
limits.HasDrawIndirect = PhysicalDeviceLimits.maxDrawIndirectCount >= 1; limits.HasDrawIndirect = PhysicalDeviceLimits.maxDrawIndirectCount >= 1;

View File

@@ -237,13 +237,14 @@ public:
bool WriteDepth; bool WriteDepth;
PixelFormat DepthFormat; PixelFormat DepthFormat;
PixelFormat RTVsFormats[GPU_MAX_RT_BINDED]; PixelFormat RTVsFormats[GPU_MAX_RT_BINDED];
VkExtent3D Extent; VkExtent2D Extent;
uint32 Layers;
public: public:
bool operator==(const RenderTargetLayoutVulkan& other) const bool operator==(const RenderTargetLayoutVulkan& other) const
{ {
return Platform::MemoryCompare((void*)this, &other, sizeof(RenderTargetLayoutVulkan)) == 0; return Platform::MemoryCompare(this, &other, sizeof(RenderTargetLayoutVulkan)) == 0;
} }
}; };
@@ -263,7 +264,7 @@ public:
bool operator==(const Key& other) const bool operator==(const Key& other) const
{ {
return Platform::MemoryCompare((void*)this, &other, sizeof(Key)) == 0; return Platform::MemoryCompare(this, &other, sizeof(Key)) == 0;
} }
}; };
@@ -274,13 +275,13 @@ private:
public: public:
FramebufferVulkan(GPUDeviceVulkan* device, Key& key, VkExtent3D& extent, uint32 layers); FramebufferVulkan(GPUDeviceVulkan* device, Key& key, VkExtent2D& extent, uint32 layers);
~FramebufferVulkan(); ~FramebufferVulkan();
public: public:
VkImageView Attachments[GPU_MAX_RT_BINDED + 1]; VkImageView Attachments[GPU_MAX_RT_BINDED + 1];
VkExtent3D Extent; VkExtent2D Extent;
uint32 Layers; uint32 Layers;
public: public:
@@ -498,8 +499,6 @@ private:
public: public:
// Create new graphics device (returns Vulkan if failed)
// @returns Created device or Vulkan
static GPUDevice* Create(); static GPUDevice* Create();
/// <summary> /// <summary>
@@ -685,7 +684,7 @@ public:
} }
RenderPassVulkan* GetOrCreateRenderPass(RenderTargetLayoutVulkan& layout); RenderPassVulkan* GetOrCreateRenderPass(RenderTargetLayoutVulkan& layout);
FramebufferVulkan* GetOrCreateFramebuffer(FramebufferVulkan::Key& key, VkExtent3D& extent, uint32 layers); FramebufferVulkan* GetOrCreateFramebuffer(FramebufferVulkan::Key& key, VkExtent2D& extent, uint32 layers);
PipelineLayoutVulkan* GetOrCreateLayout(DescriptorSetLayoutInfoVulkan& key); PipelineLayoutVulkan* GetOrCreateLayout(DescriptorSetLayoutInfoVulkan& key);
void OnImageViewDestroy(VkImageView imageView); void OnImageViewDestroy(VkImageView imageView);

View File

@@ -21,6 +21,7 @@ void GPUTextureViewVulkan::Init(GPUDeviceVulkan* device, ResourceOwnerVulkan* ow
Extent.width = Math::Max<uint32_t>(1, extent.width >> firstMipIndex); Extent.width = Math::Max<uint32_t>(1, extent.width >> firstMipIndex);
Extent.height = Math::Max<uint32_t>(1, extent.height >> firstMipIndex); Extent.height = Math::Max<uint32_t>(1, extent.height >> firstMipIndex);
Extent.depth = Math::Max<uint32_t>(1, extent.depth >> firstMipIndex); Extent.depth = Math::Max<uint32_t>(1, extent.depth >> firstMipIndex);
Layers = arraySize;
RenderToolsVulkan::ZeroStruct(Info, VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO); RenderToolsVulkan::ZeroStruct(Info, VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
Info.image = image; Info.image = image;
@@ -74,16 +75,30 @@ VkImageView GPUTextureViewVulkan::GetFramebufferView()
if (ViewFramebuffer) if (ViewFramebuffer)
return ViewFramebuffer; return ViewFramebuffer;
if (Info.subresourceRange.levelCount == 1) if (Info.viewType == VK_IMAGE_VIEW_TYPE_3D)
return View; {
// Special case:
// Special case: // Render Target Handle to a 3D Volume texture.
// Render Target Handle can be created for full texture including its mip maps but framebuffer image view can use only a single surface // Use it as Texture2D Array with layers.
// Use an additional view for that case with modified level count to 1. VkImageViewCreateInfo createInfo = Info;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
VkImageViewCreateInfo createInfo = Info; createInfo.subresourceRange.layerCount = Extent.depth;
createInfo.subresourceRange.levelCount = 1; Layers = Extent.depth;
VALIDATE_VULKAN_RESULT(vkCreateImageView(Device->Device, &createInfo, nullptr, &ViewFramebuffer)); VALIDATE_VULKAN_RESULT(vkCreateImageView(Device->Device, &createInfo, nullptr, &ViewFramebuffer));
}
else if (Info.subresourceRange.levelCount != 1)
{
// Special case:
// Render Target Handle can be created for full texture including its mip maps but framebuffer image view can use only a single surface
// Use an additional view for that case with modified level count to 1.
VkImageViewCreateInfo createInfo = Info;
createInfo.subresourceRange.levelCount = 1;
VALIDATE_VULKAN_RESULT(vkCreateImageView(Device->Device, &createInfo, nullptr, &ViewFramebuffer));
}
else
{
ViewFramebuffer = View;
}
return ViewFramebuffer; return ViewFramebuffer;
} }
@@ -92,15 +107,15 @@ void GPUTextureViewVulkan::Release()
{ {
if (View != VK_NULL_HANDLE) if (View != VK_NULL_HANDLE)
{ {
Device->OnImageViewDestroy(View); if (ViewFramebuffer != View && ViewFramebuffer != VK_NULL_HANDLE)
Device->DeferredDeletionQueue.EnqueueResource(DeferredDeletionQueueVulkan::Type::ImageView, View);
if (ViewFramebuffer != VK_NULL_HANDLE)
{ {
Device->OnImageViewDestroy(ViewFramebuffer); Device->OnImageViewDestroy(ViewFramebuffer);
Device->DeferredDeletionQueue.EnqueueResource(DeferredDeletionQueueVulkan::Type::ImageView, ViewFramebuffer); Device->DeferredDeletionQueue.EnqueueResource(DeferredDeletionQueueVulkan::Type::ImageView, ViewFramebuffer);
} }
Device->OnImageViewDestroy(View);
Device->DeferredDeletionQueue.EnqueueResource(DeferredDeletionQueueVulkan::Type::ImageView, View);
View = VK_NULL_HANDLE; View = VK_NULL_HANDLE;
ViewFramebuffer = VK_NULL_HANDLE; ViewFramebuffer = VK_NULL_HANDLE;
@@ -236,32 +251,20 @@ bool GPUTextureVulkan::OnInit()
imageInfo.extent.depth = Depth(); imageInfo.extent.depth = Depth();
imageInfo.flags = IsCubeMap() ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; imageInfo.flags = IsCubeMap() ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
if (IsSRGB()) if (IsSRGB())
{
imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; imageInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
}
#if VK_KHR_maintenance1 #if VK_KHR_maintenance1
if (_device->OptionalDeviceExtensions.HasKHRMaintenance1 && imageInfo.imageType == VK_IMAGE_TYPE_3D) if (_device->OptionalDeviceExtensions.HasKHRMaintenance1 && imageInfo.imageType == VK_IMAGE_TYPE_3D)
{
imageInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR; imageInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
}
#endif #endif
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
if (useSRV) if (useSRV)
{
imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
if (useDSV) if (useDSV)
{
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
}
if (useRTV) if (useRTV)
{
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
if (useUAV) if (useUAV)
{
imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT; imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
}
imageInfo.tiling = optimalTiling ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR; imageInfo.tiling = optimalTiling ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR;
imageInfo.samples = (VkSampleCountFlagBits)MultiSampleLevel(); imageInfo.samples = (VkSampleCountFlagBits)MultiSampleLevel();
// TODO: set initialLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for IsRegularTexture() ??? // TODO: set initialLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for IsRegularTexture() ???

View File

@@ -51,6 +51,7 @@ public:
VkImageView View = VK_NULL_HANDLE; VkImageView View = VK_NULL_HANDLE;
VkImageView ViewFramebuffer = VK_NULL_HANDLE; VkImageView ViewFramebuffer = VK_NULL_HANDLE;
VkExtent3D Extent; VkExtent3D Extent;
uint32 Layers;
VkImageViewCreateInfo Info; VkImageViewCreateInfo Info;
int32 SubresourceIndex; int32 SubresourceIndex;
VkImageLayout LayoutRTV; VkImageLayout LayoutRTV;

View File

@@ -695,7 +695,7 @@ DRAW:
if (drawCall.InstanceCount == 0) if (drawCall.InstanceCount == 0)
{ {
// No support for batching indirect draw calls // No support for batching indirect draw calls
ASSERT(batch.BatchSize == 1); ASSERT_LOW_LAYER(batch.BatchSize == 1);
context->BindVB(ToSpan(vb, vbCount), vbOffsets); context->BindVB(ToSpan(vb, vbCount), vbOffsets);
context->DrawIndexedInstancedIndirect(drawCall.Draw.IndirectArgsBuffer, drawCall.Draw.IndirectArgsOffset); context->DrawIndexedInstancedIndirect(drawCall.Draw.IndirectArgsBuffer, drawCall.Draw.IndirectArgsOffset);