Commit 84527537 authored by Joshua Ashton's avatar Joshua Ashton 🐸

[d3d9] Implement volume/3d textures.

parent 5e736cbc
......@@ -23,6 +23,41 @@ namespace dxup {
return false;
}
DXUPResource* DXUPResource::CreateTexture3D(Direct3DDevice9Ex* device, ID3D11Texture3D* texture, DWORD d3d9Usage, D3DFORMAT d3d9Format) {
D3D11_TEXTURE3D_DESC desc;
texture->GetDesc(&desc);
Com<ID3D11ShaderResourceView> srv;
Com<ID3D11ShaderResourceView> srvSRGB;
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) {
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.ViewDimension = D3D10_1_SRV_DIMENSION_TEXTURE3D;
srvDesc.Texture3D.MipLevels = 0xFFFFFFFF;
srvDesc.Texture3D.MostDetailedMip = 0;
srvDesc.Format = desc.Format;
srvDesc.Format = convert::makeUntypeless(srvDesc.Format, false);
device->GetD3D11Device()->CreateShaderResourceView(texture, &srvDesc, &srv);
srvDesc.Format = desc.Format;
srvDesc.Format = convert::makeUntypeless(srvDesc.Format, true);
device->GetD3D11Device()->CreateShaderResourceView(texture, &srvDesc, &srvSRGB);
}
Com<ID3D11Texture3D> stagingTexture;
if (NeedsStaging(desc.Usage, d3d9Usage, d3d9Format)) {
makeStagingDesc(desc, d3d9Usage, d3d9Format);
device->GetD3D11Device()->CreateTexture3D(&desc, nullptr, &stagingTexture);
if (d3d9Format == D3DFMT_R8G8B8)
log::warn("CreateTexture3D: has format D3DFMT_R8G8B8.");
}
return new DXUPResource(device, texture, stagingTexture.ptr(), nullptr, srv.ptr(), srvSRGB.ptr(), desc.Format, 1, std::max(desc.MipLevels, 1u), desc.Usage == D3D11_USAGE_DYNAMIC);
}
DXUPResource* DXUPResource::CreateTexture2D(Direct3DDevice9Ex* device, ID3D11Texture2D* texture, DWORD d3d9Usage, D3DFORMAT d3d9Format) {
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
......@@ -86,6 +121,8 @@ namespace dxup {
D3D11_RESOURCE_DIMENSION dimension;
resource->GetType(&dimension);
if (dimension == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
return CreateTexture3D(device, useAs<ID3D11Texture3D>(resource), d3d9Usage, d3d9Format);
if (dimension == D3D11_RESOURCE_DIMENSION_TEXTURE2D)
return CreateTexture2D(device, useAs<ID3D11Texture2D>(resource), d3d9Usage, d3d9Format);
else if (dimension == D3D11_RESOURCE_DIMENSION_BUFFER)
......
......@@ -71,6 +71,7 @@ namespace dxup {
static bool NeedsStaging(D3D11_USAGE d3d11Usage, DWORD d3d9Usage, D3DFORMAT d3d9Format);
static DXUPResource* CreateTexture2D(Direct3DDevice9Ex* device, ID3D11Texture2D* texture, DWORD d3d9Usage, D3DFORMAT d3d9Format);
static DXUPResource* CreateTexture3D(Direct3DDevice9Ex* device, ID3D11Texture3D* texture, DWORD d3d9Usage, D3DFORMAT d3d9Format);
static DXUPResource* CreateBuffer(Direct3DDevice9Ex* device, ID3D11Buffer* buffer, DWORD d3d9Usage);
DXUPResource(Direct3DDevice9Ex* device, ID3D11Resource* resource, ID3D11Resource* staging, ID3D11Resource* fixup8888, ID3D11ShaderResourceView* srv, ID3D11ShaderResourceView* srvSRGB, DXGI_FORMAT dxgiFormat, UINT slices, UINT mips, bool dynamic);
......
......@@ -166,13 +166,30 @@ namespace dxup {
D3D11_BOX box = { 0 };
if (useRect) {
box.left = alignRectForFormat(true, m_dxgiFormat, m_stagingBoxes[subresource].Left);
box.top = alignRectForFormat(true, m_dxgiFormat, m_stagingBoxes[subresource].Top);
box.right = alignRectForFormat(false, m_dxgiFormat, m_stagingBoxes[subresource].Right);
box.bottom = alignRectForFormat(false, m_dxgiFormat, m_stagingBoxes[subresource].Bottom);
D3D11_RESOURCE_DIMENSION dimension;
GetResource()->GetType(&dimension);
if (dimension == D3D11_RESOURCE_DIMENSION_BUFFER) {
box.top = 0;
box.bottom = 1;
box.left = m_stagingBoxes[subresource].Left;
box.right = m_stagingBoxes[subresource].Right;
}
else {
box.top = alignRectForFormat(true, m_dxgiFormat, m_stagingBoxes[subresource].Top);
box.bottom = alignRectForFormat(false, m_dxgiFormat, m_stagingBoxes[subresource].Bottom);
box.left = alignRectForFormat(true, m_dxgiFormat, m_stagingBoxes[subresource].Left);
box.right = alignRectForFormat(false, m_dxgiFormat, m_stagingBoxes[subresource].Right);
}
box.front = 0;
box.back = 1;
if (dimension == D3D11_RESOURCE_DIMENSION_TEXTURE2D || dimension == D3D11_RESOURCE_DIMENSION_BUFFER) {
box.front = 0;
box.back = 1;
}
else {
box.front = alignRectForFormat(true, m_dxgiFormat, m_stagingBoxes[subresource].Front);
box.back = alignRectForFormat(false, m_dxgiFormat, m_stagingBoxes[subresource].Back);
}
}
if (delta & (1ull << mip))
......
......@@ -640,8 +640,7 @@ namespace dxup {
HRESULT STDMETHODCALLTYPE Direct3DDevice9Ex::CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) {
CriticalSection cs(this);
log::stub("Direct3DDevice9Ex::CreateVolumeTexture");
return D3D_OK;
return Direct3DVolumeTexture9::Create(this, Width, Height, Depth, Levels, Usage, Format, Pool, (Direct3DVolumeTexture9**)ppVolumeTexture);
}
HRESULT STDMETHODCALLTYPE Direct3DDevice9Ex::CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) {
CriticalSection cs(this);
......
......@@ -36,17 +36,15 @@ namespace dxup {
HRESULT STDMETHODCALLTYPE Direct3DTexture9::GetSurfaceLevel(UINT Level, IDirect3DSurface9** ppSurfaceLevel) {
CriticalSection(this->GetD3D9Device());
UINT subresource = D3D11CalcSubresource(Level, 0, this->GetDXUPResource()->GetMips());
InitReturnPtr(ppSurfaceLevel);
if (subresource >= m_surfaces.size())
if (Level >= m_surfaces.size())
return log::d3derr(D3DERR_INVALIDCALL, "GetSurfaceLevel: subresource out of bounds (Level = %d).", Level);
if (ppSurfaceLevel == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "GetSurfaceLevel: ppSurfaceLevel was nullptr.");
*ppSurfaceLevel = ref(m_surfaces[subresource]);
*ppSurfaceLevel = ref(m_surfaces[Level]);
return D3D_OK;
}
......@@ -54,23 +52,19 @@ namespace dxup {
HRESULT STDMETHODCALLTYPE Direct3DTexture9::LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, const RECT* pRect, DWORD Flags) {
CriticalSection(this->GetD3D9Device());
UINT subresource = D3D11CalcSubresource(Level, 0, this->GetDXUPResource()->GetMips());
if (subresource >= m_surfaces.size())
if (Level >= m_surfaces.size())
return log::d3derr(D3DERR_INVALIDCALL, "LockRect: subresource out of bounds (Level = %d).", Level);
return m_surfaces[subresource]->LockRect(pLockedRect, pRect, Flags);
return m_surfaces[Level]->LockRect(pLockedRect, pRect, Flags);
}
HRESULT STDMETHODCALLTYPE Direct3DTexture9::UnlockRect(UINT Level) {
CriticalSection(this->GetD3D9Device());
UINT subresource = D3D11CalcSubresource(Level, 0, this->GetDXUPResource()->GetMips());
if (subresource >= m_surfaces.size())
if (Level >= m_surfaces.size())
return log::d3derr(D3DERR_INVALIDCALL, "UnlockRect: subresource out of bounds (Level = %d).", Level);
return m_surfaces[subresource]->UnlockRect();
return m_surfaces[Level]->UnlockRect();
}
HRESULT STDMETHODCALLTYPE Direct3DTexture9::AddDirtyRect(const RECT* pDirtyRect) {
......@@ -294,4 +288,139 @@ namespace dxup {
return D3D_OK;
}
// Direct3DVolumeTexture9
Direct3DVolumeTexture9::Direct3DVolumeTexture9(Direct3DDevice9Ex* device, DXUPResource* resource, const D3D9ResourceDesc& desc)
: Direct3DVolumeTexture9Base{ device, resource, desc } {
m_volumes.reserve(resource->GetSubresources());
for (UINT mip = 0; mip < resource->GetMips(); mip++) {
Direct3DVolume9* volume = Direct3DVolume9::Wrap(mip, device, this, resource, desc);
volume->AddRefPrivate();
m_volumes.push_back(volume);
}
}
Direct3DVolumeTexture9::~Direct3DVolumeTexture9() {
for (IDirect3DVolume9* surface : m_volumes) {
Direct3DVolume9* internalVolume = reinterpret_cast<Direct3DVolume9*>(surface);
internalVolume->ReleasePrivate();
}
}
HRESULT STDMETHODCALLTYPE Direct3DVolumeTexture9::GetLevelDesc(UINT Level, D3DVOLUME_DESC* pDesc) {
CriticalSection(this->GetD3D9Device());
if (Level >= m_volumes.size())
return log::d3derr(D3DERR_INVALIDCALL, "GetLevelDesc: level out of bounds.");
return m_volumes[Level]->GetDesc(pDesc);
}
HRESULT STDMETHODCALLTYPE Direct3DVolumeTexture9::GetVolumeLevel(UINT Level, IDirect3DVolume9** ppVolumeLevel) {
CriticalSection(this->GetD3D9Device());
InitReturnPtr(ppVolumeLevel);
if (Level >= m_volumes.size())
return log::d3derr(D3DERR_INVALIDCALL, "GetVolumeLevel: subresource out of bounds (Level = %d).", Level);
if (ppVolumeLevel == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "GetVolumeLevel: ppVolumeLevel was nullptr.");
*ppVolumeLevel = ref(m_volumes[Level]);
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE Direct3DVolumeTexture9::LockBox(UINT Level, D3DLOCKED_BOX* pLockedBox, const D3DBOX* pBox, DWORD Flags) {
CriticalSection(this->GetD3D9Device());
if (Level >= m_volumes.size())
return log::d3derr(D3DERR_INVALIDCALL, "LockBox: subresource out of bounds (Level = %d).", Level);
return m_volumes[Level]->LockBox(pLockedBox, pBox, Flags);
}
HRESULT STDMETHODCALLTYPE Direct3DVolumeTexture9::UnlockBox(UINT Level) {
CriticalSection(this->GetD3D9Device());
if (Level >= m_volumes.size())
return log::d3derr(D3DERR_INVALIDCALL, "UnlockBox: subresource out of bounds (Level = %d).", Level);
return m_volumes[Level]->UnlockBox();
}
HRESULT STDMETHODCALLTYPE Direct3DVolumeTexture9::AddDirtyBox(const D3DBOX* pDirtyBox) {
CriticalSection(this->GetD3D9Device());
log::stub("Direct3DVolumeTexture9::AddDirtyRect");
return D3D_OK;
}
HRESULT Direct3DVolumeTexture9::Create(Direct3DDevice9Ex* device,
UINT width,
UINT height,
UINT depth,
UINT levels,
DWORD usage,
D3DFORMAT format,
D3DPOOL pool,
Direct3DVolumeTexture9** outTexture) {
InitReturnPtr(outTexture);
if (width == 0)
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: width was 0.");
if (height == 0)
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: height was 0.");
if (depth == 0)
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: depth was 0.");
if (!device->checkFormat(usage, D3DRTYPE_VOLUMETEXTURE, format))
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: unsupported format (%d).", format);
if (outTexture == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: outTexture was nullptr.");
D3D11_USAGE d3d11Usage = convert::usage(pool, usage);
D3D11_TEXTURE3D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.Format = convert::format(format);
desc.Usage = d3d11Usage;
desc.CPUAccessFlags = convert::cpuFlags(pool, usage);
desc.MipLevels = d3d11Usage == D3D11_USAGE_DYNAMIC ? 1 : levels;
desc.BindFlags = 0;
desc.MiscFlags = 0;
if (d3d11Usage != D3D11_USAGE_STAGING)
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
Com<ID3D11Texture3D> texture;
HRESULT result = device->GetD3D11Device()->CreateTexture3D(&desc, nullptr, &texture);
if (result == E_OUTOFMEMORY)
return log::d3derr(D3DERR_OUTOFVIDEOMEMORY, "Direct3DVolumeTexture9::Create: out of vram.");
if (FAILED(result))
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: failed to create D3D11 texture. D3DFORMAT: %d, DXGI_FORMAT: %d", format, desc.Format); // TODO: stringify
DXUPResource * resource = DXUPResource::Create(device, texture.ptr(), usage, format);
if (resource == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "Direct3DVolumeTexture9::Create: failed to create DXUP resource.");
D3D9ResourceDesc d3d9Desc;
d3d9Desc.Format = format;
d3d9Desc.Pool = pool;
d3d9Desc.Usage = usage;
*outTexture = ref(new Direct3DVolumeTexture9(device, resource, d3d9Desc));
return D3D_OK;
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include "d3d9_d3d11_resource.h"
#include "d3d9_resource.h"
#include "d3d9_surface.h"
#include "d3d9_volume.h"
#include <vector>
namespace dxup {
......@@ -120,4 +121,35 @@ namespace dxup {
};
using Direct3DVolumeTexture9Base = Direct3DBaseTexture9<D3DRTYPE_VOLUMETEXTURE, IDirect3DVolumeTexture9>;
class Direct3DVolumeTexture9 final : public Direct3DVolumeTexture9Base {
public:
~Direct3DVolumeTexture9();
HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DVOLUME_DESC* pDesc) override;
HRESULT STDMETHODCALLTYPE GetVolumeLevel(UINT Level, IDirect3DVolume9** ppVolumeLevel) override;
HRESULT STDMETHODCALLTYPE LockBox(UINT Level, D3DLOCKED_BOX* pLockedBox, const D3DBOX* pBox, DWORD Flags) override;
HRESULT STDMETHODCALLTYPE UnlockBox(UINT Level) override;
HRESULT STDMETHODCALLTYPE AddDirtyBox(const D3DBOX* pDirtyBox) override;
static HRESULT Create(Direct3DDevice9Ex* device,
UINT width,
UINT height,
UINT depth,
UINT levels,
DWORD usage,
D3DFORMAT format,
D3DPOOL pool,
Direct3DVolumeTexture9** outTexture);
private:
Direct3DVolumeTexture9(Direct3DDevice9Ex* device, DXUPResource* resource, const D3D9ResourceDesc& desc);
std::vector<IDirect3DVolume9*> m_volumes;
};
}
\ No newline at end of file
#include "d3d9_volume.h"
#include "d3d9_format.h"
#include "d3d9_texture.h"
#include "d3d9_format.h"
#include "../util/config.h"
namespace dxup {
Direct3DVolume9::Direct3DVolume9(UINT mip, Direct3DDevice9Ex* device, IUnknown* container, DXUPResource* resource, const D3D9ResourceDesc& desc)
: Direct3DVolume9Base{ device, nullptr, desc }
, m_container{ container }
, m_mip{ mip } {
this->SetResource(resource);
}
HRESULT Direct3DVolume9::GetContainer(REFIID riid, void** ppContainer) {
InitReturnPtr(ppContainer);
if (ppContainer == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "GetContainer: ppContainer was nullptr.");
if (m_container == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "GetContainer: m_container was nullptr.");
return FAILED(m_container->QueryInterface(riid, ppContainer)) ? D3DERR_INVALIDCALL : D3D_OK;
}
HRESULT Direct3DVolume9::QueryInterface(REFIID riid, void** ppvObj) {
InitReturnPtr(ppvObj);
if (ppvObj == nullptr)
return E_POINTER;
// This isn't a IDirect3DResource9. W h y?
if (riid == __uuidof(IDirect3DVolume9) || /*riid == __uuidof(IDirect3DResource9) ||*/ riid == __uuidof(IUnknown)) {
*ppvObj = ref(this);
return D3D_OK;
}
return E_NOINTERFACE;
}
HRESULT Direct3DVolume9::GetDesc(D3DVOLUME_DESC *pDesc) {
if (!pDesc)
return log::d3derr(D3DERR_INVALIDCALL, "GetDesc: pDesc was nullptr.");
D3D11_TEXTURE3D_DESC desc;
m_resource->GetResourceAs<ID3D11Texture3D>()->GetDesc(&desc);
pDesc->Format = m_d3d9Desc.Format;
pDesc->Height = std::max(1u, desc.Height >> m_mip);
pDesc->Width = std::max(1u, desc.Width >> m_mip);
pDesc->Depth = std::max(1u, desc.Depth >> m_mip);
pDesc->Pool = m_d3d9Desc.Pool;
pDesc->Type = D3DRTYPE_VOLUME;
pDesc->Usage = m_d3d9Desc.Usage;
return D3D_OK;
}
HRESULT Direct3DVolume9::LockBox(D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) {
return m_resource->D3D9LockBox(0, m_mip, pLockedBox, pBox, Flags, m_d3d9Desc.Usage);
}
HRESULT Direct3DVolume9::UnlockBox() {
return m_resource->D3D9UnlockBox(0, m_mip);
}
ULONG STDMETHODCALLTYPE Direct3DVolume9::AddRef() {
if (m_container != nullptr)
m_container->AddRef();
return Direct3DVolume9Base::AddRef();
}
ULONG STDMETHODCALLTYPE Direct3DVolume9::Release() {
if (m_container != nullptr)
m_container->Release();
return Direct3DVolume9Base::Release();
}
UINT Direct3DVolume9::GetMip() {
return m_mip;
}
UINT Direct3DVolume9::GetSubresource() {
return GetMip();
}
void Direct3DVolume9::ClearResource() {
m_resource = nullptr;
}
void Direct3DVolume9::SetResource(DXUPResource* resource) {
this->ClearResource();
m_resource = resource;
}
Direct3DVolume9* Direct3DVolume9::Wrap(UINT mip, Direct3DDevice9Ex* device, IUnknown* container, DXUPResource* resource, const D3D9ResourceDesc& desc) {
return new Direct3DVolume9(mip, device, container, resource, desc);
}
}
\ No newline at end of file
#pragma once
#include "d3d9_resource.h"
#include "d3d9_d3d11_resource.h"
#include <vector>
namespace dxup {
using Direct3DVolume9Base = Direct3DResource9<D3DRTYPE_VOLUME, IDirect3DVolume9>;
// A d3d9 surface is essentially some subresource of a d3d11 texture.
class Direct3DVolume9 final : public Direct3DVolume9Base {
public:
HRESULT WINAPI QueryInterface(REFIID riid, LPVOID* ppv) override;
HRESULT WINAPI GetContainer(REFIID riid, void** ppContainer) override;
HRESULT WINAPI GetDesc(D3DVOLUME_DESC *pDesc) override;
HRESULT WINAPI LockBox(D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) override;
HRESULT WINAPI UnlockBox() override;
UINT GetMip();
UINT GetSubresource();
ULONG STDMETHODCALLTYPE AddRef() override;
ULONG STDMETHODCALLTYPE Release() override;
void ClearResource();
void SetResource(DXUPResource* resource);
static Direct3DVolume9* Wrap(UINT mip, Direct3DDevice9Ex* device, IUnknown* container, DXUPResource* resource, const D3D9ResourceDesc& desc);
private:
Direct3DVolume9(UINT mip, Direct3DDevice9Ex* device, IUnknown* container, DXUPResource* resource, const D3D9ResourceDesc& desc);
IUnknown* m_container;
UINT m_mip;
};
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ d3d9_main_src = [
'd3d9_interface.cpp',
'd3d9_main.cpp',
'd3d9_surface.cpp',
'd3d9_volume.cpp',
'd3d9_swapchain.cpp',
'd3d9_util.cpp',
'd3d9_format.cpp',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment