Add support for programmable samplers in shaders
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "Engine/Core/Math/Color.h"
|
||||
#include "GPUBufferVulkan.h"
|
||||
#include "GPUShaderVulkan.h"
|
||||
#include "GPUSamplerVulkan.h"
|
||||
#include "GPUPipelineStateVulkan.h"
|
||||
#include "Engine/Profiler/RenderStats.h"
|
||||
#include "GPUShaderProgramVulkan.h"
|
||||
@@ -447,7 +448,8 @@ void GPUContextVulkan::UpdateDescriptorSets(const SpirvShaderDescriptorInfo& des
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
{
|
||||
// Sampler
|
||||
const VkSampler sampler = _device->HelperResources.GetStaticSampler((HelperResourcesVulkan::StaticSamplers)descriptor.Slot);
|
||||
const VkSampler sampler = _samplerHandles[descriptor.Slot];
|
||||
ASSERT(sampler);
|
||||
needsWrite |= dsWriter.WriteSampler(descriptorIndex, sampler);
|
||||
break;
|
||||
}
|
||||
@@ -715,8 +717,6 @@ void GPUContextVulkan::FrameBegin()
|
||||
_psDirtyFlag = 0;
|
||||
_rtDirtyFlag = 0;
|
||||
_cbDirtyFlag = 0;
|
||||
_srDirtyFlag = 0;
|
||||
_uaDirtyFlag = 0;
|
||||
_rtCount = 0;
|
||||
_vbCount = 0;
|
||||
_renderPass = nullptr;
|
||||
@@ -726,6 +726,8 @@ void GPUContextVulkan::FrameBegin()
|
||||
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
Platform::MemoryClear(_uaHandles, sizeof(_uaHandles));
|
||||
Platform::MemoryCopy(_samplerHandles, _device->HelperResources.GetStaticSamplers(), sizeof(VkSampler) * GPU_STATIC_SAMPLERS_COUNT);
|
||||
Platform::MemoryClear(_samplerHandles + GPU_STATIC_SAMPLERS_COUNT, sizeof(_samplerHandles) - sizeof(VkSampler) * GPU_STATIC_SAMPLERS_COUNT);
|
||||
|
||||
#if VULKAN_RESET_QUERY_POOLS
|
||||
// Reset pending queries
|
||||
@@ -916,13 +918,11 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* rt, GPUBuffer* uaOutput)
|
||||
|
||||
void GPUContextVulkan::ResetSR()
|
||||
{
|
||||
_srDirtyFlag = false;
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
}
|
||||
|
||||
void GPUContextVulkan::ResetUA()
|
||||
{
|
||||
_uaDirtyFlag = false;
|
||||
Platform::MemoryClear(_uaHandles, sizeof(_uaHandles));
|
||||
}
|
||||
|
||||
@@ -951,7 +951,6 @@ void GPUContextVulkan::BindSR(int32 slot, GPUResourceView* view)
|
||||
const auto handle = view ? (DescriptorOwnerResourceVulkan*)view->GetNativePtr() : nullptr;
|
||||
if (_srHandles[slot] != handle)
|
||||
{
|
||||
_srDirtyFlag = true;
|
||||
_srHandles[slot] = handle;
|
||||
if (view)
|
||||
*view->LastRenderTime = _lastRenderTime;
|
||||
@@ -964,7 +963,6 @@ void GPUContextVulkan::BindUA(int32 slot, GPUResourceView* view)
|
||||
const auto handle = view ? (DescriptorOwnerResourceVulkan*)view->GetNativePtr() : nullptr;
|
||||
if (_uaHandles[slot] != handle)
|
||||
{
|
||||
_uaDirtyFlag = true;
|
||||
_uaHandles[slot] = handle;
|
||||
if (view)
|
||||
*view->LastRenderTime = _lastRenderTime;
|
||||
@@ -997,6 +995,16 @@ void GPUContextVulkan::BindIB(GPUBuffer* indexBuffer)
|
||||
vkCmdBindIndexBuffer(cmdBuffer->GetHandle(), ibVulkan, 0, indexBuffer->GetFormat() == PixelFormat::R32_UInt ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
|
||||
void GPUContextVulkan::BindSampler(int32 slot, GPUSampler* sampler)
|
||||
{
|
||||
ASSERT(slot >= 0 && slot < GPU_MAX_SR_BINDED);
|
||||
const auto handle = sampler ? ((GPUSamplerVulkan*)sampler)->Sampler : nullptr;
|
||||
if (_samplerHandles[slot] != handle)
|
||||
{
|
||||
_samplerHandles[slot] = handle;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextVulkan::UpdateCB(GPUConstantBuffer* cb, const void* data)
|
||||
{
|
||||
ASSERT(data && cb);
|
||||
|
||||
@@ -94,8 +94,6 @@ private:
|
||||
int32 _psDirtyFlag : 1;
|
||||
int32 _rtDirtyFlag : 1;
|
||||
int32 _cbDirtyFlag : 1;
|
||||
int32 _srDirtyFlag : 1;
|
||||
int32 _uaDirtyFlag : 1;
|
||||
|
||||
int32 _rtCount;
|
||||
int32 _vbCount;
|
||||
@@ -107,6 +105,7 @@ private:
|
||||
DescriptorOwnerResourceVulkan* _cbHandles[GPU_MAX_CB_BINDED];
|
||||
DescriptorOwnerResourceVulkan* _srHandles[GPU_MAX_SR_BINDED];
|
||||
DescriptorOwnerResourceVulkan* _uaHandles[GPU_MAX_UA_BINDED];
|
||||
VkSampler _samplerHandles[GPU_MAX_SAMPLER_BINDED];
|
||||
DescriptorOwnerResourceVulkan** _handles[(int32)SpirvShaderResourceBindingType::MAX];
|
||||
|
||||
typedef Array<DescriptorPoolVulkan*> DescriptorPoolArray;
|
||||
@@ -188,6 +187,7 @@ public:
|
||||
void BindUA(int32 slot, GPUResourceView* view) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override;
|
||||
void BindIB(GPUBuffer* indexBuffer) override;
|
||||
void BindSampler(int32 slot, GPUSampler* sampler) override;
|
||||
void UpdateCB(GPUConstantBuffer* cb, const void* data) override;
|
||||
void Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ) override;
|
||||
void DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* bufferForArgs, uint32 offsetForArgs) override;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "GPUTextureVulkan.h"
|
||||
#include "GPUTimerQueryVulkan.h"
|
||||
#include "GPUBufferVulkan.h"
|
||||
#include "GPUSamplerVulkan.h"
|
||||
#include "GPUSwapChainVulkan.h"
|
||||
#include "RenderToolsVulkan.h"
|
||||
#include "QueueVulkan.h"
|
||||
@@ -369,7 +370,7 @@ void DeferredDeletionQueueVulkan::ReleaseResources(bool deleteImmediately)
|
||||
#undef SWITCH_CASE
|
||||
default:
|
||||
#if !BUILD_RELEASE
|
||||
CRASH;
|
||||
CRASH;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -730,8 +731,9 @@ void InitSampler(VkSamplerCreateInfo& createInfo, bool supportsMirrorClampToEdge
|
||||
createInfo.compareOp = RenderToolsVulkan::ToVulkanSamplerCompareFunction(compareFunction);
|
||||
}
|
||||
|
||||
VkSampler HelperResourcesVulkan::GetStaticSampler(StaticSamplers type)
|
||||
VkSampler* HelperResourcesVulkan::GetStaticSamplers()
|
||||
{
|
||||
static_assert(GPU_STATIC_SAMPLERS_COUNT == 6, "Update static samplers setup.");
|
||||
if (!_staticSamplers[0])
|
||||
{
|
||||
const bool supportsMirrorClampToEdge = GPUDeviceVulkan::OptionalDeviceExtensions.HasMirrorClampToEdge;
|
||||
@@ -769,8 +771,7 @@ VkSampler HelperResourcesVulkan::GetStaticSampler(StaticSamplers type)
|
||||
InitSampler(createInfo, supportsMirrorClampToEdge, GPUSamplerFilter::Trilinear, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerAddressMode::Clamp, GPUSamplerCompareFunction::Less);
|
||||
VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &_staticSamplers[5]));
|
||||
}
|
||||
|
||||
return _staticSamplers[static_cast<int32>(type)];
|
||||
return _staticSamplers;
|
||||
}
|
||||
|
||||
GPUTextureVulkan* HelperResourcesVulkan::GetDummyTexture(SpirvShaderResourceType type)
|
||||
@@ -797,7 +798,7 @@ GPUTextureVulkan* HelperResourcesVulkan::GetDummyTexture(SpirvShaderResourceType
|
||||
index = 5;
|
||||
break;
|
||||
default:
|
||||
CRASH;
|
||||
CRASH;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1172,7 +1173,7 @@ GPUDevice* GPUDeviceVulkan::Create()
|
||||
volkLoadInstance(Instance);
|
||||
#endif
|
||||
|
||||
// Setup debug layer
|
||||
// Setup debug layer
|
||||
#if VULKAN_USE_DEBUG_LAYER
|
||||
SetupDebugLayerCallback();
|
||||
#endif
|
||||
@@ -1692,6 +1693,7 @@ bool GPUDeviceVulkan::Init()
|
||||
limits.MaximumTexture2DArraySize = PhysicalDeviceLimits.maxImageArrayLayers;
|
||||
limits.MaximumTexture3DSize = PhysicalDeviceLimits.maxImageDimension3D;
|
||||
limits.MaximumTextureCubeSize = PhysicalDeviceLimits.maxImageDimensionCube;
|
||||
limits.MaximumSamplerAnisotropy = PhysicalDeviceLimits.maxSamplerAnisotropy;
|
||||
|
||||
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
||||
{
|
||||
@@ -1957,6 +1959,11 @@ GPUBuffer* GPUDeviceVulkan::CreateBuffer(const StringView& name)
|
||||
return New<GPUBufferVulkan>(this, name);
|
||||
}
|
||||
|
||||
GPUSampler* GPUDeviceVulkan::CreateSampler()
|
||||
{
|
||||
return New<GPUSamplerVulkan>(this);
|
||||
}
|
||||
|
||||
GPUSwapChain* GPUDeviceVulkan::CreateSwapChain(Window* window)
|
||||
{
|
||||
return New<GPUSwapChainVulkan>(this, window);
|
||||
|
||||
@@ -385,46 +385,24 @@ public:
|
||||
/// </summary>
|
||||
class HelperResourcesVulkan
|
||||
{
|
||||
public:
|
||||
|
||||
enum class StaticSamplers
|
||||
{
|
||||
SamplerLinearClamp =0,
|
||||
SamplerPointClamp = 1,
|
||||
SamplerLinearWrap = 2,
|
||||
SamplerPointWrap = 3,
|
||||
ShadowSampler = 4,
|
||||
ShadowSamplerPCF = 5,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
GPUDeviceVulkan* _device;
|
||||
GPUTextureVulkan* _dummyTextures[6];
|
||||
GPUBufferVulkan* _dummyBuffer;
|
||||
GPUBufferVulkan* _dummyVB;
|
||||
VkSampler _staticSamplers[static_cast<int32>(StaticSamplers::MAX)];
|
||||
VkSampler _staticSamplers[GPU_STATIC_SAMPLERS_COUNT];
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DummyResourcesVulkan"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
HelperResourcesVulkan(GPUDeviceVulkan* device);
|
||||
|
||||
public:
|
||||
|
||||
VkSampler GetStaticSampler(StaticSamplers type);
|
||||
|
||||
VkSampler* GetStaticSamplers();
|
||||
GPUTextureVulkan* GetDummyTexture(SpirvShaderResourceType type);
|
||||
|
||||
GPUBufferVulkan* GetDummyBuffer();
|
||||
|
||||
GPUBufferVulkan* GetDummyVertexBuffer();
|
||||
|
||||
void Dispose();
|
||||
};
|
||||
|
||||
@@ -739,6 +717,7 @@ public:
|
||||
GPUPipelineState* CreatePipelineState() override;
|
||||
GPUTimerQuery* CreateTimerQuery() override;
|
||||
GPUBuffer* CreateBuffer(const StringView& name) override;
|
||||
GPUSampler* CreateSampler() override;
|
||||
GPUSwapChain* CreateSwapChain(Window* window) override;
|
||||
};
|
||||
|
||||
|
||||
56
Source/Engine/GraphicsDevice/Vulkan/GPUSamplerVulkan.cpp
Normal file
56
Source/Engine/GraphicsDevice/Vulkan/GPUSamplerVulkan.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_VULKAN
|
||||
|
||||
#include "GPUSamplerVulkan.h"
|
||||
#include "RenderToolsVulkan.h"
|
||||
|
||||
bool GPUSamplerVulkan::OnInit()
|
||||
{
|
||||
VkSamplerCreateInfo createInfo;
|
||||
RenderToolsVulkan::ZeroStruct(createInfo, VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
|
||||
createInfo.magFilter = RenderToolsVulkan::ToVulkanMagFilterMode(_desc.Filter);
|
||||
createInfo.minFilter = RenderToolsVulkan::ToVulkanMinFilterMode(_desc.Filter);
|
||||
createInfo.mipmapMode = RenderToolsVulkan::ToVulkanMipFilterMode(_desc.Filter);
|
||||
const bool supportsMirrorClampToEdge = GPUDeviceVulkan::OptionalDeviceExtensions.HasMirrorClampToEdge;
|
||||
createInfo.addressModeU = RenderToolsVulkan::ToVulkanWrapMode(_desc.AddressU, supportsMirrorClampToEdge);
|
||||
createInfo.addressModeV = RenderToolsVulkan::ToVulkanWrapMode(_desc.AddressV, supportsMirrorClampToEdge);
|
||||
createInfo.addressModeW = RenderToolsVulkan::ToVulkanWrapMode(_desc.AddressW, supportsMirrorClampToEdge);
|
||||
createInfo.mipLodBias = _desc.MipBias;
|
||||
createInfo.anisotropyEnable = _desc.Filter == GPUSamplerFilter::Anisotropic ? VK_TRUE : VK_FALSE;
|
||||
createInfo.maxAnisotropy = (float)_desc.MaxAnisotropy;
|
||||
createInfo.compareEnable = _desc.ComparisonFunction != GPUSamplerCompareFunction::Never ? VK_TRUE : VK_FALSE;
|
||||
createInfo.compareOp = RenderToolsVulkan::ToVulkanSamplerCompareFunction(_desc.ComparisonFunction);
|
||||
createInfo.minLod = _desc.MinMipLevel;
|
||||
createInfo.maxLod = _desc.MaxMipLevel;
|
||||
switch (_desc.BorderColor)
|
||||
{
|
||||
case GPUSamplerBorderColor::TransparentBlack:
|
||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
break;
|
||||
case GPUSamplerBorderColor::OpaqueBlack:
|
||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||||
break;
|
||||
case GPUSamplerBorderColor::OpaqueWhite:
|
||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
VALIDATE_VULKAN_RESULT(vkCreateSampler(_device->Device, &createInfo, nullptr, &Sampler));
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUSamplerVulkan::OnReleaseGPU()
|
||||
{
|
||||
if (Sampler != VK_NULL_HANDLE)
|
||||
{
|
||||
_device->DeferredDeletionQueue.EnqueueResource(DeferredDeletionQueueVulkan::Buffer, Sampler);
|
||||
Sampler = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
// Base
|
||||
GPUSampler::OnReleaseGPU();
|
||||
}
|
||||
|
||||
#endif
|
||||
31
Source/Engine/GraphicsDevice/Vulkan/GPUSamplerVulkan.h
Normal file
31
Source/Engine/GraphicsDevice/Vulkan/GPUSamplerVulkan.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if GRAPHICS_API_VULKAN
|
||||
|
||||
#include "Engine/Graphics/Textures/GPUSampler.h"
|
||||
#include "GPUDeviceVulkan.h"
|
||||
|
||||
/// <summary>
|
||||
/// Sampler object for Vulkan backend.
|
||||
/// </summary>
|
||||
class GPUSamplerVulkan : public GPUResourceVulkan<GPUSampler>
|
||||
{
|
||||
public:
|
||||
|
||||
GPUSamplerVulkan(GPUDeviceVulkan* device)
|
||||
: GPUResourceVulkan<GPUSampler>(device, StringView::Empty)
|
||||
{
|
||||
}
|
||||
|
||||
VkSampler Sampler = VK_NULL_HANDLE;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUSamplerVulkan]
|
||||
bool OnInit() override;
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user