Skip to content
This repository has been archived by the owner on Nov 19, 2019. It is now read-only.

Commit

Permalink
[d3d9] Implement volume/3d textures.
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed Jan 29, 2019
1 parent 5e736cb commit 8452753
Show file tree
Hide file tree
Showing 9 changed files with 377 additions and 20 deletions.
37 changes: 37 additions & 0 deletions src/d3d9/d3d9_d3d11_resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/d3d9/d3d9_d3d11_resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 23 additions & 6 deletions src/d3d9/d3d9_d3d11_resource_mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
3 changes: 1 addition & 2 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
153 changes: 141 additions & 12 deletions src/d3d9/d3d9_texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,35 @@ 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;
}

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) {
Expand Down Expand Up @@ -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;
}

}
32 changes: 32 additions & 0 deletions src/d3d9/d3d9_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;

};

}
Loading

0 comments on commit 8452753

Please sign in to comment.