Files
WickedEngine/WickedEngine/wiGraphicsDevice_DX11.cpp
T
2020-12-12 20:05:57 +01:00

3213 lines
92 KiB
C++

#include "wiGraphicsDevice_DX11.h"
#ifdef WICKEDENGINE_BUILD_DX11
#include "wiHelper.h"
#include "ResourceMapping.h"
#include "wiBackLog.h"
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"Dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#include <sstream>
#include <algorithm>
using namespace Microsoft::WRL;
namespace wiGraphics
{
namespace DX11_Internal
{
// Engine -> Native converters
constexpr uint32_t _ParseBindFlags(uint32_t value)
{
uint32_t _flag = 0;
if (value & BIND_VERTEX_BUFFER)
_flag |= D3D11_BIND_VERTEX_BUFFER;
if (value & BIND_INDEX_BUFFER)
_flag |= D3D11_BIND_INDEX_BUFFER;
if (value & BIND_CONSTANT_BUFFER)
_flag |= D3D11_BIND_CONSTANT_BUFFER;
if (value & BIND_SHADER_RESOURCE)
_flag |= D3D11_BIND_SHADER_RESOURCE;
if (value & BIND_STREAM_OUTPUT)
_flag |= D3D11_BIND_STREAM_OUTPUT;
if (value & BIND_RENDER_TARGET)
_flag |= D3D11_BIND_RENDER_TARGET;
if (value & BIND_DEPTH_STENCIL)
_flag |= D3D11_BIND_DEPTH_STENCIL;
if (value & BIND_UNORDERED_ACCESS)
_flag |= D3D11_BIND_UNORDERED_ACCESS;
return _flag;
}
constexpr uint32_t _ParseCPUAccessFlags(uint32_t value)
{
uint32_t _flag = 0;
if (value & CPU_ACCESS_WRITE)
_flag |= D3D11_CPU_ACCESS_WRITE;
if (value & CPU_ACCESS_READ)
_flag |= D3D11_CPU_ACCESS_READ;
return _flag;
}
constexpr uint32_t _ParseResourceMiscFlags(uint32_t value)
{
uint32_t _flag = 0;
if (value & RESOURCE_MISC_SHARED)
_flag |= D3D11_RESOURCE_MISC_SHARED;
if (value & RESOURCE_MISC_TEXTURECUBE)
_flag |= D3D11_RESOURCE_MISC_TEXTURECUBE;
if (value & RESOURCE_MISC_INDIRECT_ARGS)
_flag |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
if (value & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
_flag |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
if (value & RESOURCE_MISC_BUFFER_STRUCTURED)
_flag |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
if (value & RESOURCE_MISC_TILED)
_flag |= D3D11_RESOURCE_MISC_TILED;
return _flag;
}
constexpr uint32_t _ParseColorWriteMask(uint32_t value)
{
uint32_t _flag = 0;
if (value == D3D11_COLOR_WRITE_ENABLE_ALL)
{
return D3D11_COLOR_WRITE_ENABLE_ALL;
}
else
{
if (value & COLOR_WRITE_ENABLE_RED)
_flag |= D3D11_COLOR_WRITE_ENABLE_RED;
if (value & COLOR_WRITE_ENABLE_GREEN)
_flag |= D3D11_COLOR_WRITE_ENABLE_GREEN;
if (value & COLOR_WRITE_ENABLE_BLUE)
_flag |= D3D11_COLOR_WRITE_ENABLE_BLUE;
if (value & COLOR_WRITE_ENABLE_ALPHA)
_flag |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
}
return _flag;
}
constexpr D3D11_FILTER _ConvertFilter(FILTER value)
{
switch (value)
{
case FILTER_MIN_MAG_MIP_POINT:
return D3D11_FILTER_MIN_MAG_MIP_POINT;
break;
case FILTER_MIN_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
break;
case FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
break;
case FILTER_MIN_POINT_MAG_MIP_LINEAR:
return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
break;
case FILTER_MIN_LINEAR_MAG_MIP_POINT:
return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
break;
case FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
break;
case FILTER_MIN_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
break;
case FILTER_MIN_MAG_MIP_LINEAR:
return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
break;
case FILTER_ANISOTROPIC:
return D3D11_FILTER_ANISOTROPIC;
break;
case FILTER_COMPARISON_MIN_MAG_MIP_POINT:
return D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
break;
case FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR;
break;
case FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT;
break;
case FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR:
return D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR;
break;
case FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT:
return D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
break;
case FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
break;
case FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
break;
case FILTER_COMPARISON_MIN_MAG_MIP_LINEAR:
return D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
break;
case FILTER_COMPARISON_ANISOTROPIC:
return D3D11_FILTER_COMPARISON_ANISOTROPIC;
break;
case FILTER_MINIMUM_MIN_MAG_MIP_POINT:
return D3D11_FILTER_MINIMUM_MIN_MAG_MIP_POINT;
break;
case FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR;
break;
case FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT;
break;
case FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR:
return D3D11_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR;
break;
case FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT:
return D3D11_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT;
break;
case FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
break;
case FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT;
break;
case FILTER_MINIMUM_MIN_MAG_MIP_LINEAR:
return D3D11_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR;
break;
case FILTER_MINIMUM_ANISOTROPIC:
return D3D11_FILTER_MINIMUM_ANISOTROPIC;
break;
case FILTER_MAXIMUM_MIN_MAG_MIP_POINT:
return D3D11_FILTER_MAXIMUM_MIN_MAG_MIP_POINT;
break;
case FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR;
break;
case FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT;
break;
case FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR:
return D3D11_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR;
break;
case FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT:
return D3D11_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT;
break;
case FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
return D3D11_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
break;
case FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT:
return D3D11_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT;
break;
case FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR:
return D3D11_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR;
break;
case FILTER_MAXIMUM_ANISOTROPIC:
return D3D11_FILTER_MAXIMUM_ANISOTROPIC;
break;
default:
break;
}
return D3D11_FILTER_MIN_MAG_MIP_POINT;
}
constexpr D3D11_TEXTURE_ADDRESS_MODE _ConvertTextureAddressMode(TEXTURE_ADDRESS_MODE value)
{
switch (value)
{
case TEXTURE_ADDRESS_WRAP:
return D3D11_TEXTURE_ADDRESS_WRAP;
break;
case TEXTURE_ADDRESS_MIRROR:
return D3D11_TEXTURE_ADDRESS_MIRROR;
break;
case TEXTURE_ADDRESS_CLAMP:
return D3D11_TEXTURE_ADDRESS_CLAMP;
break;
case TEXTURE_ADDRESS_BORDER:
return D3D11_TEXTURE_ADDRESS_BORDER;
break;
default:
break;
}
return D3D11_TEXTURE_ADDRESS_WRAP;
}
constexpr D3D11_COMPARISON_FUNC _ConvertComparisonFunc(COMPARISON_FUNC value)
{
switch (value)
{
case COMPARISON_NEVER:
return D3D11_COMPARISON_NEVER;
break;
case COMPARISON_LESS:
return D3D11_COMPARISON_LESS;
break;
case COMPARISON_EQUAL:
return D3D11_COMPARISON_EQUAL;
break;
case COMPARISON_LESS_EQUAL:
return D3D11_COMPARISON_LESS_EQUAL;
break;
case COMPARISON_GREATER:
return D3D11_COMPARISON_GREATER;
break;
case COMPARISON_NOT_EQUAL:
return D3D11_COMPARISON_NOT_EQUAL;
break;
case COMPARISON_GREATER_EQUAL:
return D3D11_COMPARISON_GREATER_EQUAL;
break;
case COMPARISON_ALWAYS:
return D3D11_COMPARISON_ALWAYS;
break;
default:
break;
}
return D3D11_COMPARISON_NEVER;
}
constexpr D3D11_FILL_MODE _ConvertFillMode(FILL_MODE value)
{
switch (value)
{
case FILL_WIREFRAME:
return D3D11_FILL_WIREFRAME;
break;
case FILL_SOLID:
return D3D11_FILL_SOLID;
break;
default:
break;
}
return D3D11_FILL_WIREFRAME;
}
constexpr D3D11_CULL_MODE _ConvertCullMode(CULL_MODE value)
{
switch (value)
{
case CULL_NONE:
return D3D11_CULL_NONE;
break;
case CULL_FRONT:
return D3D11_CULL_FRONT;
break;
case CULL_BACK:
return D3D11_CULL_BACK;
break;
default:
break;
}
return D3D11_CULL_NONE;
}
constexpr D3D11_DEPTH_WRITE_MASK _ConvertDepthWriteMask(DEPTH_WRITE_MASK value)
{
switch (value)
{
case DEPTH_WRITE_MASK_ZERO:
return D3D11_DEPTH_WRITE_MASK_ZERO;
break;
case DEPTH_WRITE_MASK_ALL:
return D3D11_DEPTH_WRITE_MASK_ALL;
break;
default:
break;
}
return D3D11_DEPTH_WRITE_MASK_ZERO;
}
constexpr D3D11_STENCIL_OP _ConvertStencilOp(STENCIL_OP value)
{
switch (value)
{
case STENCIL_OP_KEEP:
return D3D11_STENCIL_OP_KEEP;
break;
case STENCIL_OP_ZERO:
return D3D11_STENCIL_OP_ZERO;
break;
case STENCIL_OP_REPLACE:
return D3D11_STENCIL_OP_REPLACE;
break;
case STENCIL_OP_INCR_SAT:
return D3D11_STENCIL_OP_INCR_SAT;
break;
case STENCIL_OP_DECR_SAT:
return D3D11_STENCIL_OP_DECR_SAT;
break;
case STENCIL_OP_INVERT:
return D3D11_STENCIL_OP_INVERT;
break;
case STENCIL_OP_INCR:
return D3D11_STENCIL_OP_INCR;
break;
case STENCIL_OP_DECR:
return D3D11_STENCIL_OP_DECR;
break;
default:
break;
}
return D3D11_STENCIL_OP_KEEP;
}
constexpr D3D11_BLEND _ConvertBlend(BLEND value)
{
switch (value)
{
case BLEND_ZERO:
return D3D11_BLEND_ZERO;
break;
case BLEND_ONE:
return D3D11_BLEND_ONE;
break;
case BLEND_SRC_COLOR:
return D3D11_BLEND_SRC_COLOR;
break;
case BLEND_INV_SRC_COLOR:
return D3D11_BLEND_INV_SRC_COLOR;
break;
case BLEND_SRC_ALPHA:
return D3D11_BLEND_SRC_ALPHA;
break;
case BLEND_INV_SRC_ALPHA:
return D3D11_BLEND_INV_SRC_ALPHA;
break;
case BLEND_DEST_ALPHA:
return D3D11_BLEND_DEST_ALPHA;
break;
case BLEND_INV_DEST_ALPHA:
return D3D11_BLEND_INV_DEST_ALPHA;
break;
case BLEND_DEST_COLOR:
return D3D11_BLEND_DEST_COLOR;
break;
case BLEND_INV_DEST_COLOR:
return D3D11_BLEND_INV_DEST_COLOR;
break;
case BLEND_SRC_ALPHA_SAT:
return D3D11_BLEND_SRC_ALPHA_SAT;
break;
case BLEND_BLEND_FACTOR:
return D3D11_BLEND_BLEND_FACTOR;
break;
case BLEND_INV_BLEND_FACTOR:
return D3D11_BLEND_INV_BLEND_FACTOR;
break;
case BLEND_SRC1_COLOR:
return D3D11_BLEND_SRC1_COLOR;
break;
case BLEND_INV_SRC1_COLOR:
return D3D11_BLEND_INV_SRC1_COLOR;
break;
case BLEND_SRC1_ALPHA:
return D3D11_BLEND_SRC1_ALPHA;
break;
case BLEND_INV_SRC1_ALPHA:
return D3D11_BLEND_INV_SRC1_ALPHA;
break;
default:
break;
}
return D3D11_BLEND_ZERO;
}
constexpr D3D11_BLEND_OP _ConvertBlendOp(BLEND_OP value)
{
switch (value)
{
case BLEND_OP_ADD:
return D3D11_BLEND_OP_ADD;
break;
case BLEND_OP_SUBTRACT:
return D3D11_BLEND_OP_SUBTRACT;
break;
case BLEND_OP_REV_SUBTRACT:
return D3D11_BLEND_OP_REV_SUBTRACT;
break;
case BLEND_OP_MIN:
return D3D11_BLEND_OP_MIN;
break;
case BLEND_OP_MAX:
return D3D11_BLEND_OP_MAX;
break;
default:
break;
}
return D3D11_BLEND_OP_ADD;
}
constexpr D3D11_USAGE _ConvertUsage(USAGE value)
{
switch (value)
{
case USAGE_DEFAULT:
return D3D11_USAGE_DEFAULT;
break;
case USAGE_IMMUTABLE:
return D3D11_USAGE_IMMUTABLE;
break;
case USAGE_DYNAMIC:
return D3D11_USAGE_DYNAMIC;
break;
case USAGE_STAGING:
return D3D11_USAGE_STAGING;
break;
default:
break;
}
return D3D11_USAGE_DEFAULT;
}
constexpr D3D11_INPUT_CLASSIFICATION _ConvertInputClassification(INPUT_CLASSIFICATION value)
{
switch (value)
{
case INPUT_PER_VERTEX_DATA:
return D3D11_INPUT_PER_VERTEX_DATA;
break;
case INPUT_PER_INSTANCE_DATA:
return D3D11_INPUT_PER_INSTANCE_DATA;
break;
default:
break;
}
return D3D11_INPUT_PER_VERTEX_DATA;
}
constexpr DXGI_FORMAT _ConvertFormat(FORMAT value)
{
switch (value)
{
case FORMAT_UNKNOWN:
return DXGI_FORMAT_UNKNOWN;
break;
case FORMAT_R32G32B32A32_FLOAT:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
break;
case FORMAT_R32G32B32A32_UINT:
return DXGI_FORMAT_R32G32B32A32_UINT;
break;
case FORMAT_R32G32B32A32_SINT:
return DXGI_FORMAT_R32G32B32A32_SINT;
break;
case FORMAT_R32G32B32_FLOAT:
return DXGI_FORMAT_R32G32B32_FLOAT;
break;
case FORMAT_R32G32B32_UINT:
return DXGI_FORMAT_R32G32B32_UINT;
break;
case FORMAT_R32G32B32_SINT:
return DXGI_FORMAT_R32G32B32_SINT;
break;
case FORMAT_R16G16B16A16_FLOAT:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
break;
case FORMAT_R16G16B16A16_UNORM:
return DXGI_FORMAT_R16G16B16A16_UNORM;
break;
case FORMAT_R16G16B16A16_UINT:
return DXGI_FORMAT_R16G16B16A16_UINT;
break;
case FORMAT_R16G16B16A16_SNORM:
return DXGI_FORMAT_R16G16B16A16_SNORM;
break;
case FORMAT_R16G16B16A16_SINT:
return DXGI_FORMAT_R16G16B16A16_SINT;
break;
case FORMAT_R32G32_FLOAT:
return DXGI_FORMAT_R32G32_FLOAT;
break;
case FORMAT_R32G32_UINT:
return DXGI_FORMAT_R32G32_UINT;
break;
case FORMAT_R32G32_SINT:
return DXGI_FORMAT_R32G32_SINT;
break;
case FORMAT_R32G8X24_TYPELESS:
return DXGI_FORMAT_R32G8X24_TYPELESS;
break;
case FORMAT_D32_FLOAT_S8X24_UINT:
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
break;
case FORMAT_R10G10B10A2_UNORM:
return DXGI_FORMAT_R10G10B10A2_UNORM;
break;
case FORMAT_R10G10B10A2_UINT:
return DXGI_FORMAT_R10G10B10A2_UINT;
break;
case FORMAT_R11G11B10_FLOAT:
return DXGI_FORMAT_R11G11B10_FLOAT;
break;
case FORMAT_R8G8B8A8_UNORM:
return DXGI_FORMAT_R8G8B8A8_UNORM;
break;
case FORMAT_R8G8B8A8_UNORM_SRGB:
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
break;
case FORMAT_R8G8B8A8_UINT:
return DXGI_FORMAT_R8G8B8A8_UINT;
break;
case FORMAT_R8G8B8A8_SNORM:
return DXGI_FORMAT_R8G8B8A8_SNORM;
break;
case FORMAT_R8G8B8A8_SINT:
return DXGI_FORMAT_R8G8B8A8_SINT;
break;
case FORMAT_R16G16_FLOAT:
return DXGI_FORMAT_R16G16_FLOAT;
break;
case FORMAT_R16G16_UNORM:
return DXGI_FORMAT_R16G16_UNORM;
break;
case FORMAT_R16G16_UINT:
return DXGI_FORMAT_R16G16_UINT;
break;
case FORMAT_R16G16_SNORM:
return DXGI_FORMAT_R16G16_SNORM;
break;
case FORMAT_R16G16_SINT:
return DXGI_FORMAT_R16G16_SINT;
break;
case FORMAT_R32_TYPELESS:
return DXGI_FORMAT_R32_TYPELESS;
break;
case FORMAT_D32_FLOAT:
return DXGI_FORMAT_D32_FLOAT;
break;
case FORMAT_R32_FLOAT:
return DXGI_FORMAT_R32_FLOAT;
break;
case FORMAT_R32_UINT:
return DXGI_FORMAT_R32_UINT;
break;
case FORMAT_R32_SINT:
return DXGI_FORMAT_R32_SINT;
break;
case FORMAT_R24G8_TYPELESS:
return DXGI_FORMAT_R24G8_TYPELESS;
break;
case FORMAT_D24_UNORM_S8_UINT:
return DXGI_FORMAT_D24_UNORM_S8_UINT;
break;
case FORMAT_R8G8_UNORM:
return DXGI_FORMAT_R8G8_UNORM;
break;
case FORMAT_R8G8_UINT:
return DXGI_FORMAT_R8G8_UINT;
break;
case FORMAT_R8G8_SNORM:
return DXGI_FORMAT_R8G8_SNORM;
break;
case FORMAT_R8G8_SINT:
return DXGI_FORMAT_R8G8_SINT;
break;
case FORMAT_R16_TYPELESS:
return DXGI_FORMAT_R16_TYPELESS;
break;
case FORMAT_R16_FLOAT:
return DXGI_FORMAT_R16_FLOAT;
break;
case FORMAT_D16_UNORM:
return DXGI_FORMAT_D16_UNORM;
break;
case FORMAT_R16_UNORM:
return DXGI_FORMAT_R16_UNORM;
break;
case FORMAT_R16_UINT:
return DXGI_FORMAT_R16_UINT;
break;
case FORMAT_R16_SNORM:
return DXGI_FORMAT_R16_SNORM;
break;
case FORMAT_R16_SINT:
return DXGI_FORMAT_R16_SINT;
break;
case FORMAT_R8_UNORM:
return DXGI_FORMAT_R8_UNORM;
break;
case FORMAT_R8_UINT:
return DXGI_FORMAT_R8_UINT;
break;
case FORMAT_R8_SNORM:
return DXGI_FORMAT_R8_SNORM;
break;
case FORMAT_R8_SINT:
return DXGI_FORMAT_R8_SINT;
break;
case FORMAT_BC1_UNORM:
return DXGI_FORMAT_BC1_UNORM;
break;
case FORMAT_BC1_UNORM_SRGB:
return DXGI_FORMAT_BC1_UNORM_SRGB;
break;
case FORMAT_BC2_UNORM:
return DXGI_FORMAT_BC2_UNORM;
break;
case FORMAT_BC2_UNORM_SRGB:
return DXGI_FORMAT_BC2_UNORM_SRGB;
break;
case FORMAT_BC3_UNORM:
return DXGI_FORMAT_BC3_UNORM;
break;
case FORMAT_BC3_UNORM_SRGB:
return DXGI_FORMAT_BC3_UNORM_SRGB;
break;
case FORMAT_BC4_UNORM:
return DXGI_FORMAT_BC4_UNORM;
break;
case FORMAT_BC4_SNORM:
return DXGI_FORMAT_BC4_SNORM;
break;
case FORMAT_BC5_UNORM:
return DXGI_FORMAT_BC5_UNORM;
break;
case FORMAT_BC5_SNORM:
return DXGI_FORMAT_BC5_SNORM;
break;
case FORMAT_B8G8R8A8_UNORM:
return DXGI_FORMAT_B8G8R8A8_UNORM;
break;
case FORMAT_B8G8R8A8_UNORM_SRGB:
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
break;
case FORMAT_BC6H_UF16:
return DXGI_FORMAT_BC6H_UF16;
break;
case FORMAT_BC6H_SF16:
return DXGI_FORMAT_BC6H_SF16;
break;
case FORMAT_BC7_UNORM:
return DXGI_FORMAT_BC7_UNORM;
break;
case FORMAT_BC7_UNORM_SRGB:
return DXGI_FORMAT_BC7_UNORM_SRGB;
break;
}
return DXGI_FORMAT_UNKNOWN;
}
inline D3D11_TEXTURE1D_DESC _ConvertTextureDesc1D(const TextureDesc* pDesc)
{
D3D11_TEXTURE1D_DESC desc;
desc.Width = pDesc->Width;
desc.MipLevels = pDesc->MipLevels;
desc.ArraySize = pDesc->ArraySize;
desc.Format = _ConvertFormat(pDesc->Format);
desc.Usage = _ConvertUsage(pDesc->Usage);
desc.BindFlags = _ParseBindFlags(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags);
return desc;
}
inline D3D11_TEXTURE2D_DESC _ConvertTextureDesc2D(const TextureDesc* pDesc)
{
D3D11_TEXTURE2D_DESC desc;
desc.Width = pDesc->Width;
desc.Height = pDesc->Height;
desc.MipLevels = pDesc->MipLevels;
desc.ArraySize = pDesc->ArraySize;
desc.Format = _ConvertFormat(pDesc->Format);
desc.SampleDesc.Count = pDesc->SampleCount;
desc.SampleDesc.Quality = 0;
desc.Usage = _ConvertUsage(pDesc->Usage);
desc.BindFlags = _ParseBindFlags(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags);
return desc;
}
inline D3D11_TEXTURE3D_DESC _ConvertTextureDesc3D(const TextureDesc* pDesc)
{
D3D11_TEXTURE3D_DESC desc;
desc.Width = pDesc->Width;
desc.Height = pDesc->Height;
desc.Depth = pDesc->Depth;
desc.MipLevels = pDesc->MipLevels;
desc.Format = _ConvertFormat(pDesc->Format);
desc.Usage = _ConvertUsage(pDesc->Usage);
desc.BindFlags = _ParseBindFlags(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags);
return desc;
}
inline D3D11_SUBRESOURCE_DATA _ConvertSubresourceData(const SubresourceData& pInitialData)
{
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = pInitialData.pSysMem;
data.SysMemPitch = pInitialData.SysMemPitch;
data.SysMemSlicePitch = pInitialData.SysMemSlicePitch;
return data;
}
// Native -> Engine converters
constexpr uint32_t _ParseBindFlags_Inv(uint32_t value)
{
uint32_t _flag = 0;
if (value & D3D11_BIND_VERTEX_BUFFER)
_flag |= BIND_VERTEX_BUFFER;
if (value & D3D11_BIND_INDEX_BUFFER)
_flag |= BIND_INDEX_BUFFER;
if (value & D3D11_BIND_CONSTANT_BUFFER)
_flag |= BIND_CONSTANT_BUFFER;
if (value & D3D11_BIND_SHADER_RESOURCE)
_flag |= BIND_SHADER_RESOURCE;
if (value & D3D11_BIND_STREAM_OUTPUT)
_flag |= BIND_STREAM_OUTPUT;
if (value & D3D11_BIND_RENDER_TARGET)
_flag |= BIND_RENDER_TARGET;
if (value & D3D11_BIND_DEPTH_STENCIL)
_flag |= BIND_DEPTH_STENCIL;
if (value & D3D11_BIND_UNORDERED_ACCESS)
_flag |= BIND_UNORDERED_ACCESS;
return _flag;
}
constexpr uint32_t _ParseCPUAccessFlags_Inv(uint32_t value)
{
uint32_t _flag = 0;
if (value & D3D11_CPU_ACCESS_WRITE)
_flag |= CPU_ACCESS_WRITE;
if (value & D3D11_CPU_ACCESS_READ)
_flag |= CPU_ACCESS_READ;
return _flag;
}
constexpr uint32_t _ParseResourceMiscFlags_Inv(uint32_t value)
{
uint32_t _flag = 0;
if (value & D3D11_RESOURCE_MISC_SHARED)
_flag |= RESOURCE_MISC_SHARED;
if (value & D3D11_RESOURCE_MISC_TEXTURECUBE)
_flag |= RESOURCE_MISC_TEXTURECUBE;
if (value & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS)
_flag |= RESOURCE_MISC_INDIRECT_ARGS;
if (value & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
_flag |= RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
if (value & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)
_flag |= RESOURCE_MISC_BUFFER_STRUCTURED;
if (value & D3D11_RESOURCE_MISC_TILED)
_flag |= RESOURCE_MISC_TILED;
return _flag;
}
constexpr FORMAT _ConvertFormat_Inv(DXGI_FORMAT value)
{
switch (value)
{
case DXGI_FORMAT_UNKNOWN:
return FORMAT_UNKNOWN;
break;
case DXGI_FORMAT_R32G32B32A32_FLOAT:
return FORMAT_R32G32B32A32_FLOAT;
break;
case DXGI_FORMAT_R32G32B32A32_UINT:
return FORMAT_R32G32B32A32_UINT;
break;
case DXGI_FORMAT_R32G32B32A32_SINT:
return FORMAT_R32G32B32A32_SINT;
break;
case DXGI_FORMAT_R32G32B32_FLOAT:
return FORMAT_R32G32B32_FLOAT;
break;
case DXGI_FORMAT_R32G32B32_UINT:
return FORMAT_R32G32B32_UINT;
break;
case DXGI_FORMAT_R32G32B32_SINT:
return FORMAT_R32G32B32_SINT;
break;
case DXGI_FORMAT_R16G16B16A16_FLOAT:
return FORMAT_R16G16B16A16_FLOAT;
break;
case DXGI_FORMAT_R16G16B16A16_UNORM:
return FORMAT_R16G16B16A16_UNORM;
break;
case DXGI_FORMAT_R16G16B16A16_UINT:
return FORMAT_R16G16B16A16_UINT;
break;
case DXGI_FORMAT_R16G16B16A16_SNORM:
return FORMAT_R16G16B16A16_SNORM;
break;
case DXGI_FORMAT_R16G16B16A16_SINT:
return FORMAT_R16G16B16A16_SINT;
break;
case DXGI_FORMAT_R32G32_FLOAT:
return FORMAT_R32G32_FLOAT;
break;
case DXGI_FORMAT_R32G32_UINT:
return FORMAT_R32G32_UINT;
break;
case DXGI_FORMAT_R32G32_SINT:
return FORMAT_R32G32_SINT;
break;
case DXGI_FORMAT_R32G8X24_TYPELESS:
return FORMAT_R32G8X24_TYPELESS;
break;
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
return FORMAT_D32_FLOAT_S8X24_UINT;
break;
case DXGI_FORMAT_R10G10B10A2_UNORM:
return FORMAT_R10G10B10A2_UNORM;
break;
case DXGI_FORMAT_R10G10B10A2_UINT:
return FORMAT_R10G10B10A2_UINT;
break;
case DXGI_FORMAT_R11G11B10_FLOAT:
return FORMAT_R11G11B10_FLOAT;
break;
case DXGI_FORMAT_R8G8B8A8_UNORM:
return FORMAT_R8G8B8A8_UNORM;
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
return FORMAT_R8G8B8A8_UNORM_SRGB;
break;
case DXGI_FORMAT_R8G8B8A8_UINT:
return FORMAT_R8G8B8A8_UINT;
break;
case DXGI_FORMAT_R8G8B8A8_SNORM:
return FORMAT_R8G8B8A8_SNORM;
break;
case DXGI_FORMAT_R8G8B8A8_SINT:
return FORMAT_R8G8B8A8_SINT;
break;
case DXGI_FORMAT_R16G16_FLOAT:
return FORMAT_R16G16_FLOAT;
break;
case DXGI_FORMAT_R16G16_UNORM:
return FORMAT_R16G16_UNORM;
break;
case DXGI_FORMAT_R16G16_UINT:
return FORMAT_R16G16_UINT;
break;
case DXGI_FORMAT_R16G16_SNORM:
return FORMAT_R16G16_SNORM;
break;
case DXGI_FORMAT_R16G16_SINT:
return FORMAT_R16G16_SINT;
break;
case DXGI_FORMAT_R32_TYPELESS:
return FORMAT_R32_TYPELESS;
break;
case DXGI_FORMAT_D32_FLOAT:
return FORMAT_D32_FLOAT;
break;
case DXGI_FORMAT_R32_FLOAT:
return FORMAT_R32_FLOAT;
break;
case DXGI_FORMAT_R32_UINT:
return FORMAT_R32_UINT;
break;
case DXGI_FORMAT_R32_SINT:
return FORMAT_R32_SINT;
break;
case DXGI_FORMAT_R24G8_TYPELESS:
return FORMAT_R24G8_TYPELESS;
break;
case DXGI_FORMAT_D24_UNORM_S8_UINT:
return FORMAT_D24_UNORM_S8_UINT;
break;
case DXGI_FORMAT_R8G8_UNORM:
return FORMAT_R8G8_UNORM;
break;
case DXGI_FORMAT_R8G8_UINT:
return FORMAT_R8G8_UINT;
break;
case DXGI_FORMAT_R8G8_SNORM:
return FORMAT_R8G8_SNORM;
break;
case DXGI_FORMAT_R8G8_SINT:
return FORMAT_R8G8_SINT;
break;
case DXGI_FORMAT_R16_TYPELESS:
return FORMAT_R16_TYPELESS;
break;
case DXGI_FORMAT_R16_FLOAT:
return FORMAT_R16_FLOAT;
break;
case DXGI_FORMAT_D16_UNORM:
return FORMAT_D16_UNORM;
break;
case DXGI_FORMAT_R16_UNORM:
return FORMAT_R16_UNORM;
break;
case DXGI_FORMAT_R16_UINT:
return FORMAT_R16_UINT;
break;
case DXGI_FORMAT_R16_SNORM:
return FORMAT_R16_SNORM;
break;
case DXGI_FORMAT_R16_SINT:
return FORMAT_R16_SINT;
break;
case DXGI_FORMAT_R8_UNORM:
return FORMAT_R8_UNORM;
break;
case DXGI_FORMAT_R8_UINT:
return FORMAT_R8_UINT;
break;
case DXGI_FORMAT_R8_SNORM:
return FORMAT_R8_SNORM;
break;
case DXGI_FORMAT_R8_SINT:
return FORMAT_R8_SINT;
break;
case DXGI_FORMAT_BC1_UNORM:
return FORMAT_BC1_UNORM;
break;
case DXGI_FORMAT_BC1_UNORM_SRGB:
return FORMAT_BC1_UNORM_SRGB;
break;
case DXGI_FORMAT_BC2_UNORM:
return FORMAT_BC2_UNORM;
break;
case DXGI_FORMAT_BC2_UNORM_SRGB:
return FORMAT_BC2_UNORM_SRGB;
break;
case DXGI_FORMAT_BC3_UNORM:
return FORMAT_BC3_UNORM;
break;
case DXGI_FORMAT_BC3_UNORM_SRGB:
return FORMAT_BC3_UNORM_SRGB;
break;
case DXGI_FORMAT_BC4_UNORM:
return FORMAT_BC4_UNORM;
break;
case DXGI_FORMAT_BC4_SNORM:
return FORMAT_BC4_SNORM;
break;
case DXGI_FORMAT_BC5_UNORM:
return FORMAT_BC5_UNORM;
break;
case DXGI_FORMAT_BC5_SNORM:
return FORMAT_BC5_SNORM;
break;
case DXGI_FORMAT_B8G8R8A8_UNORM:
return FORMAT_B8G8R8A8_UNORM;
break;
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
return FORMAT_B8G8R8A8_UNORM_SRGB;
break;
case DXGI_FORMAT_BC6H_UF16:
return FORMAT_BC6H_UF16;
break;
case DXGI_FORMAT_BC6H_SF16:
return FORMAT_BC6H_SF16;
break;
case DXGI_FORMAT_BC7_UNORM:
return FORMAT_BC7_UNORM;
break;
case DXGI_FORMAT_BC7_UNORM_SRGB:
return FORMAT_BC7_UNORM_SRGB;
break;
}
return FORMAT_UNKNOWN;
}
constexpr USAGE _ConvertUsage_Inv(D3D11_USAGE value)
{
switch (value)
{
case D3D11_USAGE_DEFAULT:
return USAGE_DEFAULT;
break;
case D3D11_USAGE_IMMUTABLE:
return USAGE_IMMUTABLE;
break;
case D3D11_USAGE_DYNAMIC:
return USAGE_DYNAMIC;
break;
case D3D11_USAGE_STAGING:
return USAGE_STAGING;
break;
default:
break;
}
return USAGE_DEFAULT;
}
inline TextureDesc _ConvertTextureDesc_Inv(const D3D11_TEXTURE1D_DESC* pDesc)
{
TextureDesc desc;
desc.Width = pDesc->Width;
desc.MipLevels = pDesc->MipLevels;
desc.ArraySize = pDesc->ArraySize;
desc.Format = _ConvertFormat_Inv(pDesc->Format);
desc.Usage = _ConvertUsage_Inv(pDesc->Usage);
desc.BindFlags = _ParseBindFlags_Inv(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags_Inv(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags_Inv(pDesc->MiscFlags);
return desc;
}
inline TextureDesc _ConvertTextureDesc_Inv(const D3D11_TEXTURE2D_DESC* pDesc)
{
TextureDesc desc;
desc.Width = pDesc->Width;
desc.Height = pDesc->Height;
desc.MipLevels = pDesc->MipLevels;
desc.ArraySize = pDesc->ArraySize;
desc.Format = _ConvertFormat_Inv(pDesc->Format);
desc.SampleCount = pDesc->SampleDesc.Count;
desc.Usage = _ConvertUsage_Inv(pDesc->Usage);
desc.BindFlags = _ParseBindFlags_Inv(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags_Inv(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags_Inv(pDesc->MiscFlags);
return desc;
}
inline TextureDesc _ConvertTextureDesc_Inv(const D3D11_TEXTURE3D_DESC* pDesc)
{
TextureDesc desc;
desc.Width = pDesc->Width;
desc.Height = pDesc->Height;
desc.Depth = pDesc->Depth;
desc.MipLevels = pDesc->MipLevels;
desc.Format = _ConvertFormat_Inv(pDesc->Format);
desc.Usage = _ConvertUsage_Inv(pDesc->Usage);
desc.BindFlags = _ParseBindFlags_Inv(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags_Inv(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags_Inv(pDesc->MiscFlags);
return desc;
}
// Local Helpers:
const void* const __nullBlob[128] = {}; // this is initialized to nullptrs and used to unbind resources!
struct Resource_DX11
{
ComPtr<ID3D11Resource> resource;
ComPtr<ID3D11ShaderResourceView> srv;
ComPtr<ID3D11UnorderedAccessView> uav;
std::vector<ComPtr<ID3D11ShaderResourceView>> subresources_srv;
std::vector<ComPtr<ID3D11UnorderedAccessView>> subresources_uav;
};
struct Texture_DX11 : public Resource_DX11
{
ComPtr<ID3D11RenderTargetView> rtv;
ComPtr<ID3D11DepthStencilView> dsv;
std::vector<ComPtr<ID3D11RenderTargetView>> subresources_rtv;
std::vector<ComPtr<ID3D11DepthStencilView>> subresources_dsv;
};
struct VertexShader_DX11
{
ComPtr<ID3D11VertexShader> resource;
};
struct HullShader_DX11
{
ComPtr<ID3D11HullShader> resource;
};
struct DomainShader_DX11
{
ComPtr<ID3D11DomainShader> resource;
};
struct GeometryShader_DX11
{
ComPtr<ID3D11GeometryShader> resource;
};
struct PixelShader_DX11
{
ComPtr<ID3D11PixelShader> resource;
};
struct ComputeShader_DX11
{
ComPtr<ID3D11ComputeShader> resource;
};
struct PipelineState_DX11
{
ComPtr<ID3D11BlendState> bs;
ComPtr<ID3D11DepthStencilState> dss;
ComPtr<ID3D11RasterizerState> rs;
ComPtr<ID3D11InputLayout> il;
};
struct Sampler_DX11
{
ComPtr<ID3D11SamplerState> resource;
};
struct Query_DX11
{
ComPtr<ID3D11Query> resource;
};
Resource_DX11* to_internal(const GPUResource* param)
{
return static_cast<Resource_DX11*>(param->internal_state.get());
}
Resource_DX11* to_internal(const GPUBuffer* param)
{
return static_cast<Resource_DX11*>(param->internal_state.get());
}
Texture_DX11* to_internal(const Texture* param)
{
return static_cast<Texture_DX11*>(param->internal_state.get());
}
PipelineState_DX11* to_internal(const PipelineState* param)
{
return static_cast<PipelineState_DX11*>(param->internal_state.get());
}
Sampler_DX11* to_internal(const Sampler* param)
{
return static_cast<Sampler_DX11*>(param->internal_state.get());
}
Query_DX11* to_internal(const GPUQuery* param)
{
return static_cast<Query_DX11*>(param->internal_state.get());
}
}
using namespace DX11_Internal;
void GraphicsDevice_DX11::pso_validate(CommandList cmd)
{
if (!dirty_pso[cmd])
return;
const PipelineState* pso = active_pso[cmd];
const PipelineStateDesc& desc = pso != nullptr ? pso->GetDesc() : PipelineStateDesc();
auto internal_state = to_internal(pso);
ID3D11VertexShader* vs = desc.vs == nullptr ? nullptr : static_cast<VertexShader_DX11*>(desc.vs->internal_state.get())->resource.Get();
if (vs != prev_vs[cmd])
{
deviceContexts[cmd]->VSSetShader(vs, nullptr, 0);
prev_vs[cmd] = vs;
}
ID3D11PixelShader* ps = desc.ps == nullptr ? nullptr : static_cast<PixelShader_DX11*>(desc.ps->internal_state.get())->resource.Get();
if (ps != prev_ps[cmd])
{
deviceContexts[cmd]->PSSetShader(ps, nullptr, 0);
prev_ps[cmd] = ps;
}
ID3D11HullShader* hs = desc.hs == nullptr ? nullptr : static_cast<HullShader_DX11*>(desc.hs->internal_state.get())->resource.Get();
if (hs != prev_hs[cmd])
{
deviceContexts[cmd]->HSSetShader(hs, nullptr, 0);
prev_hs[cmd] = hs;
}
ID3D11DomainShader* ds = desc.ds == nullptr ? nullptr : static_cast<DomainShader_DX11*>(desc.ds->internal_state.get())->resource.Get();
if (ds != prev_ds[cmd])
{
deviceContexts[cmd]->DSSetShader(ds, nullptr, 0);
prev_ds[cmd] = ds;
}
ID3D11GeometryShader* gs = desc.gs == nullptr ? nullptr : static_cast<GeometryShader_DX11*>(desc.gs->internal_state.get())->resource.Get();
if (gs != prev_gs[cmd])
{
deviceContexts[cmd]->GSSetShader(gs, nullptr, 0);
prev_gs[cmd] = gs;
}
ID3D11BlendState* bs = desc.bs == nullptr ? nullptr : internal_state->bs.Get();
if (desc.bs != prev_bs[cmd] || desc.sampleMask != prev_samplemask[cmd] ||
blendFactor[cmd].x != prev_blendfactor[cmd].x ||
blendFactor[cmd].y != prev_blendfactor[cmd].y ||
blendFactor[cmd].z != prev_blendfactor[cmd].z ||
blendFactor[cmd].w != prev_blendfactor[cmd].w
)
{
const float fact[4] = { blendFactor[cmd].x, blendFactor[cmd].y, blendFactor[cmd].z, blendFactor[cmd].w };
deviceContexts[cmd]->OMSetBlendState(bs, fact, desc.sampleMask);
prev_bs[cmd] = desc.bs;
prev_blendfactor[cmd] = blendFactor[cmd];
prev_samplemask[cmd] = desc.sampleMask;
}
ID3D11RasterizerState* rs = desc.rs == nullptr ? nullptr : internal_state->rs.Get();
if (desc.rs != prev_rs[cmd])
{
deviceContexts[cmd]->RSSetState(rs);
prev_rs[cmd] = desc.rs;
}
ID3D11DepthStencilState* dss = desc.dss == nullptr ? nullptr : internal_state->dss.Get();
if (desc.dss != prev_dss[cmd] || stencilRef[cmd] != prev_stencilRef[cmd])
{
deviceContexts[cmd]->OMSetDepthStencilState(dss, stencilRef[cmd]);
prev_dss[cmd] = desc.dss;
prev_stencilRef[cmd] = stencilRef[cmd];
}
ID3D11InputLayout* il = desc.il == nullptr ? nullptr : internal_state->il.Get();
if (desc.il != prev_il[cmd])
{
deviceContexts[cmd]->IASetInputLayout(il);
prev_il[cmd] = desc.il;
}
if (prev_pt[cmd] != desc.pt)
{
D3D11_PRIMITIVE_TOPOLOGY d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
switch (desc.pt)
{
case TRIANGLELIST:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
break;
case TRIANGLESTRIP:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
break;
case POINTLIST:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
break;
case LINELIST:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
break;
case LINESTRIP:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
break;
case PATCHLIST:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;
break;
default:
d3dType = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
break;
};
deviceContexts[cmd]->IASetPrimitiveTopology(d3dType);
prev_pt[cmd] = desc.pt;
}
}
// Engine functions
GraphicsDevice_DX11::GraphicsDevice_DX11(wiPlatform::window_type window, bool fullscreen, bool debuglayer)
{
DEBUGDEVICE = debuglayer;
FULLSCREEN = fullscreen;
#ifndef PLATFORM_UWP
RECT rect;
GetClientRect(window, &rect);
RESOLUTIONWIDTH = rect.right - rect.left;
RESOLUTIONHEIGHT = rect.bottom - rect.top;
#else PLATFORM_UWP
float dpiscale = wiPlatform::GetDPIScaling();
RESOLUTIONWIDTH = int(window->Bounds.Width * dpiscale);
RESOLUTIONHEIGHT = int(window->Bounds.Height * dpiscale);
#endif
HRESULT hr = E_FAIL;
uint32_t createDeviceFlags = 0;
if (debuglayer)
{
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
}
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
uint32_t numDriverTypes = arraysize(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
uint32_t numFeatureLevels = arraysize(featureLevels);
for (uint32_t driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
{
driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDevice(nullptr, driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &device
, &featureLevel, &immediateContext);
if (SUCCEEDED(hr))
break;
}
if (FAILED(hr))
{
std::stringstream ss("");
ss << "Failed to create the graphics device! ERROR: " << std::hex << hr;
wiHelper::messageBox(ss.str(), "Error!");
wiPlatform::Exit();
}
ComPtr<IDXGIDevice2> pDXGIDevice;
hr = device.As(&pDXGIDevice);
ComPtr<IDXGIAdapter> pDXGIAdapter;
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&pDXGIAdapter);
ComPtr<IDXGIFactory2> pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory2), (void**)&pIDXGIFactory);
if (debuglayer)
{
ID3D11Debug* d3dDebug = nullptr;
if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug), (void**)&d3dDebug)))
{
ID3D11InfoQueue* d3dInfoQueue = nullptr;
if (SUCCEEDED(d3dDebug->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&d3dInfoQueue)))
{
d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
D3D11_MESSAGE_ID hide[] =
{
D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
// Add more message IDs here as needed
};
D3D11_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumIDs = _countof(hide);
filter.DenyList.pIDList = hide;
d3dInfoQueue->AddStorageFilterEntries(&filter);
d3dInfoQueue->Release();
}
d3dDebug->Release();
}
}
DXGI_SWAP_CHAIN_DESC1 sd = {};
sd.Width = RESOLUTIONWIDTH;
sd.Height = RESOLUTIONHEIGHT;
sd.Format = _ConvertFormat(GetBackBufferFormat());
sd.Stereo = false;
sd.SampleDesc.Count = 1; // Don't use multi-sampling.
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 2; // Use double-buffering to minimize latency.
sd.Flags = 0;
sd.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
#ifndef PLATFORM_UWP
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
sd.Scaling = DXGI_SCALING_STRETCH;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
fullscreenDesc.RefreshRate.Numerator = 60;
fullscreenDesc.RefreshRate.Denominator = 1;
fullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // needs to be unspecified for correct fullscreen scaling!
fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
fullscreenDesc.Windowed = !fullscreen;
hr = pIDXGIFactory->CreateSwapChainForHwnd(device.Get(), window, &sd, &fullscreenDesc, nullptr, &swapChain);
#else
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
sd.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
hr = pIDXGIFactory->CreateSwapChainForCoreWindow(device.Get(), reinterpret_cast<IUnknown*>(window.Get()), &sd, nullptr, &swapChain);
#endif
if (FAILED(hr))
{
wiHelper::messageBox("Failed to create a swapchain for the graphics device!", "Error!");
wiPlatform::Exit();
}
// 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.
hr = pDXGIDevice->SetMaximumFrameLatency(1);
D3D_FEATURE_LEVEL aquiredFeatureLevel = device->GetFeatureLevel();
if (aquiredFeatureLevel >= D3D_FEATURE_LEVEL_11_0)
{
capabilities |= GRAPHICSDEVICE_CAPABILITY_TESSELLATION;
}
//D3D11_FEATURE_DATA_D3D11_OPTIONS features_0;
//hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features_0, sizeof(features_0));
//D3D11_FEATURE_DATA_D3D11_OPTIONS1 features_1;
//hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS1, &features_1, sizeof(features_1));
D3D11_FEATURE_DATA_D3D11_OPTIONS2 features_2;
hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &features_2, sizeof(features_2));
if (features_2.ConservativeRasterizationTier >= D3D11_CONSERVATIVE_RASTERIZATION_TIER_1)
{
capabilities |= GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION;
}
if (features_2.ROVsSupported == TRUE)
{
capabilities |= GRAPHICSDEVICE_CAPABILITY_RASTERIZER_ORDERED_VIEWS;
}
if (features_2.TypedUAVLoadAdditionalFormats)
{
// More info about UAV format load support: https://docs.microsoft.com/en-us/windows/win32/direct3d12/typed-unordered-access-view-loads
capabilities |= GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON;
D3D11_FEATURE_DATA_FORMAT_SUPPORT2 FormatSupport = {};
FormatSupport.InFormat = DXGI_FORMAT_R11G11B10_FLOAT;
hr = device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &FormatSupport, sizeof(FormatSupport));
if (SUCCEEDED(hr) && (FormatSupport.OutFormatSupport2 & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD) != 0)
{
capabilities |= GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT;
}
}
D3D11_FEATURE_DATA_D3D11_OPTIONS3 features_3;
hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &features_3, sizeof(features_3));
if (features_3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE)
{
capabilities |= GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS;
}
CreateBackBufferResources();
emptyresource = std::make_shared<EmptyResourceHandle>();
wiBackLog::post("Created GraphicsDevice_DX11");
}
void GraphicsDevice_DX11::CreateBackBufferResources()
{
HRESULT hr;
hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &backBuffer);
if (FAILED(hr)) {
wiHelper::messageBox("BackBuffer creation Failed!", "Error!");
wiPlatform::Exit();
}
hr = device->CreateRenderTargetView(backBuffer.Get(), nullptr, &renderTargetView);
if (FAILED(hr)) {
wiHelper::messageBox("Main Rendertarget creation Failed!", "Error!");
wiPlatform::Exit();
}
}
void GraphicsDevice_DX11::SetResolution(int width, int height)
{
if ((width != RESOLUTIONWIDTH || height != RESOLUTIONHEIGHT) && width > 0 && height > 0)
{
RESOLUTIONWIDTH = width;
RESOLUTIONHEIGHT = height;
backBuffer.Reset();
renderTargetView.Reset();
HRESULT hr = swapChain->ResizeBuffers(GetBackBufferCount(), width, height, _ConvertFormat(GetBackBufferFormat()), 0);
assert(SUCCEEDED(hr));
CreateBackBufferResources();
}
}
Texture GraphicsDevice_DX11::GetBackBuffer()
{
auto internal_state = std::make_shared<Texture_DX11>();
internal_state->resource = backBuffer;
Texture result;
result.internal_state = internal_state;
result.type = GPUResource::GPU_RESOURCE_TYPE::TEXTURE;
D3D11_TEXTURE2D_DESC desc;
backBuffer->GetDesc(&desc);
result.desc = _ConvertTextureDesc_Inv(&desc);
return result;
}
bool GraphicsDevice_DX11::CreateBuffer(const GPUBufferDesc *pDesc, const SubresourceData* pInitialData, GPUBuffer *pBuffer)
{
auto internal_state = std::make_shared<Resource_DX11>();
pBuffer->internal_state = internal_state;
pBuffer->type = GPUResource::GPU_RESOURCE_TYPE::BUFFER;
D3D11_BUFFER_DESC desc;
desc.ByteWidth = pDesc->ByteWidth;
desc.Usage = _ConvertUsage(pDesc->Usage);
desc.BindFlags = _ParseBindFlags(pDesc->BindFlags);
desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags);
desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags);
desc.StructureByteStride = pDesc->StructureByteStride;
D3D11_SUBRESOURCE_DATA data;
if (pInitialData != nullptr)
{
data = _ConvertSubresourceData(*pInitialData);
}
pBuffer->desc = *pDesc;
HRESULT hr = device->CreateBuffer(&desc, pInitialData == nullptr ? nullptr : &data, (ID3D11Buffer**)internal_state->resource.ReleaseAndGetAddressOf());
assert(SUCCEEDED(hr) && "GPUBuffer creation failed!");
if (SUCCEEDED(hr))
{
// Create resource views if needed
if (pDesc->BindFlags & BIND_SHADER_RESOURCE)
{
CreateSubresource(pBuffer, SRV, 0);
}
if (pDesc->BindFlags & BIND_UNORDERED_ACCESS)
{
CreateSubresource(pBuffer, UAV, 0);
}
}
return SUCCEEDED(hr);
}
bool GraphicsDevice_DX11::CreateTexture(const TextureDesc* pDesc, const SubresourceData *pInitialData, Texture *pTexture)
{
auto internal_state = std::make_shared<Texture_DX11>();
pTexture->internal_state = internal_state;
pTexture->type = GPUResource::GPU_RESOURCE_TYPE::TEXTURE;
pTexture->desc = *pDesc;
std::vector<D3D11_SUBRESOURCE_DATA> data;
if (pInitialData != nullptr)
{
uint32_t dataCount = pDesc->ArraySize * std::max(1u, pDesc->MipLevels);
data.resize(dataCount);
for (uint32_t slice = 0; slice < dataCount; ++slice)
{
data[slice] = _ConvertSubresourceData(pInitialData[slice]);
}
}
HRESULT hr = S_OK;
switch (pTexture->desc.type)
{
case TextureDesc::TEXTURE_1D:
{
D3D11_TEXTURE1D_DESC desc = _ConvertTextureDesc1D(&pTexture->desc);
hr = device->CreateTexture1D(&desc, data.data(), (ID3D11Texture1D**)internal_state->resource.ReleaseAndGetAddressOf());
}
break;
case TextureDesc::TEXTURE_2D:
{
D3D11_TEXTURE2D_DESC desc = _ConvertTextureDesc2D(&pTexture->desc);
hr = device->CreateTexture2D(&desc, data.data(), (ID3D11Texture2D**)internal_state->resource.ReleaseAndGetAddressOf());
}
break;
case TextureDesc::TEXTURE_3D:
{
D3D11_TEXTURE3D_DESC desc = _ConvertTextureDesc3D(&pTexture->desc);
hr = device->CreateTexture3D(&desc, data.data(), (ID3D11Texture3D**)internal_state->resource.ReleaseAndGetAddressOf());
}
break;
default:
assert(0);
break;
}
assert(SUCCEEDED(hr));
if (FAILED(hr))
return SUCCEEDED(hr);
if (pTexture->desc.MipLevels == 0)
{
pTexture->desc.MipLevels = (uint32_t)log2(std::max(pTexture->desc.Width, pTexture->desc.Height)) + 1;
}
if (pTexture->desc.BindFlags & BIND_RENDER_TARGET)
{
CreateSubresource(pTexture, RTV, 0, -1, 0, -1);
}
if (pTexture->desc.BindFlags & BIND_DEPTH_STENCIL)
{
CreateSubresource(pTexture, DSV, 0, -1, 0, -1);
}
if (pTexture->desc.BindFlags & BIND_SHADER_RESOURCE)
{
CreateSubresource(pTexture, SRV, 0, -1, 0, -1);
}
if (pTexture->desc.BindFlags & BIND_UNORDERED_ACCESS)
{
CreateSubresource(pTexture, UAV, 0, -1, 0, -1);
}
return SUCCEEDED(hr);
}
bool GraphicsDevice_DX11::CreateShader(SHADERSTAGE stage, const void *pShaderBytecode, size_t BytecodeLength, Shader *pShader)
{
pShader->code.resize(BytecodeLength);
std::memcpy(pShader->code.data(), pShaderBytecode, BytecodeLength);
pShader->stage = stage;
HRESULT hr = E_FAIL;
switch (stage)
{
case wiGraphics::VS:
{
auto internal_state = std::make_shared<VertexShader_DX11>();
pShader->internal_state = internal_state;
hr = device->CreateVertexShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource);
}
break;
case wiGraphics::HS:
{
auto internal_state = std::make_shared<HullShader_DX11>();
pShader->internal_state = internal_state;
hr = device->CreateHullShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource);
}
break;
case wiGraphics::DS:
{
auto internal_state = std::make_shared<DomainShader_DX11>();
pShader->internal_state = internal_state;
hr = device->CreateDomainShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource);
}
break;
case wiGraphics::GS:
{
auto internal_state = std::make_shared<GeometryShader_DX11>();
pShader->internal_state = internal_state;
hr = device->CreateGeometryShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource);
}
break;
case wiGraphics::PS:
{
auto internal_state = std::make_shared<PixelShader_DX11>();
pShader->internal_state = internal_state;
hr = device->CreatePixelShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource);
}
break;
case wiGraphics::CS:
{
auto internal_state = std::make_shared<ComputeShader_DX11>();
pShader->internal_state = internal_state;
hr = device->CreateComputeShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource);
}
break;
}
assert(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
bool GraphicsDevice_DX11::CreateSampler(const SamplerDesc *pSamplerDesc, Sampler *pSamplerState)
{
auto internal_state = std::make_shared<Sampler_DX11>();
pSamplerState->internal_state = internal_state;
D3D11_SAMPLER_DESC desc;
desc.Filter = _ConvertFilter(pSamplerDesc->Filter);
desc.AddressU = _ConvertTextureAddressMode(pSamplerDesc->AddressU);
desc.AddressV = _ConvertTextureAddressMode(pSamplerDesc->AddressV);
desc.AddressW = _ConvertTextureAddressMode(pSamplerDesc->AddressW);
desc.MipLODBias = pSamplerDesc->MipLODBias;
desc.MaxAnisotropy = pSamplerDesc->MaxAnisotropy;
desc.ComparisonFunc = _ConvertComparisonFunc(pSamplerDesc->ComparisonFunc);
desc.BorderColor[0] = pSamplerDesc->BorderColor[0];
desc.BorderColor[1] = pSamplerDesc->BorderColor[1];
desc.BorderColor[2] = pSamplerDesc->BorderColor[2];
desc.BorderColor[3] = pSamplerDesc->BorderColor[3];
desc.MinLOD = pSamplerDesc->MinLOD;
desc.MaxLOD = pSamplerDesc->MaxLOD;
pSamplerState->desc = *pSamplerDesc;
HRESULT hr = device->CreateSamplerState(&desc, &internal_state->resource);
assert(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
bool GraphicsDevice_DX11::CreateQuery(const GPUQueryDesc *pDesc, GPUQuery *pQuery)
{
auto internal_state = std::make_shared<Query_DX11>();
pQuery->internal_state = internal_state;
pQuery->desc = *pDesc;
D3D11_QUERY_DESC desc;
desc.MiscFlags = 0;
desc.Query = D3D11_QUERY_EVENT;
if (pDesc->Type == GPU_QUERY_TYPE_EVENT)
{
desc.Query = D3D11_QUERY_EVENT;
}
else if (pDesc->Type == GPU_QUERY_TYPE_OCCLUSION)
{
desc.Query = D3D11_QUERY_OCCLUSION;
}
else if (pDesc->Type == GPU_QUERY_TYPE_OCCLUSION_PREDICATE)
{
desc.Query = D3D11_QUERY_OCCLUSION_PREDICATE;
}
else if (pDesc->Type == GPU_QUERY_TYPE_TIMESTAMP)
{
desc.Query = D3D11_QUERY_TIMESTAMP;
}
else if (pDesc->Type == GPU_QUERY_TYPE_TIMESTAMP_DISJOINT)
{
desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
}
HRESULT hr = device->CreateQuery(&desc, &internal_state->resource);
return SUCCEEDED(hr);
}
bool GraphicsDevice_DX11::CreatePipelineState(const PipelineStateDesc* pDesc, PipelineState* pso)
{
auto internal_state = std::make_shared<PipelineState_DX11>();
pso->internal_state = internal_state;
pso->desc = *pDesc;
HRESULT hr;
if (pDesc->il != nullptr)
{
std::vector<D3D11_INPUT_ELEMENT_DESC> desc(pDesc->il->elements.size());
for (size_t i = 0; i < desc.size(); ++i)
{
desc[i].SemanticName = pDesc->il->elements[i].SemanticName.c_str();
desc[i].SemanticIndex = pDesc->il->elements[i].SemanticIndex;
desc[i].Format = _ConvertFormat(pDesc->il->elements[i].Format);
desc[i].InputSlot = pDesc->il->elements[i].InputSlot;
desc[i].AlignedByteOffset = pDesc->il->elements[i].AlignedByteOffset;
if (desc[i].AlignedByteOffset == InputLayout::APPEND_ALIGNED_ELEMENT)
desc[i].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
desc[i].InputSlotClass = _ConvertInputClassification(pDesc->il->elements[i].InputSlotClass);
desc[i].InstanceDataStepRate = pDesc->il->elements[i].InstanceDataStepRate;
}
assert(pDesc->vs != nullptr);
hr = device->CreateInputLayout(desc.data(), (UINT)desc.size(), pDesc->vs->code.data(), pDesc->vs->code.size(), &internal_state->il);
assert(SUCCEEDED(hr));
}
if (pDesc->bs != nullptr)
{
D3D11_BLEND_DESC desc;
desc.AlphaToCoverageEnable = pDesc->bs->AlphaToCoverageEnable;
desc.IndependentBlendEnable = pDesc->bs->IndependentBlendEnable;
for (int i = 0; i < 8; ++i)
{
desc.RenderTarget[i].BlendEnable = pDesc->bs->RenderTarget[i].BlendEnable;
desc.RenderTarget[i].SrcBlend = _ConvertBlend(pDesc->bs->RenderTarget[i].SrcBlend);
desc.RenderTarget[i].DestBlend = _ConvertBlend(pDesc->bs->RenderTarget[i].DestBlend);
desc.RenderTarget[i].BlendOp = _ConvertBlendOp(pDesc->bs->RenderTarget[i].BlendOp);
desc.RenderTarget[i].SrcBlendAlpha = _ConvertBlend(pDesc->bs->RenderTarget[i].SrcBlendAlpha);
desc.RenderTarget[i].DestBlendAlpha = _ConvertBlend(pDesc->bs->RenderTarget[i].DestBlendAlpha);
desc.RenderTarget[i].BlendOpAlpha = _ConvertBlendOp(pDesc->bs->RenderTarget[i].BlendOpAlpha);
desc.RenderTarget[i].RenderTargetWriteMask = _ParseColorWriteMask(pDesc->bs->RenderTarget[i].RenderTargetWriteMask);
}
hr = device->CreateBlendState(&desc, &internal_state->bs);
assert(SUCCEEDED(hr));
}
if (pDesc->dss != nullptr)
{
D3D11_DEPTH_STENCIL_DESC desc;
desc.DepthEnable = pDesc->dss->DepthEnable;
desc.DepthWriteMask = _ConvertDepthWriteMask(pDesc->dss->DepthWriteMask);
desc.DepthFunc = _ConvertComparisonFunc(pDesc->dss->DepthFunc);
desc.StencilEnable = pDesc->dss->StencilEnable;
desc.StencilReadMask = pDesc->dss->StencilReadMask;
desc.StencilWriteMask = pDesc->dss->StencilWriteMask;
desc.FrontFace.StencilDepthFailOp = _ConvertStencilOp(pDesc->dss->FrontFace.StencilDepthFailOp);
desc.FrontFace.StencilFailOp = _ConvertStencilOp(pDesc->dss->FrontFace.StencilFailOp);
desc.FrontFace.StencilFunc = _ConvertComparisonFunc(pDesc->dss->FrontFace.StencilFunc);
desc.FrontFace.StencilPassOp = _ConvertStencilOp(pDesc->dss->FrontFace.StencilPassOp);
desc.BackFace.StencilDepthFailOp = _ConvertStencilOp(pDesc->dss->BackFace.StencilDepthFailOp);
desc.BackFace.StencilFailOp = _ConvertStencilOp(pDesc->dss->BackFace.StencilFailOp);
desc.BackFace.StencilFunc = _ConvertComparisonFunc(pDesc->dss->BackFace.StencilFunc);
desc.BackFace.StencilPassOp = _ConvertStencilOp(pDesc->dss->BackFace.StencilPassOp);
hr = device->CreateDepthStencilState(&desc, &internal_state->dss);
assert(SUCCEEDED(hr));
}
if (pDesc->rs != nullptr)
{
D3D11_RASTERIZER_DESC desc;
desc.FillMode = _ConvertFillMode(pDesc->rs->FillMode);
desc.CullMode = _ConvertCullMode(pDesc->rs->CullMode);
desc.FrontCounterClockwise = pDesc->rs->FrontCounterClockwise;
desc.DepthBias = pDesc->rs->DepthBias;
desc.DepthBiasClamp = pDesc->rs->DepthBiasClamp;
desc.SlopeScaledDepthBias = pDesc->rs->SlopeScaledDepthBias;
desc.DepthClipEnable = pDesc->rs->DepthClipEnable;
desc.ScissorEnable = true;
desc.MultisampleEnable = pDesc->rs->MultisampleEnable;
desc.AntialiasedLineEnable = pDesc->rs->AntialiasedLineEnable;
if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION) && pDesc->rs->ConservativeRasterizationEnable == TRUE)
{
ComPtr<ID3D11Device3> device3;
if (SUCCEEDED(device.As(&device3)))
{
D3D11_RASTERIZER_DESC2 desc2;
desc2.FillMode = desc.FillMode;
desc2.CullMode = desc.CullMode;
desc2.FrontCounterClockwise = desc.FrontCounterClockwise;
desc2.DepthBias = desc.DepthBias;
desc2.DepthBiasClamp = desc.DepthBiasClamp;
desc2.SlopeScaledDepthBias = desc.SlopeScaledDepthBias;
desc2.DepthClipEnable = desc.DepthClipEnable;
desc2.ScissorEnable = desc.ScissorEnable;
desc2.MultisampleEnable = desc.MultisampleEnable;
desc2.AntialiasedLineEnable = desc.AntialiasedLineEnable;
desc2.ConservativeRaster = D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON;
desc2.ForcedSampleCount = pDesc->rs->ForcedSampleCount;
ComPtr<ID3D11RasterizerState2> rasterizer2;
hr = device3->CreateRasterizerState2(&desc2, &rasterizer2);
assert(SUCCEEDED(hr));
internal_state->rs = rasterizer2;
}
}
else if (pDesc->rs->ForcedSampleCount > 0)
{
ComPtr<ID3D11Device1> device1;
if (SUCCEEDED(device.As(&device1)))
{
D3D11_RASTERIZER_DESC1 desc1;
desc1.FillMode = desc.FillMode;
desc1.CullMode = desc.CullMode;
desc1.FrontCounterClockwise = desc.FrontCounterClockwise;
desc1.DepthBias = desc.DepthBias;
desc1.DepthBiasClamp = desc.DepthBiasClamp;
desc1.SlopeScaledDepthBias = desc.SlopeScaledDepthBias;
desc1.DepthClipEnable = desc.DepthClipEnable;
desc1.ScissorEnable = desc.ScissorEnable;
desc1.MultisampleEnable = desc.MultisampleEnable;
desc1.AntialiasedLineEnable = desc.AntialiasedLineEnable;
desc1.ForcedSampleCount = pDesc->rs->ForcedSampleCount;
ComPtr<ID3D11RasterizerState1> rasterizer1;
hr = device1->CreateRasterizerState1(&desc1, &rasterizer1);
assert(SUCCEEDED(hr));
internal_state->rs = rasterizer1;
}
}
hr = device->CreateRasterizerState(&desc, &internal_state->rs);
assert(SUCCEEDED(hr));
}
return true;
}
bool GraphicsDevice_DX11::CreateRenderPass(const RenderPassDesc* pDesc, RenderPass* renderpass)
{
renderpass->internal_state = emptyresource;
renderpass->desc = *pDesc;
return true;
}
int GraphicsDevice_DX11::CreateSubresource(Texture* texture, SUBRESOURCE_TYPE type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount)
{
auto internal_state = to_internal(texture);
switch (type)
{
case wiGraphics::SRV:
{
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {};
// Try to resolve resource format:
switch (texture->desc.Format)
{
case FORMAT_R16_TYPELESS:
srv_desc.Format = DXGI_FORMAT_R16_UNORM;
break;
case FORMAT_R32_TYPELESS:
srv_desc.Format = DXGI_FORMAT_R32_FLOAT;
break;
case FORMAT_R24G8_TYPELESS:
srv_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
break;
case FORMAT_R32G8X24_TYPELESS:
srv_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
break;
default:
srv_desc.Format = _ConvertFormat(texture->desc.Format);
break;
}
if (texture->desc.type == TextureDesc::TEXTURE_1D)
{
if (texture->desc.ArraySize > 1)
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
srv_desc.Texture1DArray.FirstArraySlice = firstSlice;
srv_desc.Texture1DArray.ArraySize = sliceCount;
srv_desc.Texture1DArray.MostDetailedMip = firstMip;
srv_desc.Texture1DArray.MipLevels = mipCount;
}
else
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
srv_desc.Texture1D.MostDetailedMip = firstMip;
srv_desc.Texture1D.MipLevels = mipCount;
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_2D)
{
if (texture->desc.ArraySize > 1)
{
if (texture->desc.MiscFlags & RESOURCE_MISC_TEXTURECUBE)
{
if (texture->desc.ArraySize > 6)
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
srv_desc.TextureCubeArray.First2DArrayFace = firstSlice;
srv_desc.TextureCubeArray.NumCubes = std::min(texture->desc.ArraySize, sliceCount) / 6;
srv_desc.TextureCubeArray.MostDetailedMip = firstMip;
srv_desc.TextureCubeArray.MipLevels = mipCount;
}
else
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
srv_desc.TextureCube.MostDetailedMip = firstMip;
srv_desc.TextureCube.MipLevels = mipCount;
}
}
else
{
if (texture->desc.SampleCount > 1)
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
srv_desc.Texture2DMSArray.FirstArraySlice = firstSlice;
srv_desc.Texture2DMSArray.ArraySize = sliceCount;
}
else
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srv_desc.Texture2DArray.FirstArraySlice = firstSlice;
srv_desc.Texture2DArray.ArraySize = sliceCount;
srv_desc.Texture2DArray.MostDetailedMip = firstMip;
srv_desc.Texture2DArray.MipLevels = mipCount;
}
}
}
else
{
if (texture->desc.SampleCount > 1)
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
}
else
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MostDetailedMip = firstMip;
srv_desc.Texture2D.MipLevels = mipCount;
}
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_3D)
{
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
srv_desc.Texture3D.MostDetailedMip = firstMip;
srv_desc.Texture3D.MipLevels = mipCount;
}
ComPtr<ID3D11ShaderResourceView> srv;
HRESULT hr = device->CreateShaderResourceView(internal_state->resource.Get(), &srv_desc, &srv);
if (SUCCEEDED(hr))
{
if (!internal_state->srv)
{
internal_state->srv = srv;
return -1;
}
internal_state->subresources_srv.push_back(srv);
return int(internal_state->subresources_srv.size() - 1);
}
else
{
assert(0);
}
}
break;
case wiGraphics::UAV:
{
D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = {};
// Try to resolve resource format:
switch (texture->desc.Format)
{
case FORMAT_R16_TYPELESS:
uav_desc.Format = DXGI_FORMAT_R16_UNORM;
break;
case FORMAT_R32_TYPELESS:
uav_desc.Format = DXGI_FORMAT_R32_FLOAT;
break;
case FORMAT_R24G8_TYPELESS:
uav_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
break;
case FORMAT_R32G8X24_TYPELESS:
uav_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
break;
default:
uav_desc.Format = _ConvertFormat(texture->desc.Format);
break;
}
if (texture->desc.type == TextureDesc::TEXTURE_1D)
{
if (texture->desc.ArraySize > 1)
{
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY;
uav_desc.Texture1DArray.FirstArraySlice = firstSlice;
uav_desc.Texture1DArray.ArraySize = sliceCount;
uav_desc.Texture1DArray.MipSlice = firstMip;
}
else
{
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
uav_desc.Texture1D.MipSlice = firstMip;
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_2D)
{
if (texture->desc.ArraySize > 1)
{
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
uav_desc.Texture2DArray.FirstArraySlice = firstSlice;
uav_desc.Texture2DArray.ArraySize = sliceCount;
uav_desc.Texture2DArray.MipSlice = firstMip;
}
else
{
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
uav_desc.Texture2D.MipSlice = firstMip;
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_3D)
{
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
uav_desc.Texture3D.MipSlice = firstMip;
uav_desc.Texture3D.FirstWSlice = 0;
uav_desc.Texture3D.WSize = -1;
}
ComPtr<ID3D11UnorderedAccessView> uav;
HRESULT hr = device->CreateUnorderedAccessView(internal_state->resource.Get(), &uav_desc, &uav);
if (SUCCEEDED(hr))
{
if (!internal_state->uav)
{
internal_state->uav = uav;
return -1;
}
internal_state->subresources_uav.push_back(uav);
return int(internal_state->subresources_uav.size() - 1);
}
else
{
assert(0);
}
}
break;
case wiGraphics::RTV:
{
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {};
// Try to resolve resource format:
switch (texture->desc.Format)
{
case FORMAT_R16_TYPELESS:
rtv_desc.Format = DXGI_FORMAT_R16_UNORM;
break;
case FORMAT_R32_TYPELESS:
rtv_desc.Format = DXGI_FORMAT_R32_FLOAT;
break;
case FORMAT_R24G8_TYPELESS:
rtv_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
break;
case FORMAT_R32G8X24_TYPELESS:
rtv_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
break;
default:
rtv_desc.Format = _ConvertFormat(texture->desc.Format);
break;
}
if (texture->desc.type == TextureDesc::TEXTURE_1D)
{
if (texture->desc.ArraySize > 1)
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
rtv_desc.Texture1DArray.FirstArraySlice = firstSlice;
rtv_desc.Texture1DArray.ArraySize = sliceCount;
rtv_desc.Texture1DArray.MipSlice = firstMip;
}
else
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
rtv_desc.Texture1D.MipSlice = firstMip;
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_2D)
{
if (texture->desc.ArraySize > 1)
{
if (texture->desc.SampleCount > 1)
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtv_desc.Texture2DMSArray.FirstArraySlice = firstSlice;
rtv_desc.Texture2DMSArray.ArraySize = sliceCount;
}
else
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtv_desc.Texture2DArray.FirstArraySlice = firstSlice;
rtv_desc.Texture2DArray.ArraySize = sliceCount;
rtv_desc.Texture2DArray.MipSlice = firstMip;
}
}
else
{
if (texture->desc.SampleCount > 1)
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
}
else
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtv_desc.Texture2D.MipSlice = firstMip;
}
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_3D)
{
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtv_desc.Texture3D.MipSlice = firstMip;
rtv_desc.Texture3D.FirstWSlice = 0;
rtv_desc.Texture3D.WSize = -1;
}
ComPtr<ID3D11RenderTargetView> rtv;
HRESULT hr = device->CreateRenderTargetView(internal_state->resource.Get(), &rtv_desc, &rtv);
if (SUCCEEDED(hr))
{
if (!internal_state->rtv)
{
internal_state->rtv = rtv;
return -1;
}
internal_state->subresources_rtv.push_back(rtv);
return int(internal_state->subresources_rtv.size() - 1);
}
else
{
assert(0);
}
}
break;
case wiGraphics::DSV:
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {};
// Try to resolve resource format:
switch (texture->desc.Format)
{
case FORMAT_R16_TYPELESS:
dsv_desc.Format = DXGI_FORMAT_D16_UNORM;
break;
case FORMAT_R32_TYPELESS:
dsv_desc.Format = DXGI_FORMAT_D32_FLOAT;
break;
case FORMAT_R24G8_TYPELESS:
dsv_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
break;
case FORMAT_R32G8X24_TYPELESS:
dsv_desc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
break;
default:
dsv_desc.Format = _ConvertFormat(texture->desc.Format);
break;
}
if (texture->desc.type == TextureDesc::TEXTURE_1D)
{
if (texture->desc.ArraySize > 1)
{
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
dsv_desc.Texture1DArray.FirstArraySlice = firstSlice;
dsv_desc.Texture1DArray.ArraySize = sliceCount;
dsv_desc.Texture1DArray.MipSlice = firstMip;
}
else
{
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
dsv_desc.Texture1D.MipSlice = firstMip;
}
}
else if (texture->desc.type == TextureDesc::TEXTURE_2D)
{
if (texture->desc.ArraySize > 1)
{
if (texture->desc.SampleCount > 1)
{
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
dsv_desc.Texture2DMSArray.FirstArraySlice = firstSlice;
dsv_desc.Texture2DMSArray.ArraySize = sliceCount;
}
else
{
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
dsv_desc.Texture2DArray.FirstArraySlice = firstSlice;
dsv_desc.Texture2DArray.ArraySize = sliceCount;
dsv_desc.Texture2DArray.MipSlice = firstMip;
}
}
else
{
if (texture->desc.SampleCount > 1)
{
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
}
else
{
dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
dsv_desc.Texture2D.MipSlice = firstMip;
}
}
}
ComPtr<ID3D11DepthStencilView> dsv;
HRESULT hr = device->CreateDepthStencilView(internal_state->resource.Get(), &dsv_desc, &dsv);
if (SUCCEEDED(hr))
{
if (!internal_state->dsv)
{
internal_state->dsv = dsv;
return -1;
}
internal_state->subresources_dsv.push_back(dsv);
return int(internal_state->subresources_dsv.size() - 1);
}
else
{
assert(0);
}
}
break;
default:
break;
}
return -1;
}
int GraphicsDevice_DX11::CreateSubresource(GPUBuffer* buffer, SUBRESOURCE_TYPE type, uint64_t offset, uint64_t size)
{
auto internal_state = to_internal(buffer);
const GPUBufferDesc& desc = buffer->GetDesc();
HRESULT hr = E_FAIL;
switch (type)
{
case wiGraphics::SRV:
{
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {};
if (desc.MiscFlags & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
{
// This is a Raw Buffer
srv_desc.Format = DXGI_FORMAT_R32_TYPELESS;
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
srv_desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
srv_desc.BufferEx.FirstElement = (UINT)offset / sizeof(uint32_t);
srv_desc.BufferEx.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / sizeof(uint32_t);
}
else if (desc.MiscFlags & RESOURCE_MISC_BUFFER_STRUCTURED)
{
// This is a Structured Buffer
srv_desc.Format = DXGI_FORMAT_UNKNOWN;
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
srv_desc.BufferEx.FirstElement = (UINT)offset / desc.StructureByteStride;
srv_desc.BufferEx.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / desc.StructureByteStride;
}
else
{
// This is a Typed Buffer
uint32_t stride = GetFormatStride(desc.Format);
srv_desc.Format = _ConvertFormat(desc.Format);
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srv_desc.Buffer.FirstElement = (UINT)offset / stride;
srv_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / stride;
}
ComPtr<ID3D11ShaderResourceView> srv;
hr = device->CreateShaderResourceView(internal_state->resource.Get(), &srv_desc, &srv);
if (SUCCEEDED(hr))
{
if (internal_state->srv == nullptr)
{
internal_state->srv = srv;
return -1;
}
else
{
internal_state->subresources_srv.push_back(srv);
return int(internal_state->subresources_srv.size() - 1);
}
}
else
{
assert(0);
}
}
break;
case wiGraphics::UAV:
{
D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = {};
uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
if (desc.MiscFlags & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
{
// This is a Raw Buffer
uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; // Format must be DXGI_FORMAT_R32_TYPELESS, when creating Raw Unordered Access View
uav_desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
uav_desc.Buffer.FirstElement = (UINT)offset / sizeof(uint32_t);
uav_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / sizeof(uint32_t);
}
else if (desc.MiscFlags & RESOURCE_MISC_BUFFER_STRUCTURED)
{
// This is a Structured Buffer
uav_desc.Format = DXGI_FORMAT_UNKNOWN; // Format must be must be DXGI_FORMAT_UNKNOWN, when creating a View of a Structured Buffer
uav_desc.Buffer.FirstElement = (UINT)offset / desc.StructureByteStride;
uav_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / desc.StructureByteStride;
}
else
{
// This is a Typed Buffer
uint32_t stride = GetFormatStride(desc.Format);
uav_desc.Format = _ConvertFormat(desc.Format);
uav_desc.Buffer.FirstElement = (UINT)offset / stride;
uav_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / stride;
}
ComPtr<ID3D11UnorderedAccessView> uav;
hr = device->CreateUnorderedAccessView(internal_state->resource.Get(), &uav_desc, &uav);
if (SUCCEEDED(hr))
{
if (internal_state->uav == nullptr)
{
internal_state->uav = uav;
return -1;
}
else
{
internal_state->subresources_uav.push_back(uav);
return int(internal_state->subresources_uav.size() - 1);
}
}
else
{
assert(0);
}
}
break;
default:
assert(0);
break;
}
return -1;
}
void GraphicsDevice_DX11::Map(const GPUResource* resource, Mapping* mapping)
{
auto internal_state = to_internal(resource);
D3D11_MAPPED_SUBRESOURCE map_result = {};
D3D11_MAP map_type = D3D11_MAP_READ_WRITE;
if (mapping->_flags & Mapping::FLAG_READ)
{
if (mapping->_flags & Mapping::FLAG_WRITE)
{
map_type = D3D11_MAP_READ_WRITE;
}
else
{
map_type = D3D11_MAP_READ;
}
}
else if (mapping->_flags & Mapping::FLAG_WRITE)
{
map_type = D3D11_MAP_WRITE_NO_OVERWRITE;
}
HRESULT hr = immediateContext->Map(internal_state->resource.Get(), 0, map_type, D3D11_MAP_FLAG_DO_NOT_WAIT, &map_result);
if (SUCCEEDED(hr))
{
mapping->data = map_result.pData;
mapping->rowpitch = map_result.RowPitch;
}
else
{
assert(0);
mapping->data = nullptr;
mapping->rowpitch = 0;
}
}
void GraphicsDevice_DX11::Unmap(const GPUResource* resource)
{
auto internal_state = to_internal(resource);
immediateContext->Unmap(internal_state->resource.Get(), 0);
}
bool GraphicsDevice_DX11::QueryRead(const GPUQuery* query, GPUQueryResult* result)
{
const uint32_t _flags = D3D11_ASYNC_GETDATA_DONOTFLUSH;
auto internal_state = to_internal(query);
if (internal_state->resource == nullptr)
return false;
ID3D11Query* QUERY = internal_state->resource.Get();
HRESULT hr = S_OK;
switch (query->desc.Type)
{
case GPU_QUERY_TYPE_TIMESTAMP:
hr = immediateContext->GetData(QUERY, &result->result_timestamp, sizeof(uint64_t), _flags);
break;
case GPU_QUERY_TYPE_TIMESTAMP_DISJOINT:
{
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT _temp;
hr = immediateContext->GetData(QUERY, &_temp, sizeof(_temp), _flags);
result->result_timestamp_frequency = _temp.Frequency;
}
break;
case GPU_QUERY_TYPE_EVENT:
case GPU_QUERY_TYPE_OCCLUSION:
hr = immediateContext->GetData(QUERY, &result->result_passed_sample_count, sizeof(uint64_t), _flags);
break;
case GPU_QUERY_TYPE_OCCLUSION_PREDICATE:
{
BOOL passed = FALSE;
hr = immediateContext->GetData(QUERY, &passed, sizeof(BOOL), _flags);
result->result_passed_sample_count = (uint64_t)passed;
break;
}
}
return hr != S_FALSE;
}
void GraphicsDevice_DX11::SetName(GPUResource* pResource, const char* name)
{
auto internal_state = to_internal(pResource);
internal_state->resource->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(name), name);
}
void GraphicsDevice_DX11::PresentBegin(CommandList cmd)
{
ID3D11RenderTargetView* RTV = renderTargetView.Get();
deviceContexts[cmd]->OMSetRenderTargets(1, &RTV, 0);
float ClearColor[4] = { 0, 0, 0, 1.0f }; // red,green,blue,alpha
deviceContexts[cmd]->ClearRenderTargetView(RTV, ClearColor);
}
void GraphicsDevice_DX11::PresentEnd(CommandList cmd)
{
SubmitCommandLists();
swapChain->Present(VSYNC, 0);
}
CommandList GraphicsDevice_DX11::BeginCommandList()
{
CommandList cmd = cmd_count.fetch_add(1);
if (deviceContexts[cmd] == nullptr)
{
// need to create one more command list:
assert(cmd < COMMANDLIST_COUNT);
HRESULT hr = device->CreateDeferredContext(0, &deviceContexts[cmd]);
assert(SUCCEEDED(hr));
hr = deviceContexts[cmd].As(&userDefinedAnnotations[cmd]);
assert(SUCCEEDED(hr));
// Temporary allocations will use the following buffer type:
GPUBufferDesc frameAllocatorDesc;
frameAllocatorDesc.ByteWidth = 1024 * 1024; // 1 MB starting size
frameAllocatorDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_INDEX_BUFFER | BIND_VERTEX_BUFFER;
frameAllocatorDesc.Usage = USAGE_DYNAMIC;
frameAllocatorDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
frameAllocatorDesc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
bool success = CreateBuffer(&frameAllocatorDesc, nullptr, &frame_allocators[cmd].buffer);
assert(success);
SetName(&frame_allocators[cmd].buffer, "frame_allocator");
}
BindPipelineState(nullptr, cmd);
BindComputeShader(nullptr, cmd);
D3D11_VIEWPORT vp = {};
vp.Width = (float)RESOLUTIONWIDTH;
vp.Height = (float)RESOLUTIONHEIGHT;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
deviceContexts[cmd]->RSSetViewports(1, &vp);
D3D11_RECT pRects[8];
for (uint32_t i = 0; i < 8; ++i)
{
pRects[i].bottom = INT32_MAX;
pRects[i].left = INT32_MIN;
pRects[i].right = INT32_MAX;
pRects[i].top = INT32_MIN;
}
deviceContexts[cmd]->RSSetScissorRects(8, pRects);
stencilRef[cmd] = 0;
blendFactor[cmd] = XMFLOAT4(1, 1, 1, 1);
prev_vs[cmd] = {};
prev_ps[cmd] = {};
prev_hs[cmd] = {};
prev_ds[cmd] = {};
prev_gs[cmd] = {};
prev_cs[cmd] = {};
prev_blendfactor[cmd] = {};
prev_samplemask[cmd] = {};
prev_bs[cmd] = {};
prev_rs[cmd] = {};
prev_stencilRef[cmd] = {};
prev_dss[cmd] = {};
prev_il[cmd] = {};
prev_pt[cmd] = {};
memset(raster_uavs[cmd], 0, sizeof(raster_uavs[cmd]));
raster_uavs_slot[cmd] = {};
raster_uavs_count[cmd] = {};
active_pso[cmd] = nullptr;
dirty_pso[cmd] = false;
active_renderpass[cmd] = nullptr;
return cmd;
}
void GraphicsDevice_DX11::SubmitCommandLists()
{
// Execute deferred command lists:
CommandList cmd_last = cmd_count.load();
cmd_count.store(0);
for (CommandList cmd = 0; cmd < cmd_last; ++cmd)
{
deviceContexts[cmd]->FinishCommandList(false, &commandLists[cmd]);
immediateContext->ExecuteCommandList(commandLists[cmd].Get(), false);
commandLists[cmd].Reset();
}
immediateContext->ClearState();
FRAMECOUNT++;
}
void GraphicsDevice_DX11::WaitForGPU()
{
immediateContext->Flush();
GPUQuery query;
GPUQueryDesc desc;
desc.Type = GPU_QUERY_TYPE_EVENT;
bool success = CreateQuery(&desc, &query);
assert(success);
auto internal_state = to_internal(&query);
immediateContext->End(internal_state->resource.Get());
BOOL result;
while (immediateContext->GetData(internal_state->resource.Get(), &result, sizeof(result), 0) == S_FALSE);
assert(result == TRUE);
}
void GraphicsDevice_DX11::commit_allocations(CommandList cmd)
{
// DX11 needs to unmap allocations before it can execute safely
if (frame_allocators[cmd].dirty)
{
auto internal_state = to_internal(&frame_allocators[cmd].buffer);
deviceContexts[cmd]->Unmap(internal_state->resource.Get(), 0);
frame_allocators[cmd].dirty = false;
}
}
void GraphicsDevice_DX11::RenderPassBegin(const RenderPass* renderpass, CommandList cmd)
{
active_renderpass[cmd] = renderpass;
const RenderPassDesc& desc = renderpass->GetDesc();
uint32_t rt_count = 0;
ID3D11RenderTargetView* RTVs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
ID3D11DepthStencilView* DSV = nullptr;
for (auto& attachment : desc.attachments)
{
const Texture* texture = attachment.texture;
int subresource = attachment.subresource;
auto internal_state = to_internal(texture);
if (attachment.type == RenderPassAttachment::RENDERTARGET)
{
if (subresource < 0 || internal_state->subresources_rtv.empty())
{
RTVs[rt_count] = internal_state->rtv.Get();
}
else
{
assert(internal_state->subresources_rtv.size() > size_t(subresource) && "Invalid RTV subresource!");
RTVs[rt_count] = internal_state->subresources_rtv[subresource].Get();
}
if (attachment.loadop == RenderPassAttachment::LOADOP_CLEAR)
{
deviceContexts[cmd]->ClearRenderTargetView(RTVs[rt_count], texture->desc.clear.color);
}
rt_count++;
}
else if (attachment.type == RenderPassAttachment::DEPTH_STENCIL)
{
if (subresource < 0 || internal_state->subresources_dsv.empty())
{
DSV = internal_state->dsv.Get();
}
else
{
assert(internal_state->subresources_dsv.size() > size_t(subresource) && "Invalid DSV subresource!");
DSV = internal_state->subresources_dsv[subresource].Get();
}
if (attachment.loadop == RenderPassAttachment::LOADOP_CLEAR)
{
uint32_t _flags = D3D11_CLEAR_DEPTH;
if (IsFormatStencilSupport(texture->desc.Format))
_flags |= D3D11_CLEAR_STENCIL;
deviceContexts[cmd]->ClearDepthStencilView(DSV, _flags, texture->desc.clear.depthstencil.depth, texture->desc.clear.depthstencil.stencil);
}
}
}
if (raster_uavs_count[cmd] > 0)
{
// UAVs:
const uint32_t count = raster_uavs_count[cmd];
const uint32_t slot = raster_uavs_slot[cmd];
deviceContexts[cmd]->OMSetRenderTargetsAndUnorderedAccessViews(rt_count, RTVs, DSV, slot, count, &raster_uavs[cmd][slot], nullptr);
raster_uavs_count[cmd] = 0;
raster_uavs_slot[cmd] = 8;
}
else
{
deviceContexts[cmd]->OMSetRenderTargets(rt_count, RTVs, DSV);
}
}
void GraphicsDevice_DX11::RenderPassEnd(CommandList cmd)
{
deviceContexts[cmd]->OMSetRenderTargets(0, nullptr, nullptr);
// Perform resolves:
int dst_counter = 0;
for (auto& attachment : active_renderpass[cmd]->desc.attachments)
{
if (attachment.type == RenderPassAttachment::RESOLVE)
{
if (attachment.texture != nullptr)
{
auto dst_internal = to_internal(attachment.texture);
int src_counter = 0;
for (auto& src : active_renderpass[cmd]->desc.attachments)
{
if (src.type == RenderPassAttachment::RENDERTARGET && src.texture != nullptr)
{
if (src_counter == dst_counter)
{
auto src_internal = to_internal(src.texture);
deviceContexts[cmd]->ResolveSubresource(dst_internal->resource.Get(), 0, src_internal->resource.Get(), 0, _ConvertFormat(attachment.texture->desc.Format));
break;
}
src_counter++;
}
}
}
dst_counter++;
}
}
active_renderpass[cmd] = nullptr;
}
void GraphicsDevice_DX11::BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) {
assert(rects != nullptr);
assert(numRects <= 8);
D3D11_RECT pRects[8];
for(uint32_t i = 0; i < numRects; ++i) {
pRects[i].bottom = (LONG)rects[i].bottom;
pRects[i].left = (LONG)rects[i].left;
pRects[i].right = (LONG)rects[i].right;
pRects[i].top = (LONG)rects[i].top;
}
deviceContexts[cmd]->RSSetScissorRects(numRects, pRects);
}
void GraphicsDevice_DX11::BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd)
{
assert(NumViewports <= 6);
D3D11_VIEWPORT d3dViewPorts[6];
for (uint32_t i = 0; i < NumViewports; ++i)
{
d3dViewPorts[i].TopLeftX = pViewports[i].TopLeftX;
d3dViewPorts[i].TopLeftY = pViewports[i].TopLeftY;
d3dViewPorts[i].Width = pViewports[i].Width;
d3dViewPorts[i].Height = pViewports[i].Height;
d3dViewPorts[i].MinDepth = pViewports[i].MinDepth;
d3dViewPorts[i].MaxDepth = pViewports[i].MaxDepth;
}
deviceContexts[cmd]->RSSetViewports(NumViewports, d3dViewPorts);
}
void GraphicsDevice_DX11::BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource)
{
if (resource != nullptr && resource->IsValid())
{
auto internal_state = to_internal(resource);
ID3D11ShaderResourceView* SRV;
if (subresource < 0)
{
SRV = internal_state->srv.Get();
}
else
{
assert(internal_state->subresources_srv.size() > static_cast<size_t>(subresource) && "Invalid subresource!");
SRV = internal_state->subresources_srv[subresource].Get();
}
switch (stage)
{
case wiGraphics::VS:
deviceContexts[cmd]->VSSetShaderResources(slot, 1, &SRV);
break;
case wiGraphics::HS:
deviceContexts[cmd]->HSSetShaderResources(slot, 1, &SRV);
break;
case wiGraphics::DS:
deviceContexts[cmd]->DSSetShaderResources(slot, 1, &SRV);
break;
case wiGraphics::GS:
deviceContexts[cmd]->GSSetShaderResources(slot, 1, &SRV);
break;
case wiGraphics::PS:
deviceContexts[cmd]->PSSetShaderResources(slot, 1, &SRV);
break;
case wiGraphics::CS:
deviceContexts[cmd]->CSSetShaderResources(slot, 1, &SRV);
break;
default:
assert(0);
break;
}
}
}
void GraphicsDevice_DX11::BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd)
{
assert(count <= 16);
ID3D11ShaderResourceView* srvs[16];
for (uint32_t i = 0; i < count; ++i)
{
srvs[i] = resources[i] != nullptr && resources[i]->IsValid() ? to_internal(resources[i])->srv.Get() : nullptr;
}
switch (stage)
{
case wiGraphics::VS:
deviceContexts[cmd]->VSSetShaderResources(slot, count, srvs);
break;
case wiGraphics::HS:
deviceContexts[cmd]->HSSetShaderResources(slot, count, srvs);
break;
case wiGraphics::DS:
deviceContexts[cmd]->DSSetShaderResources(slot, count, srvs);
break;
case wiGraphics::GS:
deviceContexts[cmd]->GSSetShaderResources(slot, count, srvs);
break;
case wiGraphics::PS:
deviceContexts[cmd]->PSSetShaderResources(slot, count, srvs);
break;
case wiGraphics::CS:
deviceContexts[cmd]->CSSetShaderResources(slot, count, srvs);
break;
default:
assert(0);
break;
}
}
void GraphicsDevice_DX11::BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource)
{
if (resource != nullptr && resource->IsValid())
{
auto internal_state = to_internal(resource);
ID3D11UnorderedAccessView* UAV;
if (subresource < 0)
{
UAV = internal_state->uav.Get();
}
else
{
assert(internal_state->subresources_uav.size() > static_cast<size_t>(subresource) && "Invalid subresource!");
UAV = internal_state->subresources_uav[subresource].Get();
}
if (stage == CS)
{
deviceContexts[cmd]->CSSetUnorderedAccessViews(slot, 1, &UAV, nullptr);
}
else
{
raster_uavs[cmd][slot] = UAV;
raster_uavs_slot[cmd] = std::min(raster_uavs_slot[cmd], uint8_t(slot));
raster_uavs_count[cmd] = std::max(raster_uavs_count[cmd], uint8_t(1));
}
}
}
void GraphicsDevice_DX11::BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd)
{
assert(slot + count <= 8);
ID3D11UnorderedAccessView* uavs[8];
for (uint32_t i = 0; i < count; ++i)
{
uavs[i] = resources[i] != nullptr && resources[i]->IsValid() ? to_internal(resources[i])->uav.Get() : nullptr;
if(stage != CS)
{
raster_uavs[cmd][slot + i] = uavs[i];
}
}
if(stage == CS)
{
deviceContexts[cmd]->CSSetUnorderedAccessViews(static_cast<uint32_t>(slot), static_cast<uint32_t>(count), uavs, nullptr);
}
else
{
raster_uavs_slot[cmd] = std::min(raster_uavs_slot[cmd], uint8_t(slot));
raster_uavs_count[cmd] = std::max(raster_uavs_count[cmd], uint8_t(count));
}
}
void GraphicsDevice_DX11::UnbindResources(uint32_t slot, uint32_t num, CommandList cmd)
{
assert(num <= arraysize(__nullBlob) && "Extend nullBlob to support more resource unbinding!");
deviceContexts[cmd]->PSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob);
deviceContexts[cmd]->VSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob);
deviceContexts[cmd]->GSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob);
deviceContexts[cmd]->HSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob);
deviceContexts[cmd]->DSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob);
deviceContexts[cmd]->CSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob);
}
void GraphicsDevice_DX11::UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd)
{
assert(num <= arraysize(__nullBlob) && "Extend nullBlob to support more resource unbinding!");
deviceContexts[cmd]->CSSetUnorderedAccessViews(slot, num, (ID3D11UnorderedAccessView**)__nullBlob, 0);
raster_uavs_count[cmd] = 0;
raster_uavs_slot[cmd] = 8;
}
void GraphicsDevice_DX11::BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd)
{
if (sampler != nullptr && sampler->IsValid())
{
auto internal_state = to_internal(sampler);
ID3D11SamplerState* SAM = internal_state->resource.Get();
switch (stage)
{
case wiGraphics::VS:
deviceContexts[cmd]->VSSetSamplers(slot, 1, &SAM);
break;
case wiGraphics::HS:
deviceContexts[cmd]->HSSetSamplers(slot, 1, &SAM);
break;
case wiGraphics::DS:
deviceContexts[cmd]->DSSetSamplers(slot, 1, &SAM);
break;
case wiGraphics::GS:
deviceContexts[cmd]->GSSetSamplers(slot, 1, &SAM);
break;
case wiGraphics::PS:
deviceContexts[cmd]->PSSetSamplers(slot, 1, &SAM);
break;
case wiGraphics::CS:
deviceContexts[cmd]->CSSetSamplers(slot, 1, &SAM);
break;
case MS:
case AS:
break;
default:
assert(0);
break;
}
}
}
void GraphicsDevice_DX11::BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd)
{
ID3D11Buffer* res = buffer != nullptr && buffer->IsValid() ? (ID3D11Buffer*)to_internal(buffer)->resource.Get() : nullptr;
switch (stage)
{
case wiGraphics::VS:
deviceContexts[cmd]->VSSetConstantBuffers(slot, 1, &res);
break;
case wiGraphics::HS:
deviceContexts[cmd]->HSSetConstantBuffers(slot, 1, &res);
break;
case wiGraphics::DS:
deviceContexts[cmd]->DSSetConstantBuffers(slot, 1, &res);
break;
case wiGraphics::GS:
deviceContexts[cmd]->GSSetConstantBuffers(slot, 1, &res);
break;
case wiGraphics::PS:
deviceContexts[cmd]->PSSetConstantBuffers(slot, 1, &res);
break;
case wiGraphics::CS:
deviceContexts[cmd]->CSSetConstantBuffers(slot, 1, &res);
break;
case MS:
case AS:
break;
default:
assert(0);
break;
}
}
void GraphicsDevice_DX11::BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd)
{
assert(count <= 8);
ID3D11Buffer* res[8] = {};
for (uint32_t i = 0; i < count; ++i)
{
res[i] = vertexBuffers[i] != nullptr && vertexBuffers[i]->IsValid() ? (ID3D11Buffer*)to_internal(vertexBuffers[i])->resource.Get() : nullptr;
}
deviceContexts[cmd]->IASetVertexBuffers(slot, count, res, strides, (offsets != nullptr ? offsets : reinterpret_cast<const uint32_t*>(__nullBlob)));
}
void GraphicsDevice_DX11::BindIndexBuffer(const GPUBuffer* indexBuffer, const INDEXBUFFER_FORMAT format, uint32_t offset, CommandList cmd)
{
ID3D11Buffer* res = indexBuffer != nullptr && indexBuffer->IsValid() ? (ID3D11Buffer*)to_internal(indexBuffer)->resource.Get() : nullptr;
deviceContexts[cmd]->IASetIndexBuffer(res, (format == INDEXBUFFER_FORMAT::INDEXFORMAT_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT), offset);
}
void GraphicsDevice_DX11::BindStencilRef(uint32_t value, CommandList cmd)
{
stencilRef[cmd] = value;
}
void GraphicsDevice_DX11::BindBlendFactor(float r, float g, float b, float a, CommandList cmd)
{
blendFactor[cmd].x = r;
blendFactor[cmd].y = g;
blendFactor[cmd].z = b;
blendFactor[cmd].w = a;
}
void GraphicsDevice_DX11::BindPipelineState(const PipelineState* pso, CommandList cmd)
{
if (active_pso[cmd] == pso)
return;
active_pso[cmd] = pso;
dirty_pso[cmd] = true;
}
void GraphicsDevice_DX11::BindComputeShader(const Shader* cs, CommandList cmd)
{
ID3D11ComputeShader* _cs = cs == nullptr ? nullptr : static_cast<ComputeShader_DX11*>(cs->internal_state.get())->resource.Get();
if (_cs != prev_cs[cmd])
{
deviceContexts[cmd]->CSSetShader(_cs, nullptr, 0);
prev_cs[cmd] = _cs;
}
}
void GraphicsDevice_DX11::Draw(uint32_t vertexCount, uint32_t startVertexLocation, CommandList cmd)
{
pso_validate(cmd);
commit_allocations(cmd);
deviceContexts[cmd]->Draw(vertexCount, startVertexLocation);
}
void GraphicsDevice_DX11::DrawIndexed(uint32_t indexCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, CommandList cmd)
{
pso_validate(cmd);
commit_allocations(cmd);
deviceContexts[cmd]->DrawIndexed(indexCount, startIndexLocation, baseVertexLocation);
}
void GraphicsDevice_DX11::DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation, CommandList cmd)
{
pso_validate(cmd);
commit_allocations(cmd);
deviceContexts[cmd]->DrawInstanced(vertexCount, instanceCount, startVertexLocation, startInstanceLocation);
}
void GraphicsDevice_DX11::DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, uint32_t startInstanceLocation, CommandList cmd)
{
pso_validate(cmd);
commit_allocations(cmd);
deviceContexts[cmd]->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
}
void GraphicsDevice_DX11::DrawInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd)
{
pso_validate(cmd);
commit_allocations(cmd);
deviceContexts[cmd]->DrawInstancedIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset);
}
void GraphicsDevice_DX11::DrawIndexedInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd)
{
pso_validate(cmd);
commit_allocations(cmd);
deviceContexts[cmd]->DrawIndexedInstancedIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset);
}
void GraphicsDevice_DX11::Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd)
{
commit_allocations(cmd);
deviceContexts[cmd]->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
}
void GraphicsDevice_DX11::DispatchIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd)
{
commit_allocations(cmd);
deviceContexts[cmd]->DispatchIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset);
}
void GraphicsDevice_DX11::CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd)
{
assert(pDst != nullptr && pSrc != nullptr);
auto internal_state_src = to_internal(pSrc);
auto internal_state_dst = to_internal(pDst);
deviceContexts[cmd]->CopyResource(internal_state_dst->resource.Get(), internal_state_src->resource.Get());
}
void GraphicsDevice_DX11::UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize)
{
assert(buffer->desc.Usage != USAGE_IMMUTABLE && "Cannot update IMMUTABLE GPUBuffer!");
assert((int)buffer->desc.ByteWidth >= dataSize || dataSize < 0 && "Data size is too big!");
if (dataSize == 0)
{
return;
}
auto internal_state = to_internal(buffer);
dataSize = std::min((int)buffer->desc.ByteWidth, dataSize);
if (buffer->desc.Usage == USAGE_DYNAMIC)
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = deviceContexts[cmd]->Map(internal_state->resource.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
assert(SUCCEEDED(hr) && "GPUBuffer mapping failed!");
memcpy(mappedResource.pData, data, (dataSize >= 0 ? dataSize : buffer->desc.ByteWidth));
deviceContexts[cmd]->Unmap(internal_state->resource.Get(), 0);
}
else if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER || dataSize < 0)
{
deviceContexts[cmd]->UpdateSubresource(internal_state->resource.Get(), 0, nullptr, data, 0, 0);
}
else
{
D3D11_BOX box = {};
box.left = 0;
box.right = static_cast<uint32_t>(dataSize);
box.top = 0;
box.bottom = 1;
box.front = 0;
box.back = 1;
deviceContexts[cmd]->UpdateSubresource(internal_state->resource.Get(), 0, &box, data, 0, 0);
}
}
void GraphicsDevice_DX11::QueryBegin(const GPUQuery* query, CommandList cmd)
{
auto internal_state = to_internal(query);
if (internal_state->resource == nullptr)
return;
deviceContexts[cmd]->Begin(internal_state->resource.Get());
}
void GraphicsDevice_DX11::QueryEnd(const GPUQuery* query, CommandList cmd)
{
auto internal_state = to_internal(query);
if (internal_state->resource == nullptr)
return;
deviceContexts[cmd]->End(internal_state->resource.Get());
}
GraphicsDevice::GPUAllocation GraphicsDevice_DX11::AllocateGPU(size_t dataSize, CommandList cmd)
{
GPUAllocation result;
if (dataSize == 0)
{
return result;
}
GPUAllocator& allocator = frame_allocators[cmd];
if (allocator.buffer.desc.ByteWidth <= dataSize)
{
// If allocation too large, grow the allocator:
allocator.buffer.desc.ByteWidth = uint32_t((dataSize + 1) * 2);
bool success = CreateBuffer(&allocator.buffer.desc, nullptr, &allocator.buffer);
assert(success);
SetName(&allocator.buffer, "frame_allocator");
allocator.byteOffset = 0;
}
auto internal_state = to_internal(&allocator.buffer);
allocator.dirty = true;
size_t position = allocator.byteOffset;
bool wrap = position == 0 || position + dataSize > allocator.buffer.desc.ByteWidth || allocator.residentFrame != FRAMECOUNT;
position = wrap ? 0 : position;
// Issue buffer rename (realloc) on wrap, otherwise just append data:
D3D11_MAP mapping = wrap ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = deviceContexts[cmd]->Map(internal_state->resource.Get(), 0, mapping, 0, &mappedResource);
assert(SUCCEEDED(hr) && "GPUBuffer mapping failed!");
allocator.byteOffset = position + dataSize;
allocator.residentFrame = FRAMECOUNT;
result.buffer = &allocator.buffer;
result.offset = (uint32_t)position;
result.data = (void*)((size_t)mappedResource.pData + position);
return result;
}
void GraphicsDevice_DX11::EventBegin(const char* name, CommandList cmd)
{
wchar_t text[128];
if (wiHelper::StringConvert(name, text) > 0)
{
userDefinedAnnotations[cmd]->BeginEvent(text);
}
}
void GraphicsDevice_DX11::EventEnd(CommandList cmd)
{
userDefinedAnnotations[cmd]->EndEvent();
}
void GraphicsDevice_DX11::SetMarker(const char* name, CommandList cmd)
{
wchar_t text[128];
if (wiHelper::StringConvert(name, text) > 0)
{
userDefinedAnnotations[cmd]->SetMarker(text);
}
}
}
#endif // WICKEDENGINE_BUILD_DX11