@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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() ???
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user