1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-01 19:29:16 +01:00

[d3d11] Experimental implementation of OMSetRenderTargets and ClearRenderTargetView

This commit is contained in:
Philip Rebohle 2017-11-29 20:19:40 +01:00
parent b35f0c64b4
commit b389c9ea1f
12 changed files with 336 additions and 30 deletions

View File

@ -1,3 +1,5 @@
#include <cstring>
#include "d3d11_context.h"
#include "d3d11_device.h"
@ -168,7 +170,53 @@ namespace dxvk {
void D3D11DeviceContext::ClearRenderTargetView(
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]) {
Logger::err("D3D11DeviceContext::ClearRenderTargetView: Not implemented");
Com<ID3D11RenderTargetViewPrivate> rtv;
pRenderTargetView->QueryInterface(
__uuidof(ID3D11RenderTargetViewPrivate),
reinterpret_cast<void**>(&rtv));
// Find out whether the given attachment is currently bound
// or not, and if it is, which attachment index it has.
int32_t attachmentIndex = -1;
for (uint32_t i = 0; i < m_state.omRenderTargetViews.size(); i++) {
if (rtv.ptr() == m_state.omRenderTargetViews.at(i).ptr())
attachmentIndex = static_cast<int32_t>(i);
}
if (attachmentIndex < 0) {
// FIXME bind render target, then restore framebuffer or mark dirty
Logger::err("D3D11DeviceContext::ClearRenderTargetView: Render target not bound. This is currently not supported.");
return;
}
// Retrieve image info, which we will need in
// order to determine the size of the clear area
const Rc<DxvkImage> image = rtv->GetDXVKImageView()->image();
// Set up attachment info and copy the clear color
VkClearAttachment clearInfo;
clearInfo.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
clearInfo.colorAttachment = static_cast<uint32_t>(attachmentIndex);
std::memcpy(clearInfo.clearValue.color.float32, ColorRGBA,
sizeof(clearInfo.clearValue.color.float32));
// Clear the full area. On FL 9.x, only the first array
// layer will be cleared, rather than all array layers.
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = image->info().extent.width;
clearRect.rect.extent.height = image->info().extent.height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = image->info().numLayers;
if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
clearRect.layerCount = 1;
// Record the clear operation
m_context->clearRenderTarget(clearInfo, clearRect);
}
@ -780,7 +828,37 @@ namespace dxvk {
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView) {
Logger::err("D3D11DeviceContext::OMSetRenderTargets: Not implemented");
// Update state vector for OMGetRenderTargets
for (UINT i = 0; i < m_state.omRenderTargetViews.size(); i++) {
Com<ID3D11RenderTargetViewPrivate> view = nullptr;
if ((i < NumViews) && (ppRenderTargetViews[i] != nullptr)) {
ppRenderTargetViews[i]->QueryInterface(
__uuidof(ID3D11RenderTargetViewPrivate),
reinterpret_cast<void**>(&view));
}
m_state.omRenderTargetViews.at(i) = view;
}
// TODO unbind overlapping shader resource views
// D3D11 doesn't have the concept of a framebuffer object,
// so we'll just create a new one every time the render
// target bindings are updated. Set up the attachments.
DxvkRenderTargets attachments;
for (UINT i = 0; i < m_state.omRenderTargetViews.size(); i++) {
if (m_state.omRenderTargetViews.at(i) != nullptr)
attachments.setColorTarget(i, m_state.omRenderTargetViews.at(i)->GetDXVKImageView());
}
// TODO implement depth-stencil views
if (pDepthStencilView != nullptr)
Logger::err("D3D11DeviceContext::OMSetRenderTargets: Depth-stencil view not supported");
// Create and bind the framebuffer object using the given attachments
m_context->bindFramebuffer(m_device->createFramebuffer(attachments));
}
@ -791,7 +869,7 @@ namespace dxvk {
UINT UAVStartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
const UINT* pUAVInitialCounts) {
const UINT* pUAVInitialCounts) {
Logger::err("D3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews: Not implemented");
}
@ -815,7 +893,17 @@ namespace dxvk {
UINT NumViews,
ID3D11RenderTargetView** ppRenderTargetViews,
ID3D11DepthStencilView** ppDepthStencilView) {
Logger::err("D3D11DeviceContext::OMGetRenderTargets: Not implemented");
if (ppRenderTargetViews != nullptr) {
for (UINT i = 0; i < NumViews; i++)
ppRenderTargetViews[i] = i < m_state.omRenderTargetViews.size()
? m_state.omRenderTargetViews.at(i).ref()
: nullptr;
}
if (ppDepthStencilView != nullptr) {
Logger::err("D3D11DeviceContext::OMGetRenderTargets: Stencil view not supported");
*ppDepthStencilView = nullptr;
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "d3d11_context_state.h"
#include "d3d11_device_child.h"
#include <dxvk_adapter.h>
@ -471,7 +472,7 @@ namespace dxvk {
UINT UAVStartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
const UINT* pUAVInitialCounts) final;
const UINT* pUAVInitialCounts) final;
void OMSetBlendState(
ID3D11BlendState* pBlendState,
@ -546,6 +547,8 @@ namespace dxvk {
Rc<DxvkContext> m_context;
Rc<DxvkCommandList> m_cmdList;
D3D11ContextState m_state;
};
}

View File

@ -0,0 +1,18 @@
#pragma once
#include <array>
#include "d3d11_interfaces.h"
namespace dxvk {
/**
* \brief Context state
*/
struct D3D11ContextState {
std::array<
Com<ID3D11RenderTargetViewPrivate>,
D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> omRenderTargetViews;
};
}

View File

@ -106,19 +106,6 @@ namespace dxvk {
ID3D11Resource* pResource,
const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
ID3D11RenderTargetView** ppRTView) {
// TODO fill desc
// TODO create view
D3D11_RENDER_TARGET_VIEW_DESC desc;
*ppRTView = ref(new D3D11RenderTargetView(this, desc));
return S_OK;
}
HRESULT D3D11Device::CreateDepthStencilView(
ID3D11Resource* pResource,
const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
ID3D11DepthStencilView** ppDepthStencilView) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
@ -128,9 +115,140 @@ namespace dxvk {
return E_INVALIDARG;
}
// Make sure we can retrieve the image object
Com<ID3D11Texture2DPrivate> texture = nullptr;
if (FAILED(pResource->QueryInterface(__uuidof(ID3D11Texture2DPrivate),
reinterpret_cast<void**>(&texture)))) {
Logger::err("D3D11Device::CreateRenderTargetView: Invalid texture");
return E_INVALIDARG;
}
// Image that we are going to create the view for
const Rc<DxvkImage> image = texture->GetDXVKImage();
// The view description is optional. If not defined, it
// will use the resource's format and all subresources.
D3D11_RENDER_TARGET_VIEW_DESC desc;
if (pDesc != nullptr) {
desc = *pDesc;
} else {
D3D11_TEXTURE2D_DESC texDesc;
texture->GetDesc(&texDesc);
// Select the view dimension based on the
// texture's array size and sample count.
const std::array<D3D11_RTV_DIMENSION, 4> viewDims = {
D3D11_RTV_DIMENSION_TEXTURE2D,
D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
D3D11_RTV_DIMENSION_TEXTURE2DMS,
D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY,
};
uint32_t viewDimIndex = 0;
if (texDesc.ArraySize > 1)
viewDimIndex |= 0x1;
if (texDesc.SampleDesc.Count > 1)
viewDimIndex |= 0x2;
// Fill the correct union member
desc.ViewDimension = viewDims.at(viewDimIndex);
desc.Format = texDesc.Format;
switch (desc.ViewDimension) {
case D3D11_RTV_DIMENSION_TEXTURE2D:
desc.Texture2D.MipSlice = 0;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
desc.Texture2DArray.MipSlice = 0;
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = texDesc.ArraySize;
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMS:
break;
case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
desc.Texture2DMSArray.FirstArraySlice = 0;
desc.Texture2DMSArray.ArraySize = texDesc.ArraySize;
break;
default:
Logger::err("D3D11Device::CreateRenderTargetView: Internal error");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
}
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
// FIXME look up Vulkan format for DXGI format
viewInfo.format = image->info().format;
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
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(
"D3D11Device::CreateRenderTargetView: pDesc->ViewDimension not supported: ",
desc.ViewDimension));
return E_INVALIDARG;
}
// Create the actual image view if requested
if (ppRTView == nullptr)
return S_OK;
try {
Rc<DxvkImageView> view = m_dxvkDevice->createImageView(image, viewInfo);
*ppRTView = ref(new D3D11RenderTargetView(this, pResource, desc, view));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
}
Logger::err("D3D11Device::CreateRenderTargetView: Not implemented");
HRESULT D3D11Device::CreateDepthStencilView(
ID3D11Resource* pResource,
const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
ID3D11DepthStencilView** ppDepthStencilView) {
Logger::err("D3D11Device::CreateDepthStencilView: Not implemented");
return E_NOTIMPL;
}

View File

@ -6,3 +6,48 @@
#include "../dxvk/dxvk_device.h"
MIDL_INTERFACE("776fc4de-9cd9-4a4d-936a-7837d20ec5d9")
ID3D11BufferPrivate : public ID3D11Buffer {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkBuffer> GetDXVKBuffer() = 0;
};
MIDL_INTERFACE("cc62022f-eb7c-473c-b58c-c621bc27b405")
ID3D11Texture1DPrivate : public ID3D11Texture1D {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkImage> GetDXVKImage() = 0;
};
MIDL_INTERFACE("0ca9d5af-96e6-41f2-a2c0-6b43d4dc837d")
ID3D11Texture2DPrivate : public ID3D11Texture2D {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkImage> GetDXVKImage() = 0;
};
MIDL_INTERFACE("b0f7d56e-761e-46c0-8fca-d465b742b2f8")
ID3D11Texture3DPrivate : public ID3D11Texture3D {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkImage> GetDXVKImage() = 0;
};
MIDL_INTERFACE("175a9e94-115c-416a-967d-afabadfa0ea8")
ID3D11RenderTargetViewPrivate : public ID3D11RenderTargetView {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkImageView> GetDXVKImageView() = 0;
};
DXVK_DEFINE_GUID(ID3D11BufferPrivate);
DXVK_DEFINE_GUID(ID3D11Texture1DPrivate);
DXVK_DEFINE_GUID(ID3D11Texture2DPrivate);
DXVK_DEFINE_GUID(ID3D11Texture3DPrivate);
DXVK_DEFINE_GUID(ID3D11RenderTargetViewPrivate);

View File

@ -24,6 +24,7 @@ namespace dxvk {
COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceChild);
COM_QUERY_IFACE(riid, ppvObject, ID3D11Resource);
COM_QUERY_IFACE(riid, ppvObject, ID3D11Texture2D);
COM_QUERY_IFACE(riid, ppvObject, ID3D11Texture2DPrivate);
if (riid == __uuidof(IDXGIResource)
|| riid == __uuidof(IDXGIImageResourcePrivate))
@ -60,4 +61,9 @@ namespace dxvk {
*pDesc = m_desc;
}
Rc<DxvkImage> D3D11Texture2D::GetDXVKImage() {
return m_resource->GetDXVKImage();
}
}

View File

@ -10,7 +10,7 @@ namespace dxvk {
class D3D11Device;
class D3D11Texture2D : public D3D11DeviceChild<ID3D11Texture2D> {
class D3D11Texture2D : public D3D11DeviceChild<ID3D11Texture2DPrivate> {
public:
@ -37,6 +37,8 @@ namespace dxvk {
void GetDesc(
D3D11_TEXTURE2D_DESC *pDesc) final;
Rc<DxvkImage> GetDXVKImage() final;
private:
Com<D3D11Device> m_device;

View File

@ -5,9 +5,13 @@ namespace dxvk {
D3D11RenderTargetView::D3D11RenderTargetView(
D3D11Device* device,
const D3D11_RENDER_TARGET_VIEW_DESC& desc)
ID3D11Resource* resource,
const D3D11_RENDER_TARGET_VIEW_DESC& desc,
Rc<DxvkImageView> view)
: m_device (device),
m_desc (desc) {
m_resource(resource),
m_desc (desc),
m_view (view) {
}
@ -22,6 +26,7 @@ namespace dxvk {
COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceChild);
COM_QUERY_IFACE(riid, ppvObject, ID3D11View);
COM_QUERY_IFACE(riid, ppvObject, ID3D11RenderTargetView);
COM_QUERY_IFACE(riid, ppvObject, ID3D11RenderTargetViewPrivate);
Logger::warn("D3D11RenderTargetView::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
@ -34,7 +39,7 @@ namespace dxvk {
void D3D11RenderTargetView::GetResource(ID3D11Resource **ppResource) {
*ppResource = m_resource.ref();
}
@ -42,4 +47,9 @@ namespace dxvk {
*pDesc = m_desc;
}
Rc<DxvkImageView> D3D11RenderTargetView::GetDXVKImageView() {
return m_view;
}
}

View File

@ -8,13 +8,15 @@ namespace dxvk {
class D3D11Device;
class D3D11RenderTargetView : public D3D11DeviceChild<ID3D11RenderTargetView> {
class D3D11RenderTargetView : public D3D11DeviceChild<ID3D11RenderTargetViewPrivate> {
public:
D3D11RenderTargetView(
D3D11Device* device,
const D3D11_RENDER_TARGET_VIEW_DESC& desc);
ID3D11Resource* resource,
const D3D11_RENDER_TARGET_VIEW_DESC& desc,
Rc<DxvkImageView> view);
~D3D11RenderTargetView();
HRESULT QueryInterface(
@ -30,10 +32,15 @@ namespace dxvk {
void GetDesc(
D3D11_RENDER_TARGET_VIEW_DESC* pDesc) final;
Rc<DxvkImageView> GetDXVKImageView() final;
private:
Com<D3D11Device> m_device;
Com<ID3D11Resource> m_resource;
D3D11_RENDER_TARGET_VIEW_DESC m_desc;
Rc<DxvkImageView> m_view;
};

View File

@ -282,6 +282,8 @@ namespace dxvk {
m_cmd->cmdBeginRenderPass(&info,
VK_SUBPASS_CONTENTS_INLINE);
m_cmd->trackResource(
m_state.om.framebuffer);
}
}

View File

@ -67,6 +67,7 @@ namespace dxvk {
Rc<DxvkImage> DxvkDevice::createImage(
const DxvkImageCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
// TODO record image initialization commands
return new DxvkImage(m_vkd,
createInfo, *m_memory, memoryType);
}

View File

@ -4,11 +4,17 @@
#include "../../dxgi/dxgi_interfaces.h"
const GUID IDXGIAdapterPrivate::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}};
const GUID IDXGIDevicePrivate::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}};
const GUID IDXGIPresentDevicePrivate::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}};
const GUID IDXGIBufferResourcePrivate::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}};
const GUID IDXGIImageResourcePrivate::guid = {0x1cfe6592,0x7de0,0x4a07,{0x8d,0xcb,0x45,0x43,0xcb,0xbc,0x6a,0x7d}};
const GUID IDXGIAdapterPrivate::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}};
const GUID IDXGIDevicePrivate::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}};
const GUID IDXGIPresentDevicePrivate::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}};
const GUID IDXGIBufferResourcePrivate::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}};
const GUID IDXGIImageResourcePrivate::guid = {0x1cfe6592,0x7de0,0x4a07,{0x8d,0xcb,0x45,0x43,0xcb,0xbc,0x6a,0x7d}};
const GUID ID3D11BufferPrivate::guid = {0x776fc4de,0x9cd9,0x4a4d,{0x93,0x6a,0x78,0x37,0xd2,0x0e,0xc5,0xd9}};
const GUID ID3D11Texture1DPrivate::guid = {0xcc62022f,0xeb7c,0x473c,{0xb5,0x8c,0xc6,0x21,0xbc,0x27,0xb4,0x05}};
const GUID ID3D11Texture2DPrivate::guid = {0x0ca9d5af,0x96e6,0x41f2,{0xa2,0xc0,0x6b,0x43,0xd4,0xdc,0x83,0x7d}};
const GUID ID3D11Texture3DPrivate::guid = {0xb0f7d56e,0x761e,0x46c0,{0x8f,0xca,0xd4,0x65,0xb7,0x42,0xb2,0xf8}};
const GUID ID3D11RenderTargetViewPrivate::guid = {0x175a9e94,0x115c,0x416a,{0x96,0x7d,0xaf,0xab,0xad,0xfa,0x0e,0xa8}};
std::ostream& operator << (std::ostream& os, REFIID guid) {
os.width(8);