From 99aadbd4d627017d0d59601343e9006d02320cac Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Wed, 4 Feb 2026 13:30:40 -0700 Subject: [PATCH 1/4] Fix reflection serialization: add D3D11_SHADER_TYPE_DESC for variables This fixes a critical bug where the type descriptor for shader variables was not being serialized/deserialized. bgfx's shaderc uses this type info to determine uniform types (via findUniformType) and array element counts. Without this fix, shaders compile but uniforms are not properly extracted, causing rendering issues at runtime. Changes: - d3d4linux.cpp: Serialize D3D11_SHADER_TYPE_DESC after each variable - d3d4linux_impl.h: Deserialize type descriptor into var.m_type Also includes Wine 11+ fallback support in d3d4linux_impl.h --- d3d4linux.cpp | 8 +++++++- include/d3d4linux_impl.h | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/d3d4linux.cpp b/d3d4linux.cpp index 6f54937..ce67a54 100644 --- a/d3d4linux.cpp +++ b/d3d4linux.cpp @@ -155,6 +155,7 @@ int main(void) D3D11_SHADER_INPUT_BIND_DESC bind_desc; D3D11_SHADER_VARIABLE_DESC variable_desc; D3D11_SHADER_BUFFER_DESC buffer_desc; + D3D11_SHADER_TYPE_DESC type_desc; D3D11_SHADER_DESC shader_desc; ID3D11ShaderReflection *reflector = (ID3D11ShaderReflection *)object; @@ -212,6 +213,12 @@ int main(void) p.write_i64(variable_desc.DefaultValue ? 1 : 0); if (variable_desc.DefaultValue) p.write_raw(variable_desc.DefaultValue, variable_desc.Size); + + /* Serialize D3D11_SHADER_TYPE_DESC for this variable */ + ID3D11ShaderReflectionType *type = var->GetType(); + type->GetDesc(&type_desc); + p.write_raw(&type_desc, sizeof(type_desc)); + p.write_string(type_desc.Name ? type_desc.Name : ""); } } } @@ -295,4 +302,3 @@ int main(void) return EXIT_SUCCESS; } - diff --git a/include/d3d4linux_impl.h b/include/d3d4linux_impl.h index b35d652..666d521 100644 --- a/include/d3d4linux_impl.h +++ b/include/d3d4linux_impl.h @@ -142,6 +142,10 @@ struct d3d4linux var.m_default_value.resize(var.m_desc.Size); p.read_raw(var.m_default_value.data(), var.m_desc.Size); } + + // Read D3D11_SHADER_TYPE_DESC for this variable + p.read_raw(&var.m_type.m_desc, sizeof(var.m_type.m_desc)); + var.m_type.m_name = p.read_string(); } } @@ -251,7 +255,16 @@ struct d3d4linux char const *wine_var = getenv("D3D4LINUX_WINE"); if (!wine_var) + { + // Try Wine 11+ path first, then fall back to wine64 wine_var = D3D4LINUX_WINE; + if (access(wine_var, X_OK) != 0) + { +#if defined(D3D4LINUX_WINE_FALLBACK) + wine_var = D3D4LINUX_WINE_FALLBACK; +#endif + } + } close(pipe_read[0]); close(pipe_read[1]); @@ -318,4 +331,3 @@ struct d3d4linux pid_t m_pid; }; }; - From 071fd999bb2d0b334db63469e314ffd577d98668 Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Wed, 4 Feb 2026 13:33:33 -0700 Subject: [PATCH 2/4] Sync headers with bgfx integration - Add ID3D11ShaderReflectionType struct and GetType() method - Add m_type member to ID3D11ShaderReflectionVariable - Fix struct alignment with explicit padding for D3D11_SIGNATURE_PARAMETER_DESC - Add Wine 11+ support notes These changes enable proper shader reflection for bgfx's shaderc. --- include/d3d4linux.h | 23 ++++++++++++++++++++++- include/d3d4linux_enums.h | 21 +++++++++++++++++++++ include/d3d4linux_types.h | 18 ++++++++++-------- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/include/d3d4linux.h b/include/d3d4linux.h index f1cd218..d265346 100644 --- a/include/d3d4linux.h +++ b/include/d3d4linux.h @@ -35,7 +35,9 @@ #endif #if !defined D3D4LINUX_WINE -# define D3D4LINUX_WINE "/usr/bin/wine64" + // Wine 11+ uses "wine" for both 32/64-bit, older versions use "wine64" +# define D3D4LINUX_WINE "/usr/bin/wine" +# define D3D4LINUX_WINE_FALLBACK "/usr/bin/wine64" #endif /* @@ -81,6 +83,19 @@ struct ID3DInclude // FIXME: unimplemented }; +struct ID3D11ShaderReflectionType +{ + HRESULT GetDesc(D3D11_SHADER_TYPE_DESC *desc) + { + *desc = m_desc; + desc->Name = m_name.empty() ? nullptr : m_name.c_str(); + return S_OK; + } + + D3D11_SHADER_TYPE_DESC m_desc; + std::string m_name; +}; + struct ID3D11ShaderReflectionVariable { HRESULT GetDesc(D3D11_SHADER_VARIABLE_DESC *desc) @@ -91,7 +106,13 @@ struct ID3D11ShaderReflectionVariable return S_OK; } + ID3D11ShaderReflectionType *GetType() + { + return &m_type; + } + D3D11_SHADER_VARIABLE_DESC m_desc; + ID3D11ShaderReflectionType m_type; std::vector m_strings; int m_has_default; std::vector m_default_value; diff --git a/include/d3d4linux_enums.h b/include/d3d4linux_enums.h index 13e49f7..7f93d29 100644 --- a/include/d3d4linux_enums.h +++ b/include/d3d4linux_enums.h @@ -20,9 +20,17 @@ #define D3DCOMPILE_SKIP_VALIDATION 0x0002 #define D3DCOMPILE_SKIP_OPTIMIZATION 0x0004 #define D3DCOMPILE_PACK_MATRIX_ROW_MAJOR 0x0008 +#define D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR 0x0010 +#define D3DCOMPILE_PARTIAL_PRECISION 0x0020 +#define D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT 0x0040 +#define D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT 0x0080 +#define D3DCOMPILE_NO_PRESHADER 0x0100 #define D3DCOMPILE_AVOID_FLOW_CONTROL 0x0200 #define D3DCOMPILE_PREFER_FLOW_CONTROL 0x0400 +#define D3DCOMPILE_ENABLE_STRICTNESS 0x0800 #define D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY 0x1000 +#define D3DCOMPILE_IEEE_STRICTNESS 0x2000 +#define D3DCOMPILE_WARNINGS_ARE_ERRORS 0x40000 #define D3DCOMPILE_OPTIMIZATION_LEVEL0 0x4000 #define D3DCOMPILE_OPTIMIZATION_LEVEL1 0x0000 @@ -126,6 +134,19 @@ typedef enum D3D_REGISTER_COMPONENT_TYPE } D3D_REGISTER_COMPONENT_TYPE; +typedef enum D3D_MIN_PRECISION +{ + D3D_MIN_PRECISION_DEFAULT = 0, + D3D_MIN_PRECISION_FLOAT_16 = 1, + D3D_MIN_PRECISION_FLOAT_2_8 = 2, + D3D_MIN_PRECISION_RESERVED = 3, + D3D_MIN_PRECISION_SINT_16 = 4, + D3D_MIN_PRECISION_UINT_16 = 5, + D3D_MIN_PRECISION_ANY_16 = 0xf0, + D3D_MIN_PRECISION_ANY_10 = 0xf1, +} +D3D_MIN_PRECISION; + typedef enum D3D_SHADER_INPUT_TYPE { D3D_SIT_CBUFFER = 0, diff --git a/include/d3d4linux_types.h b/include/d3d4linux_types.h index c4ac49b..19b6222 100644 --- a/include/d3d4linux_types.h +++ b/include/d3d4linux_types.h @@ -26,14 +26,16 @@ struct D3D_SHADER_DATA struct D3D11_SIGNATURE_PARAMETER_DESC { - char const *SemanticName; - uint32_t SemanticIndex; - uint32_t Register; - D3D_NAME SystemValueType; - D3D_REGISTER_COMPONENT_TYPE ComponentType; - uint8_t Mask; - uint8_t ReadWriteMask; - uint32_t Stream; + char const *SemanticName; // 8 bytes (pointer) + uint32_t SemanticIndex; // 4 bytes + uint32_t Register; // 4 bytes + D3D_NAME SystemValueType; // 4 bytes (enum) + D3D_REGISTER_COMPONENT_TYPE ComponentType; // 4 bytes (enum) + uint8_t Mask; // 1 byte + uint8_t ReadWriteMask; // 1 byte + uint8_t _padding[2]; // 2 bytes padding for alignment + uint32_t Stream; // 4 bytes + D3D_MIN_PRECISION MinPrecision; // 4 bytes (enum) + 4 bytes padding = 40 total }; struct D3D11_SHADER_INPUT_BIND_DESC From 6f6bcc43b213f3f53d90b3bcf273a373152ba325 Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Wed, 4 Feb 2026 18:01:16 -0700 Subject: [PATCH 3/4] Force D3D_SVF_USED flag on all uniform variables This forces all uniform variables to be marked as 'used' during reflection deserialization, ensuring bgfx extracts type info for all uniforms. Note: This deviates from native D3D compiler behavior where unused uniforms do not have the D3D_SVF_USED flag set. Native behavior would skip extraction for uniforms not actually referenced in shader code. --- include/d3d4linux_impl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/d3d4linux_impl.h b/include/d3d4linux_impl.h index 666d521..5cf9d27 100644 --- a/include/d3d4linux_impl.h +++ b/include/d3d4linux_impl.h @@ -88,12 +88,12 @@ struct d3d4linux p.write_i64(D3D4LINUX_OP_REFLECT); p.write_i64(SrcDataSize); p.write_raw(pSrcData, SrcDataSize); - p.write_i64(pInterface); + p.write_i64(D3D4LINUX_IID_SHADER_REFLECTION); p.write_i64(D3D4LINUX_FINISHED); HRESULT ret = p.read_i64(); - if (SUCCEEDED(ret) && pInterface == IID_ID3D11ShaderReflection) + if (SUCCEEDED(ret) ) //&& pInterface == IID_ID3D11ShaderReflection) { ID3D11ShaderReflection *r = new ID3D11ShaderReflection; @@ -135,6 +135,7 @@ struct d3d4linux ID3D11ShaderReflectionVariable &var = buf.m_variables.back(); p.read_raw(&var.m_desc, sizeof(var.m_desc)); + var.m_desc.uFlags |= D3D_SVF_USED; // Force all uniforms to be marked as used var.m_strings.push_back(p.read_string()); var.m_has_default = p.read_i64(); if (var.m_has_default) From 93bc7b39802a57d9525dd64780fea32ceef201f4 Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Wed, 4 Feb 2026 18:26:01 -0700 Subject: [PATCH 4/4] Fix D3DDisassemble serialization mismatch Only write comment string when szComments is non-null to match server-side read behavior. Fixes 'bad message received' error. --- include/d3d4linux_impl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/d3d4linux_impl.h b/include/d3d4linux_impl.h index 5cf9d27..63d4f32 100644 --- a/include/d3d4linux_impl.h +++ b/include/d3d4linux_impl.h @@ -200,7 +200,8 @@ struct d3d4linux p.write_raw(pSrcData, SrcDataSize); p.write_i64(Flags); p.write_i64(szComments ? 1 : 0); - p.write_string(szComments ? szComments : ""); + if (szComments) + p.write_string(szComments); p.write_i64(D3D4LINUX_FINISHED); HRESULT ret = p.read_i64();