1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 00:48:44 +01:00
dxvk/src/d3d11/d3d11_device.cpp

1399 lines
49 KiB
C++
Raw Normal View History

2017-10-11 09:51:48 +02:00
#include <cstring>
2017-10-15 21:38:09 +02:00
#include "d3d11_buffer.h"
#include "d3d11_class_linkage.h"
2017-10-11 09:51:48 +02:00
#include "d3d11_context.h"
#include "d3d11_device.h"
#include "d3d11_input_layout.h"
#include "d3d11_present.h"
2017-12-09 20:49:56 +01:00
#include "d3d11_sampler.h"
#include "d3d11_shader.h"
#include "d3d11_texture.h"
#include "d3d11_view.h"
2017-10-11 09:51:48 +02:00
namespace dxvk {
D3D11Device::D3D11Device(
2017-11-27 15:51:53 +01:00
IDXGIDevicePrivate* dxgiDevice,
2017-10-11 09:51:48 +02:00
D3D_FEATURE_LEVEL featureLevel,
UINT featureFlags)
: m_dxgiDevice (dxgiDevice),
2017-12-04 13:39:37 +01:00
m_presentDevice (new D3D11PresentDevice()),
m_featureLevel (featureLevel),
m_featureFlags (featureFlags),
m_dxvkDevice (m_dxgiDevice->GetDXVKDevice()),
m_dxvkAdapter (m_dxvkDevice->adapter()) {
Com<IDXGIAdapter> adapter;
if (FAILED(m_dxgiDevice->GetAdapter(&adapter))
|| FAILED(adapter->QueryInterface(__uuidof(IDXGIAdapterPrivate),
reinterpret_cast<void**>(&m_dxgiAdapter))))
throw DxvkError("D3D11Device: Failed to query adapter");
m_dxgiDevice->SetDeviceLayer(this);
m_presentDevice->SetDeviceLayer(this);
m_context = new D3D11DeviceContext(this, m_dxvkDevice);
m_resourceInitContext = m_dxvkDevice->createContext();
2017-10-11 09:51:48 +02:00
}
D3D11Device::~D3D11Device() {
m_presentDevice->SetDeviceLayer(nullptr);
m_dxgiDevice->SetDeviceLayer(nullptr);
delete m_context;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::QueryInterface(REFIID riid, void** ppvObject) {
2017-10-15 21:50:34 +02:00
COM_QUERY_IFACE(riid, ppvObject, IUnknown);
2017-10-11 09:51:48 +02:00
COM_QUERY_IFACE(riid, ppvObject, ID3D11Device);
if (riid == __uuidof(IDXGIDevice)
|| riid == __uuidof(IDXGIDevice1)
|| riid == __uuidof(IDXGIDevicePrivate))
return m_dxgiDevice->QueryInterface(riid, ppvObject);
if (riid == __uuidof(IDXGIPresentDevicePrivate))
return m_presentDevice->QueryInterface(riid, ppvObject);
2017-10-11 09:51:48 +02:00
Logger::warn("D3D11Device::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
2017-10-11 09:51:48 +02:00
return E_NOINTERFACE;
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateBuffer(
2017-10-11 09:51:48 +02:00
const D3D11_BUFFER_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Buffer** ppBuffer) {
if (ppBuffer != nullptr) {
const Com<D3D11Buffer> buffer
= new D3D11Buffer(this, pDesc);
2017-12-07 13:31:32 +01:00
this->InitBuffer(buffer.ptr(), pInitialData);
*ppBuffer = buffer.ref();
}
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture1D(
2017-10-11 09:51:48 +02:00
const D3D11_TEXTURE1D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture1D** ppTexture1D) {
Logger::err("D3D11Device::CreateTexture1D: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2D(
2017-10-11 09:51:48 +02:00
const D3D11_TEXTURE2D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture2D** ppTexture2D) {
2017-12-08 23:13:15 +01:00
DxvkImageCreateInfo info;
info.type = VK_IMAGE_TYPE_2D;
info.format = m_dxgiAdapter->LookupFormat(pDesc->Format).actual;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent.width = pDesc->Width;
info.extent.height = pDesc->Height;
info.extent.depth = 1;
info.numLayers = pDesc->ArraySize;
info.mipLevels = pDesc->MipLevels;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.layout = VK_IMAGE_LAYOUT_GENERAL;
if (FAILED(GetSampleCount(pDesc->SampleDesc.Count, &info.sampleCount))) {
Logger::err(str::format("D3D11: Invalid sample count: ", pDesc->SampleDesc.Count));
return E_INVALIDARG;
}
if (pDesc->BindFlags & D3D11_BIND_SHADER_RESOURCE) {
info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
info.stages |= GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_RENDER_TARGET) {
info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
info.access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_DEPTH_STENCIL) {
info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
info.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
info.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
info.stages |= GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
}
2017-12-10 17:36:32 +01:00
if (pDesc->CPUAccessFlags != 0) {
info.tiling = VK_IMAGE_TILING_LINEAR;
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
if (pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
info.access |= VK_ACCESS_HOST_WRITE_BIT;
if (pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_READ)
info.access |= VK_ACCESS_HOST_READ_BIT;
}
2017-12-08 23:13:15 +01:00
if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
if (pDesc->MipLevels == 0)
info.mipLevels = util::computeMipLevelCount(info.extent);
2017-12-08 23:13:15 +01:00
if (ppTexture2D != nullptr) {
Com<IDXGIImageResourcePrivate> image;
HRESULT hr = DXGICreateImageResourcePrivate(
m_dxgiDevice.ptr(), &info,
GetMemoryFlagsForUsage(pDesc->Usage), 0,
&image);
if (FAILED(hr))
return hr;
*ppTexture2D = ref(new D3D11Texture2D(
this, image.ptr(), *pDesc));
InitTexture(image.ptr(), pInitialData);
}
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3D(
2017-10-11 09:51:48 +02:00
const D3D11_TEXTURE3D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture3D** ppTexture3D) {
Logger::err("D3D11Device::CreateTexture3D: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceView(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
ID3D11ShaderResourceView** ppSRView) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
2017-12-09 19:36:38 +01:00
// The description is optional. If omitted, we'll create
// a view that covers all subresources of the image.
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
if (pDesc == nullptr) {
if (FAILED(GetShaderResourceViewDescFromResource(pResource, &desc)))
return E_INVALIDARG;
} else {
desc = *pDesc;
}
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
Logger::err("D3D11: Shader resource views for buffers not yet supported");
return E_INVALIDARG;
} else {
2017-12-09 19:36:38 +01:00
// Retrieve the image that we are going to create a view for
Com<IDXGIImageResourcePrivate> imageResource;
if (FAILED(pResource->QueryInterface(
__uuidof(IDXGIImageResourcePrivate),
reinterpret_cast<void**>(&imageResource))))
return E_INVALIDARG;
// Fill in the view info. The view type depends solely
// on the view dimension field in the view description,
// not on the resource type.
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format).actual;
viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
switch (desc.ViewDimension) {
case D3D11_SRV_DIMENSION_TEXTURE1D:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D;
viewInfo.minLevel = desc.Texture1D.MostDetailedMip;
viewInfo.numLevels = desc.Texture1D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
viewInfo.minLevel = desc.Texture1DArray.MostDetailedMip;
viewInfo.numLevels = desc.Texture1DArray.MipLevels;
viewInfo.minLayer = desc.Texture1DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture1DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2D:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MostDetailedMip;
viewInfo.numLevels = desc.Texture2D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MostDetailedMip;
viewInfo.numLevels = desc.Texture2DArray.MipLevels;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DMSArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DMSArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.minLevel = desc.Texture3D.MostDetailedMip;
viewInfo.numLevels = desc.Texture3D.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBE:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE;
viewInfo.minLevel = desc.TextureCube.MostDetailedMip;
viewInfo.numLevels = desc.TextureCube.MipLevels;
viewInfo.minLayer = 0;
viewInfo.numLayers = 6;
break;
case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
2017-12-09 19:36:38 +01:00
viewInfo.type = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
viewInfo.minLevel = desc.TextureCubeArray.MostDetailedMip;
viewInfo.numLevels = desc.TextureCubeArray.MipLevels;
viewInfo.minLayer = desc.TextureCubeArray.First2DArrayFace;
viewInfo.numLayers = desc.TextureCubeArray.NumCubes * 6;
break;
default:
Logger::err(str::format(
"D3D11: View dimension not supported for SRV: ",
desc.ViewDimension));
return E_INVALIDARG;
}
2017-12-09 19:36:38 +01:00
if (ppSRView == nullptr)
return S_OK;
try {
2017-12-09 19:36:38 +01:00
*ppSRView = ref(new D3D11ShaderResourceView(
this, pResource, desc, nullptr,
m_dxvkDevice->createImageView(
imageResource->GetDXVKImage(),
viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessView(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
ID3D11UnorderedAccessView** ppUAView) {
Logger::err("D3D11Device::CreateUnorderedAccessView: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetView(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
ID3D11RenderTargetView** ppRTView) {
// Only 2D textures and 2D texture arrays are allowed
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
if (resourceDim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::err("D3D11: Unsupported resource type for render target views");
return E_INVALIDARG;
}
// The view description is optional. If not defined, it
// will use the resource's format and all array layers.
D3D11_RENDER_TARGET_VIEW_DESC desc;
2017-12-09 19:36:38 +01:00
if (pDesc == nullptr) {
if (FAILED(GetRenderTargetViewDescFromResource(pResource, &desc)))
return E_INVALIDARG;
} else {
2017-12-09 19:36:38 +01:00
desc = *pDesc;
}
2017-12-09 19:36:38 +01:00
// Retrieve the image that we are going to create the view for
Com<IDXGIImageResourcePrivate> imageResource;
if (FAILED(pResource->QueryInterface(
__uuidof(IDXGIImageResourcePrivate),
reinterpret_cast<void**>(&imageResource))))
return E_INVALIDARG;
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format).actual;
2017-12-09 02:44:59 +01:00
viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
switch (desc.ViewDimension) {
case D3D11_RTV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
default:
Logger::err(str::format(
"D3D11: pDesc->ViewDimension not supported for render target views: ",
desc.ViewDimension));
return E_INVALIDARG;
}
// Create the actual image view if requested
if (ppRTView == nullptr)
return S_OK;
try {
*ppRTView = ref(new D3D11RenderTargetView(
2017-12-09 19:36:38 +01:00
this, pResource, desc, nullptr,
m_dxvkDevice->createImageView(
imageResource->GetDXVKImage(),
viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilView(
ID3D11Resource* pResource,
const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
ID3D11DepthStencilView** ppDepthStencilView) {
// Only 2D textures and 2D texture arrays are allowed
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
if (resourceDim != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::err("D3D11: Unsupported resource type for depth-stencil views");
return E_INVALIDARG;
}
// The view description is optional. If not defined, it
// will use the resource's format and all array layers.
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
2017-12-09 19:36:38 +01:00
if (pDesc == nullptr) {
if (FAILED(GetDepthStencilViewDescFromResource(pResource, &desc)))
return E_INVALIDARG;
} else {
2017-12-09 19:36:38 +01:00
desc = *pDesc;
}
2017-12-09 19:36:38 +01:00
// Retrieve the image that we are going to create the view for
Com<IDXGIImageResourcePrivate> imageResource;
if (FAILED(pResource->QueryInterface(
__uuidof(IDXGIImageResourcePrivate),
reinterpret_cast<void**>(&imageResource))))
return E_INVALIDARG;
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format).actual;
2017-12-09 02:44:59 +01:00
viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
switch (desc.ViewDimension) {
case D3D11_DSV_DIMENSION_TEXTURE2D:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = desc.Texture2D.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = desc.Texture2DArray.MipSlice;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMS:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = 0;
viewInfo.numLayers = 1;
break;
case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
viewInfo.minLayer = desc.Texture2DArray.FirstArraySlice;
viewInfo.numLayers = desc.Texture2DArray.ArraySize;
break;
default:
Logger::err(str::format(
"D3D11: pDesc->ViewDimension not supported for depth-stencil views: ",
desc.ViewDimension));
return E_INVALIDARG;
}
// Create the actual image view if requested
if (ppDepthStencilView == nullptr)
return S_OK;
try {
*ppDepthStencilView = ref(new D3D11DepthStencilView(
2017-12-09 19:36:38 +01:00
this, pResource, desc, nullptr,
m_dxvkDevice->createImageView(
imageResource->GetDXVKImage(),
viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateInputLayout(
2017-10-11 09:51:48 +02:00
const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,
UINT NumElements,
const void* pShaderBytecodeWithInputSignature,
SIZE_T BytecodeLength,
ID3D11InputLayout** ppInputLayout) {
try {
DxbcReader dxbcReader(reinterpret_cast<const char*>(
pShaderBytecodeWithInputSignature), BytecodeLength);
DxbcModule dxbcModule(dxbcReader);
Rc<DxbcIsgn> inputSignature = dxbcModule.isgn();
2017-12-08 00:44:58 +01:00
std::vector<DxvkVertexAttribute> attributes;
std::vector<DxvkVertexBinding> bindings;
for (uint32_t i = 0; i < NumElements; i++) {
const DxbcSgnEntry* entry = inputSignature->find(
pInputElementDescs[i].SemanticName,
pInputElementDescs[i].SemanticIndex);
if (entry == nullptr) {
Logger::err(str::format(
"D3D11Device::CreateInputLayout: No such semantic: ",
pInputElementDescs[i].SemanticName,
pInputElementDescs[i].SemanticIndex));
return E_INVALIDARG;
}
// Create vertex input attribute description
2017-12-08 00:44:58 +01:00
DxvkVertexAttribute attrib;
attrib.location = entry->registerId;
attrib.binding = pInputElementDescs[i].InputSlot;
attrib.format = m_dxgiAdapter->LookupFormat(
pInputElementDescs[i].Format).actual;
attrib.offset = pInputElementDescs[i].AlignedByteOffset;
2017-12-08 11:19:12 +01:00
// TODO implement D3D11_APPEND_ALIGNED_ELEMENT
if (attrib.offset == D3D11_APPEND_ALIGNED_ELEMENT) {
Logger::err("D3D11Device::CreateInputLayout: D3D11_APPEND_ALIGNED_ELEMENT not supported yet");
return E_INVALIDARG;
}
attributes.push_back(attrib);
// Create vertex input binding description. The
// stride is dynamic state in D3D11 and will be
2017-12-12 12:50:52 +01:00
// set by STDMETHODCALLTYPE D3D11DeviceContext::IASetVertexBuffers.
2017-12-08 00:44:58 +01:00
DxvkVertexBinding binding;
binding.binding = pInputElementDescs[i].InputSlot;
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
if (pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) {
binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
if (pInputElementDescs[i].InstanceDataStepRate != 1) {
Logger::err(str::format(
"D3D11Device::CreateInputLayout: Unsupported instance data step rate: ",
pInputElementDescs[i].InstanceDataStepRate));
}
}
// Check if the binding was already defined. If so, the
// parameters must be identical (namely, the input rate).
bool bindingDefined = false;
for (const auto& existingBinding : bindings) {
if (binding.binding == existingBinding.binding) {
bindingDefined = true;
if (binding.inputRate != existingBinding.inputRate) {
Logger::err(str::format(
"D3D11Device::CreateInputLayout: Conflicting input rate for binding ",
binding.binding));
return E_INVALIDARG;
}
}
}
if (!bindingDefined)
bindings.push_back(binding);
}
// Create the actual input layout object
// if the application requests it.
if (ppInputLayout != nullptr) {
*ppInputLayout = ref(
new D3D11InputLayout(this,
2017-12-08 00:44:58 +01:00
attributes.size(),
attributes.data(),
bindings.size(),
bindings.data()));
}
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_INVALIDARG;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateVertexShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11VertexShader** ppVertexShader) {
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppVertexShader != nullptr) {
*ppVertexShader = ref(new D3D11VertexShader(
this, std::move(module)));
}
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11GeometryShader** ppGeometryShader) {
Logger::err("D3D11Device::CreateGeometryShader: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShaderWithStreamOutput(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
UINT NumEntries,
const UINT* pBufferStrides,
UINT NumStrides,
UINT RasterizedStream,
ID3D11ClassLinkage* pClassLinkage,
ID3D11GeometryShader** ppGeometryShader) {
Logger::err("D3D11Device::CreateGeometryShaderWithStreamOutput: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePixelShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11PixelShader** ppPixelShader) {
D3D11ShaderModule module;
if (FAILED(this->CreateShaderModule(&module,
pShaderBytecode, BytecodeLength, pClassLinkage)))
return E_INVALIDARG;
if (ppPixelShader != nullptr) {
*ppPixelShader = ref(new D3D11PixelShader(
this, std::move(module)));
}
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateHullShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11HullShader** ppHullShader) {
Logger::err("D3D11Device::CreateHullShader: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDomainShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11DomainShader** ppDomainShader) {
Logger::err("D3D11Device::CreateDomainShader: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateComputeShader(
2017-10-11 09:51:48 +02:00
const void* pShaderBytecode,
SIZE_T BytecodeLength,
ID3D11ClassLinkage* pClassLinkage,
ID3D11ComputeShader** ppComputeShader) {
Logger::err("D3D11Device::CreateComputeShader: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateClassLinkage(ID3D11ClassLinkage** ppLinkage) {
*ppLinkage = ref(new D3D11ClassLinkage(this));
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState(
2017-10-11 09:51:48 +02:00
const D3D11_BLEND_DESC* pBlendStateDesc,
ID3D11BlendState** ppBlendState) {
D3D11_BLEND_DESC desc;
if (pBlendStateDesc != nullptr) {
desc = *pBlendStateDesc;
} else {
desc.AlphaToCoverageEnable = FALSE;
desc.IndependentBlendEnable = FALSE;
// 1-7 must be ignored if IndependentBlendEnable is disabled so
// technically this is not needed, but since this structure is
// going to be copied around we'll initialize it nonetheless
for (uint32_t i = 0; i < 8; i++) {
desc.RenderTarget[i].BlendEnable = FALSE;
desc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
desc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
}
}
if (ppBlendState != nullptr)
*ppBlendState = m_bsStateObjects.Create(this, desc);
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilState(
2017-10-11 09:51:48 +02:00
const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc,
ID3D11DepthStencilState** ppDepthStencilState) {
D3D11_DEPTH_STENCIL_DESC desc;
if (pDepthStencilDesc != nullptr) {
desc = *pDepthStencilDesc;
} else {
D3D11_DEPTH_STENCILOP_DESC stencilOp;
stencilOp.StencilFunc = D3D11_COMPARISON_ALWAYS;
stencilOp.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
stencilOp.StencilPassOp = D3D11_STENCIL_OP_KEEP;
stencilOp.StencilFailOp = D3D11_STENCIL_OP_KEEP;
desc.DepthEnable = TRUE;
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
desc.DepthFunc = D3D11_COMPARISON_LESS;
desc.StencilEnable = FALSE;
desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
desc.FrontFace = stencilOp;
desc.BackFace = stencilOp;
}
if (ppDepthStencilState != nullptr)
*ppDepthStencilState = m_dsStateObjects.Create(this, desc);
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateRasterizerState(
2017-10-11 09:51:48 +02:00
const D3D11_RASTERIZER_DESC* pRasterizerDesc,
ID3D11RasterizerState** ppRasterizerState) {
D3D11_RASTERIZER_DESC desc;
if (pRasterizerDesc != nullptr) {
desc = *pRasterizerDesc;
} else {
desc.FillMode = D3D11_FILL_SOLID;
desc.CullMode = D3D11_CULL_BACK;
desc.FrontCounterClockwise = FALSE;
desc.DepthBias = 0;
desc.SlopeScaledDepthBias = 0.0f;
desc.DepthBiasClamp = 0.0f;
desc.DepthClipEnable = TRUE;
desc.ScissorEnable = FALSE;
desc.MultisampleEnable = FALSE;
desc.AntialiasedLineEnable = FALSE;
}
if (ppRasterizerState != nullptr)
*ppRasterizerState = m_rsStateObjects.Create(this, desc);
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateSamplerState(
2017-10-11 09:51:48 +02:00
const D3D11_SAMPLER_DESC* pSamplerDesc,
ID3D11SamplerState** ppSamplerState) {
2017-12-09 20:49:56 +01:00
DxvkSamplerCreateInfo info;
// While D3D11_FILTER is technically an enum, its value bits
// can be used to decode the filter properties more efficiently.
const uint32_t filterBits = static_cast<uint32_t>(pSamplerDesc->Filter);
info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE;
info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE;
// Check for any unknown flags
if (filterBits & 0xFFFFFF2A) {
Logger::err(str::format("D3D11: Unsupported filter bits: ", filterBits));
return E_INVALIDARG;
}
// Set up the remaining properties, which are
// stored directly in the sampler description
info.mipmapLodBias = pSamplerDesc->MipLODBias;
info.mipmapLodMin = pSamplerDesc->MinLOD;
info.mipmapLodMax = pSamplerDesc->MaxLOD;
info.maxAnisotropy = pSamplerDesc->MaxAnisotropy;
info.addressModeU = DecodeAddressMode(pSamplerDesc->AddressU);
info.addressModeV = DecodeAddressMode(pSamplerDesc->AddressV);
info.addressModeW = DecodeAddressMode(pSamplerDesc->AddressW);
info.compareOp = DecodeCompareOp(pSamplerDesc->ComparisonFunc);
info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
info.usePixelCoord = VK_FALSE;
if (info.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
|| info.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
|| info.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
Logger::warn("D3D11: Border color not supported yet");
// Create sampler object if the application requests it
if (ppSamplerState == nullptr)
return S_OK;
try {
*ppSamplerState = ref(new D3D11SamplerState(this,
*pSamplerDesc, m_dxvkDevice->createSampler(info)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return S_OK;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery(
2017-10-11 09:51:48 +02:00
const D3D11_QUERY_DESC* pQueryDesc,
ID3D11Query** ppQuery) {
Logger::err("D3D11Device::CreateQuery: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate(
2017-10-11 09:51:48 +02:00
const D3D11_QUERY_DESC* pPredicateDesc,
ID3D11Predicate** ppPredicate) {
Logger::err("D3D11Device::CreatePredicate: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateCounter(
2017-10-11 09:51:48 +02:00
const D3D11_COUNTER_DESC* pCounterDesc,
ID3D11Counter** ppCounter) {
Logger::err("D3D11Device::CreateCounter: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext(
2017-10-11 09:51:48 +02:00
UINT ContextFlags,
ID3D11DeviceContext** ppDeferredContext) {
Logger::err("D3D11Device::CreateDeferredContext: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource(
2017-10-11 09:51:48 +02:00
HANDLE hResource,
REFIID ReturnedInterface,
void** ppResource) {
Logger::err("D3D11Device::OpenSharedResource: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CheckFormatSupport(
2017-10-11 09:51:48 +02:00
DXGI_FORMAT Format,
UINT* pFormatSupport) {
Logger::err("D3D11Device::CheckFormatSupport: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CheckMultisampleQualityLevels(
2017-10-11 09:51:48 +02:00
DXGI_FORMAT Format,
UINT SampleCount,
UINT* pNumQualityLevels) {
// There are many error conditions, so we'll just assume
// that we will fail and return a non-zero value in case
// the device does actually support the format.
*pNumQualityLevels = 0;
// We need to check whether the format is
VkFormat format = m_dxgiAdapter->LookupFormat(Format).actual;
if (format == VK_FORMAT_UNDEFINED) {
Logger::err(str::format("D3D11: Unsupported format: ", Format));
return E_INVALIDARG;
}
// D3D may legally query non-power-of-two sample counts as well
VkSampleCountFlagBits sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
if (FAILED(GetSampleCount(SampleCount, &sampleCountFlag)))
return S_OK;
// Check if the device supports the given combination of format
// and sample count. D3D exposes the opaque concept of quality
// levels to the application, we'll just define one such level.
VkImageFormatProperties formatProps;
VkResult status = m_dxvkAdapter->imageFormatProperties(
format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT, 0, formatProps);
if ((status == VK_SUCCESS) && (formatProps.sampleCounts & sampleCountFlag))
*pNumQualityLevels = 1;
return S_OK;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11Device::CheckCounterInfo(D3D11_COUNTER_INFO* pCounterInfo) {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11Device::CheckCounterInfo: Not implemented");
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CheckCounter(
2017-10-11 09:51:48 +02:00
const D3D11_COUNTER_DESC* pDesc,
D3D11_COUNTER_TYPE* pType,
UINT* pActiveCounters,
LPSTR szName,
UINT* pNameLength,
LPSTR szUnits,
UINT* pUnitsLength,
LPSTR szDescription,
UINT* pDescriptionLength) {
Logger::err("D3D11Device::CheckCounter: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::CheckFeatureSupport(
2017-10-11 09:51:48 +02:00
D3D11_FEATURE Feature,
void* pFeatureSupportData,
UINT FeatureSupportDataSize) {
Logger::err("D3D11Device::CheckFeatureSupport: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::GetPrivateData(
2017-10-11 09:51:48 +02:00
REFGUID guid, UINT* pDataSize, void* pData) {
return m_dxgiDevice->GetPrivateData(guid, pDataSize, pData);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateData(
2017-10-11 09:51:48 +02:00
REFGUID guid, UINT DataSize, const void* pData) {
return m_dxgiDevice->SetPrivateData(guid, DataSize, pData);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateDataInterface(
2017-10-11 09:51:48 +02:00
REFGUID guid, const IUnknown* pData) {
return m_dxgiDevice->SetPrivateDataInterface(guid, pData);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
D3D_FEATURE_LEVEL STDMETHODCALLTYPE D3D11Device::GetFeatureLevel() {
2017-10-11 09:51:48 +02:00
return m_featureLevel;
}
2017-12-12 12:50:52 +01:00
UINT STDMETHODCALLTYPE D3D11Device::GetCreationFlags() {
2017-10-11 09:51:48 +02:00
return m_featureFlags;
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::GetDeviceRemovedReason() {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11Device::GetDeviceRemovedReason: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11Device::GetImmediateContext(ID3D11DeviceContext** ppImmediateContext) {
*ppImmediateContext = ref(m_context);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11Device::SetExceptionMode(UINT RaiseFlags) {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11Device::SetExceptionMode: Not implemented");
return E_NOTIMPL;
}
2017-12-12 12:50:52 +01:00
UINT STDMETHODCALLTYPE D3D11Device::GetExceptionMode() {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11Device::GetExceptionMode: Not implemented");
return 0;
}
VkPipelineStageFlags D3D11Device::GetEnabledShaderStages() const {
VkPipelineStageFlags enabledShaderPipelineStages
= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
if (m_dxvkDevice->features().geometryShader)
enabledShaderPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
if (m_dxvkDevice->features().tessellationShader) {
enabledShaderPipelineStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
}
return enabledShaderPipelineStages;
}
bool D3D11Device::CheckFeatureLevelSupport(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel) {
// We currently only support 11_0 interfaces
if (featureLevel > D3D_FEATURE_LEVEL_11_0)
return false;
// Check whether all features are supported
const VkPhysicalDeviceFeatures features
= GetDeviceFeatures(adapter, featureLevel);
if (!adapter->checkFeatureSupport(features))
return false;
// TODO also check for required limits
return true;
}
VkPhysicalDeviceFeatures D3D11Device::GetDeviceFeatures(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel) {
VkPhysicalDeviceFeatures supported = adapter->features();
VkPhysicalDeviceFeatures enabled;
std::memset(&enabled, 0, sizeof(enabled));
if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
enabled.depthClamp = VK_TRUE;
enabled.depthBiasClamp = VK_TRUE;
enabled.depthBounds = VK_TRUE;
enabled.fillModeNonSolid = VK_TRUE;
enabled.pipelineStatisticsQuery = supported.pipelineStatisticsQuery;
enabled.samplerAnisotropy = VK_TRUE;
enabled.shaderClipDistance = VK_TRUE;
enabled.shaderCullDistance = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
enabled.occlusionQueryPrecise = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
enabled.multiViewport = VK_TRUE;
enabled.independentBlend = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
enabled.fullDrawIndexUint32 = VK_TRUE;
enabled.fragmentStoresAndAtomics = VK_TRUE;
enabled.geometryShader = VK_TRUE;
enabled.logicOp = supported.logicOp;
enabled.shaderImageGatherExtended = VK_TRUE;
enabled.textureCompressionBC = VK_TRUE;
enabled.vertexPipelineStoresAndAtomics = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
enabled.imageCubeArray = VK_TRUE;
}
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
enabled.shaderFloat64 = supported.shaderFloat64;
enabled.shaderInt64 = supported.shaderInt64;
enabled.tessellationShader = VK_TRUE;
enabled.variableMultisampleRate = VK_TRUE;
}
return enabled;
}
HRESULT D3D11Device::CreateShaderModule(
D3D11ShaderModule* pShaderModule,
const void* pShaderBytecode,
size_t BytecodeLength,
ID3D11ClassLinkage* pClassLinkage) {
if (pClassLinkage != nullptr)
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
try {
*pShaderModule = D3D11ShaderModule(
2017-12-07 10:12:48 +01:00
this, pShaderBytecode, BytecodeLength);
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_INVALIDARG;
}
}
void D3D11Device::InitBuffer(
D3D11Buffer* pBuffer,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
const Rc<DxvkBuffer> buffer = pBuffer->GetDXVKBuffer();
if (pInitialData != nullptr) {
std::lock_guard<std::mutex> lock(m_resourceInitMutex);;
m_resourceInitContext->beginRecording(
m_dxvkDevice->createCommandList());
m_resourceInitContext->updateBuffer(
buffer, 0, buffer->info().size,
pInitialData->pSysMem);
m_dxvkDevice->submitCommandList(
m_resourceInitContext->endRecording(),
nullptr, nullptr);
}
}
2017-12-08 23:13:15 +01:00
void D3D11Device::InitTexture(
IDXGIImageResourcePrivate* pImage,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
std::lock_guard<std::mutex> lock(m_resourceInitMutex);;
m_resourceInitContext->beginRecording(
m_dxvkDevice->createCommandList());
const Rc<DxvkImage> image = pImage->GetDXVKImage();
const DxvkFormatInfo* formatInfo = imageFormatInfo(image->info().format);
2017-12-08 23:13:15 +01:00
if (pInitialData != nullptr) {
// pInitialData is an array that stores an entry for
// every single subresource. Since we will define all
// subresources, this counts as initialization.
VkImageSubresourceLayers subresourceLayers;
subresourceLayers.aspectMask = formatInfo->aspectMask;
subresourceLayers.mipLevel = 0;
subresourceLayers.baseArrayLayer = 0;
subresourceLayers.layerCount = 1;
for (uint32_t layer = 0; layer < image->info().numLayers; layer++) {
for (uint32_t level = 0; level < image->info().mipLevels; level++) {
subresourceLayers.baseArrayLayer = layer;
subresourceLayers.mipLevel = level;
const uint32_t id = D3D11CalcSubresource(
level, layer, image->info().mipLevels);
m_resourceInitContext->updateImage(
image, subresourceLayers,
VkOffset3D { 0, 0, 0 },
image->mipLevelExtent(level),
pInitialData[id].pSysMem,
pInitialData[id].SysMemPitch,
pInitialData[id].SysMemSlicePitch);
}
}
} else {
// Leave the image contents undefined
VkImageSubresourceRange subresources;
subresources.aspectMask = formatInfo->aspectMask;
subresources.baseMipLevel = 0;
subresources.levelCount = image->info().mipLevels;
subresources.baseArrayLayer = 0;
subresources.layerCount = image->info().numLayers;
m_resourceInitContext->initImage(image, subresources);
}
2017-12-08 23:13:15 +01:00
m_dxvkDevice->submitCommandList(
m_resourceInitContext->endRecording(),
nullptr, nullptr);
}
HRESULT D3D11Device::GetShaderResourceViewDescFromResource(
ID3D11Resource* pResource,
D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
switch (resourceDim) {
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
D3D11_TEXTURE2D_DESC resourceDesc;
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
pDesc->Format = resourceDesc.Format;
if (resourceDesc.SampleDesc.Count == 1) {
if (resourceDesc.ArraySize == 1) {
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
pDesc->Texture2D.MostDetailedMip = 0;
pDesc->Texture2D.MipLevels = resourceDesc.MipLevels;
} else {
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
pDesc->Texture2DArray.MostDetailedMip = 0;
pDesc->Texture2DArray.MipLevels = resourceDesc.MipLevels;
pDesc->Texture2DArray.FirstArraySlice = 0;
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
}
} else {
if (resourceDesc.ArraySize == 1) {
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
} else {
pDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
pDesc->Texture2DMSArray.FirstArraySlice = 0;
pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
}
}
} return S_OK;
default:
Logger::err(str::format(
"D3D11: Unsupported dimension for shader resource view: ",
resourceDim));
return E_INVALIDARG;
}
}
HRESULT D3D11Device::GetUnorderedAccessViewDescFromResource(
ID3D11Resource* pResource,
D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc) {
2017-12-09 19:36:38 +01:00
return E_NOTIMPL;
}
HRESULT D3D11Device::GetRenderTargetViewDescFromResource(
ID3D11Resource* pResource,
D3D11_RENDER_TARGET_VIEW_DESC* pDesc) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
2017-12-09 19:36:38 +01:00
switch (resourceDim) {
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
D3D11_TEXTURE2D_DESC resourceDesc;
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
pDesc->Format = resourceDesc.Format;
if (resourceDesc.SampleDesc.Count == 1) {
if (resourceDesc.ArraySize == 1) {
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
pDesc->Texture2D.MipSlice = 0;
} else {
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
pDesc->Texture2DArray.MipSlice = 0;
pDesc->Texture2DArray.FirstArraySlice = 0;
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
}
} else {
if (resourceDesc.ArraySize == 1) {
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else {
pDesc->ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
pDesc->Texture2DMSArray.FirstArraySlice = 0;
pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
}
}
} return S_OK;
default:
Logger::err(str::format(
"D3D11: Unsupported dimension for render target view: ",
resourceDim));
return E_INVALIDARG;
}
}
HRESULT D3D11Device::GetDepthStencilViewDescFromResource(
ID3D11Resource* pResource,
D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
2017-12-09 19:36:38 +01:00
switch (resourceDim) {
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
D3D11_TEXTURE2D_DESC resourceDesc;
static_cast<D3D11Texture2D*>(pResource)->GetDesc(&resourceDesc);
pDesc->Format = resourceDesc.Format;
if (resourceDesc.SampleDesc.Count == 1) {
if (resourceDesc.ArraySize == 1) {
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
pDesc->Texture2D.MipSlice = 0;
} else {
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
pDesc->Texture2DArray.MipSlice = 0;
pDesc->Texture2DArray.FirstArraySlice = 0;
pDesc->Texture2DArray.ArraySize = resourceDesc.ArraySize;
}
} else {
if (resourceDesc.ArraySize == 1) {
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
} else {
pDesc->ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
pDesc->Texture2DMSArray.FirstArraySlice = 0;
pDesc->Texture2DMSArray.ArraySize = resourceDesc.ArraySize;
}
}
} return S_OK;
default:
Logger::err(str::format(
"D3D11: Unsupported dimension for depth stencil view: ",
resourceDim));
return E_INVALIDARG;
}
}
2017-12-08 23:13:15 +01:00
HRESULT D3D11Device::GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) const {
switch (Count) {
case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK;
case 2: *pCount = VK_SAMPLE_COUNT_2_BIT; return S_OK;
case 4: *pCount = VK_SAMPLE_COUNT_4_BIT; return S_OK;
case 8: *pCount = VK_SAMPLE_COUNT_8_BIT; return S_OK;
case 16: *pCount = VK_SAMPLE_COUNT_16_BIT; return S_OK;
}
return E_INVALIDARG;
}
2017-12-09 20:49:56 +01:00
VkSamplerAddressMode D3D11Device::DecodeAddressMode(
D3D11_TEXTURE_ADDRESS_MODE mode) const {
switch (mode) {
case D3D11_TEXTURE_ADDRESS_WRAP:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case D3D11_TEXTURE_ADDRESS_MIRROR:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case D3D11_TEXTURE_ADDRESS_CLAMP:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case D3D11_TEXTURE_ADDRESS_BORDER:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case D3D11_TEXTURE_ADDRESS_MIRROR_ONCE:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
default:
Logger::err(str::format("D3D11: Unsupported address mode: ", mode));
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
}
}
2017-10-11 09:51:48 +02:00
}