Skip to content

unify(ww3d2): Merge dx8wrapper, dx8caps, shdlib#2499

Open
stephanmeesters wants to merge 12 commits intoTheSuperHackers:mainfrom
stephanmeesters:unify/dx8wrapper
Open

unify(ww3d2): Merge dx8wrapper, dx8caps, shdlib#2499
stephanmeesters wants to merge 12 commits intoTheSuperHackers:mainfrom
stephanmeesters:unify/dx8wrapper

Conversation

@stephanmeesters
Copy link
Copy Markdown

@stephanmeesters stephanmeesters commented Mar 29, 2026

Merged by hand using WinMerge.

@stephanmeesters stephanmeesters changed the title unify(dx8wrapper): Merge dxwrapper.cpp/h unify(dx8wrapper): Merge dxwrapper Mar 29, 2026
@stephanmeesters stephanmeesters changed the title unify(dx8wrapper): Merge dxwrapper unify(dx8wrapper): Merge dx8wrapper, dx8caps, shdlib Mar 29, 2026
@stephanmeesters stephanmeesters marked this pull request as ready for review March 29, 2026 12:26
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 29, 2026

Greptile Summary

This PR merges changes from Revision 170 of the dx8wrapper/dx8caps source tree (the "Commando" branch, authored by Kenny Mitchell) and introduces a new shdlib.h stub. The key functional changes are:

  • Multi-stream vertex buffers: RenderStateStruct replaces the single vertex_buffer/vertex_buffer_type pair with vertex_buffers[MAX_VERTEX_STREAMS] and vertex_buffer_types[MAX_VERTEX_STREAMS] arrays. All call-sites in dx8wrapper.cpp and sortingrenderer.cpp are updated consistently.
  • Unified DX8Caps: hwVPCaps/swVPCaps are collapsed into a single Caps member; a new constructor accepting pre-fetched D3DCAPS8 is added; driver version checking (Check_Driver_Version_Status()), display-mode filtering (Is_Valid_Display_Format()), and richer capability logging are introduced.
  • Smarter device enumeration: Devices with zero valid display modes are filtered out; display modes prohibited by DX8Caps (e.g. resolutions above GPU limits) are masked during enumeration.
  • Device creation robustness: Fallback from 32-bit to 16-bit z-buffer on failure, improved OOM handling for texture allocation, and D3DSWAPEFFECT_DISCARD for all swap chains.
  • SHD stub (shdlib.h): Wraps SHD_Init / SHD_Shutdown / SHD_Init_Shaders / SHD_Shutdown_Shaders behind a USE_WWSHADE compile guard; no-ops everything when the library is absent.
  • GeneralsMD sync: Minor comment cleanup and brace alignment to match the merged Generals state.

One P1 logic bug was found in the new Check_Driver_Version_Status() code, and two P2 style-rule violations were identified.

Confidence Score: 4/5

Safe to merge after fixing the fall-through bug in Check_Driver_Version_Status(); all other findings are minor style violations.

One P1 logic bug remains: the missing break in the Elsa OEM driver switch statements causes every unrecognised driver build to be silently classified as OK instead of Unknown. While the practical impact is low (these are very old GPU drivers), it is a clear defect in newly introduced code that should be corrected before merging. All other findings are P2 style-rule violations.

Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp — specifically the egdad.dll and egliid.dll switch blocks in Check_Driver_Version_Status() around lines 910–924.

Important Files Changed

Filename Overview
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp Large merge introducing Check_Driver_Version_Status(), new DX8Caps constructor, expanded Compute_Caps(), and vendor-specific hacks; contains a fall-through switch bug in Elsa OEM driver handling and single-line if statements violating style rules
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.h Extends DX8Caps with new accessors (ZBias, anisotropic, cubemap, fog, multi-pass), new constructor, and replaces hwVPCaps/swVPCaps with a single unified Caps member; clean refactor with no apparent issues
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp Major merge adding multi-stream vertex buffer support, improved device creation with 16-bit z-buffer fallback, OOM texture recovery, SHD init/shutdown hooks, and enhanced per-device enumeration filtering via DX8Caps
Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h Extends RenderStateStruct to use vertex_buffers[MAX_VERTEX_STREAMS] arrays, adds Set_Projection_Transform_With_Z_Bias(), updates RenderStateStruct constructor/destructor/operator= to handle multi-stream buffers correctly
Generals/Code/Libraries/Source/WWVegas/WW3D2/shdlib.h New stub header wrapping WWShade library macros behind USE_WWSHADE guard; no-ops all SHD_* macros when the library is absent; copyright attribution uses EA instead of TheSuperHackers for this newly-created community file
Generals/Code/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp Updated to use vertex_buffers[0] instead of single vertex_buffer, adds WWPROFILE instrumentation, promotes DEFAULT_SORTING_* globals to static, and removes obsolete commented-out code
Generals/Code/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt Adds shdlib.h to the WW3D2 source list; minimal, correct change
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp Trivial brace alignment fix in Vendor_Specific_Hacks for the NVIDIA block; no functional change
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp Cleans up a commented-out early-exit check and removes stale commented-out code in Registry_Load_Render_Device; no functional change
GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.h Removes commented-out lightsHash member and its initialiser; cosmetic-only cleanup

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[DX8Wrapper::Enumerate_Devices] --> B[GetDeviceCaps + GetAdapterIdentifier]
    B --> C[DX8Caps constructor\ncaps + adapter_id]
    C --> D[Compute_Caps]
    D --> D1[Check_Driver_Version_Status]
    D --> D2[Check_Texture_Format_Support]
    D --> D3[Check_Shader_Support]
    D --> D4[Vendor_Specific_Hacks]
    D1 --> E{Is_Valid_Display_Format}
    E -->|Invalid resolution| F[bits = 0, skip mode]
    E -->|Valid resolution| G[Add to device description]
    G --> H{Any valid resolutions?}
    H -->|Yes| I[Add device to table]
    H -->|No| J[Skip device]

    K[DX8Wrapper::Create_Device] --> L{HW T&L?}
    L -->|Yes| M[MIXED_VERTEXPROCESSING]
    L -->|No| N[SOFTWARE_VERTEXPROCESSING]
    M & N --> O[CreateDevice]
    O -->|Fail: 16bit display + 32bit z-buf| P[Retry with D3DFMT_D16]
    P --> Q{Success?}
    Q -->|Yes| R[Device ready]
    Q -->|No| S[Return false]
    O -->|Success| R

    R --> T[Do_Onetime_Device_Dependent_Inits]
    T --> U[SHD_INIT]
    T --> V[VertexMaterial init]
    T --> W[BoxRenderObj init]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp
Line: 910-924

Comment:
**Fall-through makes `default:` always produce `DRIVER_STATUS_OK`**

Both the `egdad.dll` and `egliid.dll` switch statements have their `default:` case fall through directly into the matching `case N:` label because there is no `break` after the default assignment. As a result, any build version _other_ than 312 (or 172) first writes `DRIVER_STATUS_UNKNOWN` and then immediately overwrites it with `DRIVER_STATUS_OK`, so every unknown Elsa driver version is silently treated as known-good rather than unknown.

```cpp
// egdad.dll block (lines 909–914)
switch (DriverBuildVersion) {
default:
    DriverVersionStatus=DRIVER_STATUS_UNKNOWN;
    break;          // ← add break here
case 312:
    DriverVersionStatus=DRIVER_STATUS_OK;
}
```

```cpp
// egliid.dll block (lines 919–924)
switch (DriverBuildVersion) {
default:
    DriverVersionStatus=DRIVER_STATUS_UNKNOWN;
    break;          // ← add break here
case 172:
    DriverVersionStatus=DRIVER_STATUS_OK;
}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: Generals/Code/Libraries/Source/WWVegas/WW3D2/shdlib.h
Line: 3

Comment:
**Wrong copyright owner for a newly-created community file**

`shdlib.h` is a new file added by the community (it was not present in the initial commit `3d0ee53`). Per the project copyright policy, only files that ship directly from the original EA source tree should retain `"Copyright YYYY Electronic Arts Inc."`. Newly created community files should use `"Copyright YYYY TheSuperHackers"` instead.

```suggestion
**	Copyright 2025 TheSuperHackers
```

**Rule Used:** Files from the original EA source code (present in... ([source](https://app.greptile.com/review/custom-context?memory=078076ac-7c7f-4011-8c1c-51bcca514292))

**Learnt From**
[TheSuperHackers/GeneralsGameCode#2153](https://github.com/TheSuperHackers/GeneralsGameCode/pull/2153#discussion_r2714609291)

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.cpp
Line: 559

Comment:
**Statement body on same line as condition**

Newly added code should place the if-body on a separate line to allow precise debugger breakpoint placement. The same pattern also appears in `Is_Valid_Display_Format` at lines 996 and 998.

```suggestion
		if (DriverDLL[0]=='3')
			VendorId=VENDOR_3DFX;
```

Lines 996–998 similarly need splitting:
```cpp
if (MaxDisplayWidth==0 && MaxDisplayHeight==0)
    return true;

if (width>MaxDisplayWidth || height>MaxDisplayHeight)
    return false;
```

**Rule Used:** Always place if/else/for/while statement bodies on... ([source](https://app.greptile.com/review/custom-context?memory=16b9b669-b823-49be-ba5b-2bd30ff3ba6d))

**Learnt From**
[TheSuperHackers/GeneralsGameCode#2067](https://github.com/TheSuperHackers/GeneralsGameCode/pull/2067#discussion_r2706274626)

How can I resolve this? If you propose a fix, please make it concise.

Reviews (6): Last reviewed commit: "Additional commented out code cleanup" | Re-trigger Greptile

@Mauller
Copy link
Copy Markdown

Mauller commented Mar 29, 2026

This could probably do with a prior chore PR to cleanup the dead code, commented out stuff and remove dead defines that are unused like the xbox related stuff.

@stephanmeesters
Copy link
Copy Markdown
Author

This could probably do with a prior chore PR to cleanup the dead code, commented out stuff and remove dead defines that are unused like the xbox related stuff.

Sounds like a good idea, I’ll do that soon

@stephanmeesters stephanmeesters changed the title unify(dx8wrapper): Merge dx8wrapper, dx8caps, shdlib unify(dd3d2): Merge dx8wrapper, dx8caps, shdlib Mar 30, 2026
@stephanmeesters stephanmeesters changed the title unify(dd3d2): Merge dx8wrapper, dx8caps, shdlib unify(ww3d2): Merge dx8wrapper, dx8caps, shdlib Mar 30, 2026
@xezon xezon added Gen Relates to Generals Unify Unifies code between Generals and Zero Hour labels Mar 30, 2026
@xezon xezon added this to the Code foundation build up milestone Mar 30, 2026
@bobtista
Copy link
Copy Markdown

bobtista commented Apr 2, 2026

Needs a rebase

@stephanmeesters
Copy link
Copy Markdown
Author

Needs a rebase

Done

Comment on lines +1795 to +1797
IDirect3DSurface8* depthbuffer;

_Get_D3D_Device8()->GetDepthStencilSurface(&depthbuffer);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Uninitialized pointer read if GetDepthStencilSurface fails

depthbuffer is declared uninitialized. If GetDepthStencilSurface returns a failure HRESULT (e.g., device lost), the pointer is never written and the if (depthbuffer) check on the next few lines reads an indeterminate value — undefined behaviour. Initialise to nullptr to make the null-check safe in all paths.

Suggested change
IDirect3DSurface8* depthbuffer;
_Get_D3D_Device8()->GetDepthStencilSurface(&depthbuffer);
IDirect3DSurface8* depthbuffer = nullptr;
_Get_D3D_Device8()->GetDepthStencilSurface(&depthbuffer);
Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp
Line: 1795-1797

Comment:
**Uninitialized pointer read if `GetDepthStencilSurface` fails**

`depthbuffer` is declared uninitialized. If `GetDepthStencilSurface` returns a failure HRESULT (e.g., device lost), the pointer is never written and the `if (depthbuffer)` check on the next few lines reads an indeterminate value — undefined behaviour. Initialise to `nullptr` to make the null-check safe in all paths.

```suggestion
	IDirect3DSurface8* depthbuffer = nullptr;
	_Get_D3D_Device8()->GetDepthStencilSurface(&depthbuffer);
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to fix that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to fix that.

Made an issue for this and other potential issues #2530

return;
}
*/
// if (material==render_state.material) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out now? do we not want this check?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was removed in ZH because a material can be modified potentially, and this check will not pick up on that. In the code above they tried using CRC to pick up on material changes apparently it didn't work. I think it's worth investigating later. I could add a todo note?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gen Relates to Generals Unify Unifies code between Generals and Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants