Add support for programmable samplers in shaders
This commit is contained in:
@@ -14,6 +14,12 @@
|
||||
// Maximum amount of binded unordered access resources at the same time
|
||||
#define GPU_MAX_UA_BINDED 2
|
||||
|
||||
// Maximum amount of binded texture sampler resources at the same time
|
||||
#define GPU_MAX_SAMPLER_BINDED 16
|
||||
|
||||
// Amount of initial slots used for global samplers (static, 4 common samplers + 2 comparision samplers)
|
||||
#define GPU_STATIC_SAMPLERS_COUNT 6
|
||||
|
||||
// Maximum amount of binded vertex buffers at the same time
|
||||
#define GPU_MAX_VB_BINDED 4
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ class GPUShaderProgramCS;
|
||||
class GPUBuffer;
|
||||
class GPUPipelineState;
|
||||
class GPUTexture;
|
||||
class GPUSampler;
|
||||
class GPUDevice;
|
||||
class GPUResource;
|
||||
class GPUResourceView;
|
||||
@@ -396,6 +397,13 @@ public:
|
||||
/// <param name="indexBuffer">The index buffer.</param>
|
||||
API_FUNCTION() virtual void BindIB(GPUBuffer* indexBuffer) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Binds the texture sampler to the pipeline.
|
||||
/// </summary>
|
||||
/// <param name="slot">The slot index.</param>
|
||||
/// <param name="sampler">The sampler.</param>
|
||||
API_FUNCTION() virtual void BindSampler(int32 slot, GPUSampler* sampler) = 0;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,6 +18,7 @@ class GPUShader;
|
||||
class GPUTimerQuery;
|
||||
class GPUTexture;
|
||||
class GPUBuffer;
|
||||
class GPUSampler;
|
||||
class GPUPipelineState;
|
||||
class GPUSwapChain;
|
||||
class Shader;
|
||||
@@ -360,6 +361,12 @@ public:
|
||||
/// <returns>The buffer.</returns>
|
||||
API_FUNCTION() virtual GPUBuffer* CreateBuffer(const StringView& name = StringView::Empty) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the texture sampler.
|
||||
/// </summary>
|
||||
/// <returns>The sampler.</returns>
|
||||
API_FUNCTION() virtual GPUSampler* CreateSampler() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the native window swap chain.
|
||||
/// </summary>
|
||||
|
||||
@@ -314,4 +314,9 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(GPULimits);
|
||||
/// The maximum size of the cube texture (both width and height).
|
||||
/// </summary>
|
||||
API_FIELD() int32 MaximumTextureCubeSize;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum degree of anisotropic filtering used for texture sampling.
|
||||
/// </summary>
|
||||
API_FIELD() float MaximumSamplerAnisotropy;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
/// <summary>
|
||||
/// GPU Resources types.
|
||||
/// </summary>
|
||||
DECLARE_ENUM_9(ResourceType, RenderTarget, Texture, CubeTexture, VolumeTexture, Buffer, Shader, PipelineState, Descriptor, Query);
|
||||
DECLARE_ENUM_10(ResourceType, RenderTarget, Texture, CubeTexture, VolumeTexture, Buffer, Shader, PipelineState, Descriptor, Query, Sampler);
|
||||
|
||||
/// <summary>
|
||||
/// GPU Resources object types. Used to detect Texture objects from subset of Types: RenderTarget, Texture, CubeTexture, VolumeTexture which use the same API object.
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "GPUSampler.h"
|
||||
#include "GPUSamplerDescription.h"
|
||||
#include "Engine/Core/Types/String.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
|
||||
GPUSamplerDescription GPUSamplerDescription::New(GPUSamplerFilter filter, GPUSamplerAddressMode addressMode)
|
||||
{
|
||||
GPUSamplerDescription desc;
|
||||
desc.Clear();
|
||||
desc.Filter = filter;
|
||||
desc.AddressU = desc.AddressV = desc.AddressW = addressMode;
|
||||
return desc;
|
||||
}
|
||||
|
||||
void GPUSamplerDescription::Clear()
|
||||
{
|
||||
Filter = GPUSamplerFilter::Point;
|
||||
AddressU = GPUSamplerAddressMode::Wrap;
|
||||
AddressV = GPUSamplerAddressMode::Wrap;
|
||||
AddressW = GPUSamplerAddressMode::Wrap;
|
||||
MipBias = 0;
|
||||
MaxAnisotropy = 0;
|
||||
MinMipLevel = 0;
|
||||
Platform::MemoryClear(this, sizeof(GPUSamplerDescription));
|
||||
MaxMipLevel = MAX_float;
|
||||
BorderColor = GPUSamplerBorderColor::TransparentBlack;
|
||||
SamplerComparisonFunction = GPUSamplerCompareFunction::Never;
|
||||
}
|
||||
|
||||
bool GPUSamplerDescription::Equals(const GPUSamplerDescription& other) const
|
||||
@@ -28,12 +31,12 @@ bool GPUSamplerDescription::Equals(const GPUSamplerDescription& other) const
|
||||
&& MinMipLevel == other.MinMipLevel
|
||||
&& MaxMipLevel == other.MaxMipLevel
|
||||
&& BorderColor == other.BorderColor
|
||||
&& SamplerComparisonFunction == other.SamplerComparisonFunction;
|
||||
&& ComparisonFunction == other.ComparisonFunction;
|
||||
}
|
||||
|
||||
String GPUSamplerDescription::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("Filter: {}, Address: {}x{}x{}, MipBias: {}, MaxAnisotropy: {}, MinMipLevel: {}, MaxMipLevel: {}, BorderColor: {}, SamplerComparisonFunction: {}"),
|
||||
return String::Format(TEXT("Filter: {}, Address: {}x{}x{}, MipBias: {}, MaxAnisotropy: {}, MinMipLevel: {}, MaxMipLevel: {}, BorderColor: {}, ComparisonFunction: {}"),
|
||||
(int32)Filter,
|
||||
(int32)AddressU,
|
||||
(int32)AddressV,
|
||||
@@ -43,7 +46,7 @@ String GPUSamplerDescription::ToString() const
|
||||
MinMipLevel,
|
||||
MaxMipLevel,
|
||||
(int32)BorderColor,
|
||||
(int32)SamplerComparisonFunction);
|
||||
(int32)ComparisonFunction);
|
||||
}
|
||||
|
||||
uint32 GetHash(const GPUSamplerDescription& key)
|
||||
@@ -57,6 +60,57 @@ uint32 GetHash(const GPUSamplerDescription& key)
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.MinMipLevel;
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.MaxMipLevel;
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.BorderColor;
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.SamplerComparisonFunction;
|
||||
hashCode = (hashCode * 397) ^ (uint32)key.ComparisonFunction;
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
GPUSampler* GPUSampler::Spawn(const SpawnParams& params)
|
||||
{
|
||||
return GPUDevice::Instance->CreateSampler();
|
||||
}
|
||||
|
||||
GPUSampler* GPUSampler::New()
|
||||
{
|
||||
return GPUDevice::Instance->CreateSampler();
|
||||
}
|
||||
|
||||
GPUSampler::GPUSampler()
|
||||
{
|
||||
}
|
||||
|
||||
bool GPUSampler::Init(const GPUSamplerDescription& desc)
|
||||
{
|
||||
ReleaseGPU();
|
||||
_desc = desc;
|
||||
if (OnInit())
|
||||
{
|
||||
ReleaseGPU();
|
||||
LOG(Warning, "Cannot initialize sampler. Description: {0}", desc.ToString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String GPUSampler::ToString() const
|
||||
{
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
return String::Format(TEXT("Sampler {0}, {1}"), GetName(), _desc.ToString());
|
||||
#else
|
||||
return TEXT("Sampler");
|
||||
#endif
|
||||
}
|
||||
|
||||
GPUResource::ResourceType GPUSampler::GetResourceType() const
|
||||
{
|
||||
return ResourceType::Sampler;
|
||||
}
|
||||
|
||||
GPUResource::ObjectType GPUSampler::GetObjectType() const
|
||||
{
|
||||
return ObjectType::Other;
|
||||
}
|
||||
|
||||
void GPUSampler::OnReleaseGPU()
|
||||
{
|
||||
_desc.Clear();
|
||||
}
|
||||
58
Source/Engine/Graphics/Textures/GPUSampler.h
Normal file
58
Source/Engine/Graphics/Textures/GPUSampler.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GPUSamplerDescription.h"
|
||||
#include "../GPUResource.h"
|
||||
|
||||
/// <summary>
|
||||
/// GPU texture sampler object.
|
||||
/// </summary>
|
||||
/// <seealso cref="GPUResource" />
|
||||
API_CLASS(Sealed) class FLAXENGINE_API GPUSampler : public GPUResource
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUSampler);
|
||||
static GPUSampler* Spawn(const SpawnParams& params);
|
||||
static GPUSampler* New();
|
||||
|
||||
protected:
|
||||
|
||||
GPUSamplerDescription _desc;
|
||||
|
||||
GPUSampler();
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets sampler description structure.
|
||||
/// </summary>
|
||||
API_PROPERTY() const GPUSamplerDescription& GetDescription() const
|
||||
{
|
||||
return _desc;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Creates new sampler.
|
||||
/// </summary>
|
||||
/// <param name="desc">The sampler description.</param>
|
||||
/// <returns>True if cannot create sampler, otherwise false.</returns>
|
||||
API_FUNCTION() bool Init(API_PARAM(Ref) const GPUSamplerDescription& desc);
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool OnInit() = 0;
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResource]
|
||||
String ToString() const override;
|
||||
ResourceType GetResourceType() const final override;
|
||||
ObjectType GetObjectType() const final override;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUResource]
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
76
Source/Engine/Graphics/Textures/GPUSamplerDescription.cs
Normal file
76
Source/Engine/Graphics/Textures/GPUSamplerDescription.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
|
||||
namespace FlaxEngine
|
||||
{
|
||||
partial struct GPUSamplerDescription : IEquatable<GPUSamplerDescription>
|
||||
{
|
||||
/// <summary>
|
||||
/// Clears description.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
this = new GPUSamplerDescription();
|
||||
MaxMipLevel = float.MaxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="GPUSamplerDescription" /> with default settings.
|
||||
/// </summary>
|
||||
/// <param name="filter">The filtering method.</param>
|
||||
/// <param name="addressMode">The addressing mode.</param>
|
||||
/// <returns>A new instance of <see cref="GPUSamplerDescription" /> class.</returns>
|
||||
public static GPUSamplerDescription New(GPUSamplerFilter filter = GPUSamplerFilter.Point, GPUSamplerAddressMode addressMode = GPUSamplerAddressMode.Wrap)
|
||||
{
|
||||
return new GPUSamplerDescription
|
||||
{
|
||||
Filter = filter,
|
||||
AddressU = addressMode,
|
||||
AddressV = addressMode,
|
||||
AddressW = addressMode,
|
||||
MaxMipLevel = float.MaxValue,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(GPUSamplerDescription other)
|
||||
{
|
||||
return Filter == other.Filter &&
|
||||
AddressU == other.AddressU &&
|
||||
AddressV == other.AddressV &&
|
||||
AddressW == other.AddressW &&
|
||||
Mathf.NearEqual(MipBias, other.MipBias) &&
|
||||
Mathf.NearEqual(MinMipLevel, other.MinMipLevel) &&
|
||||
Mathf.NearEqual(MaxMipLevel, other.MaxMipLevel) &&
|
||||
MaxAnisotropy == other.MaxAnisotropy &&
|
||||
BorderColor == other.BorderColor &&
|
||||
ComparisonFunction == other.ComparisonFunction;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is GPUSamplerDescription other && Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = (int)Filter;
|
||||
hashCode = (hashCode * 397) ^ (int)AddressU;
|
||||
hashCode = (hashCode * 397) ^ (int)AddressV;
|
||||
hashCode = (hashCode * 397) ^ (int)AddressW;
|
||||
hashCode = (hashCode * 397) ^ (int)MipBias;
|
||||
hashCode = (hashCode * 397) ^ (int)MinMipLevel;
|
||||
hashCode = (hashCode * 397) ^ (int)MaxMipLevel;
|
||||
hashCode = (hashCode * 397) ^ MaxAnisotropy;
|
||||
hashCode = (hashCode * 397) ^ (int)BorderColor;
|
||||
hashCode = (hashCode * 397) ^ (int)ComparisonFunction;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,49 +4,57 @@
|
||||
|
||||
#include "Engine/Graphics/Enums.h"
|
||||
|
||||
class String;
|
||||
|
||||
/// <summary>
|
||||
/// GPU sampler filter modes.
|
||||
/// </summary>
|
||||
enum class GPUSamplerFilter
|
||||
API_ENUM() enum class GPUSamplerFilter
|
||||
{
|
||||
/// <summary>Filter using the nearest found pixel. Texture appears pixelated.</summary>
|
||||
Point = 0,
|
||||
/// <summary>Filter using the linear average of the nearby pixels. Texture appears blurry.</summary>
|
||||
Bilinear = 1,
|
||||
/// <summary>Filter using the linear average of the nearby pixels and nearby mipmaps. Texture appears blurry.</summary>
|
||||
Trilinear = 2,
|
||||
/// <summary>Filter using the anisotropic filtering that improves quality when viewing textures at a steep angles. Texture appears sharp at extreme viewing angles.</summary>
|
||||
Anisotropic = 3,
|
||||
|
||||
MAX
|
||||
API_ENUM(Attributes="HideInEditor") MAX
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// GPU sampler address modes.
|
||||
/// </summary>
|
||||
enum class GPUSamplerAddressMode
|
||||
API_ENUM() enum class GPUSamplerAddressMode
|
||||
{
|
||||
/// <summary>Texture coordinates wrap back to the valid range.</summary>
|
||||
Wrap = 0,
|
||||
/// <summary>Texture coordinates are clamped within the valid range.</summary>
|
||||
Clamp = 1,
|
||||
/// <summary>Texture coordinates flip every time the size of the valid range is passed.</summary>
|
||||
Mirror = 2,
|
||||
/// <summary>Texture coordinates outside of the valid range will return a separately set border color.</summary>
|
||||
Border = 3,
|
||||
|
||||
MAX
|
||||
API_ENUM(Attributes="HideInEditor") MAX
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// GPU sampler comparision function types.
|
||||
/// </summary>
|
||||
enum class GPUSamplerCompareFunction
|
||||
API_ENUM() enum class GPUSamplerCompareFunction
|
||||
{
|
||||
/// <summary>Never pass the comparison.</summary>
|
||||
Never = 0,
|
||||
/// <summary>If the source data is less than the destination data, the comparison passes.</summary>
|
||||
Less = 1,
|
||||
|
||||
MAX
|
||||
API_ENUM(Attributes="HideInEditor") MAX
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// GPU sampler border color types.
|
||||
/// </summary>
|
||||
enum class GPUSamplerBorderColor
|
||||
API_ENUM() enum class GPUSamplerBorderColor
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates black, with the alpha component as fully transparent.
|
||||
@@ -63,105 +71,93 @@ enum class GPUSamplerBorderColor
|
||||
/// </summary>
|
||||
OpaqueWhite = 2,
|
||||
|
||||
Maximum
|
||||
API_ENUM(Attributes="HideInEditor") MAX
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A common description for all samplers.
|
||||
/// </summary>
|
||||
struct FLAXENGINE_API GPUSamplerDescription
|
||||
API_STRUCT() struct FLAXENGINE_API GPUSamplerDescription
|
||||
{
|
||||
public:
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(GPUSamplerDescription);
|
||||
|
||||
/// <summary>
|
||||
/// The filtering method to use when sampling a texture.
|
||||
/// </summary>
|
||||
GPUSamplerFilter Filter;
|
||||
API_FIELD() GPUSamplerFilter Filter;
|
||||
|
||||
/// <summary>
|
||||
/// The addressing mode for outside [0..1] range for U coordinate.
|
||||
/// </summary>
|
||||
GPUSamplerAddressMode AddressU;
|
||||
API_FIELD() GPUSamplerAddressMode AddressU;
|
||||
|
||||
/// <summary>
|
||||
/// The addressing mode for outside [0..1] range for V coordinate.
|
||||
/// </summary>
|
||||
GPUSamplerAddressMode AddressV;
|
||||
API_FIELD() GPUSamplerAddressMode AddressV;
|
||||
|
||||
/// <summary>
|
||||
/// The addressing mode for outside [0..1] range for W coordinate.
|
||||
/// </summary>
|
||||
GPUSamplerAddressMode AddressW;
|
||||
API_FIELD() GPUSamplerAddressMode AddressW;
|
||||
|
||||
/// <summary>
|
||||
/// The mip bias to be added to mipmap LOD calculation.
|
||||
/// </summary>
|
||||
float MipBias;
|
||||
API_FIELD() float MipBias;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum mip map level that will be used, where 0 is the highest resolution mip level.
|
||||
/// </summary>
|
||||
float MinMipLevel;
|
||||
API_FIELD() float MinMipLevel;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum mip map level that will be used, where 0 is the highest resolution mip level. To have no upper limit on LOD set this to a large value such as MAX_float.
|
||||
/// </summary>
|
||||
float MaxMipLevel;
|
||||
API_FIELD() float MaxMipLevel;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum anisotropy value.
|
||||
/// </summary>
|
||||
int32 MaxAnisotropy;
|
||||
API_FIELD() int32 MaxAnisotropy;
|
||||
|
||||
/// <summary>
|
||||
/// The border color to use if Border is specified for AddressU, AddressV, or AddressW.
|
||||
/// </summary>
|
||||
GPUSamplerBorderColor BorderColor;
|
||||
API_FIELD() GPUSamplerBorderColor BorderColor;
|
||||
|
||||
/// <summary>
|
||||
/// A function that compares sampled data against existing sampled data.
|
||||
/// </summary>
|
||||
GPUSamplerCompareFunction SamplerComparisonFunction;
|
||||
API_FIELD() GPUSamplerCompareFunction ComparisonFunction;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Clears description to the default values.
|
||||
/// Creates a new <see cref="GPUSamplerDescription" /> with default settings.
|
||||
/// </summary>
|
||||
/// <param name="filter">The filtering method.</param>
|
||||
/// <param name="addressMode">The addressing mode.</param>
|
||||
/// <returns>A new instance of <see cref="GPUSamplerDescription" /> class.</returns>
|
||||
static GPUSamplerDescription New(GPUSamplerFilter filter = GPUSamplerFilter::Point, GPUSamplerAddressMode addressMode = GPUSamplerAddressMode::Wrap);
|
||||
|
||||
public:
|
||||
|
||||
void Clear();
|
||||
bool Equals(const GPUSamplerDescription& other) const;
|
||||
String ToString() const;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Compares with other instance of SamplerDescription
|
||||
/// </summary>
|
||||
/// <param name="other">The other object to compare.</param>
|
||||
/// <returns>True if objects are the same, otherwise false.</returns>
|
||||
bool Equals(const GPUSamplerDescription& other) const;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator ==.
|
||||
/// </summary>
|
||||
/// <param name="other">The other description.</param>
|
||||
/// <returns>The result of the operator.</returns>
|
||||
FORCE_INLINE bool operator==(const GPUSamplerDescription& other) const
|
||||
{
|
||||
return Equals(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the operator !=.
|
||||
/// </summary>
|
||||
/// <param name="other">The other description.</param>
|
||||
/// <returns>The result of the operator.</returns>
|
||||
FORCE_INLINE bool operator!=(const GPUSamplerDescription& other) const
|
||||
{
|
||||
return !Equals(other);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
String ToString() const;
|
||||
};
|
||||
|
||||
uint32 GetHash(const GPUSamplerDescription& key);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "GPUPipelineStateDX11.h"
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "GPUBufferDX11.h"
|
||||
#include "GPUSamplerDX11.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
#include "Engine/Core/Math/Viewport.h"
|
||||
#include "Engine/Core/Math/Rectangle.h"
|
||||
@@ -384,6 +385,15 @@ void GPUContextDX11::BindIB(GPUBuffer* indexBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindSampler(int32 slot, GPUSampler* sampler)
|
||||
{
|
||||
const auto samplerDX11 = sampler ? static_cast<GPUSamplerDX11*>(sampler)->SamplerState : nullptr;
|
||||
_context->VSSetSamplers(slot, 1, &samplerDX11);
|
||||
_context->DSSetSamplers(slot, 1, &samplerDX11);
|
||||
_context->PSSetSamplers(slot, 1, &samplerDX11);
|
||||
_context->CSSetSamplers(slot, 1, &samplerDX11);
|
||||
}
|
||||
|
||||
void GPUContextDX11::UpdateCB(GPUConstantBuffer* cb, const void* data)
|
||||
{
|
||||
ASSERT(data && cb);
|
||||
|
||||
@@ -122,6 +122,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;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "GPUTimerQueryDX11.h"
|
||||
#include "GPUBufferDX11.h"
|
||||
#include "GPUSamplerDX11.h"
|
||||
#include "GPUSwapChainDX11.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Utilities.h"
|
||||
@@ -324,6 +325,7 @@ bool GPUDeviceDX11::Init()
|
||||
limits.MaximumTexture2DArraySize = D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture3DSize = D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
|
||||
limits.MaximumTextureCubeSize = D3D11_REQ_TEXTURECUBE_DIMENSION;
|
||||
limits.MaximumSamplerAnisotropy = D3D11_DEFAULT_MAX_ANISOTROPY;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -346,6 +348,7 @@ bool GPUDeviceDX11::Init()
|
||||
limits.MaximumTexture2DArraySize = D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture3DSize = D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
|
||||
limits.MaximumTextureCubeSize = D3D10_REQ_TEXTURECUBE_DIMENSION;
|
||||
limits.MaximumSamplerAnisotropy = D3D10_DEFAULT_MAX_ANISOTROPY;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
||||
@@ -685,6 +688,11 @@ GPUBuffer* GPUDeviceDX11::CreateBuffer(const StringView& name)
|
||||
return New<GPUBufferDX11>(this, name);
|
||||
}
|
||||
|
||||
GPUSampler* GPUDeviceDX11::CreateSampler()
|
||||
{
|
||||
return New<GPUSamplerDX11>(this);
|
||||
}
|
||||
|
||||
GPUSwapChain* GPUDeviceDX11::CreateSwapChain(Window* window)
|
||||
{
|
||||
return New<GPUSwapChainDX11>(this, window);
|
||||
|
||||
@@ -99,6 +99,7 @@ public:
|
||||
GPUPipelineState* CreatePipelineState() override;
|
||||
GPUTimerQuery* CreateTimerQuery() override;
|
||||
GPUBuffer* CreateBuffer(const StringView& name) override;
|
||||
GPUSampler* CreateSampler() override;
|
||||
GPUSwapChain* CreateSwapChain(Window* window) override;
|
||||
};
|
||||
|
||||
|
||||
128
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.cpp
Normal file
128
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUSamplerDX11.h"
|
||||
|
||||
D3D11_TEXTURE_ADDRESS_MODE ToDX11(GPUSamplerAddressMode value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case GPUSamplerAddressMode::Wrap:
|
||||
return D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
case GPUSamplerAddressMode::Clamp:
|
||||
return D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
case GPUSamplerAddressMode::Mirror:
|
||||
return D3D11_TEXTURE_ADDRESS_MIRROR;
|
||||
case GPUSamplerAddressMode::Border:
|
||||
return D3D11_TEXTURE_ADDRESS_BORDER;
|
||||
default:
|
||||
return (D3D11_TEXTURE_ADDRESS_MODE)-1;
|
||||
}
|
||||
}
|
||||
|
||||
bool GPUSamplerDX11::OnInit()
|
||||
{
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
if (_desc.ComparisonFunction == GPUSamplerCompareFunction::Never)
|
||||
{
|
||||
switch (_desc.Filter)
|
||||
{
|
||||
case GPUSamplerFilter::Point:
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Bilinear:
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Trilinear:
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
break;
|
||||
case GPUSamplerFilter::Anisotropic:
|
||||
samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (_desc.Filter)
|
||||
{
|
||||
case GPUSamplerFilter::Point:
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Bilinear:
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Trilinear:
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
||||
break;
|
||||
case GPUSamplerFilter::Anisotropic:
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_ANISOTROPIC;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
samplerDesc.AddressU = ToDX11(_desc.AddressU);
|
||||
samplerDesc.AddressV = ToDX11(_desc.AddressV);
|
||||
samplerDesc.AddressW = ToDX11(_desc.AddressW);
|
||||
samplerDesc.MipLODBias = _desc.MipBias;
|
||||
samplerDesc.MaxAnisotropy = _desc.MaxAnisotropy;
|
||||
switch (_desc.ComparisonFunction)
|
||||
{
|
||||
case GPUSamplerCompareFunction::Never:
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
break;
|
||||
case GPUSamplerCompareFunction::Less:
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
switch (_desc.BorderColor)
|
||||
{
|
||||
case GPUSamplerBorderColor::TransparentBlack:
|
||||
samplerDesc.BorderColor[0] = 0;
|
||||
samplerDesc.BorderColor[1] = 0;
|
||||
samplerDesc.BorderColor[2] = 0;
|
||||
samplerDesc.BorderColor[3] = 0;
|
||||
break;
|
||||
case GPUSamplerBorderColor::OpaqueBlack:
|
||||
samplerDesc.BorderColor[0] = 0;
|
||||
samplerDesc.BorderColor[1] = 0;
|
||||
samplerDesc.BorderColor[2] = 0;
|
||||
samplerDesc.BorderColor[3] = 1.0f;
|
||||
break;
|
||||
case GPUSamplerBorderColor::OpaqueWhite:
|
||||
samplerDesc.BorderColor[0] = 1.0f;
|
||||
samplerDesc.BorderColor[1] = 1.0f;
|
||||
samplerDesc.BorderColor[2] = 1.0f;
|
||||
samplerDesc.BorderColor[3] = 1.0f;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
samplerDesc.MinLOD = _desc.MinMipLevel;
|
||||
samplerDesc.MaxLOD = _desc.MaxMipLevel;
|
||||
HRESULT result = _device->GetDevice()->CreateSamplerState(&samplerDesc, &SamplerState);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
ASSERT(SamplerState != nullptr);
|
||||
_memoryUsage = sizeof(D3D11_SAMPLER_DESC);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUSamplerDX11::OnReleaseGPU()
|
||||
{
|
||||
if (SamplerState)
|
||||
{
|
||||
SamplerState->Release();
|
||||
SamplerState = nullptr;
|
||||
}
|
||||
|
||||
// Base
|
||||
GPUSampler::OnReleaseGPU();
|
||||
}
|
||||
|
||||
#endif
|
||||
31
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.h
Normal file
31
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSamplerDX11.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/Textures/GPUSampler.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// Sampler object for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUSamplerDX11 : public GPUResourceBase<GPUDeviceDX11, GPUSampler>
|
||||
{
|
||||
public:
|
||||
|
||||
GPUSamplerDX11(GPUDeviceDX11* device)
|
||||
: GPUResourceBase<GPUDeviceDX11, GPUSampler>(device, StringView::Empty)
|
||||
{
|
||||
}
|
||||
|
||||
ID3D11SamplerState* SamplerState = nullptr;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUSampler]
|
||||
bool OnInit() override;
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "UploadBufferDX12.h"
|
||||
#include "GPUTextureDX12.h"
|
||||
#include "GPUBufferDX12.h"
|
||||
#include "GPUSamplerDX12.h"
|
||||
#include "CommandQueueDX12.h"
|
||||
#include "DescriptorHeapDX12.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
@@ -74,6 +75,7 @@ GPUContextDX12::GPUContextDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE ty
|
||||
, _rtDirtyFlag(0)
|
||||
, _psDirtyFlag(0)
|
||||
, _cbDirtyFlag(0)
|
||||
, _samplersDirtyFlag(0)
|
||||
, _rtDepth(nullptr)
|
||||
, _ibHandle(nullptr)
|
||||
{
|
||||
@@ -213,6 +215,7 @@ void GPUContextDX12::Reset()
|
||||
_currentState = nullptr;
|
||||
_rtDirtyFlag = false;
|
||||
_cbDirtyFlag = false;
|
||||
_samplersDirtyFlag = false;
|
||||
_rtCount = 0;
|
||||
_rtDepth = nullptr;
|
||||
_srMaskDirtyGraphics = 0;
|
||||
@@ -226,8 +229,9 @@ void GPUContextDX12::Reset()
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
Platform::MemoryClear(_uaHandles, sizeof(_uaHandles));
|
||||
Platform::MemoryClear(_vbHandles, sizeof(_vbHandles));
|
||||
Platform::MemoryClear(&_ibHandle, sizeof(_ibHandle));
|
||||
_ibHandle = nullptr;
|
||||
Platform::MemoryClear(&_cbHandles, sizeof(_cbHandles));
|
||||
Platform::MemoryClear(&_samplers, sizeof(_samplers));
|
||||
_swapChainsUsed = 0;
|
||||
|
||||
// Bind Root Signature
|
||||
@@ -235,7 +239,7 @@ void GPUContextDX12::Reset()
|
||||
_commandList->SetComputeRootSignature(_device->GetRootSignature());
|
||||
|
||||
// Bind heaps
|
||||
ID3D12DescriptorHeap* ppHeaps[] = { _device->RingHeap_CBV_SRV_UAV.GetHeap() };
|
||||
ID3D12DescriptorHeap* ppHeaps[] = { _device->RingHeap_CBV_SRV_UAV.GetHeap(), _device->RingHeap_Sampler.GetHeap() };
|
||||
_commandList->SetDescriptorHeaps(ARRAY_COUNT(ppHeaps), ppHeaps);
|
||||
}
|
||||
|
||||
@@ -449,13 +453,9 @@ void GPUContextDX12::flushUAVs()
|
||||
|
||||
void GPUContextDX12::flushCBs()
|
||||
{
|
||||
// Check if need to flush constant buffers
|
||||
if (_cbDirtyFlag)
|
||||
{
|
||||
// Clear flag
|
||||
if (!_cbDirtyFlag)
|
||||
return;
|
||||
_cbDirtyFlag = false;
|
||||
|
||||
// Flush with the driver
|
||||
for (uint32 slotIndex = 0; slotIndex < ARRAY_COUNT(_cbHandles); slotIndex++)
|
||||
{
|
||||
auto cb = _cbHandles[slotIndex];
|
||||
@@ -468,7 +468,41 @@ void GPUContextDX12::flushCBs()
|
||||
_commandList->SetGraphicsRootConstantBufferView(slotIndex, cb->GPUAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX12::flushSamplers()
|
||||
{
|
||||
if (!_samplersDirtyFlag)
|
||||
return;
|
||||
_samplersDirtyFlag = false;
|
||||
int32 lastSlot = -1;
|
||||
for (int32 slotIndex = ARRAY_COUNT(_samplers) - 1; slotIndex >= 0; slotIndex--)
|
||||
{
|
||||
auto sampler = _samplers[slotIndex];
|
||||
if (sampler)
|
||||
{
|
||||
lastSlot = slotIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastSlot < 0)
|
||||
return;
|
||||
const uint32 samplersCount = lastSlot + 1;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srcDescriptorRangeStarts[ARRAY_COUNT(_samplers)];
|
||||
for (uint32 i = 0; i < samplersCount; i++)
|
||||
{
|
||||
const auto handle = _samplers[i];
|
||||
if (handle != nullptr)
|
||||
{
|
||||
srcDescriptorRangeStarts[i] = handle->HandleCPU;
|
||||
}
|
||||
}
|
||||
auto allocation = _device->RingHeap_Sampler.AllocateTable(samplersCount);
|
||||
_device->GetDevice()->CopyDescriptors(1, &allocation.CPU, &samplersCount, samplersCount, srcDescriptorRangeStarts, nullptr, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
if (_isCompute)
|
||||
_commandList->SetComputeRootDescriptorTable(4, allocation.GPU);
|
||||
else
|
||||
_commandList->SetGraphicsRootDescriptorTable(4, allocation.GPU);
|
||||
}
|
||||
|
||||
void GPUContextDX12::flushRBs()
|
||||
@@ -563,6 +597,7 @@ void GPUContextDX12::OnDrawCall()
|
||||
flushRBs();
|
||||
flushPS();
|
||||
flushCBs();
|
||||
flushSamplers();
|
||||
|
||||
#if BUILD_DEBUG
|
||||
// Additional verification of the state
|
||||
@@ -890,6 +925,17 @@ void GPUContextDX12::BindIB(GPUBuffer* indexBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX12::BindSampler(int32 slot, GPUSampler* sampler)
|
||||
{
|
||||
ASSERT(slot >= GPU_STATIC_SAMPLERS_COUNT && slot < GPU_MAX_SAMPLER_BINDED);
|
||||
const auto handle = sampler ? static_cast<GPUSamplerDX12*>(sampler) : nullptr;
|
||||
if (_samplers[slot - GPU_STATIC_SAMPLERS_COUNT] != handle)
|
||||
{
|
||||
_samplersDirtyFlag = true;
|
||||
_samplers[slot - GPU_STATIC_SAMPLERS_COUNT] = handle;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX12::UpdateCB(GPUConstantBuffer* cb, const void* data)
|
||||
{
|
||||
ASSERT(data && cb);
|
||||
@@ -927,6 +973,7 @@ void GPUContextDX12::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCoun
|
||||
flushUAVs();
|
||||
flushRBs();
|
||||
flushCBs();
|
||||
flushSamplers();
|
||||
|
||||
auto shaderDX12 = (GPUShaderProgramCSDX12*)shader;
|
||||
auto computeState = shaderDX12->GetOrCreateState();
|
||||
@@ -959,6 +1006,7 @@ void GPUContextDX12::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* buf
|
||||
flushUAVs();
|
||||
flushRBs();
|
||||
flushCBs();
|
||||
flushSamplers();
|
||||
|
||||
auto shaderDX12 = (GPUShaderProgramCSDX12*)shader;
|
||||
auto computeState = shaderDX12->GetOrCreateState();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
class GPUDeviceDX12;
|
||||
class GPUPipelineStateDX12;
|
||||
class GPUBufferDX12;
|
||||
class GPUSamplerDX12;
|
||||
class GPUConstantBufferDX12;
|
||||
class GPUTextureViewDX12;
|
||||
|
||||
@@ -51,6 +52,7 @@ private:
|
||||
int32 _rtDirtyFlag : 1;
|
||||
int32 _psDirtyFlag : 1;
|
||||
int32 _cbDirtyFlag : 1;
|
||||
int32 _samplersDirtyFlag : 1;
|
||||
|
||||
GPUTextureViewDX12* _rtDepth;
|
||||
GPUTextureViewDX12* _rtHandles[GPU_MAX_RT_BINDED];
|
||||
@@ -62,6 +64,7 @@ private:
|
||||
D3D12_VERTEX_BUFFER_VIEW _vbViews[GPU_MAX_VB_BINDED];
|
||||
D3D12_RESOURCE_BARRIER _rbBuffer[DX12_RB_BUFFER_SIZE];
|
||||
GPUConstantBufferDX12* _cbHandles[GPU_MAX_CB_BINDED];
|
||||
GPUSamplerDX12* _samplers[GPU_MAX_SAMPLER_BINDED - GPU_STATIC_SAMPLERS_COUNT];
|
||||
|
||||
public:
|
||||
|
||||
@@ -136,6 +139,7 @@ private:
|
||||
void flushRTVs();
|
||||
void flushUAVs();
|
||||
void flushCBs();
|
||||
void flushSamplers();
|
||||
void flushRBs();
|
||||
void flushPS();
|
||||
void OnDrawCall();
|
||||
@@ -167,6 +171,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;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "GPUTextureDX12.h"
|
||||
#include "GPUTimerQueryDX12.h"
|
||||
#include "GPUBufferDX12.h"
|
||||
#include "GPUSamplerDX12.h"
|
||||
#include "GPUSwapChainDX12.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Engine/CommandLine.h"
|
||||
@@ -191,7 +192,9 @@ GPUDeviceDX12::GPUDeviceDX12(IDXGIFactory4* dxgiFactory, GPUAdapterDX* adapter)
|
||||
, Heap_CBV_SRV_UAV(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 4 * 1024, false)
|
||||
, Heap_RTV(this, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1 * 1024, false)
|
||||
, Heap_DSV(this, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 64, false)
|
||||
, Heap_Sampler(this, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 128, false)
|
||||
, RingHeap_CBV_SRV_UAV(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 512 * 1024, true)
|
||||
, RingHeap_Sampler(this, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 1 * 1024, true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -350,6 +353,7 @@ bool GPUDeviceDX12::Init()
|
||||
limits.MaximumTexture2DArraySize = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture3DSize = D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
|
||||
limits.MaximumTextureCubeSize = D3D12_REQ_TEXTURECUBE_DIMENSION;
|
||||
limits.MaximumSamplerAnisotropy = D3D12_DEFAULT_MAX_ANISOTROPY;
|
||||
|
||||
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
||||
{
|
||||
@@ -379,6 +383,8 @@ bool GPUDeviceDX12::Init()
|
||||
_mainContext = New<GPUContextDX12>(this, D3D12_COMMAND_LIST_TYPE_DIRECT);
|
||||
if (RingHeap_CBV_SRV_UAV.Init())
|
||||
return true;
|
||||
if (RingHeap_Sampler.Init())
|
||||
return true;
|
||||
|
||||
// Create empty views
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
@@ -458,7 +464,7 @@ bool GPUDeviceDX12::Init()
|
||||
// TODO: maybe create set of different root signatures? for UAVs, for compute, for simple drawing, for post fx?
|
||||
{
|
||||
// Descriptor tables
|
||||
D3D12_DESCRIPTOR_RANGE r[2];
|
||||
D3D12_DESCRIPTOR_RANGE r[3];
|
||||
// TODO: separate ranges for pixel/vertex visibility and one shared for all?
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE& range = r[0];
|
||||
@@ -476,9 +482,17 @@ bool GPUDeviceDX12::Init()
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
}
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE& range = r[2];
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
range.NumDescriptors = GPU_MAX_SAMPLER_BINDED - GPU_STATIC_SAMPLERS_COUNT;
|
||||
range.BaseShaderRegister = GPU_STATIC_SAMPLERS_COUNT;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
}
|
||||
|
||||
// Root parameters
|
||||
D3D12_ROOT_PARAMETER rootParameters[4];
|
||||
D3D12_ROOT_PARAMETER rootParameters[5];
|
||||
{
|
||||
D3D12_ROOT_PARAMETER& rootParam = rootParameters[0];
|
||||
rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
@@ -507,11 +521,18 @@ bool GPUDeviceDX12::Init()
|
||||
rootParam.DescriptorTable.NumDescriptorRanges = 1;
|
||||
rootParam.DescriptorTable.pDescriptorRanges = &r[1];
|
||||
}
|
||||
|
||||
// TODO: describe visibilities for the static samples, maybe use all pixel? or again pixel + all combo?
|
||||
{
|
||||
D3D12_ROOT_PARAMETER& rootParam = rootParameters[4];
|
||||
rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
rootParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
rootParam.DescriptorTable.NumDescriptorRanges = 1;
|
||||
rootParam.DescriptorTable.pDescriptorRanges = &r[2];
|
||||
}
|
||||
|
||||
// Static samplers
|
||||
D3D12_STATIC_SAMPLER_DESC staticSamplers[6];
|
||||
static_assert(GPU_STATIC_SAMPLERS_COUNT == ARRAY_COUNT(staticSamplers), "Update static samplers setup.");
|
||||
// TODO: describe visibilities for the static samples, maybe use all pixel? or again pixel + all combo?
|
||||
// Linear Clamp
|
||||
staticSamplers[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
staticSamplers[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
@@ -718,7 +739,9 @@ void GPUDeviceDX12::Dispose()
|
||||
Heap_CBV_SRV_UAV.ReleaseGPU();
|
||||
Heap_RTV.ReleaseGPU();
|
||||
Heap_DSV.ReleaseGPU();
|
||||
Heap_Sampler.ReleaseGPU();
|
||||
RingHeap_CBV_SRV_UAV.ReleaseGPU();
|
||||
RingHeap_Sampler.ReleaseGPU();
|
||||
SAFE_DELETE(UploadBuffer);
|
||||
SAFE_DELETE(DrawIndirectCommandSignature);
|
||||
SAFE_DELETE(_mainContext);
|
||||
@@ -766,6 +789,11 @@ GPUBuffer* GPUDeviceDX12::CreateBuffer(const StringView& name)
|
||||
return New<GPUBufferDX12>(this, name);
|
||||
}
|
||||
|
||||
GPUSampler* GPUDeviceDX12::CreateSampler()
|
||||
{
|
||||
return New<GPUSamplerDX12>(this);
|
||||
}
|
||||
|
||||
GPUSwapChain* GPUDeviceDX12::CreateSwapChain(Window* window)
|
||||
{
|
||||
return New<GPUSwapChainDX12>(this, window);
|
||||
|
||||
@@ -141,7 +141,9 @@ public:
|
||||
DescriptorHeapPoolDX12 Heap_CBV_SRV_UAV;
|
||||
DescriptorHeapPoolDX12 Heap_RTV;
|
||||
DescriptorHeapPoolDX12 Heap_DSV;
|
||||
DescriptorHeapPoolDX12 Heap_Sampler;
|
||||
DescriptorHeapRingBufferDX12 RingHeap_CBV_SRV_UAV;
|
||||
DescriptorHeapRingBufferDX12 RingHeap_Sampler;
|
||||
|
||||
public:
|
||||
|
||||
@@ -188,6 +190,7 @@ public:
|
||||
GPUPipelineState* CreatePipelineState() override;
|
||||
GPUTimerQuery* CreateTimerQuery() override;
|
||||
GPUBuffer* CreateBuffer(const StringView& name) override;
|
||||
GPUSampler* CreateSampler() override;
|
||||
GPUSwapChain* CreateSwapChain(Window* window) override;
|
||||
};
|
||||
|
||||
|
||||
124
Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.cpp
Normal file
124
Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX12
|
||||
|
||||
#include "GPUSamplerDX12.h"
|
||||
|
||||
D3D12_TEXTURE_ADDRESS_MODE ToDX12(GPUSamplerAddressMode value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case GPUSamplerAddressMode::Wrap:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
case GPUSamplerAddressMode::Clamp:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
case GPUSamplerAddressMode::Mirror:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
|
||||
case GPUSamplerAddressMode::Border:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
|
||||
default:
|
||||
return (D3D12_TEXTURE_ADDRESS_MODE)-1;
|
||||
}
|
||||
}
|
||||
|
||||
bool GPUSamplerDX12::OnInit()
|
||||
{
|
||||
D3D12_SAMPLER_DESC samplerDesc;
|
||||
if (_desc.ComparisonFunction == GPUSamplerCompareFunction::Never)
|
||||
{
|
||||
switch (_desc.Filter)
|
||||
{
|
||||
case GPUSamplerFilter::Point:
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Bilinear:
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Trilinear:
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
break;
|
||||
case GPUSamplerFilter::Anisotropic:
|
||||
samplerDesc.Filter = D3D12_FILTER_ANISOTROPIC;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (_desc.Filter)
|
||||
{
|
||||
case GPUSamplerFilter::Point:
|
||||
samplerDesc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Bilinear:
|
||||
samplerDesc.Filter = D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
|
||||
break;
|
||||
case GPUSamplerFilter::Trilinear:
|
||||
samplerDesc.Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
||||
break;
|
||||
case GPUSamplerFilter::Anisotropic:
|
||||
samplerDesc.Filter = D3D12_FILTER_COMPARISON_ANISOTROPIC;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
samplerDesc.AddressU = ToDX12(_desc.AddressU);
|
||||
samplerDesc.AddressV = ToDX12(_desc.AddressV);
|
||||
samplerDesc.AddressW = ToDX12(_desc.AddressW);
|
||||
samplerDesc.MipLODBias = _desc.MipBias;
|
||||
samplerDesc.MaxAnisotropy = _desc.MaxAnisotropy;
|
||||
switch (_desc.ComparisonFunction)
|
||||
{
|
||||
case GPUSamplerCompareFunction::Never:
|
||||
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
||||
break;
|
||||
case GPUSamplerCompareFunction::Less:
|
||||
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
switch (_desc.BorderColor)
|
||||
{
|
||||
case GPUSamplerBorderColor::TransparentBlack:
|
||||
samplerDesc.BorderColor[0] = 0;
|
||||
samplerDesc.BorderColor[1] = 0;
|
||||
samplerDesc.BorderColor[2] = 0;
|
||||
samplerDesc.BorderColor[3] = 0;
|
||||
break;
|
||||
case GPUSamplerBorderColor::OpaqueBlack:
|
||||
samplerDesc.BorderColor[0] = 0;
|
||||
samplerDesc.BorderColor[1] = 0;
|
||||
samplerDesc.BorderColor[2] = 0;
|
||||
samplerDesc.BorderColor[3] = 1.0f;
|
||||
break;
|
||||
case GPUSamplerBorderColor::OpaqueWhite:
|
||||
samplerDesc.BorderColor[0] = 1.0f;
|
||||
samplerDesc.BorderColor[1] = 1.0f;
|
||||
samplerDesc.BorderColor[2] = 1.0f;
|
||||
samplerDesc.BorderColor[3] = 1.0f;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
samplerDesc.MinLOD = _desc.MinMipLevel;
|
||||
samplerDesc.MaxLOD = _desc.MaxMipLevel;
|
||||
_device->Heap_Sampler.AllocateSlot(Slot.Heap, Slot.Index);
|
||||
HandleCPU = Slot.CPU();
|
||||
_device->GetDevice()->CreateSampler(&samplerDesc, HandleCPU);
|
||||
_memoryUsage = sizeof(D3D12_SAMPLER_DESC);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUSamplerDX12::OnReleaseGPU()
|
||||
{
|
||||
Slot.Release();
|
||||
|
||||
// Base
|
||||
GPUSampler::OnReleaseGPU();
|
||||
}
|
||||
|
||||
#endif
|
||||
32
Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.h
Normal file
32
Source/Engine/GraphicsDevice/DirectX/DX12/GPUSamplerDX12.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/Textures/GPUSampler.h"
|
||||
#include "GPUDeviceDX12.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX12
|
||||
|
||||
/// <summary>
|
||||
/// Sampler object for DirectX 12 backend.
|
||||
/// </summary>
|
||||
class GPUSamplerDX12 : public GPUResourceDX12<GPUSampler>
|
||||
{
|
||||
public:
|
||||
|
||||
GPUSamplerDX12(GPUDeviceDX12* device)
|
||||
: GPUResourceDX12<GPUSampler>(device, StringView::Empty)
|
||||
{
|
||||
}
|
||||
|
||||
DescriptorHeapWithSlotsDX12::Slot Slot;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE HandleCPU;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUSampler]
|
||||
bool OnInit() override;
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -108,6 +108,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void BindSampler(int32 slot, GPUSampler* sampler) override
|
||||
{
|
||||
}
|
||||
|
||||
void UpdateCB(GPUConstantBuffer* cb, const void* data) override
|
||||
{
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "GPUPipelineStateNull.h"
|
||||
#include "GPUTimerQueryNull.h"
|
||||
#include "GPUBufferNull.h"
|
||||
#include "GPUSamplerNull.h"
|
||||
#include "GPUSwapChainNull.h"
|
||||
|
||||
GPUDeviceNull::GPUDeviceNull()
|
||||
@@ -66,6 +67,7 @@ bool GPUDeviceNull::Init()
|
||||
limits.MaximumTexture2DArraySize = 512;
|
||||
limits.MaximumTexture3DSize = 2048;
|
||||
limits.MaximumTextureCubeSize = 16384;
|
||||
limits.MaximumSamplerAnisotropy = 0;
|
||||
|
||||
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
||||
{
|
||||
@@ -177,6 +179,11 @@ GPUBuffer* GPUDeviceNull::CreateBuffer(const StringView& name)
|
||||
return New<GPUBufferNull>();
|
||||
}
|
||||
|
||||
GPUSampler* GPUDeviceNull::CreateSampler()
|
||||
{
|
||||
return New<GPUSamplerNull>();
|
||||
}
|
||||
|
||||
GPUSwapChain* GPUDeviceNull::CreateSwapChain(Window* window)
|
||||
{
|
||||
return New<GPUSwapChainNull>(window);
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
GPUPipelineState* CreatePipelineState() override;
|
||||
GPUTimerQuery* CreateTimerQuery() override;
|
||||
GPUBuffer* CreateBuffer(const StringView& name) override;
|
||||
GPUSampler* CreateSampler() override;
|
||||
GPUSwapChain* CreateSwapChain(Window* window) override;
|
||||
};
|
||||
|
||||
|
||||
23
Source/Engine/GraphicsDevice/Null/GPUSamplerNull.h
Normal file
23
Source/Engine/GraphicsDevice/Null/GPUSamplerNull.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if GRAPHICS_API_NULL
|
||||
|
||||
#include "Engine/Graphics/Textures/GPUSampler.h"
|
||||
|
||||
/// <summary>
|
||||
/// Sampler object for Null backend.
|
||||
/// </summary>
|
||||
class GPUSamplerNull : public GPUSampler
|
||||
{
|
||||
protected:
|
||||
|
||||
// [GPUSampler]
|
||||
bool OnInit() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
@@ -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