Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c0ba97d
feat(d3d12): add `ID3D12GraphicsCommandList2` stubs
9Shain Aug 17, 2026
6df01b4
feat(d3d12): add `ID3D12Device3` stubs
9Shain Aug 17, 2026
bee9778
feat(winemetal): expose full texture copy command
9Shain Aug 17, 2026
f85c40b
feat(d3d12): introduce `AllocateTempBuffer()` in command allocator
9Shain Aug 18, 2026
8cd10ab
feat(d3d12): implement copying single planar between depth-stencil te…
9Shain Aug 18, 2026
05026d6
feat(d3d12): implement simple copy between strictly-compatible textures
9Shain Aug 18, 2026
bc17f9d
feat(d3d12): implement `GetHeapProperties()` for texture resource
9Shain Aug 18, 2026
b5c8e25
feat(winemetal): expose `getBytes` for metal texture
9Shain Aug 18, 2026
ecb2085
fix(d3d12): correct swapchain backbuffer resource descriptor
9Shain Aug 18, 2026
78592e1
feat(d3d12): implement `CreatePipelineState()`
9Shain Aug 18, 2026
742a631
feat(d3d12): honor depth plane in clear encoder
9Shain Aug 19, 2026
66e09eb
feat(d3d12): implement more edge cases of `CopyTextureRegion()`
9Shain Aug 20, 2026
8d8afb0
feat: add render target formats into PSO data
9Shain Aug 20, 2026
e4c8e13
feat(d3d12): handle invalid integer blending
9Shain Aug 20, 2026
af84c4a
chore(d3d12): pass heap offset to placed resource factory functions
9Shain Aug 21, 2026
4c5c1c4
fix(d3d12): set correct stencil reference in `UpdateGraphicsPSO()`
9Shain Aug 24, 2026
8fffd6b
feat(d3d12): add `OMSetDepthBounds()` stub
9Shain Aug 24, 2026
e55ad28
fix(d3d12, dxgi): make some stubs non-fatal
9Shain Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions src/airconv/air_signature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,4 +693,146 @@ to_air_scaler_type(dxmt::shader::common::ScalerDataType type) {
}
}

enum class MTLPixelFormat : uint32_t {
Invalid = 0,
A8Unorm = 1,
R8Unorm = 10,
R8Unorm_sRGB = 11,
R8Snorm = 12,
R8Uint = 13,
R8Sint = 14,
R16Unorm = 20,
R16Snorm = 22,
R16Uint = 23,
R16Sint = 24,
R16Float = 25,
RG8Unorm = 30,
RG8Unorm_sRGB = 31,
RG8Snorm = 32,
RG8Uint = 33,
RG8Sint = 34,
B5G6R5Unorm = 40,
A1BGR5Unorm = 41,
ABGR4Unorm = 42,
BGR5A1Unorm = 43,
R32Uint = 53,
R32Sint = 54,
R32Float = 55,
RG16Unorm = 60,
RG16Snorm = 62,
RG16Uint = 63,
RG16Sint = 64,
RG16Float = 65,
RGBA8Unorm = 70,
RGBA8Unorm_sRGB = 71,
RGBA8Snorm = 72,
RGBA8Uint = 73,
RGBA8Sint = 74,
BGRA8Unorm = 80,
BGRA8Unorm_sRGB = 81,
RGB10A2Unorm = 90,
RGB10A2Uint = 91,
RG11B10Float = 92,
RGB9E5Float = 93,
BGR10A2Unorm = 94,
BGR10_XR = 554,
BGR10_XR_sRGB = 555,
RG32Uint = 103,
RG32Sint = 104,
RG32Float = 105,
RGBA16Unorm = 110,
RGBA16Snorm = 112,
RGBA16Uint = 113,
RGBA16Sint = 114,
RGBA16Float = 115,
BGRA10_XR = 552,
BGRA10_XR_sRGB = 553,
RGBA32Uint = 123,
RGBA32Sint = 124,
RGBA32Float = 125,
BC1_RGBA = 130,
BC1_RGBA_sRGB = 131,
BC2_RGBA = 132,
BC2_RGBA_sRGB = 133,
BC3_RGBA = 134,
BC3_RGBA_sRGB = 135,
BC4_RUnorm = 140,
BC4_RSnorm = 141,
BC5_RGUnorm = 142,
BC5_RGSnorm = 143,
BC6H_RGBFloat = 150,
BC6H_RGBUfloat = 151,
BC7_RGBAUnorm = 152,
BC7_RGBAUnorm_sRGB = 153,
PVRTC_RGB_2BPP = 160,
PVRTC_RGB_2BPP_sRGB = 161,
PVRTC_RGB_4BPP = 162,
PVRTC_RGB_4BPP_sRGB = 163,
PVRTC_RGBA_2BPP = 164,
PVRTC_RGBA_2BPP_sRGB = 165,
PVRTC_RGBA_4BPP = 166,
PVRTC_RGBA_4BPP_sRGB = 167,
EAC_R11Unorm = 170,
EAC_R11Snorm = 172,
EAC_RG11Unorm = 174,
EAC_RG11Snorm = 176,
EAC_RGBA8 = 178,
EAC_RGBA8_sRGB = 179,
ETC2_RGB8 = 180,
ETC2_RGB8_sRGB = 181,
ETC2_RGB8A1 = 182,
ETC2_RGB8A1_sRGB = 183,
ASTC_4x4_sRGB = 186,
ASTC_5x4_sRGB = 187,
ASTC_5x5_sRGB = 188,
ASTC_6x5_sRGB = 189,
ASTC_6x6_sRGB = 190,
ASTC_8x5_sRGB = 192,
ASTC_8x6_sRGB = 193,
ASTC_8x8_sRGB = 194,
ASTC_10x5_sRGB = 195,
ASTC_10x6_sRGB = 196,
ASTC_10x8_sRGB = 197,
ASTC_10x10_sRGB = 198,
ASTC_12x10_sRGB = 199,
ASTC_12x12_sRGB = 200,
ASTC_4x4_LDR = 204,
ASTC_5x4_LDR = 205,
ASTC_5x5_LDR = 206,
ASTC_6x5_LDR = 207,
ASTC_6x6_LDR = 208,
ASTC_8x5_LDR = 210,
ASTC_8x6_LDR = 211,
ASTC_8x8_LDR = 212,
ASTC_10x5_LDR = 213,
ASTC_10x6_LDR = 214,
ASTC_10x8_LDR = 215,
ASTC_10x10_LDR = 216,
ASTC_12x10_LDR = 217,
ASTC_12x12_LDR = 218,
ASTC_4x4_HDR = 222,
ASTC_5x4_HDR = 223,
ASTC_5x5_HDR = 224,
ASTC_6x5_HDR = 225,
ASTC_6x6_HDR = 226,
ASTC_8x5_HDR = 228,
ASTC_8x6_HDR = 229,
ASTC_8x8_HDR = 230,
ASTC_10x5_HDR = 231,
ASTC_10x6_HDR = 232,
ASTC_10x8_HDR = 233,
ASTC_10x10_HDR = 234,
ASTC_12x10_HDR = 235,
ASTC_12x12_HDR = 236,
GBGR422 = 240,
BGRG422 = 241,
Depth16Unorm = 250,
Depth32Float = 252,
Stencil8 = 253,
Depth24Unorm_Stencil8 = 255,
Depth32Float_Stencil8 = 260,
X32_Stencil8 = 261,
X24_Stencil8 = 262,
};

} // namespace dxmt::air
2 changes: 2 additions & 0 deletions src/airconv/airconv_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ struct SM50_SHADER_PSO_PIXEL_SHADER_DATA {
bool dual_source_blending;
bool disable_depth_output;
uint32_t unorm_output_reg_mask;
/** MTLPixelFormat */
uint32_t pixel_formats[8];
};

struct SM50_IA_INPUT_ELEMENT {
Expand Down
85 changes: 85 additions & 0 deletions src/airconv/dxbc_converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,87 @@ void setup_metal_version(llvm::Module &module, SM50_SHADER_METAL_VERSION metal_v
}
}

RegisterComponentType
component_type_from_pixel_format(air::MTLPixelFormat format) {
switch (format) {
case air::MTLPixelFormat::R8Sint:
case air::MTLPixelFormat::R16Sint:
case air::MTLPixelFormat::RG8Sint:
case air::MTLPixelFormat::R32Sint:
case air::MTLPixelFormat::RG16Sint:
case air::MTLPixelFormat::RGBA8Sint:
case air::MTLPixelFormat::RG32Sint:
case air::MTLPixelFormat::RGBA16Sint:
case air::MTLPixelFormat::RGBA32Sint:
return RegisterComponentType::Int;
case air::MTLPixelFormat::R8Uint:
case air::MTLPixelFormat::R16Uint:
case air::MTLPixelFormat::RG8Uint:
case air::MTLPixelFormat::R32Uint:
case air::MTLPixelFormat::RG16Uint:
case air::MTLPixelFormat::RGBA8Uint:
case air::MTLPixelFormat::RGB10A2Uint:
case air::MTLPixelFormat::RG32Uint:
case air::MTLPixelFormat::RGBA16Uint:
case air::MTLPixelFormat::RGBA32Uint:
return RegisterComponentType::Uint;
case air::MTLPixelFormat::A8Unorm:
case air::MTLPixelFormat::R8Unorm:
case air::MTLPixelFormat::R8Unorm_sRGB:
case air::MTLPixelFormat::R8Snorm:
case air::MTLPixelFormat::R16Unorm:
case air::MTLPixelFormat::R16Snorm:
case air::MTLPixelFormat::R16Float:
case air::MTLPixelFormat::RG8Unorm:
case air::MTLPixelFormat::RG8Unorm_sRGB:
case air::MTLPixelFormat::RG8Snorm:
case air::MTLPixelFormat::B5G6R5Unorm:
case air::MTLPixelFormat::A1BGR5Unorm:
case air::MTLPixelFormat::ABGR4Unorm:
case air::MTLPixelFormat::BGR5A1Unorm:
case air::MTLPixelFormat::R32Float:
case air::MTLPixelFormat::RG16Unorm:
case air::MTLPixelFormat::RG16Snorm:
case air::MTLPixelFormat::RG16Float:
case air::MTLPixelFormat::RGBA8Unorm:
case air::MTLPixelFormat::RGBA8Unorm_sRGB:
case air::MTLPixelFormat::RGBA8Snorm:
case air::MTLPixelFormat::BGRA8Unorm:
case air::MTLPixelFormat::BGRA8Unorm_sRGB:
case air::MTLPixelFormat::RGB10A2Unorm:
case air::MTLPixelFormat::RG11B10Float:
case air::MTLPixelFormat::RGB9E5Float:
case air::MTLPixelFormat::BGR10A2Unorm:
case air::MTLPixelFormat::BGR10_XR:
case air::MTLPixelFormat::BGR10_XR_sRGB:
case air::MTLPixelFormat::RG32Float:
case air::MTLPixelFormat::RGBA16Unorm:
case air::MTLPixelFormat::RGBA16Snorm:
case air::MTLPixelFormat::RGBA16Float:
case air::MTLPixelFormat::BGRA10_XR:
case air::MTLPixelFormat::BGRA10_XR_sRGB:
case air::MTLPixelFormat::RGBA32Float:
case air::MTLPixelFormat::BC1_RGBA:
case air::MTLPixelFormat::BC1_RGBA_sRGB:
case air::MTLPixelFormat::BC2_RGBA:
case air::MTLPixelFormat::BC2_RGBA_sRGB:
case air::MTLPixelFormat::BC3_RGBA:
case air::MTLPixelFormat::BC3_RGBA_sRGB:
case air::MTLPixelFormat::BC4_RUnorm:
case air::MTLPixelFormat::BC4_RSnorm:
case air::MTLPixelFormat::BC5_RGUnorm:
case air::MTLPixelFormat::BC5_RGSnorm:
case air::MTLPixelFormat::BC6H_RGBFloat:
case air::MTLPixelFormat::BC6H_RGBUfloat:
case air::MTLPixelFormat::BC7_RGBAUnorm:
case air::MTLPixelFormat::BC7_RGBAUnorm_sRGB:
return RegisterComponentType::Float;
default:
break;
}
return RegisterComponentType::Unknown;
}

llvm::Error convert_dxbc_pixel_shader(
SM50ShaderInternal *pShaderInternal, const char *name,
llvm::LLVMContext &context, llvm::Module &module,
Expand All @@ -250,12 +331,14 @@ llvm::Error convert_dxbc_pixel_shader(
bool pso_dual_source_blending = false;
bool pso_disable_depth_output = false;
uint32_t pso_unorm_output_reg_mask = 0;
uint32_t *pso_pixel_formats = nullptr;
SM50_SHADER_PSO_PIXEL_SHADER_DATA *pso_data = nullptr;
if (args_get_data<SM50_SHADER_PSO_PIXEL_SHADER, SM50_SHADER_PSO_PIXEL_SHADER_DATA>(pArgs, &pso_data)) {
pso_dual_source_blending = pso_data->dual_source_blending;
pso_disable_depth_output = pso_data->disable_depth_output;
pso_unorm_output_reg_mask = pso_data->unorm_output_reg_mask;
pso_sample_mask = pso_data->sample_mask;
pso_pixel_formats = pso_data->pixel_formats;
}
SM50_SHADER_METAL_VERSION metal_version = SM50_SHADER_METAL_310;
SM50_SHADER_FLAG shader_flags = {};
Expand Down Expand Up @@ -285,6 +368,8 @@ llvm::Error convert_dxbc_pixel_shader(
sig_ctx.disable_depth_output = pso_disable_depth_output;
sig_ctx.pull_mode_reg_mask = shader_info->pull_mode_reg_mask;
sig_ctx.unorm_output_reg_mask = pso_unorm_output_reg_mask;
if (pso_pixel_formats)
memcpy(sig_ctx.pixel_formats, pso_pixel_formats, sizeof(sig_ctx.pixel_formats));
for (auto &p : pShaderInternal->signature_handlers) {
p(sig_ctx);
}
Expand Down
23 changes: 18 additions & 5 deletions src/airconv/dxbc_converter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,28 @@ struct SignatureContext {
bool skip_vertex_output;
uint32_t pull_mode_reg_mask;
uint32_t unorm_output_reg_mask;
// it is considered optional (as a hint)
air::MTLPixelFormat pixel_formats[8];

SignatureContext(
IREffect &prologue, IRValue &epilogue, air::FunctionSignatureBuilder &func_signature, io_binding_map &resource
)
: prologue(prologue), epilogue(epilogue), func_signature(func_signature), resource(resource), ia_layout(nullptr),
dual_source_blending(false), disable_depth_output(false), skip_vertex_output(false), pull_mode_reg_mask(0),
unorm_output_reg_mask(0){};
IREffect &prologue, IRValue &epilogue, air::FunctionSignatureBuilder &func_signature, io_binding_map &resource
) :
prologue(prologue),
epilogue(epilogue),
func_signature(func_signature),
resource(resource),
ia_layout(nullptr),
dual_source_blending(false),
disable_depth_output(false),
skip_vertex_output(false),
pull_mode_reg_mask(0),
unorm_output_reg_mask(0) {
memset(pixel_formats, 0, sizeof(pixel_formats));
};
};

RegisterComponentType component_type_from_pixel_format(air::MTLPixelFormat format);

struct MeshOutputContext {
llvm::Value *vertex_id;
llvm::Value *primitive_id;
Expand Down
5 changes: 4 additions & 1 deletion src/airconv/dxbc_signature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,11 @@ void handle_signature_ps(
max_output_register = std::max(reg + 1, max_output_register);
pso_valid_output_reg_mask |= (1 << reg);
if (sig.mask() == 0) break;
auto type = sig.componentType();
auto sig_type = sig.componentType();
signature_handlers.push_back([=](SignatureContext &ctx) {
auto type = component_type_from_pixel_format(ctx.pixel_formats[reg]);
if (ctx.dual_source_blending || type == RegisterComponentType::Unknown)
type = sig_type;
uint32_t assigned_index;
if (ctx.dual_source_blending) {
if (reg > 1 || reg < 0)
Expand Down
1 change: 1 addition & 0 deletions src/d3d11/d3d11_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ CreateVariantShader(MTLD3D11Device *pDevice, ManagedShader shader,
data.dual_source_blending = variant.dual_source_blending;
data.disable_depth_output = variant.disable_depth_output;
data.unorm_output_reg_mask = variant.unorm_output_reg_mask;
memset(data.pixel_formats, 0, sizeof(data.pixel_formats));

sm50_bitcode_t compile_result = nullptr;
sm50_error_t sm50_err = nullptr;
Expand Down
10 changes: 5 additions & 5 deletions src/d3d12/d3d12_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class MTLD3D12Buffer : public MTLD3D12Pageable<MTLD3D12Resource> {
HRESULT
Initialize(
const D3D12_HEAP_PROPERTIES *pHeapProps, D3D12_HEAP_FLAGS HeapFlags, const D3D12_RESOURCE_DESC *pDesc,
const D3D12_CLEAR_VALUE *OptimizedClearValue, MTLD3D12Heap *pHeap
const D3D12_CLEAR_VALUE *OptimizedClearValue, MTLD3D12Heap *pHeap, UINT64 Offset
) {
if (OptimizedClearValue)
return E_INVALIDARG;
Expand Down Expand Up @@ -249,7 +249,7 @@ CreateCommittedBuffer(
REFIID riid, void **ppResource
) {
auto buffer = Com(new MTLD3D12Buffer(pDevice));
HRESULT hr = buffer->Initialize(pHeapProps, HeapFlags, pDesc, OptimizedClearValue, nullptr);
HRESULT hr = buffer->Initialize(pHeapProps, HeapFlags, pDesc, OptimizedClearValue, nullptr, 0);
if (FAILED(hr))
return hr;
if (!ppResource)
Expand All @@ -259,12 +259,12 @@ CreateCommittedBuffer(

HRESULT
CreatePlacedBuffer(
MTLD3D12Device *pDevice, MTLD3D12Heap *pHeap, const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialState,
const D3D12_CLEAR_VALUE *OptimizedClearValue, REFIID riid, void **ppResource
MTLD3D12Device *pDevice, MTLD3D12Heap *pHeap, UINT64 Offset, const D3D12_RESOURCE_DESC *pDesc,
D3D12_RESOURCE_STATES InitialState, const D3D12_CLEAR_VALUE *OptimizedClearValue, REFIID riid, void **ppResource
) {
auto buffer = Com(new MTLD3D12Buffer(pDevice));
D3D12_HEAP_DESC heap_desc = pHeap->GetDesc();
HRESULT hr = buffer->Initialize(&heap_desc.Properties, heap_desc.Flags, pDesc, OptimizedClearValue, pHeap);
HRESULT hr = buffer->Initialize(&heap_desc.Properties, heap_desc.Flags, pDesc, OptimizedClearValue, pHeap, Offset);
if (FAILED(hr))
return hr;
if (!ppResource)
Expand Down
8 changes: 7 additions & 1 deletion src/d3d12/d3d12_command_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ namespace dxmt {
MTLD3D12CommandAllocatorImpl::MTLD3D12CommandAllocatorImpl(MTLD3D12Device *pDevice, D3D12_COMMAND_LIST_TYPE Type) :
MTLD3D12Pageable<MTLD3D12CommandAllocator>(pDevice),
type_(Type),
clear_uav_(device_->GetMTLDevice(), *this) {}
clear_uav_(device_->GetMTLDevice(), *this),
copy_temp_allocator_(
{device_->GetMTLDevice(), WMTResourceHazardTrackingModeUntracked | WMTResourceStorageModePrivate}
),
copy_temp_version_(0) {}

HRESULT
CreateCommandAllocator(MTLD3D12Device *pDevice, D3D12_COMMAND_LIST_TYPE Type, REFIID riid, void **ppCommandAllocator) {
Expand Down Expand Up @@ -77,6 +81,8 @@ MTLD3D12CommandAllocatorImpl::Initialize() {

icb_.clear();

copy_temp_allocator_.free_blocks(copy_temp_version_++);

return S_OK;
}

Expand Down
Loading
Loading