...
 
Commits (509)
build
build32
\ No newline at end of file
build32
build.w32
build.w64
*.vcxproj
*.filters
*.vpc_crc
*.sentinel
Release
Debug
.vscode
\ No newline at end of file
dxup:
script:
- chmod +x package-release.sh
- ./package-release.sh release build --no-package
artifacts:
name: "dxup-${CI_COMMIT_REF_NAME}.${CI_COMMIT_SHA}"
paths:
- build/dxup-release
\ No newline at end of file
Copyright 2018 Joshua Ashton
Copyright (c) 2018 Joshua Ashton
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
zlib/libpng license
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
– The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
– Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
– This notice may not be removed or altered from any source distribution.
\ No newline at end of file
# DXUP
## A D3D10 -> D3D11 Translation Layer
Click this for builds: [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/61mhejmwu4lah9mq?retina=true)](https://ci.appveyor.com/project/Joshua-Ashton/dxup)
## A D3D9 and D3D10 -> D3D11 Translation Layer
Important! To get the d3d10 dll to go with the d3d10_1. Symlink d3d10 to be d3d10_1.
### Get [latest build here](https://git.froggi.es/joshua/dxup/pipelines) or [tagged builds here](https://github.com/Joshua-Ashton/dxup/releases).
### What's the point?
- The main reason is for [DXVK](https://github.com/doitsujin/dxvk), a d3d11->Vulkan translation layer. I'm sure where you can see where this is going...
- You can use this if you're a lazy gamedev and want to get access to some d3d11 features by querying the interfaces.
- The main reason is for [DXVK](https://github.com/doitsujin/dxvk), a D3D11->Vulkan translation layer. I'm sure where you can see where this is going... (linux, wine stuff.)
- You can use this if you're a lazy gamedev and want to get access to some D3D11 features by querying the interfaces (and get some extensions, coming soon!)
- You write a D3D9Ex game and don't want to deal with sync and other issues for VR.
- You write a D3D9 game and don't want to deal with D3D9Ex's pool changes and therefore can't get shared resources.
D3D10 support is now deprecated on Linux platforms and won't be installed with the script or the verb as DXVK now implements this.
### How do I use it?
Simple (Linux Only):
In order to install DXUP, get a release from either the [releases](https://github.com/Joshua-Ashton/dxup/releases) page (for versioned releases) or from the [build server](https://git.froggi.es/joshua/dxup/pipelines) if you want one built against the latest or a specific commit then run
```
export WINEPREFIX=/path/to/.wine-prefix
winetricks --force setup_dxup_d3d9.verb
```
### How do I build it?
**Simple (Linux Only):**
Use ``./package-release.sh master /your/target/directory --no-package`` to automagically.
Advanced (Windows & Linux):
Use meson to build the dlls.
Then set those up as wine overrides if you're on Linux or if you're on windows copy them & the d3d10_original and dxgi_original dlls for the right arch to the game/application folder.
**Advanced (Windows & Linux):**
You can use meson to build the DLLs:
**If you wish to use DXVK then use their dxgi as the dxgi_original dll and the DXUP one as the main override.**
Windows: ``meson --backend vs2017 --buildtype release build`` in a Visual Studio x86/x64 Command Prompt depending on the arch you wish to build.
Linux: ``meson --cross-file build-win64.txt --buildtype release --prefix /your/dxup/directory build.w64 `` and vice versa for each arch (change 64s to 32s.)
### Screenshots
With DXVK:
#### D3D10 (before DXVK got D3D10 support)
![Crysis Warhead Menu](https://i.imgur.com/q1l2gLb.png)
![Crysis Warhead Game](https://i.imgur.com/7yY5bZy.jpg)
![Crysis Warhead Game](https://i.imgur.com/eJbUdxK.jpg)
......@@ -28,4 +40,5 @@ With DXVK:
![Just Cause 2](https://i.imgur.com/Q6FoDvj.jpg)
![Just Cause 2](https://i.imgur.com/jGgGrYt.jpg)
# Have fun!
# Have fun! 🐸
clone_folder: C:\Projects\DXUP
shallow_clone: true
version: 0.{build}
environment:
parallel: true
matrix:
- frontend: meson
builder: msbuild
compiler: cl
toolchain: vs2017
arch: x64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- frontend: meson
builder: msbuild
compiler: cl
toolchain: vs2017
arch: x86
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
install:
- set PATH=C:\Python35\scripts;%PATH%
- pip3 install meson
- if "%arch%" == "x64" (call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat")
- if "%arch%" == "x86" (call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat")
before_build:
- cd C:\Projects\DXUP
- mkdir build
- mkdir out
- meson build --backend vs2017 --buildtype release
build_script:
- msbuild /m /p:Configuration=Release C:\Projects\DXUP\build\dxup.sln
- copy C:\Projects\DXUP\build\src\d3d10_1\d3d10_1.dll C:\Projects\DXUP\out
- copy C:\Projects\DXUP\build\src\dxgi\dxgi.dll C:\Projects\DXUP\out
- copy C:\Projects\DXUP\wine_utils\setup_dxup.in C:\Projects\DXUP\out\setup_dxup.sh
- copy C:\Projects\DXUP\wine_utils\readme.txt C:\Projects\DXUP\out
- powershell -Command "(gc C:\Projects\DXUP\out\setup_dxup.sh) -replace '@arch@', \"%arch%\" | Out-File C:\Projects\DXUP\out\setup_dxup.sh"
artifacts:
- path: out
name: dxup-%arch%
[binaries]
c = '/usr/bin/i686-w64-mingw32-gcc'
cpp = '/usr/bin/i686-w64-mingw32-g++'
ar = '/usr/bin/i686-w64-mingw32-ar'
strip = '/usr/bin/i686-w64-mingw32-strip'
exe_wrapper = 'wine'
c = 'i686-w64-mingw32-gcc'
cpp = 'i686-w64-mingw32-g++'
ar = 'i686-w64-mingw32-ar'
strip = 'i686-w64-mingw32-strip'
[properties]
c_args = ['-Og', '-gdwarf-2']
c_args=['-msse', '-msse2']
cpp_args=['-msse', '-msse2']
c_link_args = ['-static', '-static-libgcc']
cpp_args = ['-Og', '-gdwarf-2']
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++', '-Wl,--add-stdcall-alias,--enable-stdcall-fixup']
needs_exe_wrapper = true
[host_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'x86'
endian = 'little'
endian = 'little'
\ No newline at end of file
[binaries]
c = '/usr/bin/x86_64-w64-mingw32-gcc'
cpp = '/usr/bin/x86_64-w64-mingw32-g++'
ar = '/usr/bin/x86_64-w64-mingw32-ar'
strip = '/usr/bin/x86_64-w64-mingw32-strip'
exe_wrapper = 'wine'
c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
strip = 'x86_64-w64-mingw32-strip'
[properties]
c_args = ['-Og', '-gdwarf-2']
c_link_args = ['-static', '-static-libgcc']
cpp_args = ['-Og', '-gdwarf-2']
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
needs_exe_wrapper = true
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
endian = 'little'
\ No newline at end of file
......@@ -5,14 +5,14 @@ ar = 'ar'
strip = 'strip'
[properties]
winelib = true
needs_exe_wrapper = true
c_args = ['-m32']
cpp_args = ['-m32', '--no-gnu-unique']
cpp_link_args = ['-m32', '-mwindows']
c_args=['-m32', '-msse', '-msse2']
cpp_args=['-m32', '--no-gnu-unique', '-msse', '-msse2']
cpp_link_args=['-m32', '-mwindows']
[host_machine]
system = 'linux'
cpu_family = 'x86'
cpu = 'x86'
cpu = 'i686'
endian = 'little'
......@@ -5,11 +5,11 @@ ar = 'ar'
strip = 'strip'
[properties]
winelib = true
needs_exe_wrapper = true
c_args = ['-m64']
cpp_args = ['-m64', '--no-gnu-unique']
cpp_link_args = ['-m64', '-mwindows']
c_args=['-m64']
cpp_args=['-m64', '--no-gnu-unique']
cpp_link_args=['-m64', '-mwindows']
[host_machine]
system = 'linux'
......
; File generated automatically from d3dcompiler_43.spec; do not edit!
LIBRARY d3dcompiler_43.dll
EXPORTS
D3DAssemble @1
D3DCompile @3
D3DCreateBlob @5
D3DDisassemble @8
D3DGetBlobPart @9
D3DGetDebugInfo @10
D3DGetInputAndOutputSignatureBlob @11
D3DGetInputSignatureBlob @12
D3DGetOutputSignatureBlob @13
D3DPreprocess @14
D3DReflect @15
D3DStripShader @17
; File generated automatically from d3dcompiler_43.spec; do not edit!
LIBRARY d3dcompiler_43.dll
EXPORTS
D3DAssemble@32 @1
D3DCompile@44 @3
D3DCreateBlob@8 @5
D3DDisassemble@20 @8
D3DGetBlobPart@20 @9
D3DGetDebugInfo@12 @10
D3DGetInputAndOutputSignatureBlob@12 @11
D3DGetInputSignatureBlob@12 @12
D3DGetOutputSignatureBlob@12 @13
D3DPreprocess@28 @14
D3DReflect@16 @15
D3DStripShader@16 @17
project('dxup', ['c', 'cpp'])
project('dxup', ['c', 'cpp'], version : 'v0.00', meson_version : '>= 0.43')
cpu_family = target_machine.cpu_family()
add_project_arguments('-DNOMINMAX', language : 'cpp')
dxup_compiler = meson.get_compiler('cpp')
......@@ -13,26 +12,58 @@ else
dxup_msvc=false
endif
if dxup_compiler.get_id() == 'msvc'
add_global_arguments('/std:' + dxup_cpp_std, language : 'cpp')
endif
if meson.get_cross_property('winelib', false)
if (cpu_family == 'x86_64')
dxup_library_path = meson.source_root() + '/lib'
else
dxup_library_path = meson.source_root() + '/lib32'
endif
code = '''#ifndef __WINE__
#error 1
#endif'''
dxup_winelib = dxup_compiler.compiles(code, name: 'winelib check')
dxup_extradep = [ ]
if dxup_winelib
lib_d3d11 = declare_dependency(link_args: [ '-ld3d11' ])
lib_dxgi = declare_dependency(link_args: [ '-ldxgi' ])
lib_shlwapi = declare_dependency(link_args: [ '-lshlwapi' ])
lib_d3dcompiler_43 = declare_dependency(link_args: [ '-L'+dxup_library_path, '-ld3dcompiler_43' ])
lib_d3dcompiler_47 = declare_dependency(link_args: [ '-ld3dcompiler' ])
dxup_extradep += [ declare_dependency(link_args: [ '-ldl' ]) ]
exe_ext = '.exe.so'
dll_ext = '.dll'
def_spec_ext = '.spec'
else
lib_d3d11 = dxup_compiler.find_library('d3d11')
lib_d3dcompiler_47 = dxup_compiler.find_library('d3dcompiler')
lib_d3d11 = dxup_compiler.find_library('d3d11')
lib_dxgi = dxup_compiler.find_library('dxgi')
lib_shlwapi = dxup_compiler.find_library('shlwapi')
lib_d3dcompiler_43 = dxup_compiler.find_library('d3dcompiler_43', dirs : dxup_library_path)
if dxup_compiler.get_id() == 'msvc'
lib_d3dcompiler_47 = dxup_compiler.find_library('d3dcompiler')
else
lib_d3dcompiler_47 = dxup_compiler.find_library('d3dcompiler_47')
endif
exe_ext = ''
dll_ext = ''
def_spec_ext = '.def'
endif
dxup_version = vcs_tag(
command: ['git', 'describe', '--always', '--dirty=+'],
input: 'version.h.in',
output: 'version.h')
subdir('src')
if dxup_compiler.get_id() != 'msvc'
subdir('wine_utils')
subdir('utils')
endif
option('enable_tests', type : 'boolean', value : false)
#!/bin/bash
set -e
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: package-release.sh version destdir [--no-package]"
exit 1
......@@ -10,6 +12,11 @@ DXUP_SRC_DIR=`dirname $(readlink -f $0)`
DXUP_BUILD_DIR=$(realpath "$2")"/dxup-$DXUP_VERSION"
DXUP_ARCHIVE_PATH=$(realpath "$2")"/dxup-$DXUP_VERSION.tar.gz"
if [ -e "$DXUP_BUILD_DIR" ]; then
echo "Build directory $DXUP_BUILD_DIR already exists"
exit 1
fi
function build_arch {
export WINEARCH="win$1"
export WINEPREFIX="$DXUP_BUILD_DIR/wine.$1"
......@@ -19,7 +26,6 @@ function build_arch {
meson --cross-file "$DXUP_SRC_DIR/build-win$1.txt" \
--buildtype "release" \
--prefix "$DXUP_BUILD_DIR/install.$1" \
--unity off \
--strip \
-Denable_tests=false \
"$DXUP_BUILD_DIR/build.$1"
......@@ -29,15 +35,16 @@ function build_arch {
mkdir "$DXUP_BUILD_DIR/x$1"
cp "$DXUP_BUILD_DIR/install.$1/bin/d3d10_1.dll" "$DXUP_BUILD_DIR/x$1/d3d10_1.dll"
cp "$DXUP_BUILD_DIR/install.$1/bin/dxgi.dll" "$DXUP_BUILD_DIR/x$1/dxgi.dll"
cp "$DXUP_BUILD_DIR/install.$1/bin/setup_dxup.sh" "$DXUP_BUILD_DIR/x$1/setup_dxup.sh"
cp "$DXUP_BUILD_DIR/install.$1/bin/d3d9.dll" "$DXUP_BUILD_DIR/x$1/d3d9.dll"
rm -R "$DXUP_BUILD_DIR/wine.$1"
rm -R "$DXUP_BUILD_DIR/build.$1"
rm -R "$DXUP_BUILD_DIR/install.$1"
}
function build_verb {
cp "$DXUP_SRC_DIR/utils/setup_dxup_d3d9.verb" "$DXUP_BUILD_DIR/setup_dxup_d3d9.verb"
}
function package {
cd "$DXUP_BUILD_DIR/.."
tar -czf "$DXUP_ARCHIVE_PATH" "dxup-$DXUP_VERSION"
......@@ -46,6 +53,7 @@ function package {
build_arch 64
build_arch 32
build_verb
if [ "$3" != "--no-package" ]; then
package
......
......@@ -36,75 +36,3 @@
#ifndef D3D11_KEEP_UNORDERED_ACCESS_VIEWS
#define D3D11_KEEP_UNORDERED_ACCESS_VIEWS 0xFFFFFFFF
#endif
// Most of these were copied from d3d11.h
// For some strange reason, we cannot use the structures
// directly, although others from the same header work.
// Some structures are missing from the mingw headers.
#ifndef _MSC_VER
typedef enum D3D11_FORMAT_SUPPORT2 {
D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD = 0x1,
D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS = 0x2,
D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 0x4,
D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE = 0x8,
D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX = 0x10,
D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 0x20,
D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD = 0x40,
D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE = 0x80,
D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP = 0x100,
D3D11_FORMAT_SUPPORT2_TILED = 0x200,
D3D11_FORMAT_SUPPORT2_SHAREABLE = 0x400,
D3D11_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x4000
} D3D11_FORMAT_SUPPORT2;
#ifndef __WINE__
typedef struct D3D11_FEATURE_DATA_FORMAT_SUPPORT2 {
DXGI_FORMAT InFormat;
UINT OutFormatSupport2;
} D3D11_FEATURE_DATA_FORMAT_SUPPORT2;
typedef struct D3D11_FEATURE_DATA_THREADING {
BOOL DriverConcurrentCreates;
BOOL DriverCommandLists;
} D3D11_FEATURE_DATA_THREADING;
typedef struct D3D11_FEATURE_DATA_DOUBLES {
BOOL DoublePrecisionFloatShaderOps;
} D3D11_FEATURE_DATA_DOUBLES;
typedef struct D3D11_FEATURE_DATA_FORMAT_SUPPORT {
DXGI_FORMAT InFormat;
UINT OutFormatSupport;
} D3D11_FEATURE_DATA_FORMAT_SUPPORT;
typedef struct D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS {
BOOL ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x;
} D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS;
typedef enum D3D11_BUFFEREX_SRV_FLAG {
D3D11_BUFFEREX_SRV_FLAG_RAW = 1
} D3D11_BUFFEREX_SRV_FLAG;
typedef enum D3D11_UAV_FLAG {
D3D11_BUFFER_UAV_FLAG_RAW = 0x1,
D3D11_BUFFER_UAV_FLAG_APPEND = 0x2,
D3D11_BUFFER_UAV_FLAG_COUNTER = 0x4
} D3D11_UAV_FLAG;
typedef struct D3D11_QUERY_DATA_PIPELINE_STATISTICS {
UINT64 IAVertices;
UINT64 IAPrimitives;
UINT64 VSInvocations;
UINT64 GSInvocations;
UINT64 GSPrimitives;
UINT64 CInvocations;
UINT64 CPrimitives;
UINT64 PSInvocations;
UINT64 HSInvocations;
UINT64 DSInvocations;
UINT64 CSInvocations;
} D3D11_QUERY_DATA_PIPELINE_STATISTICS;
typedef struct D3D11_FEATURE_DATA_ARCHITECTURE_INFO {
BOOL TileBasedDeferredRenderer;
} D3D11_FEATURE_DATA_ARCHITECTURE_INFO;
typedef struct D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT {
UINT PixelShaderMinPrecision;
UINT AllOtherShaderStagesMinPrecision;
} D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT;
typedef struct D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT {
BOOL SupportsDepthAsTextureWithLessEqualComparisonFilter;
} D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT;
#endif // __WINE__
#endif // _MSC_VER
......@@ -16,7 +16,7 @@ d3d10_1_src = [
d3d10_1_dll = shared_library('d3d10_1'+dll_ext, d3d10_1_src,
name_prefix : '',
install : true,
install : false,
dependencies : [ lib_d3d11, lib_d3dcompiler_47 ],
objects : not dxup_msvc ? 'd3d10_1'+def_spec_ext : [],
vs_module_defs : 'd3d10_1'+def_spec_ext,
......
#include "d3d11_dynamic_buffer.h"
namespace dxup {
D3D11DynamicBuffer::D3D11DynamicBuffer(ID3D11Device* device, uint32_t bindFlags)
: m_device{ device }
, m_size{ 0 }
, m_offset{ 0 }
, m_bindFlags{ bindFlags } {}
ID3D11Buffer* D3D11DynamicBuffer::getBuffer() {
return m_buffer.ptr();
}
void D3D11DynamicBuffer::reserve(uint32_t length) {
if (m_buffer != nullptr && m_size >= m_offset + length)
return;
m_buffer = nullptr;
D3D11_BUFFER_DESC desc;
desc.ByteWidth = m_offset + length;
desc.BindFlags = m_bindFlags;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
Com<ID3D11Buffer> buffer;
HRESULT result = m_device->CreateBuffer(&desc, nullptr, &buffer);
if (FAILED(result)) {
log::warn("reserve: CreateBuffer failed (length = %d + %d.)", m_offset + length);
return;
}
m_buffer = buffer;
m_size = m_offset + length;
m_offset = 0;
return;
}
uint32_t D3D11DynamicBuffer::update(ID3D11DeviceContext* context, const void* src, uint32_t length) {
void* data;
this->map(context, &data, length);
std::memcpy(&data, src, length);
return this->unmap(context, length);
}
void D3D11DynamicBuffer::map(ID3D11DeviceContext* context, void** data, uint32_t length) {
D3D11_MAPPED_SUBRESOURCE res;
context->Map(m_buffer.ptr(), 0, m_offset == 0 ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE, 0, &res);
uint8_t* resourceData = (uint8_t*)res.pData;
*data = resourceData + m_offset;
}
uint32_t D3D11DynamicBuffer::unmap(ID3D11DeviceContext* context, uint32_t length) {
context->Unmap(m_buffer.ptr(), 0);
uint32_t offset = m_offset;
m_offset += length;
return offset;
}
void D3D11DynamicBuffer::endFrame() {
m_offset = 0;
}
}
\ No newline at end of file
#pragma once
#include "d3d9_base.h"
namespace dxup {
class D3D11DynamicBuffer {
public:
D3D11DynamicBuffer(ID3D11Device* device, uint32_t bindFlags);
void reserve(uint32_t length);
uint32_t update(ID3D11DeviceContext* context, const void* src, uint32_t length);
void map(ID3D11DeviceContext* context, void** data, uint32_t length);
uint32_t unmap(ID3D11DeviceContext* context, uint32_t length);
void endFrame();
ID3D11Buffer* getBuffer();
private:
ID3D11Device* m_device;
Com<ID3D11Buffer> m_buffer;
uint32_t m_size;
uint32_t m_offset;
uint32_t m_bindFlags;
};
}
\ No newline at end of file
LIBRARY D3D9.DLL
EXPORTS
Direct3DCreate9
Direct3DCreate9Ex
D3DPERF_BeginEvent
D3DPERF_EndEvent
D3DPERF_SetMarker
D3DPERF_SetRegion
D3DPERF_QueryRepeatFrame
D3DPERF_SetOptions
D3DPERF_GetStatus
@ stdcall Direct3DCreate9(long)
@ stdcall Direct3DCreate9Ex(long ptr)
@ stdcall D3DPERF_BeginEvent(long wstr)
@ stdcall D3DPERF_EndEvent()
@ stdcall D3DPERF_SetMarker(long wstr)
@ stdcall D3DPERF_SetRegion(long wstr)
@ stdcall D3DPERF_QueryRepeatFrame()
@ stdcall D3DPERF_SetOptions(long)
@ stdcall D3DPERF_GetStatus()
#pragma once
#include "../util/unknown.h"
#include "../util/misc_helpers.h"
#include "d3d9_includes.h"
#include "d3d9_definitions.h"
#include "d3d9_util.h"
\ No newline at end of file
#pragma once
#include "d3d9_resource.h"
#include "d3d9_d3d11_resource.h"
#include <vector>
namespace dxup {
template <D3DRESOURCETYPE ResourceType, typename ID3D9BaseType>
class Direct3DBuffer9 : public Direct3DResource9<ResourceType, ID3D9BaseType>
{
public:
Direct3DBuffer9(Direct3DDevice9Ex* device, DXUPResource* resource, const D3D9ResourceDesc& d3d9Desc)
: Direct3DResource9<ResourceType, ID3D9BaseType>{ device, resource, d3d9Desc } {}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObj) override {
InitReturnPtr(ppvObj);
if (ppvObj == nullptr)
return E_POINTER;
if (riid == __uuidof(ID3D9BaseType) || riid == __uuidof(IDirect3DResource9) || riid == __uuidof(IUnknown)) {
*ppvObj = ref(this);
return D3D_OK;
}
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE Lock(UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) override {
InitReturnPtr(ppbData);
if (ppbData == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "ReturnPtr for buffer lock was null!");
D3DLOCKED_BOX lockedBox;
D3DBOX boxToLock;
boxToLock.Top = 0;
boxToLock.Bottom = 1;
boxToLock.Left = OffsetToLock;
boxToLock.Right = OffsetToLock + SizeToLock;
boxToLock.Front = 0;
boxToLock.Back = 1;
bool degenerate = OffsetToLock == 0 && SizeToLock == 0;
HRESULT result = this->GetDXUPResource()->D3D9LockBox(0, 0, &lockedBox, degenerate ? nullptr : &boxToLock, Flags, this->GetD3D9Desc().Usage);
if (FAILED(result))
return result;
*ppbData = lockedBox.pBits;
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE Unlock() override {
return this->GetDXUPResource()->D3D9UnlockBox(0, 0);
}
};
using Direct3DVertexBuffer9Base = Direct3DBuffer9<D3DRTYPE_VERTEXBUFFER, IDirect3DVertexBuffer9>;
class Direct3DVertexBuffer9 final : public Direct3DVertexBuffer9Base {
public:
Direct3DVertexBuffer9(Direct3DDevice9Ex* device, DXUPResource* resource, const D3D9ResourceDesc& d3d9Desc)
: Direct3DVertexBuffer9Base{ device, resource, d3d9Desc } { }
HRESULT STDMETHODCALLTYPE GetDesc(D3DVERTEXBUFFER_DESC *pDesc) override {
D3D11_BUFFER_DESC desc;
this->GetDXUPResource()->GetResourceAs<ID3D11Buffer>()->GetDesc(&desc);
pDesc->Format = D3DFMT_VERTEXDATA;
pDesc->FVF = this->GetD3D9Desc().FVF;
pDesc->Pool = this->GetD3D9Desc().Pool;
pDesc->Size = desc.ByteWidth;
pDesc->Type = D3DRTYPE_VERTEXBUFFER;
pDesc->Usage = this->GetD3D9Desc().Usage;
return D3D_OK;
}
};
using Direct3DIndexBuffer9Base = Direct3DBuffer9<D3DRTYPE_INDEXBUFFER, IDirect3DIndexBuffer9>;
class Direct3DIndexBuffer9 final : public Direct3DIndexBuffer9Base {
public:
Direct3DIndexBuffer9(Direct3DDevice9Ex* device, DXUPResource* resource, const D3D9ResourceDesc& d3d9Desc)
: Direct3DIndexBuffer9Base{ device, resource, d3d9Desc } {}
HRESULT STDMETHODCALLTYPE GetDesc(D3DINDEXBUFFER_DESC *pDesc) override {
D3D11_BUFFER_DESC d3d11Desc;
this->GetDXUPResource()->GetResourceAs<ID3D11Buffer>()->GetDesc(&d3d11Desc);
const D3D9ResourceDesc& d3d9Desc = this->GetD3D9Desc();
pDesc->Format = d3d9Desc.Format;
pDesc->Pool = d3d9Desc.Pool;
pDesc->Size = d3d11Desc.ByteWidth;
pDesc->Type = D3DRTYPE_INDEXBUFFER;
pDesc->Usage = d3d9Desc.Usage;
return D3D_OK;
}
};
}
\ No newline at end of file
#pragma once
#include "../dx9asm/dx9asm_meta.h"
#include "d3d9_base.h"
#include <array>
#include <memory>
#include <cstring>
#include "../util/vectypes.h"
#include "d3d11_dynamic_buffer.h"
namespace dxup {
struct D3D9ShaderConstants {
D3D9ShaderConstants() {
std::memset(floatConstants.data(), 0, floatConstants.size() * sizeof(floatConstants[0]));
std::memset(intConstants.data(), 0, intConstants.size() * sizeof(intConstants[0]));
std::memset(boolConstants.data(), 0, boolConstants.size() * sizeof(boolConstants[0]));
}
std::array<Vector<float, 4>, 256> floatConstants;
std::array<Vector<int, 4>, 16> intConstants;
std::array<int, 16> boolConstants;
};
template <bool Pixel>
class D3D9ConstantBuffer {
public:
D3D9ConstantBuffer(ID3D11Device1* device, ID3D11DeviceContext1* context)
: m_device{ device }
, m_context{ context }
, m_buffer{ device, D3D11_BIND_CONSTANT_BUFFER }
, m_offset{ 0 } {
}
constexpr uint32_t getConstantSize() {
return 4 * sizeof(float);
}
constexpr uint32_t getLength() {
uint32_t length = sizeof(D3D9ShaderConstants::floatConstants) + sizeof(D3D9ShaderConstants::intConstants) + (4 * sizeof(D3D9ShaderConstants::boolConstants));
return alignTo(length, 16 * getConstantSize());
}
constexpr uint32_t getConstantCount() {
return getLength() / (getConstantSize());
}
void update(const D3D9ShaderConstants& constants) {
const uint32_t length = getLength();
m_buffer.reserve(length); // TODO make bool constants a bitfield.
uint8_t* data;
m_buffer.map(m_context, (void**)(&data), length);
// This can probably be consolidated into a single one.
std::memcpy(data, constants.floatConstants.data(), sizeof(constants.floatConstants));
std::memcpy(data + sizeof(constants.floatConstants), constants.intConstants.data(), sizeof(constants.intConstants));
int* boolData = (int*)(data + sizeof(constants.floatConstants) + sizeof(constants.intConstants));
for (uint32_t i = 0; i < constants.boolConstants.size(); i++) {
for (uint32_t j = 0; j < 4; j++)
boolData[i * 4 + j] = constants.boolConstants[i];
}
m_offset = m_buffer.unmap(m_context, length);
bind();
}
void bind() {
const uint32_t constantOffset = m_offset / getConstantSize();
const uint32_t constantCount = getConstantCount();
ID3D11Buffer* buffer = m_buffer.getBuffer();
if constexpr (Pixel)
m_context->PSSetConstantBuffers1(0, 1, &buffer, &constantOffset, &constantCount);
else
m_context->VSSetConstantBuffers1(0, 1, &buffer, &constantOffset, &constantCount);
}
void endFrame() {
m_buffer.endFrame();
}
private:
// I exist as long as my parent D3D9 device exists. No need for COM.
ID3D11Device1* m_device;
ID3D11DeviceContext1* m_context;
D3D11DynamicBuffer m_buffer;
uint32_t m_offset;
};
}
\ No newline at end of file
#include "d3d9_d3d11_resource.h"
#include "d3d9_util.h"
#include <algorithm>
namespace dxup {
// If we are not a dynamic resource or we need read access on our dynamic, we have a staging buffer.
// We then map this and CopySubresourceRegion on unmapping.
// If we don't need the staging res. will be nullptr, some logic relies on this.
bool DXUPResource::NeedsStaging(D3D11_USAGE d3d11Usage, DWORD d3d9Usage, D3DFORMAT d3d9Format) {
if (d3d11Usage == D3D11_USAGE_DEFAULT)
return true;
if (d3d9Format == D3DFMT_R8G8B8)
return true;
if (d3d11Usage == D3D11_USAGE_STAGING)
return false;
if (!(d3d9Usage & D3DUSAGE_WRITEONLY))
return true;
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);
Com<ID3D11ShaderResourceView> srv;
Com<ID3D11ShaderResourceView> srvSRGB;
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) {
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
if (desc.ArraySize == 1) {
srvDesc.ViewDimension = D3D10_1_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 0xFFFFFFFF;
srvDesc.Texture2D.MostDetailedMip = 0;
}
else {
srvDesc.ViewDimension = D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MipLevels = 0xFFFFFFFF;
srvDesc.Texture2DArray.MostDetailedMip = 0;
srvDesc.Texture2DArray.FirstArraySlice = 0;
srvDesc.Texture2DArray.ArraySize = -1;
}
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<ID3D11Texture2D> stagingTexture;
Com<ID3D11Texture2D> fixup8888;
if (NeedsStaging(desc.Usage, d3d9Usage, d3d9Format)) {
makeStagingDesc(desc, d3d9Usage, d3d9Format);
device->GetD3D11Device()->CreateTexture2D(&desc, nullptr, &stagingTexture);
if (d3d9Format == D3DFMT_R8G8B8)
device->GetD3D11Device()->CreateTexture2D(&desc, nullptr, &fixup8888);
}
return new DXUPResource(device, texture, stagingTexture.ptr(), fixup8888.ptr(), srv.ptr(), srvSRGB.ptr(), desc.Format, desc.ArraySize, std::max(desc.MipLevels, 1u), desc.Usage == D3D11_USAGE_DYNAMIC);
}
DXUPResource* DXUPResource::CreateBuffer(Direct3DDevice9Ex* device, ID3D11Buffer* buffer, DWORD d3d9Usage) {
D3D11_BUFFER_DESC desc;
buffer->GetDesc(&desc);
Com<ID3D11Buffer> stagingBuffer;
if (NeedsStaging(desc.Usage, d3d9Usage, D3DFMT_UNKNOWN)) {
makeStagingDesc(desc, d3d9Usage, D3DFMT_UNKNOWN);
device->GetD3D11Device()->CreateBuffer(&desc, nullptr, &stagingBuffer);
}
return new DXUPResource(device, buffer, stagingBuffer.ptr(), nullptr, nullptr, nullptr, DXGI_FORMAT_R8_TYPELESS, 1, 1, desc.Usage == D3D11_USAGE_DYNAMIC);
}
DXUPResource* DXUPResource::Create(Direct3DDevice9Ex* device, ID3D11Resource* resource, DWORD d3d9Usage, D3DFORMAT d3d9Format) {
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)
return CreateBuffer(device, useAs<ID3D11Buffer>(resource), d3d9Usage);
log::fail("Unable to create DXUP resource for unknown type.");
return nullptr;
}
bool DXUPResource::HasStaging() {
return GetStaging() != nullptr;
}
ID3D11Resource* DXUPResource::GetResource() {
return GetResourceAs<ID3D11Resource>();
}
ID3D11Resource* DXUPResource::GetStaging() {
return GetStagingAs<ID3D11Resource>();
}
ID3D11Resource* DXUPResource::GetMapping() {
return GetMappingAs<ID3D11Resource>();
}
ID3D11ShaderResourceView* DXUPResource::GetSRV(bool srgb) {
if (srgb && m_srvSRGB != nullptr)
return m_srvSRGB.ptr();
return m_srv.ptr();
}
UINT DXUPResource::GetSlices() {
return m_slices;
}
UINT DXUPResource::GetMips() {
return m_mips;
}
UINT DXUPResource::GetSubresources() {
return m_slices * m_mips;
}
void DXUPResource::SetMipMapped(UINT slice, UINT mip) {
m_mappedSubresources[slice] |= 1ull << mip;
}
void DXUPResource::SetMipUnmapped(UINT slice, UINT mip) {
m_unmappedSubresources[slice] |= 1ull << mip;
}
uint64_t DXUPResource::GetChangedMips(UINT slice) {
return m_mappedSubresources[slice];
}
bool DXUPResource::CanPushStaging() {
for (uint32_t i = 0; i < GetSlices(); i++) {
if ((m_mappedSubresources[i] - m_unmappedSubresources[i]) != 0)
return false;
}
return true;
}
void DXUPResource::ResetMipMapTracking() {
for (uint32_t slice = 0; slice < GetSlices(); slice++) {
m_mappedSubresources[slice] = 0;
m_unmappedSubresources[slice] = 0;
}
}
HRESULT STDMETHODCALLTYPE DXUPResource::QueryInterface(REFIID riid, void** ppvObj) {
InitReturnPtr(ppvObj);
log::warn("QueryInterface called on DXUPResource.");
return E_NOINTERFACE;
}
DXGI_FORMAT DXUPResource::GetDXGIFormat() {
return m_dxgiFormat;
}
DXUPResource::DXUPResource(Direct3DDevice9Ex* device, ID3D11Resource* resource, ID3D11Resource* staging, ID3D11Resource* fixup8888, ID3D11ShaderResourceView* srv, ID3D11ShaderResourceView* srvSRGB, DXGI_FORMAT dxgiFormat, UINT slices, UINT mips, bool dynamic)
: m_device{ device }
, m_resource{ resource }
, m_staging{ staging }
, m_fixup8888{ fixup8888 }
, m_srv{ srv }
, m_srvSRGB{ srvSRGB }
, m_slices{ slices }
, m_mips{ mips }
, m_dxgiFormat{ dxgiFormat }
, m_dynamic{ dynamic } {
m_stagingBoxes.resize(GetSubresources());
ResetMipMapTracking();
for (uint32_t i = 0; i < 6; i++)
m_dirtySubresources[i] = 0;
}
}
\ No newline at end of file
#pragma once
#include "d3d9_base.h"
#include "d3d9_device.h"
namespace dxup {
class DXUPResource : public Unknown<IUnknown> {
public:
static DXUPResource* Create(Direct3DDevice9Ex* device, ID3D11Resource* resource, DWORD d3d9Usage, D3DFORMAT d3d9Format);
bool HasStaging();
template <typename T>
T* GetResourceAs() {
return reinterpret_cast<T*>(m_resource.ptr());
}
template <typename T>
T* GetStagingAs() {
return reinterpret_cast<T*>(m_staging.ptr());
}
template <typename T>
T* GetMappingAs() {
if (HasStaging())
return GetStagingAs<T>();
return GetResourceAs<T>();
}
ID3D11Resource* GetResource();
ID3D11Resource* GetStaging();
ID3D11Resource* GetMapping();
ID3D11ShaderResourceView* GetSRV(bool srgb);
UINT GetSlices();
UINT GetMips();
UINT GetSubresources();
void SetMipMapped(UINT slice, UINT mip);
void SetMipUnmapped(UINT slice, UINT mip);
void MarkDirty(UINT slice, UINT mip);
void MakeClean();
uint64_t GetChangedMips(UINT slice);
bool CanPushStaging();
void ResetMipMapTracking();
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObj) override;
HRESULT D3D9LockBox(UINT slice, UINT mip, D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags, DWORD Usage);
HRESULT D3D9UnlockBox(UINT slice, UINT mip);
DXGI_FORMAT GetDXGIFormat();
private:
UINT CalcMapFlags(UINT d3d9LockFlags);
D3D11_MAP CalcMapType(UINT d3d9LockFlags, DWORD d3d9Usage);
void PushStaging();
Direct3DDevice9Ex* m_device;
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);
UINT m_slices;
UINT m_mips;
DXGI_FORMAT m_dxgiFormat;
uint64_t m_mappedSubresources[6];
uint64_t m_unmappedSubresources[6];
uint64_t m_dirtySubresources[6];
Com<ID3D11Resource> m_resource;
Com<ID3D11Resource> m_staging;
Com<ID3D11Resource> m_fixup8888;
bool IsStagingBoxDegenerate(UINT subresource);
std::vector<D3DBOX> m_stagingBoxes;
bool m_dynamic;
Com<ID3D11ShaderResourceView> m_srv;
Com<ID3D11ShaderResourceView> m_srvSRGB;
};
}
\ No newline at end of file
#include "d3d9_d3d11_resource.h"
#include "d3d9_format.h"
namespace dxup {
bool DXUPResource::IsStagingBoxDegenerate(UINT subresource) {
return isBoxDegenerate(m_stagingBoxes[subresource]);
}
UINT DXUPResource::CalcMapFlags(UINT d3d9LockFlags) {
return d3d9LockFlags & D3DLOCK_DONOTWAIT ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0;
}
D3D11_MAP DXUPResource::CalcMapType(UINT d3d9LockFlags, DWORD d3d9Usage) {
if (m_dynamic) {
if (d3d9LockFlags & D3DLOCK_NOOVERWRITE)
return D3D11_MAP_WRITE_NO_OVERWRITE;
if (d3d9LockFlags & D3DLOCK_DISCARD)
return D3D11_MAP_WRITE_DISCARD;
}
if (d3d9LockFlags & D3DLOCK_READONLY)
return D3D11_MAP_READ;
if (d3d9Usage & D3DUSAGE_WRITEONLY)
return D3D11_MAP_WRITE;
return D3D11_MAP_READ_WRITE;
}
void DXUPResource::MarkDirty(UINT slice, UINT mip) {
m_dirtySubresources[slice] = 1ull << mip;
}
void DXUPResource::MakeClean() {
bool dirty = false;
for (uint32_t slice = 0; slice < m_slices; slice++) {
if (m_dirtySubresources[slice] != 0)
dirty = true;
}
if (!dirty)
return;
// This is needed for RTs, we only want staging buffers for them if they NEED them.
if (GetStaging() == nullptr) {
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D* tex = GetResourceAs<ID3D11Texture2D>();
tex->GetDesc(&desc);
makeStagingDesc(desc, 0, D3DFMT_UNKNOWN);
m_device->GetD3D11Device()->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**)&m_staging);
}
for (uint32_t slice = 0; slice < m_slices; slice++) {
uint64_t* dirtyFlags = &m_dirtySubresources[slice];
for (uint64_t mip = 0; mip < m_mips; mip++) {
UINT subresource = D3D11CalcSubresource(mip, slice, m_mips);
if (*dirtyFlags & (1ull << mip))
m_device->GetContext()->CopySubresourceRegion(GetStaging(), subresource, 0, 0, 0, GetResource(), subresource, nullptr);
}
*dirtyFlags = 0;
}
}
HRESULT DXUPResource::D3D9LockBox(UINT slice, UINT mip, D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags, DWORD Usage) {
CriticalSection cs(m_device);
if (pLockedBox == nullptr)
return log::d3derr(D3DERR_INVALIDCALL, "D3D9LockBox: return value (locked box) was nullptr.");
pLockedBox->pBits = nullptr;
pLockedBox->RowPitch = 0;
pLockedBox->SlicePitch = 0;
UINT subresource = D3D11CalcSubresource(mip, slice, m_mips);
if (pBox == nullptr)
std::memset(&m_stagingBoxes[subresource], 0, sizeof(D3DBOX));
else
m_stagingBoxes[subresource] = *pBox;
if (!(Flags & D3DLOCK_DISCARD) && !(Flags & D3DLOCK_NOOVERWRITE) && !(Usage & D3DUSAGE_WRITEONLY))
MakeClean();
D3D11_MAPPED_SUBRESOURCE res;
HRESULT result = m_device->GetContext()->Map(GetMapping(), subresource, CalcMapType(Flags, Usage), CalcMapFlags(Flags), &res);
if (result == DXGI_ERROR_WAS_STILL_DRAWING)
return D3DERR_WASSTILLDRAWING;
if (FAILED(result))
return log::d3derr(D3DERR_INVALIDCALL, "D3D9LockRect: unknown error mapping subresource.");
SetMipMapped(slice, mip);
size_t offset = 0;
if (!IsStagingBoxDegenerate(subresource))
offset = (m_stagingBoxes[subresource].Top * res.RowPitch) + (m_stagingBoxes[subresource].Left * bitsPerPixel(m_dxgiFormat) / 8);
uint8_t* data = (uint8_t*)res.pData;
pLockedBox->pBits = &data[offset];
pLockedBox->RowPitch = res.RowPitch;
pLockedBox->SlicePitch = res.DepthPitch;
return D3D_OK;
}
HRESULT DXUPResource::D3D9UnlockBox(UINT slice, UINT mip) {
CriticalSection cs(m_device);
UINT subresource = D3D11CalcSubresource(mip, slice, m_mips);
ID3D11DeviceContext* context = m_device->GetContext();
context->Unmap(GetMapping(), D3D11CalcSubresource(mip, slice, m_mips));
SetMipUnmapped(slice, mip);
// We need to make this format an 8888. DXGI has no 888 type.
if (m_fixup8888 != nullptr) {
D3D11_MAPPED_SUBRESOURCE d3d9Res;
D3D11_MAPPED_SUBRESOURCE fixupRes;
context->Map(GetStaging(), subresource, D3D11_MAP_READ, 0, &d3d9Res);
context->Map(m_fixup8888.ptr(), subresource, D3D11_MAP_WRITE, 0, &fixupRes);
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D* texture = reinterpret_cast<ID3D11Texture2D*>(m_staging.ptr());
texture->GetDesc(&desc);
uint8_t* read = (uint8_t*)d3d9Res.pData;
uint8_t* write = (uint8_t*)fixupRes.pData;
// TODO: Investigate if this is right or good enough.
uint32_t mippedHeight = std::max(1u, desc.Height >> mip);
uint32_t mippedWidth = std::max(1u, desc.Width >> mip);
for (uint32_t y = 0; y < mippedHeight; y++) {
for (uint32_t x = 0; x < mippedWidth; x++) {
for (uint32_t c = 0; c < 3; c++) {
write[y * fixupRes.RowPitch + x * 4 + c] = read[y * fixupRes.RowPitch + x * 3 + c];
}
write[y * fixupRes.RowPitch + x * 4 + 3] = 255;
}
}
context->Unmap(m_fixup8888.ptr(), subresource);
context->Unmap(GetStaging(), subresource);
}
if (HasStaging() && CanPushStaging())
PushStaging();
return D3D_OK;
}
void DXUPResource::PushStaging() {
for (uint32_t slice = 0; slice < m_slices; slice++) {
uint64_t delta = GetChangedMips(slice);
for (uint64_t mip = 0; mip < m_mips; mip++) {
UINT subresource = D3D11CalcSubresource(mip, slice, m_mips);
bool useRect = !IsStagingBoxDegenerate(subresource);
D3D11_BOX box = { 0 };
if (useRect) {
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);
}
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))
m_device->GetContext()->CopySubresourceRegion(GetResource(), subresource, box.left, box.top, 0, m_fixup8888 == nullptr ? GetStaging() : m_fixup8888.ptr(), subresource, useRect ? &box : nullptr);
}
}
ResetMipMapTracking();
}
}
\ No newline at end of file
#pragma once
#include "d3d9_includes.h"