You're breathtaking!
This commit is contained in:
165
Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.cpp
Normal file
165
Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUBufferDX11.h"
|
||||
#include "../RenderToolsDX.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
GPUBufferDX11::GPUBufferDX11(GPUDeviceDX11* device, const StringView& name)
|
||||
: GPUResourceDX11(device, name)
|
||||
{
|
||||
}
|
||||
|
||||
GPUBufferView* GPUBufferDX11::View() const
|
||||
{
|
||||
return (GPUBufferView*)&_view;
|
||||
}
|
||||
|
||||
void* GPUBufferDX11::Map(GPUResourceMapMode mode)
|
||||
{
|
||||
if (!IsInMainThread())
|
||||
_device->Locker.Lock();
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
map.pData = nullptr;
|
||||
D3D11_MAP mapType;
|
||||
switch (mode)
|
||||
{
|
||||
case GPUResourceMapMode::Read:
|
||||
mapType = D3D11_MAP_READ;
|
||||
break;
|
||||
case GPUResourceMapMode::Write:
|
||||
mapType = D3D11_MAP_WRITE_DISCARD;
|
||||
break;
|
||||
case GPUResourceMapMode::ReadWrite:
|
||||
mapType = D3D11_MAP_READ_WRITE;
|
||||
break;
|
||||
default:
|
||||
CRASH;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const HRESULT result = _device->GetIM()->Map(_resource, 0, mapType, 0, &map);
|
||||
LOG_DIRECTX_RESULT(result);
|
||||
return map.pData;
|
||||
}
|
||||
|
||||
void GPUBufferDX11::Unmap()
|
||||
{
|
||||
_device->GetIM()->Unmap(_resource, 0);
|
||||
|
||||
if (!IsInMainThread())
|
||||
_device->Locker.Unlock();
|
||||
}
|
||||
|
||||
bool GPUBufferDX11::OnInit()
|
||||
{
|
||||
bool useSRV = IsShaderResource();
|
||||
bool useUAV = IsUnorderedAccess();
|
||||
|
||||
// Create buffer description
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.ByteWidth = _desc.Size;
|
||||
bufferDesc.Usage = RenderToolsDX::ToD3D11Usage(_desc.Usage);
|
||||
bufferDesc.BindFlags = 0;
|
||||
bufferDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage);
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
//
|
||||
if (_desc.Flags & GPUBufferFlags::VertexBuffer)
|
||||
bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER;
|
||||
if (_desc.Flags & GPUBufferFlags::IndexBuffer)
|
||||
bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER;
|
||||
if (useSRV)
|
||||
bufferDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
||||
if (useUAV)
|
||||
bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
|
||||
//
|
||||
if (_desc.Flags & GPUBufferFlags::Argument)
|
||||
bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
|
||||
if (_desc.Flags & GPUBufferFlags::RawBuffer)
|
||||
bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
|
||||
if (_desc.Flags & GPUBufferFlags::Structured)
|
||||
{
|
||||
bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||
bufferDesc.StructureByteStride = _desc.Stride;
|
||||
}
|
||||
|
||||
// Create resource
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
if (_desc.InitData)
|
||||
{
|
||||
data.pSysMem = _desc.InitData;
|
||||
data.SysMemPitch = bufferDesc.ByteWidth;
|
||||
data.SysMemSlicePitch = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateBuffer(&bufferDesc, _desc.InitData ? &data : nullptr, &_resource));
|
||||
|
||||
// Set state
|
||||
DX_SET_DEBUG_NAME(_resource, GetName());
|
||||
_memoryUsage = _desc.Size;
|
||||
int32 numElements = _desc.GetElementsCount();
|
||||
|
||||
// Create views
|
||||
if (useSRV)
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
if (_desc.Flags & GPUBufferFlags::RawBuffer)
|
||||
{
|
||||
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
|
||||
srvDesc.BufferEx.FirstElement = 0;
|
||||
srvDesc.BufferEx.NumElements = numElements;
|
||||
srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_desc.Flags & GPUBufferFlags::Structured)
|
||||
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
else
|
||||
srvDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindShaderResourceFormat(_desc.Format, false));
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvDesc.Buffer.FirstElement = 0;
|
||||
srvDesc.Buffer.NumElements = numElements;
|
||||
}
|
||||
ID3D11ShaderResourceView* srv;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srvDesc, &srv));
|
||||
_view.SetSRV(srv);
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
||||
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||
uavDesc.Buffer.FirstElement = 0;
|
||||
uavDesc.Buffer.NumElements = numElements;
|
||||
uavDesc.Buffer.Flags = 0;
|
||||
if (_desc.Flags & GPUBufferFlags::RawBuffer)
|
||||
uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW;
|
||||
if (_desc.Flags & GPUBufferFlags::Append)
|
||||
uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_APPEND;
|
||||
if (_desc.Flags & GPUBufferFlags::Counter)
|
||||
uavDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_COUNTER;
|
||||
if (_desc.Flags & GPUBufferFlags::Structured)
|
||||
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
else
|
||||
uavDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(_desc.Format));
|
||||
ID3D11UnorderedAccessView* uav;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateUnorderedAccessView(_resource, &uavDesc, &uav));
|
||||
_view.SetUAV(uav);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUBufferDX11::OnReleaseGPU()
|
||||
{
|
||||
_view.Release();
|
||||
DX_SAFE_RELEASE_CHECK(_resource, 0);
|
||||
|
||||
// Base
|
||||
GPUBuffer::OnReleaseGPU();
|
||||
}
|
||||
|
||||
#endif
|
||||
145
Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.h
Normal file
145
Source/Engine/GraphicsDevice/DirectX/DX11/GPUBufferDX11.h
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "Engine/Graphics/GPUBuffer.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
#include "IShaderResourceDX11.h"
|
||||
|
||||
/// <summary>
|
||||
/// The buffer view for DirectX 11 backend.
|
||||
/// </summary>
|
||||
/// <seealso cref="GPUBufferView" />
|
||||
/// <seealso cref="IShaderResourceDX11" />
|
||||
class GPUBufferViewDX11 : public GPUBufferView, public IShaderResourceDX11
|
||||
{
|
||||
private:
|
||||
|
||||
ID3D11ShaderResourceView* _srv = nullptr;
|
||||
ID3D11UnorderedAccessView* _uav = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUBufferViewDX11"/> class.
|
||||
/// </summary>
|
||||
GPUBufferViewDX11()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUBufferViewDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUBufferViewDX11()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Release the view.
|
||||
/// </summary>
|
||||
void Release()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_srv, 0);
|
||||
DX_SAFE_RELEASE_CHECK(_uav, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Sets new shader resource view.
|
||||
/// </summary>
|
||||
/// <param name="srv">A new shader resource view.</param>
|
||||
void SetSRV(ID3D11ShaderResourceView* srv)
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_srv, 0);
|
||||
_srv = srv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets new unordered access view.
|
||||
/// </summary>
|
||||
/// <param name="uav">A new unordered access view.</param>
|
||||
void SetUAV(ID3D11UnorderedAccessView* uav)
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_uav, 0);
|
||||
_uav = uav;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceView]
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return (void*)(IShaderResourceDX11*)this;
|
||||
}
|
||||
|
||||
// [IShaderResourceDX11]
|
||||
ID3D11ShaderResourceView* SRV() const override
|
||||
{
|
||||
return _srv;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* UAV() const override
|
||||
{
|
||||
return _uav;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// GPU buffer for DirectX 11 backend.
|
||||
/// </summary>
|
||||
/// <seealso cref="GPUResourceDX11" />
|
||||
class GPUBufferDX11 : public GPUResourceDX11<GPUBuffer>
|
||||
{
|
||||
private:
|
||||
|
||||
ID3D11Buffer* _resource = nullptr;
|
||||
GPUBufferViewDX11 _view;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUBufferDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="name">The resource name.</param>
|
||||
GPUBufferDX11(GPUDeviceDX11* device, const StringView& name);
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets DirectX 11 buffer object handle
|
||||
/// </summary>
|
||||
/// <returns>Buffer</returns>
|
||||
FORCE_INLINE ID3D11Buffer* GetBuffer() const
|
||||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUBuffer]
|
||||
GPUBufferView* View() const override;
|
||||
void* Map(GPUResourceMapMode mode) override;
|
||||
void Unmap() override;
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() override
|
||||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUBuffer]
|
||||
bool OnInit() override;
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
880
Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
Normal file
880
Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp
Normal file
@@ -0,0 +1,880 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "GPUShaderDX11.h"
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUContextDX11.h"
|
||||
#include "Engine/Core/Math/Viewport.h"
|
||||
#include "Engine/Core/Math/Rectangle.h"
|
||||
#include "GPUShaderProgramDX11.h"
|
||||
#include "GPUPipelineStateDX11.h"
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "GPUBufferDX11.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
#include "Engine/Profiler/RenderStats.h"
|
||||
|
||||
#define DX11_CLEAR_SR_ON_STAGE_DISABLE 0
|
||||
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
ID3D11ShaderResourceView* EmptySRHandles[GPU_MAX_SR_BINDED] = {};
|
||||
#endif
|
||||
|
||||
// Ensure to match the indirect commands arguments layout
|
||||
static_assert(sizeof(GPUDispatchIndirectArgs) == sizeof(uint32) * 3, "Wrong size of GPUDrawIndirectArgs.");
|
||||
static_assert(OFFSET_OF(GPUDispatchIndirectArgs, ThreadGroupCountX) == sizeof(uint32) * 0, "Wrong offset for GPUDrawIndirectArgs::ThreadGroupCountX");
|
||||
static_assert(OFFSET_OF(GPUDispatchIndirectArgs, ThreadGroupCountY) == sizeof(uint32) * 1,"Wrong offset for GPUDrawIndirectArgs::ThreadGroupCountY");
|
||||
static_assert(OFFSET_OF(GPUDispatchIndirectArgs, ThreadGroupCountZ) == sizeof(uint32) * 2, "Wrong offset for GPUDrawIndirectArgs::ThreadGroupCountZ");
|
||||
//
|
||||
static_assert(sizeof(GPUDrawIndirectArgs) == sizeof(D3D11_DRAW_INSTANCED_INDIRECT_ARGS), "Wrong size of GPUDrawIndirectArgs.");
|
||||
static_assert(OFFSET_OF(GPUDrawIndirectArgs, VerticesCount) == OFFSET_OF(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, VertexCountPerInstance), "Wrong offset for GPUDrawIndirectArgs::VerticesCount");
|
||||
static_assert(OFFSET_OF(GPUDrawIndirectArgs, InstanceCount) == OFFSET_OF(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, InstanceCount),"Wrong offset for GPUDrawIndirectArgs::InstanceCount");
|
||||
static_assert(OFFSET_OF(GPUDrawIndirectArgs, StartVertex) == OFFSET_OF(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, StartVertexLocation), "Wrong offset for GPUDrawIndirectArgs::StartVertex");
|
||||
static_assert(OFFSET_OF(GPUDrawIndirectArgs, StartInstance) == OFFSET_OF(D3D11_DRAW_INSTANCED_INDIRECT_ARGS, StartInstanceLocation), "Wrong offset for GPUDrawIndirectArgs::StartInstance");
|
||||
//
|
||||
static_assert(sizeof(GPUDrawIndexedIndirectArgs) == sizeof(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS), "Wrong size of GPUDrawIndexedIndirectArgs.");
|
||||
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, IndicesCount) == OFFSET_OF(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, IndexCountPerInstance), "Wrong offset for GPUDrawIndexedIndirectArgs::IndicesCount");
|
||||
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, InstanceCount) == OFFSET_OF(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, InstanceCount),"Wrong offset for GPUDrawIndexedIndirectArgs::InstanceCount");
|
||||
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, StartIndex) == OFFSET_OF(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, StartIndexLocation), "Wrong offset for GPUDrawIndexedIndirectArgs::StartIndex");
|
||||
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, StartVertex) == OFFSET_OF(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, BaseVertexLocation), "Wrong offset for GPUDrawIndexedIndirectArgs::StartVertex");
|
||||
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, StartInstance) == OFFSET_OF(D3D11_DRAW_INDEXED_INSTANCED_INDIRECT_ARGS, StartInstanceLocation), "Wrong offset for GPUDrawIndexedIndirectArgs::StartInstance");
|
||||
|
||||
GPUContextDX11::GPUContextDX11(GPUDeviceDX11* device, ID3D11DeviceContext* context)
|
||||
: GPUContext(device)
|
||||
, _device(device)
|
||||
, _context(context)
|
||||
#if GPU_ALLOW_PROFILE_EVENTS
|
||||
, _userDefinedAnnotations(nullptr)
|
||||
#endif
|
||||
, _omDirtyFlag(false)
|
||||
, _rtCount(0)
|
||||
, _rtDepth(nullptr)
|
||||
, _uaOutput(nullptr)
|
||||
, _srDirtyFlag(false)
|
||||
, _uaDirtyFlag(false)
|
||||
, _cbDirtyFlag(false)
|
||||
, _currentState(nullptr)
|
||||
{
|
||||
ASSERT(_context);
|
||||
#if GPU_ALLOW_PROFILE_EVENTS
|
||||
_context->QueryInterface(IID_PPV_ARGS(&_userDefinedAnnotations));
|
||||
#endif
|
||||
|
||||
// Only DirectX 11 supports more than 1 UAV
|
||||
_maxUASlotsForCS = GPU_MAX_UA_BINDED;
|
||||
if (_device->GetRendererType() != RendererType::DirectX11)
|
||||
_maxUASlotsForCS = 1;
|
||||
}
|
||||
|
||||
GPUContextDX11::~GPUContextDX11()
|
||||
{
|
||||
#if GPU_ALLOW_PROFILE_EVENTS
|
||||
SAFE_RELEASE(_userDefinedAnnotations);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GPUContextDX11::FrameBegin()
|
||||
{
|
||||
// Base
|
||||
GPUContext::FrameBegin();
|
||||
|
||||
// Setup
|
||||
_omDirtyFlag = false;
|
||||
_uaDirtyFlag = false;
|
||||
_srDirtyFlag = false;
|
||||
_cbDirtyFlag = false;
|
||||
_rtCount = 0;
|
||||
_currentState = nullptr;
|
||||
_rtDepth = nullptr;
|
||||
_uaOutput = nullptr;
|
||||
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
Platform::MemoryClear(_uaHandles, sizeof(_uaHandles));
|
||||
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
|
||||
Platform::MemoryClear(_vbHandles, sizeof(_vbHandles));
|
||||
Platform::MemoryClear(_vbStrides, sizeof(_vbStrides));
|
||||
Platform::MemoryClear(_vbOffsets, sizeof(_vbOffsets));
|
||||
_ibHandle = nullptr;
|
||||
CurrentBlendState = nullptr;
|
||||
CurrentRasterizerState = nullptr;
|
||||
CurrentDepthStencilState = nullptr;
|
||||
CurrentVS = nullptr;
|
||||
CurrentHS = nullptr;
|
||||
CurrentDS = nullptr;
|
||||
CurrentGS = nullptr;
|
||||
CurrentPS = nullptr;
|
||||
CurrentCS = nullptr;
|
||||
CurrentPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
|
||||
// Bind static samplers
|
||||
ID3D11SamplerState* samplers[] =
|
||||
{
|
||||
_device->_samplerLinearClamp,
|
||||
_device->_samplerPointClamp,
|
||||
_device->_samplerLinearWrap,
|
||||
_device->_samplerPointWrap,
|
||||
_device->_samplerShadow,
|
||||
_device->_samplerShadowPCF
|
||||
};
|
||||
_context->VSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
_context->DSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
_context->PSSetSamplers(0, ARRAY_COUNT(samplers), samplers);
|
||||
_context->CSSetSamplers(0, ARRAY_COUNT(samplers), samplers); // TODO: maybe we don't want to bind those static sampler always?
|
||||
}
|
||||
|
||||
#if GPU_ALLOW_PROFILE_EVENTS
|
||||
|
||||
void GPUContextDX11::EventBegin(const Char* name)
|
||||
{
|
||||
if (_userDefinedAnnotations)
|
||||
_userDefinedAnnotations->BeginEvent(name);
|
||||
}
|
||||
|
||||
void GPUContextDX11::EventEnd()
|
||||
{
|
||||
if (_userDefinedAnnotations)
|
||||
_userDefinedAnnotations->EndEvent();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void* GPUContextDX11::GetNativePtr() const
|
||||
{
|
||||
return (void*)_context;
|
||||
}
|
||||
|
||||
bool GPUContextDX11::IsDepthBufferBinded()
|
||||
{
|
||||
return _rtDepth != nullptr;
|
||||
}
|
||||
|
||||
void GPUContextDX11::Clear(GPUTextureView* rt, const Color& color)
|
||||
{
|
||||
auto rtDX11 = static_cast<GPUTextureViewDX11*>(rt);
|
||||
|
||||
if (rtDX11)
|
||||
{
|
||||
_context->ClearRenderTargetView(rtDX11->RTV(), color.Raw);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::ClearDepth(GPUTextureView* depthBuffer, float depthValue)
|
||||
{
|
||||
auto depthBufferDX11 = static_cast<GPUTextureViewDX11*>(depthBuffer);
|
||||
|
||||
if (depthBufferDX11)
|
||||
{
|
||||
ASSERT(depthBufferDX11->DSV());
|
||||
_context->ClearDepthStencilView(depthBufferDX11->DSV(), D3D11_CLEAR_DEPTH, depthValue, 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::ClearUA(GPUBuffer* buf, const Vector4& value)
|
||||
{
|
||||
ASSERT(buf != nullptr && buf->IsUnorderedAccess());
|
||||
|
||||
auto uav = ((GPUBufferViewDX11*)buf->View())->UAV();
|
||||
|
||||
_context->ClearUnorderedAccessViewFloat(uav, value.Raw);
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResetRenderTarget()
|
||||
{
|
||||
if (_rtCount > 0 || _uaOutput || _rtDepth)
|
||||
{
|
||||
_omDirtyFlag = true;
|
||||
_rtCount = 0;
|
||||
_rtDepth = nullptr;
|
||||
_uaOutput = nullptr;
|
||||
|
||||
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
|
||||
|
||||
flushOM();
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetRenderTarget(GPUTextureView* rt)
|
||||
{
|
||||
auto rtDX11 = reinterpret_cast<GPUTextureViewDX11*>(rt);
|
||||
|
||||
ID3D11RenderTargetView* rtv = rtDX11 ? rtDX11->RTV() : nullptr;
|
||||
int32 newRtCount = rtv ? 1 : 0;
|
||||
|
||||
if (_rtCount != newRtCount || _rtHandles[0] != rtv || _rtDepth != nullptr || _uaOutput)
|
||||
{
|
||||
_omDirtyFlag = true;
|
||||
_rtCount = newRtCount;
|
||||
_rtDepth = nullptr;
|
||||
_rtHandles[0] = rtv;
|
||||
_uaOutput = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt)
|
||||
{
|
||||
auto rtDX11 = reinterpret_cast<GPUTextureViewDX11*>(rt);
|
||||
auto depthBufferDX11 = static_cast<GPUTextureViewDX11*>(depthBuffer);
|
||||
|
||||
ID3D11RenderTargetView* rtv = rtDX11 ? rtDX11->RTV() : nullptr;
|
||||
ID3D11DepthStencilView* dsv = depthBufferDX11 ? depthBufferDX11->DSV() : nullptr;
|
||||
int32 newRtCount = rtv ? 1 : 0;
|
||||
|
||||
if (_rtCount != newRtCount || _rtHandles[0] != rtv || _rtDepth != dsv || _uaOutput)
|
||||
{
|
||||
_omDirtyFlag = true;
|
||||
_rtCount = newRtCount;
|
||||
_rtDepth = dsv;
|
||||
_rtHandles[0] = rtv;
|
||||
_uaOutput = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts)
|
||||
{
|
||||
ASSERT(Math::IsInRange(rts.Length(), 1, GPU_MAX_RT_BINDED));
|
||||
|
||||
auto depthBufferDX11 = static_cast<GPUTextureViewDX11*>(depthBuffer);
|
||||
ID3D11DepthStencilView* dsv = depthBufferDX11 ? depthBufferDX11->DSV() : nullptr;
|
||||
|
||||
ID3D11RenderTargetView* rtvs[GPU_MAX_RT_BINDED];
|
||||
for (int32 i = 0; i < rts.Length(); i++)
|
||||
{
|
||||
auto rtDX11 = reinterpret_cast<GPUTextureViewDX11*>(rts[i]);
|
||||
rtvs[i] = rtDX11 ? rtDX11->RTV() : nullptr;
|
||||
}
|
||||
int32 rtvsSize = sizeof(ID3D11RenderTargetView*) * rts.Length();
|
||||
|
||||
if (_rtCount != rts.Length() || _rtDepth != dsv || _uaOutput || Platform::MemoryCompare(_rtHandles, rtvs, rtvsSize) != 0)
|
||||
{
|
||||
_omDirtyFlag = true;
|
||||
_rtCount = rts.Length();
|
||||
_rtDepth = dsv;
|
||||
_uaOutput = nullptr;
|
||||
Platform::MemoryCopy(_rtHandles, rtvs, rtvsSize);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetRenderTarget(GPUTextureView* rt, GPUBuffer* uaOutput)
|
||||
{
|
||||
auto rtDX11 = reinterpret_cast<GPUTextureViewDX11*>(rt);
|
||||
auto uaOutputDX11 = reinterpret_cast<GPUBufferDX11*>(uaOutput);
|
||||
|
||||
ID3D11RenderTargetView* rtv = rtDX11 ? rtDX11->RTV() : nullptr;
|
||||
ID3D11UnorderedAccessView* uav = uaOutputDX11 ? ((GPUBufferViewDX11*)uaOutputDX11->View())->UAV() : nullptr;
|
||||
int32 newRtCount = rtv ? 1 : 0;
|
||||
|
||||
if (_rtCount != newRtCount || _rtHandles[0] != rtv || _rtDepth != nullptr || _uaOutput != uav)
|
||||
{
|
||||
_omDirtyFlag = true;
|
||||
_rtCount = newRtCount;
|
||||
_rtDepth = nullptr;
|
||||
_rtHandles[0] = rtv;
|
||||
_uaOutput = uav;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResetSR()
|
||||
{
|
||||
_srDirtyFlag = false;
|
||||
Platform::MemoryClear(_srHandles, sizeof(_srHandles));
|
||||
|
||||
_context->VSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->HSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->DSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->GSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->PSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
_context->CSSetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles);
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResetUA()
|
||||
{
|
||||
_uaDirtyFlag = false;
|
||||
Platform::MemoryClear(_uaHandles, sizeof(_uaHandles));
|
||||
|
||||
_context->CSSetUnorderedAccessViews(0, _maxUASlotsForCS, _uaHandles, nullptr);
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResetCB()
|
||||
{
|
||||
_cbDirtyFlag = false;
|
||||
Platform::MemoryClear(_cbHandles, sizeof(_cbHandles));
|
||||
|
||||
_context->VSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->HSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->DSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->GSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->PSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
_context->CSSetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles);
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindCB(int32 slot, GPUConstantBuffer* cb)
|
||||
{
|
||||
ASSERT(slot >= 0 && slot < GPU_MAX_CB_BINDED);
|
||||
|
||||
ID3D11Buffer* buffer = nullptr;
|
||||
if (cb && cb->GetSize() > 0)
|
||||
{
|
||||
auto cbDX11 = static_cast<GPUConstantBufferDX11*>(cb);
|
||||
buffer = cbDX11->GetBuffer();
|
||||
}
|
||||
|
||||
if (_cbHandles[slot] != buffer)
|
||||
{
|
||||
_cbDirtyFlag = true;
|
||||
_cbHandles[slot] = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindSR(int32 slot, GPUResourceView* view)
|
||||
{
|
||||
ASSERT(slot >= 0 && slot < GPU_MAX_SR_BINDED);
|
||||
|
||||
auto handle = view ? ((IShaderResourceDX11*)view->GetNativePtr())->SRV() : nullptr;
|
||||
|
||||
if (_srHandles[slot] != handle)
|
||||
{
|
||||
_srDirtyFlag = true;
|
||||
_srHandles[slot] = handle;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindUA(int32 slot, GPUResourceView* view)
|
||||
{
|
||||
ASSERT(slot >= 0 && slot < GPU_MAX_UA_BINDED);
|
||||
|
||||
auto handle = view ? ((IShaderResourceDX11*)view->GetNativePtr())->UAV() : nullptr;
|
||||
|
||||
if (_uaHandles[slot] != handle)
|
||||
{
|
||||
_uaDirtyFlag = true;
|
||||
_uaHandles[slot] = handle;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
|
||||
{
|
||||
ASSERT(vertexBuffers.Length() >= 0 && vertexBuffers.Length() <= GPU_MAX_VB_BINDED);
|
||||
|
||||
bool vbEdited = false;
|
||||
for (int32 i = 0; i < vertexBuffers.Length(); i++)
|
||||
{
|
||||
const auto vbDX11 = static_cast<GPUBufferDX11*>(vertexBuffers[i]);
|
||||
const auto vb = vbDX11 ? vbDX11->GetBuffer() : nullptr;
|
||||
vbEdited |= vb != _vbHandles[i];
|
||||
_vbHandles[i] = vb;
|
||||
const UINT stride = vbDX11 ? vbDX11->GetStride() : 0;
|
||||
vbEdited |= stride != _vbStrides[i];
|
||||
_vbStrides[i] = stride;
|
||||
const UINT offset = vertexBuffersOffsets ? vertexBuffersOffsets[i] : 0;
|
||||
vbEdited |= offset != _vbOffsets[i];
|
||||
_vbOffsets[i] = offset;
|
||||
}
|
||||
if (vbEdited)
|
||||
{
|
||||
_context->IASetVertexBuffers(0, vertexBuffers.Length(), _vbHandles, _vbStrides, _vbOffsets);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::BindIB(GPUBuffer* indexBuffer)
|
||||
{
|
||||
const auto ibDX11 = static_cast<GPUBufferDX11*>(indexBuffer);
|
||||
if (ibDX11 != _ibHandle)
|
||||
{
|
||||
_ibHandle = ibDX11;
|
||||
_context->IASetIndexBuffer(ibDX11->GetBuffer(), RenderToolsDX::ToDxgiFormat(ibDX11->GetFormat()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::UpdateCB(GPUConstantBuffer* cb, const void* data)
|
||||
{
|
||||
ASSERT(data && cb);
|
||||
auto cbDX11 = static_cast<GPUConstantBufferDX11*>(cb);
|
||||
const uint32 size = cbDX11->GetSize();
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
_context->UpdateSubresource(cbDX11->GetBuffer(), 0, nullptr, data, size, 1);
|
||||
}
|
||||
|
||||
void GPUContextDX11::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ)
|
||||
{
|
||||
CurrentCS = (GPUShaderProgramCSDX11*)shader;
|
||||
|
||||
// Flush
|
||||
flushCBs();
|
||||
flushSRVs();
|
||||
flushUAVs();
|
||||
flushOM();
|
||||
|
||||
// Dispatch
|
||||
_context->CSSetShader((ID3D11ComputeShader*)shader->GetBufferHandle(), nullptr, 0);
|
||||
_context->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
|
||||
RENDER_STAT_DISPATCH_CALL();
|
||||
|
||||
CurrentCS = nullptr;
|
||||
}
|
||||
|
||||
void GPUContextDX11::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
||||
{
|
||||
CurrentCS = (GPUShaderProgramCSDX11*)shader;
|
||||
|
||||
auto bufferForArgsDX11 = (GPUBufferDX11*)bufferForArgs;
|
||||
|
||||
// Flush
|
||||
flushCBs();
|
||||
flushSRVs();
|
||||
flushUAVs();
|
||||
flushOM();
|
||||
|
||||
// Dispatch
|
||||
_context->CSSetShader((ID3D11ComputeShader*)shader->GetBufferHandle(), nullptr, 0);
|
||||
_context->DispatchIndirect(bufferForArgsDX11->GetBuffer(), offsetForArgs);
|
||||
RENDER_STAT_DISPATCH_CALL();
|
||||
|
||||
CurrentCS = nullptr;
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResolveMultisample(GPUTexture* sourceMultisampleTexture, GPUTexture* destTexture, int32 sourceSubResource, int32 destSubResource, PixelFormat format)
|
||||
{
|
||||
ASSERT(sourceMultisampleTexture && sourceMultisampleTexture->IsMultiSample());
|
||||
ASSERT(destTexture && !destTexture->IsMultiSample());
|
||||
|
||||
auto dstResourceDX11 = static_cast<GPUTextureDX11*>(destTexture);
|
||||
auto srcResourceDX11 = static_cast<GPUTextureDX11*>(sourceMultisampleTexture);
|
||||
|
||||
const auto formatDXGI = RenderToolsDX::ToDxgiFormat(format == PixelFormat::Unknown ? destTexture->Format() : format);
|
||||
_context->ResolveSubresource(dstResourceDX11->GetResource(), destSubResource, srcResourceDX11->GetResource(), destSubResource, formatDXGI);
|
||||
}
|
||||
|
||||
void GPUContextDX11::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex)
|
||||
{
|
||||
onDrawCall();
|
||||
if (instanceCount > 1)
|
||||
_context->DrawInstanced(verticesCount, instanceCount, startVertex, startInstance);
|
||||
else
|
||||
_context->Draw(verticesCount, startVertex);
|
||||
RENDER_STAT_DRAW_CALL(verticesCount * instanceCount, verticesCount * instanceCount / 3);
|
||||
}
|
||||
|
||||
void GPUContextDX11::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex)
|
||||
{
|
||||
onDrawCall();
|
||||
if (instanceCount > 1)
|
||||
_context->DrawIndexedInstanced(indicesCount, instanceCount, startIndex, startVertex, startInstance);
|
||||
else
|
||||
_context->DrawIndexed(indicesCount, startIndex, startVertex);
|
||||
RENDER_STAT_DRAW_CALL(0, indicesCount / 3 * instanceCount);
|
||||
}
|
||||
|
||||
void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
||||
{
|
||||
ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
|
||||
|
||||
const auto bufferForArgsDX11 = static_cast<GPUBufferDX11*>(bufferForArgs);
|
||||
|
||||
onDrawCall();
|
||||
_context->DrawInstancedIndirect(bufferForArgsDX11->GetBuffer(), offsetForArgs);
|
||||
RENDER_STAT_DRAW_CALL(0, 0);
|
||||
}
|
||||
|
||||
void GPUContextDX11::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
||||
{
|
||||
ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument);
|
||||
|
||||
const auto bufferForArgsDX11 = static_cast<GPUBufferDX11*>(bufferForArgs);
|
||||
|
||||
onDrawCall();
|
||||
_context->DrawIndexedInstancedIndirect(bufferForArgsDX11->GetBuffer(), offsetForArgs);
|
||||
RENDER_STAT_DRAW_CALL(0, 0);
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetViewport(const Viewport& viewport)
|
||||
{
|
||||
_context->RSSetViewports(1, (D3D11_VIEWPORT*)&viewport);
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetScissor(const Rectangle& scissorRect)
|
||||
{
|
||||
D3D11_RECT rect;
|
||||
rect.left = (LONG)scissorRect.GetLeft();
|
||||
rect.right = (LONG)scissorRect.GetRight();
|
||||
rect.top = (LONG)scissorRect.GetTop();
|
||||
rect.bottom = (LONG)scissorRect.GetBottom();
|
||||
_context->RSSetScissorRects(1, &rect);
|
||||
}
|
||||
|
||||
GPUPipelineState* GPUContextDX11::GetState() const
|
||||
{
|
||||
return _currentState;
|
||||
}
|
||||
|
||||
void GPUContextDX11::SetState(GPUPipelineState* state)
|
||||
{
|
||||
if (_currentState != state)
|
||||
{
|
||||
_currentState = static_cast<GPUPipelineStateDX11*>(state);
|
||||
|
||||
ID3D11BlendState* blendState = nullptr;
|
||||
ID3D11RasterizerState* rasterizerState = nullptr;
|
||||
ID3D11DepthStencilState* depthStencilState = nullptr;
|
||||
GPUShaderProgramVSDX11* vs = nullptr;
|
||||
GPUShaderProgramHSDX11* hs = nullptr;
|
||||
GPUShaderProgramDSDX11* ds = nullptr;
|
||||
GPUShaderProgramGSDX11* gs = nullptr;
|
||||
GPUShaderProgramPSDX11* ps = nullptr;
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
|
||||
if (state)
|
||||
{
|
||||
ASSERT(_currentState->IsValid());
|
||||
|
||||
blendState = _currentState->BlendState;
|
||||
rasterizerState = _device->RasterizerStates[_currentState->RasterizerStateIndex];
|
||||
depthStencilState = _device->DepthStencilStates[_currentState->DepthStencilStateIndex];
|
||||
|
||||
ASSERT(_currentState->VS != nullptr);
|
||||
vs = _currentState->VS;
|
||||
hs = _currentState->HS;
|
||||
ds = _currentState->DS;
|
||||
gs = _currentState->GS;
|
||||
ps = _currentState->PS;
|
||||
|
||||
primitiveTopology = _currentState->PrimitiveTopology;
|
||||
}
|
||||
|
||||
// Per pipeline stage state caching
|
||||
if (CurrentDepthStencilState != depthStencilState)
|
||||
{
|
||||
CurrentDepthStencilState = depthStencilState;
|
||||
_context->OMSetDepthStencilState(depthStencilState, 0);
|
||||
}
|
||||
if (CurrentRasterizerState != rasterizerState)
|
||||
{
|
||||
CurrentRasterizerState = rasterizerState;
|
||||
_context->RSSetState(rasterizerState);
|
||||
}
|
||||
if (CurrentBlendState != blendState)
|
||||
{
|
||||
CurrentBlendState = blendState;
|
||||
FLOAT blendFactor[4] = { 1, 1, 1, 1 };
|
||||
_context->OMSetBlendState(blendState, blendFactor, D3D11_DEFAULT_SAMPLE_MASK);
|
||||
}
|
||||
if (CurrentVS != vs)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
if (CurrentVS && !vs)
|
||||
{
|
||||
_context->VSSetShaderResources(0, ARRAY_COUNT(EmptySRHandles), EmptySRHandles);
|
||||
}
|
||||
#endif
|
||||
CurrentVS = vs;
|
||||
_context->VSSetShader(vs ? vs->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
_context->IASetInputLayout(vs ? vs->GetInputLayoutDX11() : nullptr);
|
||||
}
|
||||
if (CurrentHS != hs)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
if (CurrentHS && !hs)
|
||||
{
|
||||
_context->HSSetShaderResources(0, ARRAY_COUNT(EmptySRHandles), EmptySRHandles);
|
||||
}
|
||||
#endif
|
||||
CurrentHS = hs;
|
||||
_context->HSSetShader(hs ? hs->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
}
|
||||
if (CurrentDS != ds)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
if (CurrentDS && !ds)
|
||||
{
|
||||
_context->DSSetShaderResources(0, ARRAY_COUNT(EmptySRHandles), EmptySRHandles);
|
||||
}
|
||||
#endif
|
||||
CurrentDS = ds;
|
||||
_context->DSSetShader(ds ? ds->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
}
|
||||
if (CurrentGS != gs)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
if (CurrentGS && !gs)
|
||||
{
|
||||
_context->GSSetShaderResources(0, ARRAY_COUNT(EmptySRHandles), EmptySRHandles);
|
||||
}
|
||||
#endif
|
||||
CurrentGS = gs;
|
||||
_context->GSSetShader(gs ? gs->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
}
|
||||
if (CurrentPS != ps)
|
||||
{
|
||||
#if DX11_CLEAR_SR_ON_STAGE_DISABLE
|
||||
if (CurrentPS && !ps)
|
||||
{
|
||||
_context->PSSetShaderResources(0, ARRAY_COUNT(EmptySRHandles), EmptySRHandles);
|
||||
}
|
||||
#endif
|
||||
CurrentPS = ps;
|
||||
_context->PSSetShader(ps ? ps->GetBufferHandleDX11() : nullptr, nullptr, 0);
|
||||
}
|
||||
if (CurrentPrimitiveTopology != primitiveTopology)
|
||||
{
|
||||
CurrentPrimitiveTopology = primitiveTopology;
|
||||
_context->IASetPrimitiveTopology(primitiveTopology);
|
||||
}
|
||||
|
||||
RENDER_STAT_PS_STATE_CHANGE();
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::ClearState()
|
||||
{
|
||||
if (!_context)
|
||||
return;
|
||||
|
||||
ResetRenderTarget();
|
||||
ResetSR();
|
||||
ResetUA();
|
||||
ResetCB();
|
||||
SetState(nullptr);
|
||||
|
||||
FlushState();
|
||||
|
||||
//_context->ClearState();
|
||||
}
|
||||
|
||||
void GPUContextDX11::FlushState()
|
||||
{
|
||||
// Flush
|
||||
flushCBs();
|
||||
flushSRVs();
|
||||
flushUAVs();
|
||||
flushOM();
|
||||
}
|
||||
|
||||
void GPUContextDX11::Flush()
|
||||
{
|
||||
if (_context)
|
||||
_context->Flush();
|
||||
}
|
||||
|
||||
void GPUContextDX11::UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset)
|
||||
{
|
||||
ASSERT(data);
|
||||
ASSERT(buffer && buffer->GetSize() >= size);
|
||||
|
||||
auto bufferDX11 = (GPUBufferDX11*)buffer;
|
||||
|
||||
// Use map/unmap for dynamic buffers
|
||||
if (buffer->IsDynamic())
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
const HRESULT result = _context->Map(bufferDX11->GetResource(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_DIRECTX_RESULT(result);
|
||||
return;
|
||||
}
|
||||
Platform::MemoryCopy(map.pData, data, size);
|
||||
_context->Unmap(bufferDX11->GetResource(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_BOX box;
|
||||
box.left = offset;
|
||||
box.right = offset + size;
|
||||
box.front = 0;
|
||||
box.back = 1;
|
||||
box.top = 0;
|
||||
box.bottom = 1;
|
||||
_context->UpdateSubresource(bufferDX11->GetResource(), 0, &box, data, size, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::CopyBuffer(GPUBuffer* dstBuffer, GPUBuffer* srcBuffer, uint32 size, uint32 dstOffset, uint32 srcOffset)
|
||||
{
|
||||
ASSERT(dstBuffer && srcBuffer);
|
||||
|
||||
auto dstBufferDX11 = static_cast<GPUBufferDX11*>(dstBuffer);
|
||||
auto srcBufferDX11 = static_cast<GPUBufferDX11*>(srcBuffer);
|
||||
|
||||
D3D11_BOX box;
|
||||
box.left = srcOffset;
|
||||
box.right = srcOffset + size;
|
||||
box.top = 0;
|
||||
box.bottom = 1;
|
||||
box.front = 0;
|
||||
box.back = 1;
|
||||
_context->CopySubresourceRegion(dstBufferDX11->GetResource(), 0, dstOffset, 0, 0, srcBufferDX11->GetResource(), 0, &box);
|
||||
}
|
||||
|
||||
void GPUContextDX11::UpdateTexture(GPUTexture* texture, int32 arrayIndex, int32 mipIndex, const void* data, uint32 rowPitch, uint32 slicePitch)
|
||||
{
|
||||
ASSERT(texture && texture->IsAllocated() && data);
|
||||
|
||||
auto textureDX11 = static_cast<GPUTextureDX11*>(texture);
|
||||
|
||||
const int32 subresourceIndex = RenderToolsDX::CalcSubresourceIndex(mipIndex, arrayIndex, texture->MipLevels());
|
||||
_context->UpdateSubresource(textureDX11->GetResource(), subresourceIndex, nullptr, data, static_cast<UINT>(rowPitch), slicePitch);
|
||||
|
||||
//D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
//_device->GetIM()->Map(_resource, textureMipIndex, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
//Platform::MemoryCopy(mapped.pData, data, size);
|
||||
//_device->GetIM()->Unmap(_resource, textureMipIndex);
|
||||
}
|
||||
|
||||
void GPUContextDX11::CopyTexture(GPUTexture* dstResource, uint32 dstSubresource, uint32 dstX, uint32 dstY, uint32 dstZ, GPUTexture* srcResource, uint32 srcSubresource)
|
||||
{
|
||||
ASSERT(dstResource && srcResource);
|
||||
|
||||
auto dstResourceDX11 = static_cast<GPUTextureDX11*>(dstResource);
|
||||
auto srcResourceDX11 = static_cast<GPUTextureDX11*>(srcResource);
|
||||
|
||||
_context->CopySubresourceRegion(dstResourceDX11->GetResource(), dstSubresource, dstX, dstY, dstZ, srcResourceDX11->GetResource(), srcSubresource, nullptr);
|
||||
}
|
||||
|
||||
void GPUContextDX11::ResetCounter(GPUBuffer* buffer)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUContextDX11::CopyCounter(GPUBuffer* dstBuffer, uint32 dstOffset, GPUBuffer* srcBuffer)
|
||||
{
|
||||
ASSERT(dstBuffer && srcBuffer);
|
||||
|
||||
auto dstBufferDX11 = static_cast<GPUBufferDX11*>(dstBuffer);
|
||||
auto srvUavView = ((GPUBufferViewDX11*)srcBuffer->View())->UAV();
|
||||
|
||||
_context->CopyStructureCount(dstBufferDX11->GetBuffer(), dstOffset, srvUavView);
|
||||
}
|
||||
|
||||
void GPUContextDX11::CopyResource(GPUResource* dstResource, GPUResource* srcResource)
|
||||
{
|
||||
ASSERT(dstResource && srcResource);
|
||||
|
||||
auto dstResourceDX11 = dynamic_cast<IGPUResourceDX11*>(dstResource);
|
||||
auto srcResourceDX11 = dynamic_cast<IGPUResourceDX11*>(srcResource);
|
||||
|
||||
_context->CopyResource(dstResourceDX11->GetResource(), srcResourceDX11->GetResource());
|
||||
}
|
||||
|
||||
void GPUContextDX11::CopySubresource(GPUResource* dstResource, uint32 dstSubresource, GPUResource* srcResource, uint32 srcSubresource)
|
||||
{
|
||||
ASSERT(dstResource && srcResource);
|
||||
|
||||
auto dstResourceDX11 = dynamic_cast<IGPUResourceDX11*>(dstResource);
|
||||
auto srcResourceDX11 = dynamic_cast<IGPUResourceDX11*>(srcResource);
|
||||
|
||||
_context->CopySubresourceRegion(dstResourceDX11->GetResource(), dstSubresource, 0, 0, 0, srcResourceDX11->GetResource(), srcSubresource, nullptr);
|
||||
}
|
||||
|
||||
void GPUContextDX11::flushSRVs()
|
||||
{
|
||||
// Check if need to flush shader resources
|
||||
if (_srDirtyFlag)
|
||||
{
|
||||
// Clear flag
|
||||
_srDirtyFlag = false;
|
||||
|
||||
// Flush with the driver
|
||||
// TODO: don't bind SRV to all stages and all slots (use mask for bind diff?)
|
||||
#define FLUSH_STAGE(STAGE) \
|
||||
if (Current##STAGE) \
|
||||
{ \
|
||||
_context->STAGE##SetShaderResources(0, ARRAY_COUNT(_srHandles), _srHandles); \
|
||||
}
|
||||
FLUSH_STAGE(VS);
|
||||
FLUSH_STAGE(HS);
|
||||
FLUSH_STAGE(DS);
|
||||
FLUSH_STAGE(GS);
|
||||
FLUSH_STAGE(PS);
|
||||
FLUSH_STAGE(CS);
|
||||
#undef FLUSH_STAGE
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::flushUAVs()
|
||||
{
|
||||
// Check if need to flush unordered access
|
||||
if (_uaDirtyFlag)
|
||||
{
|
||||
// Clear flag
|
||||
_uaDirtyFlag = false;
|
||||
|
||||
// Flush with the driver
|
||||
uint32 initialCounts[GPU_MAX_UA_BINDED] = { 0 };
|
||||
_context->CSSetUnorderedAccessViews(0, _maxUASlotsForCS, _uaHandles, initialCounts);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::flushCBs()
|
||||
{
|
||||
// Check if need to flush constant buffers
|
||||
if (_cbDirtyFlag)
|
||||
{
|
||||
// Clear flag
|
||||
_cbDirtyFlag = false;
|
||||
|
||||
// Flush with the driver
|
||||
// TODO: don't bind CBV to all stages and all slots (use mask for bind diff? eg. cache mask from last flush and check if there is a diff + include mask from diff slots?)
|
||||
#define FLUSH_STAGE(STAGE) \
|
||||
if (Current##STAGE) \
|
||||
{ \
|
||||
_context->STAGE##SetConstantBuffers(0, ARRAY_COUNT(_cbHandles), _cbHandles); \
|
||||
}
|
||||
FLUSH_STAGE(VS);
|
||||
FLUSH_STAGE(HS);
|
||||
FLUSH_STAGE(DS);
|
||||
FLUSH_STAGE(GS);
|
||||
FLUSH_STAGE(PS);
|
||||
FLUSH_STAGE(CS);
|
||||
#undef FLUSH_STAGE
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::flushOM()
|
||||
{
|
||||
// Check if need to flush output merger state or/and unordered access views
|
||||
if (_omDirtyFlag)
|
||||
{
|
||||
#if _DEBUG
|
||||
// Validate binded render targets amount
|
||||
int32 rtCount = 0;
|
||||
for (int i = 0; i < ARRAY_COUNT(_rtHandles) && i < _rtCount; i++)
|
||||
{
|
||||
if (_rtHandles[i] != nullptr)
|
||||
rtCount++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
ASSERT(rtCount == _rtCount);
|
||||
#endif
|
||||
|
||||
// Check if don't use UAVs and set output merger render targets table
|
||||
if (_uaOutput == nullptr)
|
||||
{
|
||||
_context->OMSetRenderTargets(_rtCount, _rtHandles, _rtDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: current dx11 content implementation assumes that there must be one or more render targets binded in order to use uav output
|
||||
ASSERT(_rtCount > 0);
|
||||
|
||||
uint32 initialCounts[1] = { 0 };
|
||||
// TODO: set -1 if buffer had no ResetCounter call since last time
|
||||
_context->OMSetRenderTargetsAndUnorderedAccessViews(_rtCount, _rtHandles, _rtDepth, _rtCount, 1, &_uaOutput, initialCounts);
|
||||
}
|
||||
|
||||
// Clear flag
|
||||
_omDirtyFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUContextDX11::onDrawCall()
|
||||
{
|
||||
ASSERT(_currentState);
|
||||
|
||||
// Flush
|
||||
flushCBs();
|
||||
flushSRVs();
|
||||
flushUAVs();
|
||||
flushOM();
|
||||
}
|
||||
|
||||
#endif
|
||||
150
Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h
Normal file
150
Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/GPUContext.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
#include "GPUPipelineStateDX11.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
class GPUBufferDX11;
|
||||
|
||||
/// <summary>
|
||||
/// GPU Context for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUContextDX11 : public GPUContext
|
||||
{
|
||||
private:
|
||||
|
||||
GPUDeviceDX11* _device;
|
||||
ID3D11DeviceContext* _context;
|
||||
#if GPU_ALLOW_PROFILE_EVENTS
|
||||
ID3DUserDefinedAnnotation* _userDefinedAnnotations;
|
||||
#endif
|
||||
int32 _maxUASlotsForCS;
|
||||
|
||||
// Output Merger
|
||||
bool _omDirtyFlag;
|
||||
int32 _rtCount;
|
||||
ID3D11DepthStencilView* _rtDepth;
|
||||
ID3D11RenderTargetView* _rtHandles[GPU_MAX_RT_BINDED];
|
||||
ID3D11UnorderedAccessView* _uaOutput;
|
||||
|
||||
// Shader Resources
|
||||
bool _srDirtyFlag;
|
||||
ID3D11ShaderResourceView* _srHandles[GPU_MAX_SR_BINDED];
|
||||
|
||||
// Unordered Access
|
||||
bool _uaDirtyFlag;
|
||||
ID3D11UnorderedAccessView* _uaHandles[GPU_MAX_UA_BINDED];
|
||||
|
||||
// Constant Buffers
|
||||
bool _cbDirtyFlag;
|
||||
ID3D11Buffer* _cbHandles[GPU_MAX_CB_BINDED];
|
||||
|
||||
// Vertex Buffers
|
||||
GPUBufferDX11* _ibHandle;
|
||||
ID3D11Buffer* _vbHandles[GPU_MAX_VB_BINDED];
|
||||
UINT _vbStrides[GPU_MAX_VB_BINDED];
|
||||
UINT _vbOffsets[GPU_MAX_VB_BINDED];
|
||||
|
||||
// Pipeline State
|
||||
GPUPipelineStateDX11* _currentState;
|
||||
ID3D11BlendState* CurrentBlendState;
|
||||
ID3D11RasterizerState* CurrentRasterizerState;
|
||||
ID3D11DepthStencilState* CurrentDepthStencilState;
|
||||
GPUShaderProgramVSDX11* CurrentVS;
|
||||
GPUShaderProgramHSDX11* CurrentHS;
|
||||
GPUShaderProgramDSDX11* CurrentDS;
|
||||
GPUShaderProgramGSDX11* CurrentGS;
|
||||
GPUShaderProgramPSDX11* CurrentPS;
|
||||
GPUShaderProgramCSDX11* CurrentCS;
|
||||
D3D11_PRIMITIVE_TOPOLOGY CurrentPrimitiveTopology;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUContextDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="context">The context.</param>
|
||||
GPUContextDX11(GPUDeviceDX11* device, ID3D11DeviceContext* context);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUContextDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUContextDX11();
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets DirectX 11 device context used by this context
|
||||
/// </summary>
|
||||
/// <returns>GPU context</returns>
|
||||
FORCE_INLINE ID3D11DeviceContext* GetContext() const
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void flushSRVs();
|
||||
void flushUAVs();
|
||||
void flushCBs();
|
||||
void flushOM();
|
||||
void onDrawCall();
|
||||
|
||||
public:
|
||||
|
||||
// [GPUContext]
|
||||
void FrameBegin() override;
|
||||
#if GPU_ALLOW_PROFILE_EVENTS
|
||||
void EventBegin(const Char* name) override;
|
||||
void EventEnd() override;
|
||||
#endif
|
||||
void* GetNativePtr() const override;
|
||||
bool IsDepthBufferBinded() override;
|
||||
void Clear(GPUTextureView* rt, const Color& color) override;
|
||||
void ClearDepth(GPUTextureView* depthBuffer, float depthValue) override;
|
||||
void ClearUA(GPUBuffer* buf, const Vector4& value) override;
|
||||
void ResetRenderTarget() override;
|
||||
void SetRenderTarget(GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
|
||||
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
|
||||
void SetRenderTarget(GPUTextureView* rt, GPUBuffer* uaOutput) override;
|
||||
void ResetSR() override;
|
||||
void ResetUA() override;
|
||||
void ResetCB() override;
|
||||
void BindCB(int32 slot, GPUConstantBuffer* cb) override;
|
||||
void BindSR(int32 slot, GPUResourceView* view) override;
|
||||
void BindUA(int32 slot, GPUResourceView* view) override;
|
||||
void BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets = nullptr) override;
|
||||
void BindIB(GPUBuffer* indexBuffer) 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;
|
||||
void ResolveMultisample(GPUTexture* sourceMultisampleTexture, GPUTexture* destTexture, int32 sourceSubResource, int32 destSubResource, PixelFormat format) override;
|
||||
void DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex) override;
|
||||
void DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex) override;
|
||||
void DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs) override;
|
||||
void DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs) override;
|
||||
void SetViewport(const Viewport& viewport) override;
|
||||
void SetScissor(const Rectangle& scissorRect) override;
|
||||
GPUPipelineState* GetState() const override;
|
||||
void SetState(GPUPipelineState* state) override;
|
||||
void ClearState() override;
|
||||
void FlushState() override;
|
||||
void Flush() override;
|
||||
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
||||
void CopyBuffer(GPUBuffer* dstBuffer, GPUBuffer* srcBuffer, uint32 size, uint32 dstOffset, uint32 srcOffset) override;
|
||||
void UpdateTexture(GPUTexture* texture, int32 arrayIndex, int32 mipIndex, const void* data, uint32 rowPitch, uint32 slicePitch) override;
|
||||
void CopyTexture(GPUTexture* dstResource, uint32 dstSubresource, uint32 dstX, uint32 dstY, uint32 dstZ, GPUTexture* srcResource, uint32 srcSubresource) override;
|
||||
void ResetCounter(GPUBuffer* buffer) override;
|
||||
void CopyCounter(GPUBuffer* dstBuffer, uint32 dstOffset, GPUBuffer* srcBuffer) override;
|
||||
void CopyResource(GPUResource* dstResource, GPUResource* srcResource) override;
|
||||
void CopySubresource(GPUResource* dstResource, uint32 dstSubresource, GPUResource* srcResource, uint32 srcSubresource) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
711
Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp
Normal file
711
Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp
Normal file
@@ -0,0 +1,711 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUDeviceDX11.h"
|
||||
#include "GPUShaderDX11.h"
|
||||
#include "GPUContextDX11.h"
|
||||
#include "GPUPipelineStateDX11.h"
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "GPUTimerQueryDX11.h"
|
||||
#include "GPUBufferDX11.h"
|
||||
#include "GPUSwapChainDX11.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Utilities.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
#include "Engine/Engine/CommandLine.h"
|
||||
|
||||
#if !USE_EDITOR && PLATFORM_WINDOWS
|
||||
#include "Engine/Core/Config/PlatformSettings.h"
|
||||
#endif
|
||||
|
||||
#define DX11_FORCE_USE_DX10 0
|
||||
#define DX11_FORCE_USE_DX10_1 0
|
||||
|
||||
static bool TryCreateDevice(IDXGIAdapter* adapter, D3D_FEATURE_LEVEL maxFeatureLevel, D3D_FEATURE_LEVEL* outFeatureLevel)
|
||||
{
|
||||
// Temporary data
|
||||
ID3D11Device* device = nullptr;
|
||||
ID3D11DeviceContext* context = nullptr;
|
||||
uint32 deviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
D3D_FEATURE_LEVEL requestedFeatureLevels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0
|
||||
};
|
||||
|
||||
int32 firstAllowedFeatureLevel = 0;
|
||||
int32 numAllowedFeatureLevels = ARRAY_COUNT(requestedFeatureLevels);
|
||||
while (firstAllowedFeatureLevel < numAllowedFeatureLevels)
|
||||
{
|
||||
if (requestedFeatureLevels[firstAllowedFeatureLevel] == maxFeatureLevel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
firstAllowedFeatureLevel++;
|
||||
}
|
||||
numAllowedFeatureLevels -= firstAllowedFeatureLevel;
|
||||
if (numAllowedFeatureLevels == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to create device
|
||||
if (SUCCEEDED(D3D11CreateDevice(
|
||||
adapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
NULL,
|
||||
deviceFlags,
|
||||
&requestedFeatureLevels[firstAllowedFeatureLevel],
|
||||
numAllowedFeatureLevels,
|
||||
D3D11_SDK_VERSION,
|
||||
&device,
|
||||
outFeatureLevel,
|
||||
&context
|
||||
)))
|
||||
{
|
||||
// Release created stuff
|
||||
device->Release();
|
||||
context->Release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GPUDevice* GPUDeviceDX11::Create()
|
||||
{
|
||||
// Configuration
|
||||
#if PLATFORM_XBOX_ONE
|
||||
D3D_FEATURE_LEVEL maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_10_0;
|
||||
#elif DX11_FORCE_USE_DX10
|
||||
D3D_FEATURE_LEVEL maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_10_0;
|
||||
#elif DX11_FORCE_USE_DX10_1
|
||||
D3D_FEATURE_LEVEL maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_10_1;
|
||||
#else
|
||||
D3D_FEATURE_LEVEL maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
#endif
|
||||
if (CommandLine::Options.D3D10)
|
||||
maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_10_0;
|
||||
else if (CommandLine::Options.D3D11)
|
||||
maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
#if !USE_EDITOR && PLATFORM_WINDOWS
|
||||
auto winSettings = WindowsPlatformSettings::Instance();
|
||||
if (!winSettings->SupportDX11 && !winSettings->SupportDX10)
|
||||
{
|
||||
// Skip if there is no support
|
||||
LOG(Warning, "Cannot use DirectX (support disabled).");
|
||||
return nullptr;
|
||||
}
|
||||
if (!winSettings->SupportDX11 && maxAllowedFeatureLevel == D3D_FEATURE_LEVEL_11_0)
|
||||
{
|
||||
// Downgrade if there is no SM5 support
|
||||
maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_10_0;
|
||||
LOG(Warning, "Cannot use DirectX 11 (support disabled).");
|
||||
}
|
||||
if (!winSettings->SupportDX10 && maxAllowedFeatureLevel == D3D_FEATURE_LEVEL_10_0)
|
||||
{
|
||||
// Upgrade if there is no SM4 support
|
||||
maxAllowedFeatureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
LOG(Warning, "Cannot use DirectX 10 (support disabled).");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create DXGI factory
|
||||
#if PLATFORM_WINDOWS
|
||||
IDXGIFactory1* dxgiFactory;
|
||||
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
|
||||
#else
|
||||
IDXGIFactory2* dxgiFactory;
|
||||
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
|
||||
#endif
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LOG(Error, "Cannot create DXGI adapter. Error code: {0:x}.", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Enumerate the DXGIFactory's adapters
|
||||
Array<GPUAdapterDX> adapters;
|
||||
IDXGIAdapter* tmpAdapter;
|
||||
for (uint32 index = 0; dxgiFactory->EnumAdapters(index, &tmpAdapter) != DXGI_ERROR_NOT_FOUND; index++)
|
||||
{
|
||||
GPUAdapterDX adapter;
|
||||
if (tmpAdapter && TryCreateDevice(tmpAdapter, maxAllowedFeatureLevel, &adapter.MaxFeatureLevel))
|
||||
{
|
||||
adapter.Index = index;
|
||||
VALIDATE_DIRECTX_RESULT(tmpAdapter->GetDesc(&adapter.Description));
|
||||
uint32 outputs = RenderToolsDX::CountAdapterOutputs(tmpAdapter);
|
||||
|
||||
LOG(Info, "Adapter {1}: '{0}', DirectX {2}", adapter.Description.Description, index, RenderToolsDX::GetFeatureLevelString(adapter.MaxFeatureLevel));
|
||||
LOG(Info, " Dedicated Video Memory: {0}, Dedicated System Memory: {1}, Shared System Memory: {2}, Output(s): {3}", Utilities::BytesToText(adapter.Description.DedicatedVideoMemory), Utilities::BytesToText(adapter.Description.DedicatedSystemMemory), Utilities::BytesToText(adapter.Description.SharedSystemMemory), outputs);
|
||||
|
||||
adapters.Add(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
// Select the adapter to use
|
||||
GPUAdapterDX selectedAdapter = adapters[0];
|
||||
uint32 vendorId = 0;
|
||||
if (CommandLine::Options.NVIDIA)
|
||||
vendorId = GPU_VENDOR_ID_NVIDIA;
|
||||
else if (CommandLine::Options.AMD)
|
||||
vendorId = GPU_VENDOR_ID_AMD;
|
||||
else if (CommandLine::Options.Intel)
|
||||
vendorId = GPU_VENDOR_ID_INTEL;
|
||||
if (vendorId != 0)
|
||||
{
|
||||
for (const auto& adapter : adapters)
|
||||
{
|
||||
if (adapter.GetVendorId() == vendorId)
|
||||
{
|
||||
selectedAdapter = adapter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate adapter
|
||||
if (!selectedAdapter.IsValid())
|
||||
{
|
||||
LOG(Error, "Failed to choose valid DirectX adapter!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create device
|
||||
auto device = New<GPUDeviceDX11>(dxgiFactory, New<GPUAdapterDX>(selectedAdapter));
|
||||
if (device->Init())
|
||||
{
|
||||
LOG(Warning, "Graphics Device init failed");
|
||||
Delete(device);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
GPUDeviceDX11::GPUDeviceDX11(IDXGIFactory* dxgiFactory, GPUAdapterDX* adapter)
|
||||
: GPUDeviceDX(getRendererType(adapter), getShaderProfile(adapter), adapter)
|
||||
, _device(nullptr)
|
||||
, _imContext(nullptr)
|
||||
, _factoryDXGI(dxgiFactory)
|
||||
, _mainContext(nullptr)
|
||||
, _samplerLinearClamp(nullptr)
|
||||
, _samplerPointClamp(nullptr)
|
||||
, _samplerLinearWrap(nullptr)
|
||||
, _samplerPointWrap(nullptr)
|
||||
, _samplerShadow(nullptr)
|
||||
, _samplerShadowPCF(nullptr)
|
||||
{
|
||||
Platform::MemoryClear(RasterizerStates, sizeof(RasterizerStates));
|
||||
Platform::MemoryClear(DepthStencilStates, sizeof(DepthStencilStates));
|
||||
}
|
||||
|
||||
ID3D11BlendState* GPUDeviceDX11::GetBlendState(const BlendingMode& blending)
|
||||
{
|
||||
// Use lookup
|
||||
ID3D11BlendState* blendState = nullptr;
|
||||
if (BlendStates.TryGet(blending, blendState))
|
||||
return blendState;
|
||||
|
||||
// Make it safe
|
||||
ScopeLock lock(BlendStatesWriteLocker);
|
||||
|
||||
// Try again to prevent race condition with double-adding the same thing
|
||||
if (BlendStates.TryGet(blending, blendState))
|
||||
return blendState;
|
||||
|
||||
// Prepare description
|
||||
D3D11_BLEND_DESC desc;
|
||||
desc.AlphaToCoverageEnable = blending.AlphaToCoverageEnable ? TRUE : FALSE;
|
||||
desc.IndependentBlendEnable = FALSE;
|
||||
desc.RenderTarget[0].BlendEnable = blending.BlendEnable ? TRUE : FALSE;
|
||||
desc.RenderTarget[0].SrcBlend = (D3D11_BLEND)blending.SrcBlend;
|
||||
desc.RenderTarget[0].DestBlend = (D3D11_BLEND)blending.DestBlend;
|
||||
desc.RenderTarget[0].BlendOp = (D3D11_BLEND_OP)blending.BlendOp;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = (D3D11_BLEND)blending.SrcBlendAlpha;
|
||||
desc.RenderTarget[0].DestBlendAlpha = (D3D11_BLEND)blending.DestBlendAlpha;
|
||||
desc.RenderTarget[0].BlendOpAlpha = (D3D11_BLEND_OP)blending.BlendOpAlpha;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = (UINT8)blending.RenderTargetWriteMask;
|
||||
#if BUILD_DEBUG
|
||||
for (byte i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
||||
desc.RenderTarget[i] = desc.RenderTarget[0];
|
||||
#endif
|
||||
|
||||
// Create object
|
||||
VALIDATE_DIRECTX_RESULT(_device->CreateBlendState(&desc, &blendState));
|
||||
|
||||
// Cache blend state
|
||||
BlendStates.Add(blending, blendState);
|
||||
|
||||
return blendState;
|
||||
}
|
||||
|
||||
static MSAALevel GetMaximumMultisampleCount(ID3D11Device* device, DXGI_FORMAT dxgiFormat)
|
||||
{
|
||||
int32 maxCount = 1;
|
||||
UINT numQualityLevels;
|
||||
for (int32 i = 2; i <= 8; i *= 2)
|
||||
{
|
||||
if (SUCCEEDED(device->CheckMultisampleQualityLevels(dxgiFormat, i, &numQualityLevels)) && numQualityLevels > 0)
|
||||
maxCount = i;
|
||||
}
|
||||
return static_cast<MSAALevel>(maxCount);
|
||||
}
|
||||
|
||||
bool GPUDeviceDX11::Init()
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
// Get DXGI adapter
|
||||
ComPtr<IDXGIAdapter> adapter;
|
||||
if (_factoryDXGI->EnumAdapters(_adapter->Index, &adapter) == DXGI_ERROR_NOT_FOUND || adapter == nullptr)
|
||||
{
|
||||
LOG(Warning, "Cannot get the adapter.");
|
||||
return true;
|
||||
}
|
||||
UpdateOutputs(adapter);
|
||||
|
||||
// Get flags and device type base on current configuration
|
||||
uint32 flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
LOG(Info, "DirectX debugging layer enabled");
|
||||
#endif
|
||||
|
||||
// Create DirectX device
|
||||
D3D_FEATURE_LEVEL createdFeatureLevel = static_cast<D3D_FEATURE_LEVEL>(0);
|
||||
auto targetFeatureLevel = GetD3DFeatureLevel();
|
||||
VALIDATE_DIRECTX_RESULT(D3D11CreateDevice(
|
||||
adapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
NULL,
|
||||
flags,
|
||||
&targetFeatureLevel,
|
||||
1,
|
||||
D3D11_SDK_VERSION,
|
||||
&_device,
|
||||
&createdFeatureLevel,
|
||||
&_imContext
|
||||
));
|
||||
|
||||
// Validate result
|
||||
ASSERT(_device);
|
||||
ASSERT(_imContext);
|
||||
ASSERT(createdFeatureLevel == targetFeatureLevel);
|
||||
_state = DeviceState::Created;
|
||||
|
||||
// Verify compute shader is supported on DirectX 11
|
||||
if (createdFeatureLevel >= D3D_FEATURE_LEVEL_11_0)
|
||||
{
|
||||
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options = { 0 };
|
||||
_device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(options));
|
||||
if (!options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x)
|
||||
{
|
||||
_device->Release();
|
||||
_device = nullptr;
|
||||
LOG(Fatal, "DirectCompute is not supported by this device (DirectX 11 level).");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Init device limits
|
||||
{
|
||||
auto& limits = Limits;
|
||||
if (createdFeatureLevel >= D3D_FEATURE_LEVEL_11_0)
|
||||
{
|
||||
limits.HasCompute = true;
|
||||
limits.HasTessellation = true;
|
||||
limits.HasGeometryShaders = true;
|
||||
limits.HasInstancing = true;
|
||||
limits.HasVolumeTextureRendering = true;
|
||||
limits.HasDrawIndirect = true;
|
||||
limits.HasAppendConsumeBuffers = true;
|
||||
limits.HasSeparateRenderTargetBlendState = true;
|
||||
limits.HasDepthAsSRV = true;
|
||||
limits.HasReadOnlyDepth = true;
|
||||
limits.HasMultisampleDepthAsSRV = true;
|
||||
limits.MaximumMipLevelsCount = D3D11_REQ_MIP_LEVELS;
|
||||
limits.MaximumTexture1DSize = D3D11_REQ_TEXTURE1D_U_DIMENSION;
|
||||
limits.MaximumTexture1DArraySize = D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture2DSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
limits.MaximumTexture2DArraySize = D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture3DSize = D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
|
||||
limits.MaximumTextureCubeSize = D3D11_REQ_TEXTURECUBE_DIMENSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
limits.HasCompute = false;
|
||||
limits.HasTessellation = false;
|
||||
limits.HasGeometryShaders = true;
|
||||
limits.HasInstancing = true;
|
||||
limits.HasVolumeTextureRendering = false;
|
||||
limits.HasDrawIndirect = false;
|
||||
limits.HasAppendConsumeBuffers = false;
|
||||
limits.HasSeparateRenderTargetBlendState = false;
|
||||
limits.HasDepthAsSRV = false;
|
||||
limits.HasReadOnlyDepth = createdFeatureLevel == D3D_FEATURE_LEVEL_10_1;
|
||||
limits.HasMultisampleDepthAsSRV = false;
|
||||
limits.MaximumMipLevelsCount = D3D10_REQ_MIP_LEVELS;
|
||||
limits.MaximumTexture1DSize = D3D10_REQ_TEXTURE1D_U_DIMENSION;
|
||||
limits.MaximumTexture1DArraySize = D3D10_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture2DSize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
limits.MaximumTexture2DArraySize = D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
|
||||
limits.MaximumTexture3DSize = D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
|
||||
limits.MaximumTextureCubeSize = D3D11_REQ_TEXTURECUBE_DIMENSION;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
||||
{
|
||||
auto format = static_cast<PixelFormat>(i);
|
||||
auto dxgiFormat = RenderToolsDX::ToDxgiFormat(format);
|
||||
auto maximumMultisampleCount = GetMaximumMultisampleCount(_device, dxgiFormat);
|
||||
UINT formatSupport = 0;
|
||||
_device->CheckFormatSupport(dxgiFormat, &formatSupport);
|
||||
FeaturesPerFormat[i] = FormatFeatures(format, maximumMultisampleCount, (FormatSupport)formatSupport);
|
||||
}
|
||||
}
|
||||
|
||||
// Init debug layer
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
ComPtr<ID3D11InfoQueue> infoQueue;
|
||||
VALIDATE_DIRECTX_RESULT(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
if (infoQueue)
|
||||
{
|
||||
D3D11_INFO_QUEUE_FILTER filter;
|
||||
Platform::MemoryClear(&filter, sizeof(filter));
|
||||
|
||||
D3D11_MESSAGE_SEVERITY denySeverity = D3D11_MESSAGE_SEVERITY_INFO;
|
||||
filter.DenyList.NumSeverities = 1;
|
||||
filter.DenyList.pSeverityList = &denySeverity;
|
||||
|
||||
D3D11_MESSAGE_ID disabledMessages[] =
|
||||
{
|
||||
D3D11_MESSAGE_ID_OMSETRENDERTARGETS_INVALIDVIEW,
|
||||
D3D11_MESSAGE_ID_QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS,
|
||||
D3D11_MESSAGE_ID_QUERY_END_ABANDONING_PREVIOUS_RESULTS,
|
||||
D3D11_MESSAGE_ID_CREATEINPUTLAYOUT_EMPTY_LAYOUT,
|
||||
D3D11_MESSAGE_ID_DEVICE_DRAW_INDEX_BUFFER_TOO_SMALL,
|
||||
D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET,
|
||||
D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
|
||||
};
|
||||
|
||||
filter.DenyList.NumIDs = ARRAY_COUNT(disabledMessages);
|
||||
filter.DenyList.pIDList = disabledMessages;
|
||||
|
||||
infoQueue->PushStorageFilter(&filter);
|
||||
|
||||
infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||
infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||
//infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create main context from Immediate Context
|
||||
_mainContext = New<GPUContextDX11>(this, _imContext);
|
||||
|
||||
// Static Samplers
|
||||
{
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
Platform::MemoryClear(&samplerDesc, sizeof(samplerDesc));
|
||||
|
||||
// Linear Clamp
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerLinearClamp);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
|
||||
// Point Clamp
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerPointClamp);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
|
||||
// Linear Wrap
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerLinearWrap);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
|
||||
// Point Wrap
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerPointWrap);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
|
||||
// Shadow
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = 1;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerShadow);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
|
||||
// Shadow PCF
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = 1;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
|
||||
samplerDesc.BorderColor[0] = samplerDesc.BorderColor[1] = samplerDesc.BorderColor[2] = samplerDesc.BorderColor[3] = 0;
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerShadowPCF);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
}
|
||||
|
||||
// Rasterizer States
|
||||
{
|
||||
D3D11_RASTERIZER_DESC rDesc;
|
||||
rDesc.ScissorEnable = TRUE;
|
||||
rDesc.MultisampleEnable = TRUE;
|
||||
rDesc.FrontCounterClockwise = FALSE;
|
||||
rDesc.DepthBias = 0;
|
||||
rDesc.DepthBiasClamp = 0.0f;
|
||||
rDesc.SlopeScaledDepthBias = 0.0f;
|
||||
int32 index;
|
||||
#define CREATE_RASTERIZER_STATE(cullMode, dxCullMode, wireframe, depthClip) \
|
||||
index = (int32)cullMode + (wireframe ? 0 : 3) + (depthClip ? 0 : 6); \
|
||||
rDesc.CullMode = dxCullMode; \
|
||||
rDesc.FillMode = wireframe ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID; \
|
||||
rDesc.AntialiasedLineEnable = !!wireframe; \
|
||||
rDesc.DepthClipEnable = !!depthClip; \
|
||||
result = _device->CreateRasterizerState(&rDesc, &RasterizerStates[index]); \
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result)
|
||||
CREATE_RASTERIZER_STATE(CullMode::Normal, D3D11_CULL_BACK, false, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Inverted, D3D11_CULL_FRONT, false, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::TwoSided, D3D11_CULL_NONE, false, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Normal, D3D11_CULL_BACK, true, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Inverted, D3D11_CULL_FRONT, true, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::TwoSided, D3D11_CULL_NONE, true, false);
|
||||
//
|
||||
CREATE_RASTERIZER_STATE(CullMode::Normal, D3D11_CULL_BACK, false, true);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Inverted, D3D11_CULL_FRONT, false, true);
|
||||
CREATE_RASTERIZER_STATE(CullMode::TwoSided, D3D11_CULL_NONE, false, true);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Normal, D3D11_CULL_BACK, true, true);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Inverted, D3D11_CULL_FRONT, true, true);
|
||||
CREATE_RASTERIZER_STATE(CullMode::TwoSided, D3D11_CULL_NONE, true, true);
|
||||
#undef CREATE_RASTERIZER_STATE
|
||||
}
|
||||
|
||||
// Depth Stencil States
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC dsDesc;
|
||||
dsDesc.StencilEnable = FALSE;
|
||||
dsDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
dsDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
const D3D11_DEPTH_STENCILOP_DESC defaultStencilOp = { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS };
|
||||
dsDesc.FrontFace = defaultStencilOp;
|
||||
dsDesc.BackFace = defaultStencilOp;
|
||||
int32 index;
|
||||
#define CREATE_DEPTH_STENCIL_STATE(depthTextEnable, depthWrite) \
|
||||
dsDesc.DepthEnable = depthTextEnable; \
|
||||
dsDesc.DepthWriteMask = depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; \
|
||||
for(int32 depthFunc = 1; depthFunc <= 8; depthFunc++) { \
|
||||
dsDesc.DepthFunc = (D3D11_COMPARISON_FUNC)depthFunc; \
|
||||
index = (int32)depthFunc + (depthTextEnable ? 0 : 9) + (depthWrite ? 0 : 18); \
|
||||
HRESULT result = _device->CreateDepthStencilState(&dsDesc, &DepthStencilStates[index]); \
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result); }
|
||||
CREATE_DEPTH_STENCIL_STATE(false, false);
|
||||
CREATE_DEPTH_STENCIL_STATE(false, true);
|
||||
CREATE_DEPTH_STENCIL_STATE(true, true);
|
||||
CREATE_DEPTH_STENCIL_STATE(true, false);
|
||||
#undef CREATE_DEPTH_STENCIL_STATE
|
||||
}
|
||||
|
||||
_state
|
||||
=
|
||||
DeviceState::Ready;
|
||||
return
|
||||
GPUDeviceDX::Init();
|
||||
}
|
||||
|
||||
GPUDeviceDX11::~GPUDeviceDX11()
|
||||
{
|
||||
// Ensure to be disposed
|
||||
GPUDeviceDX11::Dispose();
|
||||
}
|
||||
|
||||
GPUDevice* CreateGPUDeviceDX11()
|
||||
{
|
||||
return GPUDeviceDX11::Create();
|
||||
}
|
||||
|
||||
void GPUDeviceDX11::Dispose()
|
||||
{
|
||||
GPUDeviceLock lock(this);
|
||||
|
||||
// Check if has been disposed already
|
||||
if (_state == DeviceState::Disposed)
|
||||
return;
|
||||
|
||||
// Set current state
|
||||
_state = DeviceState::Disposing;
|
||||
|
||||
// Wait for rendering end
|
||||
WaitForGPU();
|
||||
|
||||
// Pre dispose
|
||||
preDispose();
|
||||
|
||||
// Clear device resources
|
||||
SAFE_RELEASE(_samplerLinearClamp);
|
||||
SAFE_RELEASE(_samplerPointClamp);
|
||||
SAFE_RELEASE(_samplerLinearWrap);
|
||||
SAFE_RELEASE(_samplerPointWrap);
|
||||
SAFE_RELEASE(_samplerShadow);
|
||||
SAFE_RELEASE(_samplerShadowPCF);
|
||||
//
|
||||
for (auto i = BlendStates.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
i->Value->Release();
|
||||
}
|
||||
BlendStates.Clear();
|
||||
for (uint32 i = 0; i < ARRAY_COUNT(RasterizerStates); i++)
|
||||
{
|
||||
SAFE_RELEASE(RasterizerStates[i]);
|
||||
}
|
||||
for (uint32 i = 0; i < ARRAY_COUNT(DepthStencilStates); i++)
|
||||
{
|
||||
SAFE_RELEASE(DepthStencilStates[i]);
|
||||
}
|
||||
|
||||
// Clear DirectX stuff
|
||||
SAFE_DELETE(_mainContext);
|
||||
SAFE_DELETE(_adapter);
|
||||
SAFE_RELEASE(_imContext);
|
||||
#if GPU_ENABLE_DIAGNOSTICS && 0
|
||||
ID3D11Debug* debugLayer = nullptr;
|
||||
_device->QueryInterface(IID_PPV_ARGS(&debugLayer));
|
||||
if (debugLayer)
|
||||
{
|
||||
// Report any DirectX object leaks
|
||||
debugLayer->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL | D3D11_RLDO_IGNORE_INTERNAL);
|
||||
debugLayer->Release();
|
||||
}
|
||||
#endif
|
||||
SAFE_RELEASE(_device);
|
||||
SAFE_RELEASE(_factoryDXGI);
|
||||
|
||||
// Base
|
||||
GPUDeviceDX::Dispose();
|
||||
|
||||
// Set current state
|
||||
_state = DeviceState::Disposed;
|
||||
}
|
||||
|
||||
void GPUDeviceDX11::WaitForGPU()
|
||||
{
|
||||
// In DirectX 11 driver manages CPU/GPU work synchronization and work submission
|
||||
}
|
||||
|
||||
void GPUDeviceDX11::DrawEnd()
|
||||
{
|
||||
GPUDeviceDX::DrawEnd();
|
||||
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
// Flush debug messages queue
|
||||
ComPtr<ID3D11InfoQueue> infoQueue;
|
||||
VALIDATE_DIRECTX_RESULT(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
if (infoQueue)
|
||||
{
|
||||
Array<uint8> data;
|
||||
const uint64 messagesCount = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
|
||||
for (uint64 i = 0; i < messagesCount; i++)
|
||||
{
|
||||
SIZE_T length = 0;
|
||||
if (SUCCEEDED(infoQueue->GetMessage(i, nullptr, &length)))
|
||||
{
|
||||
data.Resize((int32)length);
|
||||
auto messageData = (D3D11_MESSAGE*)data.Get();
|
||||
if (SUCCEEDED(infoQueue->GetMessage(i, messageData, &length)))
|
||||
{
|
||||
LogType logType;
|
||||
switch (messageData->Severity)
|
||||
{
|
||||
case D3D11_MESSAGE_SEVERITY_CORRUPTION:
|
||||
logType = LogType::Fatal;
|
||||
break;
|
||||
case D3D11_MESSAGE_SEVERITY_ERROR:
|
||||
logType = LogType::Error;
|
||||
break;
|
||||
case D3D11_MESSAGE_SEVERITY_WARNING:
|
||||
logType = LogType::Warning;
|
||||
break;
|
||||
case D3D11_MESSAGE_SEVERITY_INFO:
|
||||
case D3D11_MESSAGE_SEVERITY_MESSAGE:
|
||||
default:
|
||||
logType = LogType::Info;
|
||||
break;
|
||||
}
|
||||
Log::Logger::Write(logType, String(messageData->pDescription));
|
||||
}
|
||||
}
|
||||
}
|
||||
infoQueue->ClearStoredMessages();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
GPUTexture* GPUDeviceDX11::CreateTexture(const StringView& name)
|
||||
{
|
||||
return New<GPUTextureDX11>(this, name);
|
||||
}
|
||||
|
||||
GPUShader* GPUDeviceDX11::CreateShader(const StringView& name)
|
||||
{
|
||||
return New<GPUShaderDX11>(this, name);
|
||||
}
|
||||
|
||||
GPUPipelineState* GPUDeviceDX11::CreatePipelineState()
|
||||
{
|
||||
return New<GPUPipelineStateDX11>(this);
|
||||
}
|
||||
|
||||
GPUTimerQuery* GPUDeviceDX11::CreateTimerQuery()
|
||||
{
|
||||
return New<GPUTimerQueryDX11>(this);
|
||||
}
|
||||
|
||||
GPUBuffer* GPUDeviceDX11::CreateBuffer(const StringView& name)
|
||||
{
|
||||
return New<GPUBufferDX11>(this, name);
|
||||
}
|
||||
|
||||
GPUSwapChain* GPUDeviceDX11::CreateSwapChain(Window* window)
|
||||
{
|
||||
return New<GPUSwapChainDX11>(this, window);
|
||||
}
|
||||
|
||||
#endif
|
||||
152
Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h
Normal file
152
Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/GPUResource.h"
|
||||
#include "../GPUDeviceDX.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
class Engine;
|
||||
class GPUContextDX11;
|
||||
class GPUSwapChainDX11;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of Graphics Device for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUDeviceDX11 : public GPUDeviceDX
|
||||
{
|
||||
friend GPUContextDX11;
|
||||
friend GPUSwapChainDX11;
|
||||
|
||||
private:
|
||||
|
||||
// Private Stuff
|
||||
ID3D11Device* _device;
|
||||
ID3D11DeviceContext* _imContext;
|
||||
IDXGIFactory* _factoryDXGI;
|
||||
|
||||
GPUContextDX11* _mainContext;
|
||||
|
||||
// Static Samplers
|
||||
ID3D11SamplerState* _samplerLinearClamp;
|
||||
ID3D11SamplerState* _samplerPointClamp;
|
||||
ID3D11SamplerState* _samplerLinearWrap;
|
||||
ID3D11SamplerState* _samplerPointWrap;
|
||||
ID3D11SamplerState* _samplerShadow;
|
||||
ID3D11SamplerState* _samplerShadowPCF;
|
||||
|
||||
// Shared data for pipeline states
|
||||
CriticalSection BlendStatesWriteLocker;
|
||||
Dictionary<BlendingMode, ID3D11BlendState*> BlendStates;
|
||||
ID3D11RasterizerState* RasterizerStates[3 * 2 * 2]; // Index = CullMode[0-2] + Wireframe[0?3] + DepthClipEnable[0?6]
|
||||
ID3D11DepthStencilState* DepthStencilStates[9 * 2 * 2]; // Index = ComparisonFunc[0-8] + DepthTestEnable[0?9] + DepthWriteEnable[0?18]
|
||||
|
||||
public:
|
||||
|
||||
// Create new graphics device (returns null if failed)
|
||||
// @returns Created device or null
|
||||
static GPUDevice* Create();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUDeviceDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dxgiFactory">The DXGI factory handle.</param>
|
||||
/// <param name="adapter">The GPU device adapter.</param>
|
||||
GPUDeviceDX11(IDXGIFactory* dxgiFactory, GPUAdapterDX* adapter);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUDeviceDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUDeviceDX11();
|
||||
|
||||
public:
|
||||
|
||||
// Gets DX11 device
|
||||
ID3D11Device* GetDevice() const
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
// Gets DXGI factory
|
||||
IDXGIFactory* GetDXGIFactory() const
|
||||
{
|
||||
return _factoryDXGI;
|
||||
}
|
||||
|
||||
// Gets immediate context
|
||||
ID3D11DeviceContext* GetIM() const
|
||||
{
|
||||
return _imContext;
|
||||
}
|
||||
|
||||
GPUContextDX11* GetMainContextDX11()
|
||||
{
|
||||
return _mainContext;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
ID3D11BlendState* GetBlendState(const BlendingMode& blending);
|
||||
|
||||
public:
|
||||
|
||||
// [GPUDeviceDX]
|
||||
GPUContext* GetMainContext() override
|
||||
{
|
||||
return reinterpret_cast<GPUContext*>(_mainContext);
|
||||
}
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
bool Init() override;
|
||||
void Dispose() override;
|
||||
void WaitForGPU() override;
|
||||
void DrawEnd() override;
|
||||
GPUTexture* CreateTexture(const StringView& name) override;
|
||||
GPUShader* CreateShader(const StringView& name) override;
|
||||
GPUPipelineState* CreatePipelineState() override;
|
||||
GPUTimerQuery* CreateTimerQuery() override;
|
||||
GPUBuffer* CreateBuffer(const StringView& name) override;
|
||||
GPUSwapChain* CreateSwapChain(Window* window) override;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Base interface for GPU resources on DirectX 11
|
||||
/// </summary>
|
||||
class IGPUResourceDX11
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets DirectX 11 resource object handle
|
||||
/// </summary>
|
||||
/// <returns>DirectX 11 resource object handle</returns>
|
||||
virtual ID3D11Resource* GetResource() = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// GPU resource implementation for DirectX 11 backend.
|
||||
/// </summary>
|
||||
template<class BaseType>
|
||||
class GPUResourceDX11 : public GPUResourceBase<GPUDeviceDX11, BaseType>, public IGPUResourceDX11
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUResourceDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="name">The resource name.</param>
|
||||
GPUResourceDX11(GPUDeviceDX11* device, const StringView& name) noexcept
|
||||
: GPUResourceBase(device, name)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
extern GPUDevice* CreateGPUDeviceDX11();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUPipelineStateDX11.h"
|
||||
|
||||
void GPUPipelineStateDX11::OnReleaseGPU()
|
||||
{
|
||||
BlendState = nullptr;
|
||||
VS = nullptr;
|
||||
HS = nullptr;
|
||||
DS = nullptr;
|
||||
GS = nullptr;
|
||||
PS = nullptr;
|
||||
}
|
||||
|
||||
ID3D11Resource* GPUPipelineStateDX11::GetResource()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GPUPipelineStateDX11::IsValid() const
|
||||
{
|
||||
return !!_memoryUsage;
|
||||
}
|
||||
|
||||
bool GPUPipelineStateDX11::Init(const Description& desc)
|
||||
{
|
||||
ASSERT(!IsValid());
|
||||
|
||||
// Cache shaders
|
||||
VS = (GPUShaderProgramVSDX11*)desc.VS;
|
||||
HS = desc.HS ? (GPUShaderProgramHSDX11*)desc.HS : nullptr;
|
||||
DS = desc.DS ? (GPUShaderProgramDSDX11*)desc.DS : nullptr;
|
||||
GS = desc.GS ? (GPUShaderProgramGSDX11*)desc.GS : nullptr;
|
||||
PS = desc.PS ? (GPUShaderProgramPSDX11*)desc.PS : nullptr;
|
||||
|
||||
// Primitive Topology
|
||||
const static D3D11_PRIMITIVE_TOPOLOGY D3D11_primTypes[] =
|
||||
{
|
||||
D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED,
|
||||
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST,
|
||||
D3D11_PRIMITIVE_TOPOLOGY_LINELIST,
|
||||
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
|
||||
};
|
||||
PrimitiveTopology = D3D11_primTypes[static_cast<int32>(desc.PrimitiveTopologyType)];
|
||||
if (HS)
|
||||
PrimitiveTopology = (D3D11_PRIMITIVE_TOPOLOGY)((int32)D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (HS->GetControlPointsCount() - 1));
|
||||
|
||||
// States
|
||||
DepthStencilStateIndex = static_cast<int32>(desc.DepthFunc) + (desc.DepthTestEnable ? 0 : 9) + (desc.DepthWriteEnable ? 0 : 18);
|
||||
RasterizerStateIndex = static_cast<int32>(desc.CullMode) + (desc.Wireframe ? 0 : 3) + (desc.DepthClipEnable ? 0 : 6);
|
||||
BlendState = _device->GetBlendState(desc.BlendMode);
|
||||
|
||||
// Calculate approx. memory usage (just to set sth)
|
||||
_memoryUsage = sizeof(D3D11_DEPTH_STENCIL_DESC) + sizeof(D3D11_RASTERIZER_DESC) + sizeof(D3D11_BLEND_DESC);
|
||||
|
||||
return GPUPipelineState::Init(desc);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/GPUPipelineState.h"
|
||||
#include "GPUShaderProgramDX11.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// Graphics pipeline state object for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUPipelineStateDX11 : public GPUResourceDX11<GPUPipelineState>
|
||||
{
|
||||
public:
|
||||
|
||||
int32 DepthStencilStateIndex;
|
||||
int32 RasterizerStateIndex;
|
||||
ID3D11BlendState* BlendState = nullptr;
|
||||
GPUShaderProgramVSDX11* VS = nullptr;
|
||||
GPUShaderProgramHSDX11* HS = nullptr;
|
||||
GPUShaderProgramDSDX11* DS = nullptr;
|
||||
GPUShaderProgramGSDX11* GS = nullptr;
|
||||
GPUShaderProgramPSDX11* PS = nullptr;
|
||||
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUPipelineStateDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The device.</param>
|
||||
GPUPipelineStateDX11(GPUDeviceDX11* device)
|
||||
: GPUResourceDX11<GPUPipelineState>(device, StringView::Empty)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() final override;
|
||||
|
||||
// [GPUPipelineState]
|
||||
bool IsValid() const override;
|
||||
bool Init(const Description& desc) override;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
void OnReleaseGPU() final override;
|
||||
};
|
||||
|
||||
#endif
|
||||
195
Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp
Normal file
195
Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUShaderDX11.h"
|
||||
#include "GPUShaderProgramDX11.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "../RenderToolsDX.h"
|
||||
|
||||
GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream)
|
||||
{
|
||||
GPUShaderProgram* shader = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||
|
||||
// Temporary variables
|
||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
||||
|
||||
// Load Input Layout (it may be empty)
|
||||
byte inputLayoutSize;
|
||||
stream.ReadByte(&inputLayoutSize);
|
||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||
{
|
||||
// Read description
|
||||
// TODO: maybe use struct and load at once?
|
||||
stream.ReadByte(&Type);
|
||||
stream.ReadByte(&Index);
|
||||
stream.ReadByte(&Format);
|
||||
stream.ReadByte(&InputSlot);
|
||||
stream.ReadUint32(&AlignedByteOffset);
|
||||
stream.ReadByte(&InputSlotClass);
|
||||
stream.ReadUint32(&InstanceDataStepRate);
|
||||
|
||||
// Get semantic name
|
||||
const char* semanticName = nullptr;
|
||||
// TODO: maybe use enum+mapping ?
|
||||
switch (Type)
|
||||
{
|
||||
case 1:
|
||||
semanticName = "POSITION";
|
||||
break;
|
||||
case 2:
|
||||
semanticName = "COLOR";
|
||||
break;
|
||||
case 3:
|
||||
semanticName = "TEXCOORD";
|
||||
break;
|
||||
case 4:
|
||||
semanticName = "NORMAL";
|
||||
break;
|
||||
case 5:
|
||||
semanticName = "TANGENT";
|
||||
break;
|
||||
case 6:
|
||||
semanticName = "BITANGENT";
|
||||
break;
|
||||
case 7:
|
||||
semanticName = "ATTRIBUTE";
|
||||
break;
|
||||
case 8:
|
||||
semanticName = "BLENDINDICES";
|
||||
break;
|
||||
case 9:
|
||||
semanticName = "BLENDWEIGHT";
|
||||
break;
|
||||
default:
|
||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set data
|
||||
inputLayoutDesc[a] =
|
||||
{
|
||||
semanticName,
|
||||
static_cast<UINT>(Index),
|
||||
static_cast<DXGI_FORMAT>(Format),
|
||||
static_cast<UINT>(InputSlot),
|
||||
static_cast<UINT>(AlignedByteOffset),
|
||||
static_cast<D3D11_INPUT_CLASSIFICATION>(InputSlotClass),
|
||||
static_cast<UINT>(InstanceDataStepRate)
|
||||
};
|
||||
}
|
||||
|
||||
ID3D11InputLayout* inputLayout = nullptr;
|
||||
if (inputLayoutSize > 0)
|
||||
{
|
||||
// Create input layout
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateInputLayout(inputLayoutDesc, inputLayoutSize, cacheBytes, cacheSize, &inputLayout));
|
||||
}
|
||||
|
||||
// Create shader
|
||||
ID3D11VertexShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateVertexShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, inputLayout, inputLayoutSize);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Hull:
|
||||
{
|
||||
// Read control points
|
||||
int32 controlPointsCount;
|
||||
stream.ReadInt32(&controlPointsCount);
|
||||
|
||||
// Create shader
|
||||
ID3D11HullShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateHullShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramHSDX11>(initializer, buffer, controlPointsCount);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Domain:
|
||||
{
|
||||
// Create shader
|
||||
ID3D11DomainShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramDSDX11>(initializer, buffer);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
// Create shader
|
||||
ID3D11GeometryShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateGeometryShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramGSDX11>(initializer, buffer);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
// Create shader
|
||||
ID3D11PixelShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreatePixelShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramPSDX11>(initializer, buffer);
|
||||
break;
|
||||
}
|
||||
case ShaderStage::Compute:
|
||||
{
|
||||
// Create shader
|
||||
ID3D11ComputeShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateComputeShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramCSDX11>(initializer, buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
GPUConstantBuffer* GPUShaderDX11::CreateCB(const String& name, uint32 size, MemoryReadStream& stream)
|
||||
{
|
||||
ID3D11Buffer* buffer = nullptr;
|
||||
uint32 memorySize = 0;
|
||||
if (size)
|
||||
{
|
||||
// Create buffer
|
||||
D3D11_BUFFER_DESC cbDesc;
|
||||
cbDesc.ByteWidth = Math::AlignUp<uint32>(size, 16);
|
||||
cbDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
cbDesc.CPUAccessFlags = 0;
|
||||
cbDesc.MiscFlags = 0;
|
||||
cbDesc.StructureByteStride = 0;
|
||||
const HRESULT result = _device->GetDevice()->CreateBuffer(&cbDesc, nullptr, &buffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_DIRECTX_RESULT(result);
|
||||
return nullptr;
|
||||
}
|
||||
memorySize = cbDesc.ByteWidth;
|
||||
}
|
||||
|
||||
return new(_cbs) GPUConstantBufferDX11(_device, name, size, memorySize, buffer);
|
||||
}
|
||||
|
||||
void GPUShaderDX11::OnReleaseGPU()
|
||||
{
|
||||
_cbs.Clear();
|
||||
|
||||
GPUShader::OnReleaseGPU();
|
||||
}
|
||||
|
||||
#endif
|
||||
112
Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.h
Normal file
112
Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.h
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/Shaders/GPUConstantBuffer.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
|
||||
/// <summary>
|
||||
/// Constant Buffer for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUConstantBufferDX11 : public GPUResourceDX11<GPUConstantBuffer>
|
||||
{
|
||||
private:
|
||||
|
||||
ID3D11Buffer* _resource;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUConstantBufferDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
/// <param name="name">The resource name.</param>
|
||||
/// <param name="size">The buffer size (in bytes).</param>
|
||||
/// <param name="memorySize">The buffer memory size (in bytes).</param>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
GPUConstantBufferDX11(GPUDeviceDX11* device, const String& name, uint32 size, uint32 memorySize, ID3D11Buffer* buffer) noexcept
|
||||
: GPUResourceDX11(device, name)
|
||||
, _resource(buffer)
|
||||
{
|
||||
_size = size;
|
||||
_memoryUsage = memorySize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUConstantBufferDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUConstantBufferDX11()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_resource, 0);
|
||||
_memoryUsage = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the constant buffer object.
|
||||
/// </summary>
|
||||
/// <returns>The DirectX buffer object.</returns>
|
||||
FORCE_INLINE ID3D11Buffer* GetBuffer() const
|
||||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() override
|
||||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
void OnReleaseGPU() final override
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_resource, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderDX11 : public GPUResourceDX11<GPUShader>
|
||||
{
|
||||
private:
|
||||
|
||||
Array<GPUConstantBufferDX11, FixedAllocation<MAX_CONSTANT_BUFFER_SLOTS>> _cbs;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The device.</param>
|
||||
/// <param name="name">The resource name.</param>
|
||||
GPUShaderDX11(GPUDeviceDX11* device, const StringView& name)
|
||||
: GPUResourceDX11(device, name)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUShader]
|
||||
GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override;
|
||||
GPUConstantBuffer* CreateCB(const String& name, uint32 size, MemoryReadStream& stream) override;
|
||||
void OnReleaseGPU() override;
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() final override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
217
Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderProgramDX11.h
Normal file
217
Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderProgramDX11.h
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// Shaders base class for DirectX 11 backend.
|
||||
/// </summary>
|
||||
template<typename BaseType, typename BufferType>
|
||||
class GPUShaderProgramDX11 : public BaseType
|
||||
{
|
||||
protected:
|
||||
|
||||
BufferType* _buffer;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramDX11(const GPUShaderProgramInitializer& initializer, BufferType* buffer)
|
||||
: _buffer(buffer)
|
||||
{
|
||||
BaseType::Init(initializer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramDX11()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_buffer, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets DirectX 11 buffer handle.
|
||||
/// </summary>
|
||||
/// <returns>The DirectX 11 buffer.</returns>
|
||||
FORCE_INLINE BufferType* GetBufferHandleDX11() const
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [BaseType]
|
||||
uint32 GetBufferSize() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* GetBufferHandle() const override
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Vertex Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderProgramVSDX11 : public GPUShaderProgramDX11<GPUShaderProgramVS, ID3D11VertexShader>
|
||||
{
|
||||
private:
|
||||
|
||||
byte _inputLayoutSize;
|
||||
ID3D11InputLayout* _inputLayout;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramVSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
/// <param name="inputLayout">The input layout.</param>
|
||||
/// <param name="inputLayoutSize">Size of the input layout.</param>
|
||||
GPUShaderProgramVSDX11(const GPUShaderProgramInitializer& initializer, ID3D11VertexShader* buffer, ID3D11InputLayout* inputLayout, byte inputLayoutSize)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
, _inputLayoutSize(inputLayoutSize)
|
||||
, _inputLayout(inputLayout)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUShaderProgramVSDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUShaderProgramVSDX11()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_inputLayout, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DirectX 11 input layout handle
|
||||
/// </summary>
|
||||
/// <returns>DirectX 11 input layout</returns>
|
||||
FORCE_INLINE ID3D11InputLayout* GetInputLayoutDX11() const
|
||||
{
|
||||
return _inputLayout;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUShaderProgramDX11]
|
||||
void* GetInputLayout() const override
|
||||
{
|
||||
return (void*)_inputLayout;
|
||||
}
|
||||
|
||||
byte GetInputLayoutSize() const override
|
||||
{
|
||||
return _inputLayoutSize;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Hull Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderProgramHSDX11 : public GPUShaderProgramDX11<GPUShaderProgramHS, ID3D11HullShader>
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramHSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
/// <param name="controlPointsCount">The control points used by the hull shader for processing.</param>
|
||||
GPUShaderProgramHSDX11(const GPUShaderProgramInitializer& initializer, ID3D11HullShader* buffer, int32 controlPointsCount)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
_controlPointsCount = controlPointsCount;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Domain Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderProgramDSDX11 : public GPUShaderProgramDX11<GPUShaderProgramDS, ID3D11DomainShader>
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramDSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramDSDX11(const GPUShaderProgramInitializer& initializer, ID3D11DomainShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Geometry Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderProgramGSDX11 : public GPUShaderProgramDX11<GPUShaderProgramGS, ID3D11GeometryShader>
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramGSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramGSDX11(const GPUShaderProgramInitializer& initializer, ID3D11GeometryShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Pixel Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderProgramPSDX11 : public GPUShaderProgramDX11<GPUShaderProgramPS, ID3D11PixelShader>
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramPSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramPSDX11(const GPUShaderProgramInitializer& initializer, ID3D11PixelShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Compute Shader for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUShaderProgramCSDX11 : public GPUShaderProgramDX11<GPUShaderProgramCS, ID3D11ComputeShader>
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUShaderProgramCSDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="initializer">The program initialization data.</param>
|
||||
/// <param name="buffer">The shader buffer object.</param>
|
||||
GPUShaderProgramCSDX11(const GPUShaderProgramInitializer& initializer, ID3D11ComputeShader* buffer)
|
||||
: GPUShaderProgramDX11(initializer, buffer)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
256
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp
Normal file
256
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUSwapChainDX11.h"
|
||||
#include "Engine/Platform/Window.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
#include "GPUContextDX11.h"
|
||||
|
||||
GPUSwapChainDX11::GPUSwapChainDX11(GPUDeviceDX11* device, Window* window)
|
||||
: GPUResourceDX11(device, StringView::Empty)
|
||||
#if PLATFORM_WINDOWS
|
||||
, _windowHandle(static_cast<HWND>(window->GetNativePtr()))
|
||||
#else
|
||||
, _windowHandle(static_cast<IUnknown*>(window->GetNativePtr()))
|
||||
#endif
|
||||
, _swapChain(nullptr)
|
||||
, _backBuffer(nullptr)
|
||||
{
|
||||
ASSERT(_windowHandle);
|
||||
_window = window;
|
||||
}
|
||||
|
||||
void GPUSwapChainDX11::getBackBuffer()
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->GetBuffer(0, __uuidof(_backBuffer), reinterpret_cast<void**>(&_backBuffer)));
|
||||
|
||||
ID3D11RenderTargetView* rtv;
|
||||
ID3D11ShaderResourceView* srv;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateRenderTargetView(_backBuffer, nullptr, &rtv));
|
||||
#if GPU_USE_WINDOW_SRV
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_backBuffer, nullptr, &srv));
|
||||
#else
|
||||
srv = nullptr;
|
||||
#endif
|
||||
|
||||
_backBufferHandle.Init(this, rtv, srv, nullptr, nullptr, _format, MSAALevel::None);
|
||||
}
|
||||
|
||||
void GPUSwapChainDX11::releaseBackBuffer()
|
||||
{
|
||||
// Release data
|
||||
_backBufferHandle.Release();
|
||||
DX_SAFE_RELEASE_CHECK(_backBuffer, 0);
|
||||
}
|
||||
|
||||
void GPUSwapChainDX11::OnReleaseGPU()
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
// Disable fullscreen mode
|
||||
if (_swapChain)
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->SetFullscreenState(false, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Release data
|
||||
releaseBackBuffer();
|
||||
DX_SAFE_RELEASE_CHECK(_swapChain, 0);
|
||||
_width = _height = 0;
|
||||
}
|
||||
|
||||
ID3D11Resource* GPUSwapChainDX11::GetResource()
|
||||
{
|
||||
return _backBuffer;
|
||||
}
|
||||
|
||||
bool GPUSwapChainDX11::IsFullscreen()
|
||||
{
|
||||
// Check if has swap chain created
|
||||
if (_swapChain == nullptr)
|
||||
return false;
|
||||
|
||||
// Get state
|
||||
BOOL state;
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->GetFullscreenState(&state, nullptr));
|
||||
return state == TRUE;
|
||||
}
|
||||
|
||||
void GPUSwapChainDX11::SetFullscreen(bool isFullscreen)
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
if (_swapChain && isFullscreen != IsFullscreen())
|
||||
{
|
||||
_device->WaitForGPU();
|
||||
GPUDeviceLock lock(_device);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
_swapChain->GetDesc(&swapChainDesc);
|
||||
|
||||
// Setup target for fullscreen mode
|
||||
IDXGIOutput* output = nullptr;
|
||||
if (isFullscreen && _device->Outputs.HasItems())
|
||||
{
|
||||
const uint32 outputIdx = 0;
|
||||
auto& outputDX = _device->Outputs[outputIdx];
|
||||
output = outputDX.Output.Get();
|
||||
swapChainDesc.BufferDesc = outputDX.DesktopViewMode;
|
||||
}
|
||||
|
||||
releaseBackBuffer();
|
||||
|
||||
if (FAILED(_swapChain->ResizeTarget(&swapChainDesc.BufferDesc)))
|
||||
{
|
||||
LOG(Warning, "Swapchain resize failed.");
|
||||
}
|
||||
|
||||
if (FAILED(_swapChain->SetFullscreenState(isFullscreen, output)))
|
||||
{
|
||||
LOG(Warning, "Cannot change fullscreen mode for '{0}' to {1}.", ToString(), isFullscreen);
|
||||
}
|
||||
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, _width, _height, swapChainDesc.BufferDesc.Format, swapChainDesc.Flags));
|
||||
|
||||
getBackBuffer();
|
||||
}
|
||||
#else
|
||||
LOG(Info, "Cannot change fullscreen mode on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
GPUTextureView* GPUSwapChainDX11::GetBackBufferView()
|
||||
{
|
||||
return &_backBufferHandle;
|
||||
}
|
||||
|
||||
void GPUSwapChainDX11::Present(bool vsync)
|
||||
{
|
||||
// Present frame
|
||||
ASSERT(_swapChain);
|
||||
const HRESULT result = _swapChain->Present(vsync ? 1 : 0, 0);
|
||||
LOG_DIRECTX_RESULT(result);
|
||||
|
||||
// Base
|
||||
GPUSwapChain::Present(vsync);
|
||||
}
|
||||
|
||||
bool GPUSwapChainDX11::Resize(int32 width, int32 height)
|
||||
{
|
||||
// Check if size won't change
|
||||
if (width == _width && height == _height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_device->WaitForGPU();
|
||||
GPUDeviceLock lock(_device);
|
||||
_format = GPU_BACK_BUFFER_PIXEL_FORMAT;
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
#else
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
|
||||
#endif
|
||||
if (_swapChain == nullptr)
|
||||
{
|
||||
ReleaseGPU();
|
||||
|
||||
// Create swap chain description
|
||||
#if PLATFORM_WINDOWS
|
||||
if (_device->Outputs.HasItems())
|
||||
{
|
||||
const uint32 outputIdx = 0;
|
||||
auto& output = _device->Outputs[outputIdx];
|
||||
swapChainDesc.BufferDesc = output.DesktopViewMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
|
||||
swapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
|
||||
swapChainDesc.BufferDesc.Format = RenderToolsDX::ToDxgiFormat(_format);
|
||||
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
}
|
||||
swapChainDesc.BufferDesc.Width = width;
|
||||
swapChainDesc.BufferDesc.Height = height;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 2;
|
||||
swapChainDesc.OutputWindow = _windowHandle;
|
||||
swapChainDesc.Windowed = TRUE;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
#else
|
||||
swapChainDesc.Width = width;
|
||||
swapChainDesc.Height = height;
|
||||
swapChainDesc.Format = RenderToolsDX::ToDxgiFormat(_format);
|
||||
swapChainDesc.Stereo = false;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 2;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
swapChainDesc.Scaling = DXGI_SCALING_NONE;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
#endif
|
||||
#if GPU_USE_WINDOW_SRV
|
||||
swapChainDesc.BufferUsage |= DXGI_USAGE_SHADER_INPUT;
|
||||
#endif
|
||||
|
||||
// Create swap chain
|
||||
#if PLATFORM_WINDOWS
|
||||
auto dxgi = _device->GetDXGIFactory();
|
||||
VALIDATE_DIRECTX_RESULT(dxgi->CreateSwapChain(_device->GetDevice(), &swapChainDesc, &_swapChain));
|
||||
ASSERT(_swapChain);
|
||||
|
||||
// Disable DXGI changes to the window
|
||||
VALIDATE_DIRECTX_RESULT(dxgi->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER));
|
||||
#else
|
||||
auto dxgiFactory = (IDXGIFactory2*)_device->GetDXGIFactory();
|
||||
VALIDATE_DIRECTX_RESULT(dxgiFactory->CreateSwapChainForCoreWindow(_device->GetDevice(), static_cast<IUnknown*>(_windowHandle), &swapChainDesc, nullptr, &_swapChain));
|
||||
ASSERT(_swapChain);
|
||||
|
||||
// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
|
||||
// ensures that the application will only render after each VSync, minimizing power consumption.
|
||||
ComPtr<IDXGIDevice2> dxgiDevice;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->QueryInterface(IID_PPV_ARGS(&dxgiDevice)));
|
||||
VALIDATE_DIRECTX_RESULT(dxgiDevice->SetMaximumFrameLatency(1));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseBackBuffer();
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
_swapChain->GetDesc(&swapChainDesc);
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.BufferDesc.Format, swapChainDesc.Flags));
|
||||
#else
|
||||
_swapChain->GetDesc1(&swapChainDesc);
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.Format, swapChainDesc.Flags));
|
||||
#endif
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
#if PLATFORM_WINDOWS
|
||||
_memoryUsage = CalculateTextureMemoryUsage(RenderToolsDX::ToPixelFormat(swapChainDesc.BufferDesc.Format), _width, _height, 1) * swapChainDesc.BufferCount;
|
||||
#else
|
||||
_memoryUsage = CalculateTextureMemoryUsage(RenderToolsDX::ToPixelFormat(swapChainDesc.Format), _width, _height, 1) * swapChainDesc.BufferCount;
|
||||
#endif
|
||||
|
||||
getBackBuffer();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUSwapChainDX11::CopyBackbuffer(GPUContext* context, GPUTexture* dst)
|
||||
{
|
||||
const auto contextDX11 = (GPUContextDX11*)context;
|
||||
contextDX11->GetContext()->CopyResource((ID3D11Resource*)dst->GetNativePtr(), _backBuffer);
|
||||
}
|
||||
|
||||
#endif
|
||||
61
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h
Normal file
61
Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GPUDeviceDX11.h"
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "Engine/Graphics/GPUSwapChain.h"
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// Graphics Device rendering output for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUSwapChainDX11 : public GPUResourceDX11<GPUSwapChain>
|
||||
{
|
||||
friend class WindowsWindow;
|
||||
friend class GPUContextDX11;
|
||||
friend GPUDeviceDX11;
|
||||
|
||||
private:
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
HWND _windowHandle;
|
||||
IDXGISwapChain* _swapChain;
|
||||
#else
|
||||
IUnknown* _windowHandle;
|
||||
IDXGISwapChain1* _swapChain;
|
||||
#endif
|
||||
ID3D11Texture2D* _backBuffer;
|
||||
GPUTextureViewDX11 _backBufferHandle;
|
||||
|
||||
public:
|
||||
|
||||
GPUSwapChainDX11(GPUDeviceDX11* device, Window* window);
|
||||
|
||||
private:
|
||||
|
||||
void getBackBuffer();
|
||||
void releaseBackBuffer();
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() override;
|
||||
|
||||
// [GPUSwapChain]
|
||||
bool IsFullscreen() override;
|
||||
void SetFullscreen(bool isFullscreen) override;
|
||||
GPUTextureView* GetBackBufferView() override;
|
||||
void Present(bool vsync) override;
|
||||
bool Resize(int32 width, int32 height) override;
|
||||
void CopyBackbuffer(GPUContext* context, GPUTexture* dst) override;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
void OnReleaseGPU() final override;
|
||||
};
|
||||
|
||||
#endif
|
||||
604
Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
Normal file
604
Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
Normal file
@@ -0,0 +1,604 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUTextureDX11.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Graphics/Textures/TextureData.h"
|
||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||
|
||||
bool GPUTextureDX11::OnInit()
|
||||
{
|
||||
// Cache formats
|
||||
const PixelFormat format = Format();
|
||||
const PixelFormat typelessFormat = PixelFormatExtensions::MakeTypeless(format);
|
||||
const DXGI_FORMAT dxgiFormat = RenderToolsDX::ToDxgiFormat(typelessFormat);
|
||||
_dxgiFormatDSV = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindDepthStencilFormat(format));
|
||||
_dxgiFormatSRV = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindShaderResourceFormat(format, _sRGB));
|
||||
_dxgiFormatRTV = _dxgiFormatSRV;
|
||||
_dxgiFormatUAV = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(format));
|
||||
|
||||
// Cache properties
|
||||
auto device = _device->GetDevice();
|
||||
bool useSRV = IsShaderResource();
|
||||
bool useDSV = IsDepthStencil();
|
||||
bool useRTV = IsRenderTarget();
|
||||
bool useUAV = IsUnorderedAccess();
|
||||
|
||||
// Create resource
|
||||
HRESULT result;
|
||||
if (IsVolume())
|
||||
{
|
||||
// Create texture description
|
||||
D3D11_TEXTURE3D_DESC textureDesc;
|
||||
textureDesc.MipLevels = MipLevels();
|
||||
textureDesc.Format = dxgiFormat;
|
||||
textureDesc.Width = Width();
|
||||
textureDesc.Height = Height();
|
||||
textureDesc.Depth = Depth();
|
||||
textureDesc.BindFlags = 0;
|
||||
textureDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage);
|
||||
textureDesc.MiscFlags = 0;
|
||||
textureDesc.Usage = RenderToolsDX::ToD3D11Usage(_desc.Usage);
|
||||
if (useSRV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
||||
if (useRTV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
||||
if (useDSV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
|
||||
if (useUAV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
|
||||
|
||||
// Create texture
|
||||
ID3D11Texture3D* texture;
|
||||
result = device->CreateTexture3D(&textureDesc, nullptr, &texture);
|
||||
_resource = texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create texture description
|
||||
D3D11_TEXTURE2D_DESC textureDesc;
|
||||
textureDesc.MipLevels = MipLevels();
|
||||
textureDesc.Format = dxgiFormat;
|
||||
textureDesc.Width = Width();
|
||||
textureDesc.Height = Height();
|
||||
textureDesc.Usage = RenderToolsDX::ToD3D11Usage(_desc.Usage);
|
||||
textureDesc.BindFlags = 0;
|
||||
textureDesc.CPUAccessFlags = RenderToolsDX::GetDX11CpuAccessFlagsFromUsage(_desc.Usage);
|
||||
textureDesc.ArraySize = ArraySize();
|
||||
textureDesc.SampleDesc.Count = static_cast<UINT>(_desc.MultiSampleLevel);
|
||||
textureDesc.SampleDesc.Quality = 0;
|
||||
textureDesc.MiscFlags = 0;
|
||||
if (useSRV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
|
||||
if (useRTV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_RENDER_TARGET;
|
||||
if (useDSV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
|
||||
if (useUAV)
|
||||
textureDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
|
||||
if (_device->GetFeatureLevel() >= FeatureLevel::SM5 && IsMultiSample())
|
||||
textureDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
if (IsCubeMap())
|
||||
textureDesc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
|
||||
// Create texture
|
||||
ID3D11Texture2D* texture;
|
||||
result = device->CreateTexture2D(&textureDesc, nullptr, &texture);
|
||||
_resource = texture;
|
||||
}
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
ASSERT(_resource != nullptr);
|
||||
DX_SET_DEBUG_NAME(_resource, GetName());
|
||||
|
||||
// Update memory usage
|
||||
_memoryUsage = calculateMemoryUsage();
|
||||
|
||||
// Initialize handles to the resource
|
||||
if (IsRegularTexture())
|
||||
{
|
||||
// 'Regular' texture is using only one handle (texture/cubemap)
|
||||
_handlesPerSlice.Resize(1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create all handles
|
||||
initHandles();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUTextureDX11::onResidentMipsChanged()
|
||||
{
|
||||
// We support changing resident mip maps only for regular textures (render targets and depth buffers don't use that feature at all)
|
||||
ASSERT(IsRegularTexture() && _handlesPerSlice.Count() == 1);
|
||||
ASSERT(!IsVolume());
|
||||
|
||||
// Fill description
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
|
||||
srDesc.Format = _dxgiFormatSRV;
|
||||
if (IsCubeMap())
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srDesc.TextureCube.MostDetailedMip = MipLevels() - ResidentMipLevels();
|
||||
srDesc.TextureCube.MipLevels = ResidentMipLevels();
|
||||
}
|
||||
else
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srDesc.Texture2D.MostDetailedMip = MipLevels() - ResidentMipLevels();
|
||||
srDesc.Texture2D.MipLevels = ResidentMipLevels();
|
||||
}
|
||||
|
||||
// Create new view
|
||||
ID3D11ShaderResourceView* srView;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
|
||||
// Change view
|
||||
if (_handlesPerSlice[0].GetParent() == nullptr)
|
||||
_handlesPerSlice[0].Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
|
||||
else
|
||||
_handlesPerSlice[0].SetSRV(srView);
|
||||
}
|
||||
|
||||
void GPUTextureDX11::OnReleaseGPU()
|
||||
{
|
||||
_handlesPerMip.Resize(0, false);
|
||||
_handlesPerSlice.Resize(0, false);
|
||||
_handleArray.Release();
|
||||
_handleVolume.Release();
|
||||
_handleReadOnlyDepth.Release();
|
||||
DX_SAFE_RELEASE_CHECK(_resource, 0);
|
||||
|
||||
// Base
|
||||
GPUTexture::OnReleaseGPU();
|
||||
}
|
||||
|
||||
#define CLEAR_VIEWS() rtView = nullptr; srView = nullptr; dsView = nullptr; uaView = nullptr
|
||||
|
||||
void GPUTextureDX11::initHandles()
|
||||
{
|
||||
ID3D11RenderTargetView* rtView;
|
||||
ID3D11ShaderResourceView* srView;
|
||||
ID3D11DepthStencilView* dsView;
|
||||
ID3D11UnorderedAccessView* uaView;
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtDesc;
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC dsDesc;
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC uaDesc;
|
||||
|
||||
CLEAR_VIEWS();
|
||||
|
||||
rtDesc.Format = _dxgiFormatRTV;
|
||||
srDesc.Format = _dxgiFormatSRV;
|
||||
dsDesc.Format = _dxgiFormatDSV;
|
||||
dsDesc.Flags = 0;
|
||||
uaDesc.Format = _dxgiFormatUAV;
|
||||
|
||||
// Cache properties
|
||||
auto device = _device->GetDevice();
|
||||
bool useSRV = IsShaderResource();
|
||||
bool useDSV = IsDepthStencil();
|
||||
bool useRTV = IsRenderTarget();
|
||||
bool useUAV = IsUnorderedAccess();
|
||||
int32 arraySize = ArraySize();
|
||||
int32 mipLevels = MipLevels();
|
||||
bool isArray = arraySize > 1;
|
||||
bool isCubeMap = IsCubeMap();
|
||||
bool isMsaa = IsMultiSample();
|
||||
bool isVolume = IsVolume();
|
||||
auto format = Format();
|
||||
auto msaa = MultiSampleLevel();
|
||||
|
||||
// Create resource views
|
||||
if (isVolume)
|
||||
{
|
||||
// Create handle for whole 3d texture
|
||||
if (useSRV)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
||||
srDesc.Texture3D.MostDetailedMip = 0;
|
||||
srDesc.Texture3D.MipLevels = mipLevels;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
|
||||
rtDesc.Texture3D.MipSlice = 0;
|
||||
rtDesc.Texture3D.FirstWSlice = 0;
|
||||
rtDesc.Texture3D.WSize = Depth();
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
|
||||
uaDesc.Texture3D.MipSlice = 0;
|
||||
uaDesc.Texture3D.WSize = Depth();
|
||||
uaDesc.Texture3D.FirstWSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
}
|
||||
_handleVolume.Init(this, rtView, srView, nullptr, uaView, format, msaa);
|
||||
|
||||
// Init per slice views
|
||||
_handlesPerSlice.Resize(Depth(), false);
|
||||
if (_desc.HasPerSliceViews() && useRTV)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
|
||||
rtDesc.Texture3D.MipSlice = 0;
|
||||
rtDesc.Texture3D.WSize = 1;
|
||||
|
||||
for (int32 sliceIndex = 0; sliceIndex < Depth(); sliceIndex++)
|
||||
{
|
||||
rtDesc.Texture3D.FirstWSlice = sliceIndex;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
_handlesPerSlice[sliceIndex].Init(this, rtView, nullptr, nullptr, nullptr, format, msaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isArray)
|
||||
{
|
||||
// Resize handles
|
||||
_handlesPerSlice.Resize(ArraySize(), false);
|
||||
|
||||
// Create per array slice handles
|
||||
for (int32 arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
|
||||
{
|
||||
CLEAR_VIEWS();
|
||||
|
||||
if (useDSV)
|
||||
{
|
||||
/*if (isCubeMap)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsDesc.Texture2DArray.ArraySize = 6;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex * 6;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsDesc.Texture2DArray.ArraySize = 1;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
/*if (isCubeMap)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtDesc.Texture2DArray.ArraySize = 6;
|
||||
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex * 6;
|
||||
rtDesc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtDesc.Texture2DArray.ArraySize = 1;
|
||||
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
rtDesc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useSRV)
|
||||
{
|
||||
// When GetFeatureLevel returns D3D_FEATURE_LEVEL_10_0 or less, Resources created with D3D11_RESOURCE_MISC_TEXTURECUBE may only be treated as cubemap ShaderResourceViews.
|
||||
// (ViewDimension must be D3D11_SRV_DIMENSION_TEXTURECUBE) [ STATE_CREATION ERROR #126: CREATESHADERRESOURCEVIEW_INVALIDDESC]
|
||||
if (isCubeMap && _device->GetRendererType() != RendererType::DirectX10)
|
||||
{
|
||||
RendererType aa = _device->GetRendererType();
|
||||
/*if (isCubeMap)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
|
||||
srDesc.TextureCubeArray.First2DArrayFace = arrayIndex * 6;
|
||||
srDesc.TextureCubeArray.NumCubes = 1;
|
||||
srDesc.TextureCubeArray.MipLevels = mipLevels;
|
||||
srDesc.TextureCubeArray.MostDetailedMip = 0;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srDesc.Texture2DArray.ArraySize = 1;
|
||||
srDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
srDesc.Texture2DArray.MipLevels = mipLevels;
|
||||
srDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
}
|
||||
|
||||
_handlesPerSlice[arrayIndex].Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
||||
}
|
||||
|
||||
// Create whole array handle
|
||||
{
|
||||
CLEAR_VIEWS();
|
||||
|
||||
if (useDSV)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsDesc.Texture2DArray.ArraySize = arraySize;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtDesc.Texture2DArray.ArraySize = arraySize;
|
||||
rtDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
rtDesc.Texture2DArray.MipSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useSRV)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srDesc.TextureCube.MostDetailedMip = 0;
|
||||
srDesc.TextureCube.MipLevels = mipLevels;
|
||||
}
|
||||
else
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srDesc.Texture2DArray.ArraySize = arraySize;
|
||||
srDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
srDesc.Texture2DArray.MipLevels = mipLevels;
|
||||
srDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
|
||||
uaDesc.Texture2DArray.MipSlice = 0;
|
||||
uaDesc.Texture2DArray.ArraySize = arraySize;
|
||||
uaDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
}
|
||||
_handleArray.Init(this, rtView, srView, dsView, uaView, format, msaa);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resize handles
|
||||
_handlesPerSlice.Resize(1, false);
|
||||
CLEAR_VIEWS();
|
||||
|
||||
// Create single handle for the whole texture
|
||||
if (useDSV)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
dsDesc.Texture2DArray.ArraySize = arraySize * 6;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
dsDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtDesc.Texture2DArray.MipSlice = 0;
|
||||
rtDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
rtDesc.Texture2DArray.ArraySize = arraySize * 6;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
rtDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useSRV)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srDesc.TextureCube.MostDetailedMip = 0;
|
||||
srDesc.TextureCube.MipLevels = mipLevels;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srDesc.Texture2D.MostDetailedMip = 0;
|
||||
srDesc.Texture2D.MipLevels = mipLevels;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
||||
uaDesc.Texture2D.MipSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
}
|
||||
_handlesPerSlice[0].Init(this, rtView, srView, dsView, uaView, format, msaa);
|
||||
}
|
||||
|
||||
// Init per mip map handles
|
||||
if (HasPerMipViews())
|
||||
{
|
||||
// Init handles
|
||||
_handlesPerMip.Resize(arraySize, false);
|
||||
for (int32 arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
|
||||
{
|
||||
auto& slice = _handlesPerMip[arrayIndex];
|
||||
slice.Resize(mipLevels, false);
|
||||
|
||||
for (int32 mipIndex = 0; mipIndex < mipLevels; mipIndex++)
|
||||
{
|
||||
dsView = nullptr;
|
||||
rtView = nullptr;
|
||||
srView = nullptr;
|
||||
|
||||
// DSV
|
||||
if (useDSV)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsDesc.Texture2DArray.ArraySize = 1;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
dsDesc.Texture2DArray.MipSlice = mipIndex;
|
||||
_device->GetDevice()->CreateDepthStencilView(_resource, &dsDesc, &dsView);
|
||||
}
|
||||
|
||||
// RTV
|
||||
if (useRTV)
|
||||
{
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtDesc.Texture2DArray.ArraySize = 1;
|
||||
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
rtDesc.Texture2DArray.MipSlice = mipIndex;
|
||||
_device->GetDevice()->CreateRenderTargetView(_resource, &rtDesc, &rtView);
|
||||
}
|
||||
|
||||
// SRV
|
||||
if (useSRV)
|
||||
{
|
||||
// When GetFeatureLevel returns D3D_FEATURE_LEVEL_10_0 or less, Resources created with D3D11_RESOURCE_MISC_TEXTURECUBE may only be treated as cubemap ShaderResourceViews.
|
||||
// (ViewDimension must be D3D11_SRV_DIMENSION_TEXTURECUBE) [ STATE_CREATION ERROR #126: CREATESHADERRESOURCEVIEW_INVALIDDESC]
|
||||
if ((isCubeMap && _device->GetRendererType() == RendererType::DirectX10) == false)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srDesc.Texture2DArray.ArraySize = 1;
|
||||
srDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
srDesc.Texture2DArray.MipLevels = 1;
|
||||
srDesc.Texture2DArray.MostDetailedMip = mipIndex;
|
||||
_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView);
|
||||
}
|
||||
}
|
||||
|
||||
slice[mipIndex].Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read-only depth-stencil
|
||||
if (_desc.Flags & GPUTextureFlags::ReadOnlyDepthView)
|
||||
{
|
||||
CLEAR_VIEWS();
|
||||
|
||||
// Create single handle for the whole texture
|
||||
if (useDSV)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
dsDesc.Texture2DArray.ArraySize = arraySize * 6;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
dsDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
dsDesc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
|
||||
if (PixelFormatExtensions::HasStencil(format))
|
||||
dsDesc.Flags |= D3D11_DSV_READ_ONLY_STENCIL;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
ASSERT(!useRTV);
|
||||
rtView = nullptr;
|
||||
if (useSRV)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srDesc.TextureCube.MostDetailedMip = 0;
|
||||
srDesc.TextureCube.MipLevels = mipLevels;
|
||||
}
|
||||
else if (isMsaa)
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srDesc.Texture2D.MostDetailedMip = 0;
|
||||
srDesc.Texture2D.MipLevels = mipLevels;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
_handleReadOnlyDepth.Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPUTextureDX11::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
|
||||
{
|
||||
if (!IsStaging())
|
||||
{
|
||||
LOG(Warning, "Texture::GetData is valid only for staging resources.");
|
||||
return true;
|
||||
}
|
||||
|
||||
GPUDeviceLock lock(_device);
|
||||
|
||||
// Map the staging resource mip map for reading
|
||||
const uint32 subresource = RenderToolsDX::CalcSubresourceIndex(mipMapIndex, arrayOrDepthSliceIndex, MipLevels());
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
const HRESULT mapResult = _device->GetIM()->Map(_resource, subresource, D3D11_MAP_READ, 0, &mapped);
|
||||
if (FAILED(mapResult))
|
||||
{
|
||||
LOG_DIRECTX_RESULT(mapResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if target row pitch is the same
|
||||
if (mipRowPitch == mapped.RowPitch || mipRowPitch == 0)
|
||||
{
|
||||
// Init mip info
|
||||
data.Lines = mapped.DepthPitch / mapped.RowPitch;
|
||||
data.DepthPitch = mapped.DepthPitch;
|
||||
data.RowPitch = mapped.RowPitch;
|
||||
|
||||
// Copy data
|
||||
data.Data.Copy((byte*)mapped.pData, mapped.DepthPitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Init mip info
|
||||
data.Lines = mapped.DepthPitch / mapped.RowPitch;
|
||||
data.DepthPitch = mipRowPitch * data.Lines;
|
||||
data.RowPitch = mipRowPitch;
|
||||
|
||||
// Copy data
|
||||
data.Data.Allocate(data.DepthPitch);
|
||||
for (uint32 i = 0; i < data.Lines; i++)
|
||||
{
|
||||
Platform::MemoryCopy(data.Data.Get() + data.RowPitch * i, ((byte*)mapped.pData) + mapped.RowPitch * i, data.RowPitch);
|
||||
}
|
||||
}
|
||||
|
||||
// Unmap texture
|
||||
_device->GetIM()->Unmap(_resource, subresource);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
284
Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h
Normal file
284
Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h
Normal file
@@ -0,0 +1,284 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Graphics/Textures/GPUTexture.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
#include "IShaderResourceDX11.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// The texture view for DirectX 11 backend.
|
||||
/// </summary>
|
||||
/// <seealso cref="GPUTextureView" />
|
||||
/// <seealso cref="IShaderResourceDX11" />
|
||||
class GPUTextureViewDX11 : public GPUTextureView, public IShaderResourceDX11
|
||||
{
|
||||
private:
|
||||
|
||||
ID3D11RenderTargetView* _rtv = nullptr;
|
||||
ID3D11ShaderResourceView* _srv = nullptr;
|
||||
ID3D11DepthStencilView* _dsv = nullptr;
|
||||
ID3D11UnorderedAccessView* _uav = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUTextureViewDX11"/> class.
|
||||
/// </summary>
|
||||
GPUTextureViewDX11()
|
||||
{
|
||||
}
|
||||
|
||||
GPUTextureViewDX11(const GPUTextureViewDX11& other)
|
||||
: GPUTextureViewDX11()
|
||||
{
|
||||
#if !BUILD_RELEASE
|
||||
CRASH; // Not used
|
||||
#endif
|
||||
}
|
||||
|
||||
GPUTextureViewDX11& operator=(const GPUTextureViewDX11& other)
|
||||
{
|
||||
#if !BUILD_RELEASE
|
||||
CRASH; // Not used
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUTextureViewDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUTextureViewDX11()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Init
|
||||
/// </summary>
|
||||
/// <param name="parent">Resource that owns that handle</param>
|
||||
/// <param name="rtv">Render Target View</param>
|
||||
/// <param name="srv">Shader Resource view</param>
|
||||
/// <param name="dsv">Depth Stencil View</param>
|
||||
/// <param name="uav">Unordered Access View</param>
|
||||
/// <param name="format">Parent texture format</param>
|
||||
/// <param name="msaa">Parent texture multi-sample level</param>
|
||||
void Init(GPUResource* parent, ID3D11RenderTargetView* rtv, ID3D11ShaderResourceView* srv, ID3D11DepthStencilView* dsv, ID3D11UnorderedAccessView* uav, PixelFormat format, MSAALevel msaa)
|
||||
{
|
||||
GPUTextureView::Init(parent, format, msaa);
|
||||
_rtv = rtv;
|
||||
_srv = srv;
|
||||
_dsv = dsv;
|
||||
_uav = uav;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release the view.
|
||||
/// </summary>
|
||||
void Release()
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_rtv, 0);
|
||||
DX_SAFE_RELEASE_CHECK(_srv, 0);
|
||||
DX_SAFE_RELEASE_CHECK(_dsv, 0);
|
||||
DX_SAFE_RELEASE_CHECK(_uav, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Sets new render target view.
|
||||
/// </summary>
|
||||
/// <param name="rtv">A new render target view.</param>
|
||||
void SetRTV(ID3D11RenderTargetView* rtv)
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_rtv, 0);
|
||||
_rtv = rtv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets new shader resource view.
|
||||
/// </summary>
|
||||
/// <param name="srv">A new shader resource view.</param>
|
||||
void SetSRV(ID3D11ShaderResourceView* srv)
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_srv, 0);
|
||||
_srv = srv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets new depth stencil view.
|
||||
/// </summary>
|
||||
/// <param name="dsv">A new depth stencil view.</param>
|
||||
void SetDSV(ID3D11DepthStencilView* dsv)
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_dsv, 0);
|
||||
_dsv = dsv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets new unordered access view.
|
||||
/// </summary>
|
||||
/// <param name="uav">A new unordered access view.</param>
|
||||
void SetUAV(ID3D11UnorderedAccessView* uav)
|
||||
{
|
||||
DX_SAFE_RELEASE_CHECK(_uav, 0);
|
||||
_uav = uav;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the render target view.
|
||||
/// </summary>
|
||||
/// <returns>The render target view.</returns>
|
||||
ID3D11RenderTargetView* RTV() const
|
||||
{
|
||||
return _rtv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the depth stencil view.
|
||||
/// </summary>
|
||||
/// <returns>The depth stencil view.</returns>
|
||||
ID3D11DepthStencilView* DSV() const
|
||||
{
|
||||
return _dsv;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceView]
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return (void*)(IShaderResourceDX11*)this;
|
||||
}
|
||||
|
||||
// [IShaderResourceDX11]
|
||||
ID3D11ShaderResourceView* SRV() const override
|
||||
{
|
||||
return _srv;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* UAV() const override
|
||||
{
|
||||
return _uav;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Texture object for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUTextureDX11 : public GPUResourceDX11<GPUTexture>
|
||||
{
|
||||
private:
|
||||
|
||||
ID3D11Resource* _resource = nullptr;
|
||||
|
||||
GPUTextureViewDX11 _handleArray;
|
||||
GPUTextureViewDX11 _handleVolume;
|
||||
GPUTextureViewDX11 _handleReadOnlyDepth;
|
||||
Array<GPUTextureViewDX11> _handlesPerSlice; // [slice]
|
||||
Array<Array<GPUTextureViewDX11>> _handlesPerMip; // [slice][mip]
|
||||
|
||||
DXGI_FORMAT _dxgiFormatDSV;
|
||||
DXGI_FORMAT _dxgiFormatSRV;
|
||||
DXGI_FORMAT _dxgiFormatRTV;
|
||||
DXGI_FORMAT _dxgiFormatUAV;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUTextureDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The device.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
GPUTextureDX11(GPUDeviceDX11* device, const StringView& name)
|
||||
: GPUResourceDX11<GPUTexture>(device, name)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets DX11 texture resource.
|
||||
/// </summary>
|
||||
/// <returns>DX11 texture resource.</returns>
|
||||
FORCE_INLINE ID3D11Resource* GetResource() const
|
||||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void initHandles();
|
||||
|
||||
ID3D11Texture2D* GetTexture2D() const
|
||||
{
|
||||
ASSERT(_desc.Dimensions == TextureDimensions::Texture || _desc.Dimensions == TextureDimensions::CubeTexture);
|
||||
return (ID3D11Texture2D*)_resource;
|
||||
}
|
||||
|
||||
ID3D11Texture3D* GetTexture3D() const
|
||||
{
|
||||
ASSERT(_desc.Dimensions == TextureDimensions::VolumeTexture);
|
||||
return (ID3D11Texture3D*)_resource;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [GPUTexture]
|
||||
GPUTextureView* View(int32 arrayOrDepthIndex) const override
|
||||
{
|
||||
return (GPUTextureView*)&_handlesPerSlice[arrayOrDepthIndex];
|
||||
}
|
||||
|
||||
GPUTextureView* View(int32 arrayOrDepthIndex, int32 mipMapIndex) const override
|
||||
{
|
||||
return (GPUTextureView*)&_handlesPerMip[arrayOrDepthIndex][mipMapIndex];
|
||||
}
|
||||
|
||||
GPUTextureView* ViewArray() const override
|
||||
{
|
||||
ASSERT(ArraySize() > 1);
|
||||
return (GPUTextureView*)&_handleArray;
|
||||
}
|
||||
|
||||
GPUTextureView* ViewVolume() const override
|
||||
{
|
||||
ASSERT(IsVolume());
|
||||
return (GPUTextureView*)&_handleVolume;
|
||||
}
|
||||
|
||||
GPUTextureView* ViewReadOnlyDepth() const override
|
||||
{
|
||||
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
|
||||
return (GPUTextureView*)&_handleReadOnlyDepth;
|
||||
}
|
||||
|
||||
void* GetNativePtr() const override
|
||||
{
|
||||
return static_cast<void*>(_resource);
|
||||
}
|
||||
|
||||
bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() override
|
||||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUTexture]
|
||||
bool OnInit() override;
|
||||
void onResidentMipsChanged() override;
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
124
Source/Engine/GraphicsDevice/DirectX/DX11/GPUTimerQueryDX11.cpp
Normal file
124
Source/Engine/GraphicsDevice/DirectX/DX11/GPUTimerQueryDX11.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
#include "GPUTimerQueryDX11.h"
|
||||
|
||||
GPUTimerQueryDX11::GPUTimerQueryDX11(GPUDeviceDX11* device)
|
||||
: GPUResourceDX11<GPUTimerQuery>(device, String::Empty)
|
||||
{
|
||||
D3D11_QUERY_DESC queryDesc;
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||
queryDesc.MiscFlags = 0;
|
||||
|
||||
HRESULT hr = device->GetDevice()->CreateQuery(&queryDesc, &_disjointQuery);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LOG(Fatal, "Failed to create a timer query.");
|
||||
}
|
||||
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
|
||||
hr = device->GetDevice()->CreateQuery(&queryDesc, &_beginQuery);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LOG(Fatal, "Failed to create a timer query.");
|
||||
}
|
||||
|
||||
hr = device->GetDevice()->CreateQuery(&queryDesc, &_endQuery);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LOG(Fatal, "Failed to create a timer query.");
|
||||
}
|
||||
|
||||
// Set non-zero mem usage (fake)
|
||||
_memoryUsage = sizeof(D3D11_QUERY_DESC) * 3;
|
||||
}
|
||||
|
||||
GPUTimerQueryDX11::~GPUTimerQueryDX11()
|
||||
{
|
||||
if (_beginQuery)
|
||||
_beginQuery->Release();
|
||||
if (_endQuery)
|
||||
_endQuery->Release();
|
||||
if (_disjointQuery)
|
||||
_disjointQuery->Release();
|
||||
}
|
||||
|
||||
void GPUTimerQueryDX11::OnReleaseGPU()
|
||||
{
|
||||
SAFE_RELEASE(_beginQuery);
|
||||
SAFE_RELEASE(_endQuery);
|
||||
SAFE_RELEASE(_disjointQuery);
|
||||
}
|
||||
|
||||
ID3D11Resource* GPUTimerQueryDX11::GetResource()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GPUTimerQueryDX11::Begin()
|
||||
{
|
||||
auto context = _device->GetIM();
|
||||
context->Begin(_disjointQuery);
|
||||
context->End(_beginQuery);
|
||||
|
||||
_endCalled = false;
|
||||
}
|
||||
|
||||
void GPUTimerQueryDX11::End()
|
||||
{
|
||||
if (_endCalled)
|
||||
return;
|
||||
|
||||
auto context = _device->GetIM();
|
||||
context->End(_endQuery);
|
||||
context->End(_disjointQuery);
|
||||
|
||||
_endCalled = true;
|
||||
_finalized = false;
|
||||
}
|
||||
|
||||
bool GPUTimerQueryDX11::HasResult()
|
||||
{
|
||||
if (!_endCalled)
|
||||
return false;
|
||||
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
|
||||
return _device->GetIM()->GetData(_disjointQuery, &disjointData, sizeof(disjointData), 0) == S_OK;
|
||||
}
|
||||
|
||||
float GPUTimerQueryDX11::GetResult()
|
||||
{
|
||||
if (!_finalized)
|
||||
{
|
||||
#if BUILD_DEBUG
|
||||
ASSERT(HasResult());
|
||||
#endif
|
||||
|
||||
UINT64 timeStart, timeEnd;
|
||||
auto context = _device->GetIM();
|
||||
|
||||
context->GetData(_beginQuery, &timeStart, sizeof(timeStart), 0);
|
||||
context->GetData(_endQuery, &timeEnd, sizeof(timeEnd), 0);
|
||||
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
|
||||
context->GetData(_disjointQuery, &disjointData, sizeof(disjointData), 0);
|
||||
|
||||
if (disjointData.Disjoint == FALSE)
|
||||
{
|
||||
const float frequency = static_cast<float>(disjointData.Frequency);
|
||||
const UINT64 delta = timeEnd - timeStart;
|
||||
_timeDelta = (float)((delta / frequency) * 1000.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(Warning, "Unrealiable GPU timer query detected.");
|
||||
}
|
||||
|
||||
_finalized = true;
|
||||
}
|
||||
return _timeDelta;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Graphics/GPUTimerQuery.h"
|
||||
#include "GPUDeviceDX11.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// GPU timer query object for DirectX 11 backend.
|
||||
/// </summary>
|
||||
class GPUTimerQueryDX11 : public GPUResourceDX11<GPUTimerQuery>
|
||||
{
|
||||
private:
|
||||
|
||||
bool _finalized = false;
|
||||
bool _endCalled = false;
|
||||
float _timeDelta = 0.0f;
|
||||
|
||||
ID3D11Query* _beginQuery = nullptr;
|
||||
ID3D11Query* _endQuery = nullptr;
|
||||
ID3D11Query* _disjointQuery = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUTimerQueryDX11"/> class.
|
||||
/// </summary>
|
||||
/// <param name="device">The graphics device.</param>
|
||||
GPUTimerQueryDX11(GPUDeviceDX11* device);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="GPUTimerQueryDX11"/> class.
|
||||
/// </summary>
|
||||
~GPUTimerQueryDX11();
|
||||
|
||||
public:
|
||||
|
||||
// [GPUResourceDX11]
|
||||
ID3D11Resource* GetResource() final override;
|
||||
|
||||
// [GPUTimerQuery]
|
||||
void Begin() override;
|
||||
void End() override;
|
||||
bool HasResult() override;
|
||||
float GetResult() override;
|
||||
|
||||
protected:
|
||||
|
||||
// [GPUResource]
|
||||
void OnReleaseGPU() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
using Flax.Build.NativeCpp;
|
||||
|
||||
/// <summary>
|
||||
/// DirectX 11 graphics backend module.
|
||||
/// </summary>
|
||||
public class GraphicsDeviceDX11 : GraphicsDeviceBaseModule
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void Setup(BuildOptions options)
|
||||
{
|
||||
base.Setup(options);
|
||||
|
||||
options.PublicDefinitions.Add("GRAPHICS_API_DIRECTX11");
|
||||
options.OutputFiles.Add("d3d11.lib");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../IncludeDirectXHeaders.h"
|
||||
|
||||
#if GRAPHICS_API_DIRECTX11
|
||||
|
||||
/// <summary>
|
||||
/// Interface for objects that can be bound to the shader slots in DirectX 11.
|
||||
/// </summary>
|
||||
class IShaderResourceDX11
|
||||
{
|
||||
public:
|
||||
|
||||
IShaderResourceDX11()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets handle to the shader resource view object.
|
||||
/// </summary>
|
||||
/// <returns>SRV</returns>
|
||||
virtual ID3D11ShaderResourceView* SRV() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets CPU to the unordered access view object.
|
||||
/// </summary>
|
||||
/// <returns>UAV</returns>
|
||||
virtual ID3D11UnorderedAccessView* UAV() const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user