Add support for programmable samplers in shaders

This commit is contained in:
Wojtek Figat
2021-06-28 15:56:32 +02:00
parent 971449bef1
commit 3c1fd427eb
31 changed files with 866 additions and 121 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
};

View 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

View 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