From a4d710d4a8540b6085344783da71804df6e23813 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 10 Apr 2026 14:42:32 -0400 Subject: [PATCH 01/17] feat(ww3d2): add IRenderBackend abstract interface --- .../Source/WWVegas/WW3D2/CMakeLists.txt | 1 + .../Source/WWVegas/WW3D2/IRenderBackend.h | 224 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index 4e10ae78d31..a6c4061d87a 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -90,6 +90,7 @@ set(WW3D2_SRC htree.h #htreemgr.cpp #htreemgr.h + IRenderBackend.h intersec.cpp intersec.h intersec.inl diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h new file mode 100644 index 00000000000..2071d987b55 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -0,0 +1,224 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 Electronic Arts Inc. +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 Introduce IRenderBackend +// abstract interface so WW3D2 rendering can be re-targeted to modern backends +// (bgfx, Diligent, etc.) while the existing DX8 path stays functional as the +// reference implementation. See Core/Libraries/Source/WWVegas/WW3D2/RENDER_BACKEND.md. + +#pragma once + +#include "ww3dformat.h" + +// ----------------------------------------------------------------------------- +// Forward declarations +// ----------------------------------------------------------------------------- +// +// Kept lightweight deliberately. IRenderBackend.h must be includable without +// dragging in the full WW3D2 header graph, so callers only pay for the types +// they actually use. +// +// All W3D classes passed through this interface are referenced by pointer or +// reference; none of them need a full definition in this header. + +class ShaderClass; +class VertexMaterialClass; +class TextureBaseClass; +class TextureClass; +class ZTextureClass; +class SurfaceClass; +class VertexBufferClass; +class IndexBufferClass; +class DynamicVBAccessClass; +class DynamicIBAccessClass; +class LightClass; +class LightEnvironmentClass; +class Matrix4x4; +class Matrix3D; +class Vector3; + +// ----------------------------------------------------------------------------- +// POD types owned by the interface +// ----------------------------------------------------------------------------- + +enum TransformKind +{ + // Values chosen so they can be mapped directly to D3DTS_* inside the + // DX8Backend without a branch. A modern backend ignores these indices + // and uses whichever matrix storage is convenient for it. + RB_TRANSFORM_VIEW = 2, // D3DTS_VIEW + RB_TRANSFORM_PROJECTION = 3, // D3DTS_PROJECTION + RB_TRANSFORM_WORLD = 256 // D3DTS_WORLD +}; + +struct RenderBackendViewport +{ + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + float min_z; + float max_z; +}; + +// ----------------------------------------------------------------------------- +// IRenderBackend — abstract W3D-facing rendering interface +// ----------------------------------------------------------------------------- +// +// This interface exposes the *high-level* subset of DX8Wrapper's public API: +// the calls that take and return W3D types (ShaderClass, TextureBaseClass, +// Matrix4x4, etc.) and are backend-neutral by construction. The low-level +// D3D8-specific entry points on DX8Wrapper (Set_DX8_Render_State, +// _Create_DX8_Texture, _Get_D3D_Device8, etc.) are NOT exposed here and +// remain reachable only through DX8Wrapper's static methods. Code that +// needs them is DX8-only and must be migrated during later phases. +// +// **Method names intentionally match the existing DX8Wrapper names** so +// that migrating callers is a mechanical `DX8Wrapper::X(...)` → +// `g_renderBackend->X(...)` rewrite with minimal diff noise. +// +// **This header is included from VC6-compiled translation units** (the +// DX8 reference path and the tools). Keep it C++98-compatible: +// - No , no , no or other STL in signatures +// - No `override`, `= default`, `= delete`, `auto`, `constexpr` +// - `nullptr` is OK (the project has a VC6 shim) +// - POD structs for parameter bundles +// - Forward-declare W3D types rather than including their headers +// +// Implementations (DX8Backend.cpp, future BgfxBackend.cpp, etc.) can use +// whatever C++ features the project's main build allows. + +class IRenderBackend +{ +public: + virtual ~IRenderBackend() {} + + // ------------------------------------------------------------------------- + // Device state queries + // ------------------------------------------------------------------------- + + virtual bool Is_Device_Lost() const = 0; + virtual bool Has_Stencil() = 0; + virtual WW3DFormat Get_Back_Buffer_Format() = 0; + virtual SurfaceClass * Get_Back_Buffer(unsigned int num) = 0; + virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) = 0; + + // ------------------------------------------------------------------------- + // Frame lifecycle + // ------------------------------------------------------------------------- + + virtual void Begin_Scene() = 0; + virtual void End_Scene(bool flip_frame) = 0; + virtual void Flip_To_Primary() = 0; + virtual void Clear(bool clear_color, bool clear_z_stencil, + const Vector3 & color, + float dest_alpha, float z, unsigned int stencil) = 0; + virtual void Set_Viewport(const RenderBackendViewport & viewport) = 0; + + // ------------------------------------------------------------------------- + // Vertex / index buffers + // ------------------------------------------------------------------------- + + virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) = 0; + virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba) = 0; + virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) = 0; + virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) = 0; + virtual void Set_Index_Buffer_Index_Offset(unsigned int offset) = 0; + + // ------------------------------------------------------------------------- + // State: shaders, materials, textures + // ------------------------------------------------------------------------- + + virtual void Set_Shader(const ShaderClass & shader) = 0; + virtual void Get_Shader(ShaderClass & shader) = 0; + virtual void Set_Material(const VertexMaterialClass * material) = 0; + virtual void Set_Texture(unsigned int stage, TextureBaseClass * texture) = 0; + + virtual void Apply_Render_State_Changes() = 0; + virtual void Apply_Default_State() = 0; + virtual void Invalidate_Cached_Render_States() = 0; + + // ------------------------------------------------------------------------- + // Transforms + // ------------------------------------------------------------------------- + + virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m) = 0; + virtual void Set_Transform(TransformKind transform, const Matrix3D & m) = 0; + virtual void Get_Transform(TransformKind transform, Matrix4x4 & m) = 0; + virtual void Set_World_Identity() = 0; + virtual void Set_View_Identity() = 0; + virtual bool Is_World_Identity() = 0; + virtual bool Is_View_Identity() = 0; + virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, + float znear, float zfar) = 0; + + // ------------------------------------------------------------------------- + // Lighting and fog + // ------------------------------------------------------------------------- + + virtual void Set_Light(unsigned int index, const LightClass & light) = 0; + virtual void Set_Ambient(const Vector3 & color) = 0; + virtual const Vector3 & Get_Ambient() const = 0; + virtual void Set_Fog(bool enable, const Vector3 & color, float start, float end) = 0; + virtual bool Get_Fog_Enable() const = 0; + virtual void Set_Light_Environment(LightEnvironmentClass * light_env) = 0; + virtual LightEnvironmentClass * Get_Light_Environment() const = 0; + + // ------------------------------------------------------------------------- + // Draw calls + // ------------------------------------------------------------------------- + + virtual void Draw_Triangles(unsigned short start_index, + unsigned short polygon_count, + unsigned short min_vertex_index, + unsigned short vertex_count) = 0; + + virtual void Draw_Triangles(unsigned int buffer_type, + unsigned short start_index, + unsigned short polygon_count, + unsigned short min_vertex_index, + unsigned short vertex_count) = 0; + + virtual void Draw_Strip(unsigned short start_index, + unsigned short index_count, + unsigned short min_vertex_index, + unsigned short vertex_count) = 0; + + // ------------------------------------------------------------------------- + // Programmable pipeline (GPU vertex / pixel shaders) + // ------------------------------------------------------------------------- + // + // These correspond to DX8's programmable shader slots. Modern backends + // will re-interpret the handles internally; the interface treats the + // shader id as an opaque unsigned long. + + virtual void Set_Vertex_Shader(unsigned long vertex_shader) = 0; + virtual void Set_Pixel_Shader(unsigned long pixel_shader) = 0; + virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count) = 0; + virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count) = 0; + + // ------------------------------------------------------------------------- + // Render targets + // ------------------------------------------------------------------------- + + virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format) = 0; + virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture) = 0; + virtual bool Is_Render_To_Texture() = 0; + virtual void Set_Shadow_Map(int idx, ZTextureClass * ztex) = 0; + virtual ZTextureClass * Get_Shadow_Map(int idx) = 0; +}; From e4a898146c03f9ea2c1b7a18982b5ce1b7433a58 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 10 Apr 2026 14:45:14 -0400 Subject: [PATCH 02/17] feat(ww3d2): add DX8Backend adapter forwarding to DX8Wrapper statics --- .../Source/WWVegas/WW3D2/CMakeLists.txt | 2 + .../Source/WWVegas/WW3D2/DX8Backend.cpp | 321 ++++++++++++++++++ .../Source/WWVegas/WW3D2/DX8Backend.h | 123 +++++++ 3 files changed, 446 insertions(+) create mode 100644 Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp create mode 100644 Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index a6c4061d87a..5ef2ef11e0c 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -43,6 +43,8 @@ set(WW3D2_SRC distlod.cpp distlod.h dllist.h + DX8Backend.cpp + DX8Backend.h dx8caps.cpp dx8caps.h dx8fvf.cpp diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp new file mode 100644 index 00000000000..542a776a22d --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp @@ -0,0 +1,321 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 Electronic Arts Inc. +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend forwarding adapter. +// Every method in this file is a one-line trampoline to the existing +// DX8Wrapper static API. Keep it that way — if behavior needs to change it +// should change in DX8Wrapper, not here. + +#include "DX8Backend.h" + +#include "dx8wrapper.h" +#include "vector3.h" +#include "matrix4.h" +#include "matrix3d.h" +#include "light.h" +#include "lightenvironment.h" + +DX8Backend::DX8Backend() +{ +} + +DX8Backend::~DX8Backend() +{ +} + +// -- Device state queries ---------------------------------------------------- + +bool DX8Backend::Is_Device_Lost() const +{ + return DX8Wrapper::Is_Device_Lost(); +} + +bool DX8Backend::Has_Stencil() +{ + return DX8Wrapper::Has_Stencil(); +} + +WW3DFormat DX8Backend::Get_Back_Buffer_Format() +{ + return DX8Wrapper::getBackBufferFormat(); +} + +SurfaceClass * DX8Backend::Get_Back_Buffer(unsigned int num) +{ + return DX8Wrapper::_Get_DX8_Back_Buffer(num); +} + +void DX8Backend::Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) +{ + DX8Wrapper::Set_Gamma(gamma, bright, contrast, calibrate, uselimit); +} + +// -- Frame lifecycle --------------------------------------------------------- + +void DX8Backend::Begin_Scene() +{ + DX8Wrapper::Begin_Scene(); +} + +void DX8Backend::End_Scene(bool flip_frame) +{ + DX8Wrapper::End_Scene(flip_frame); +} + +void DX8Backend::Flip_To_Primary() +{ + DX8Wrapper::Flip_To_Primary(); +} + +void DX8Backend::Clear(bool clear_color, bool clear_z_stencil, + const Vector3 & color, + float dest_alpha, float z, unsigned int stencil) +{ + DX8Wrapper::Clear(clear_color, clear_z_stencil, color, dest_alpha, z, stencil); +} + +void DX8Backend::Set_Viewport(const RenderBackendViewport & viewport) +{ + D3DVIEWPORT8 vp; + vp.X = viewport.x; + vp.Y = viewport.y; + vp.Width = viewport.width; + vp.Height = viewport.height; + vp.MinZ = viewport.min_z; + vp.MaxZ = viewport.max_z; + DX8Wrapper::Set_Viewport(&vp); +} + +// -- Vertex / index buffers -------------------------------------------------- + +void DX8Backend::Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) +{ + DX8Wrapper::Set_Vertex_Buffer(vb, stream); +} + +void DX8Backend::Set_Vertex_Buffer(const DynamicVBAccessClass & vba) +{ + DX8Wrapper::Set_Vertex_Buffer(vba); +} + +void DX8Backend::Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) +{ + DX8Wrapper::Set_Index_Buffer(ib, index_base_offset); +} + +void DX8Backend::Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) +{ + DX8Wrapper::Set_Index_Buffer(iba, index_base_offset); +} + +void DX8Backend::Set_Index_Buffer_Index_Offset(unsigned int offset) +{ + DX8Wrapper::Set_Index_Buffer_Index_Offset(offset); +} + +// -- State: shaders, materials, textures ------------------------------------ + +void DX8Backend::Set_Shader(const ShaderClass & shader) +{ + DX8Wrapper::Set_Shader(shader); +} + +void DX8Backend::Get_Shader(ShaderClass & shader) +{ + DX8Wrapper::Get_Shader(shader); +} + +void DX8Backend::Set_Material(const VertexMaterialClass * material) +{ + DX8Wrapper::Set_Material(material); +} + +void DX8Backend::Set_Texture(unsigned int stage, TextureBaseClass * texture) +{ + DX8Wrapper::Set_Texture(stage, texture); +} + +void DX8Backend::Apply_Render_State_Changes() +{ + DX8Wrapper::Apply_Render_State_Changes(); +} + +void DX8Backend::Apply_Default_State() +{ + DX8Wrapper::Apply_Default_State(); +} + +void DX8Backend::Invalidate_Cached_Render_States() +{ + DX8Wrapper::Invalidate_Cached_Render_States(); +} + +// -- Transforms -------------------------------------------------------------- + +void DX8Backend::Set_Transform(TransformKind transform, const Matrix4x4 & m) +{ + DX8Wrapper::Set_Transform(static_cast(transform), m); +} + +void DX8Backend::Set_Transform(TransformKind transform, const Matrix3D & m) +{ + DX8Wrapper::Set_Transform(static_cast(transform), m); +} + +void DX8Backend::Get_Transform(TransformKind transform, Matrix4x4 & m) +{ + DX8Wrapper::Get_Transform(static_cast(transform), m); +} + +void DX8Backend::Set_World_Identity() +{ + DX8Wrapper::Set_World_Identity(); +} + +void DX8Backend::Set_View_Identity() +{ + DX8Wrapper::Set_View_Identity(); +} + +bool DX8Backend::Is_World_Identity() +{ + return DX8Wrapper::Is_World_Identity(); +} + +bool DX8Backend::Is_View_Identity() +{ + return DX8Wrapper::Is_View_Identity(); +} + +void DX8Backend::Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar) +{ + DX8Wrapper::Set_Projection_Transform_With_Z_Bias(matrix, znear, zfar); +} + +// -- Lighting and fog -------------------------------------------------------- + +void DX8Backend::Set_Light(unsigned int index, const LightClass & light) +{ + DX8Wrapper::Set_Light(index, light); +} + +void DX8Backend::Set_Ambient(const Vector3 & color) +{ + DX8Wrapper::Set_Ambient(color); +} + +const Vector3 & DX8Backend::Get_Ambient() const +{ + return DX8Wrapper::Get_Ambient(); +} + +void DX8Backend::Set_Fog(bool enable, const Vector3 & color, float start, float end) +{ + DX8Wrapper::Set_Fog(enable, color, start, end); +} + +bool DX8Backend::Get_Fog_Enable() const +{ + return DX8Wrapper::Get_Fog_Enable(); +} + +void DX8Backend::Set_Light_Environment(LightEnvironmentClass * light_env) +{ + DX8Wrapper::Set_Light_Environment(light_env); +} + +LightEnvironmentClass * DX8Backend::Get_Light_Environment() const +{ + return DX8Wrapper::Get_Light_Environment(); +} + +// -- Draw calls -------------------------------------------------------------- + +void DX8Backend::Draw_Triangles(unsigned short start_index, + unsigned short polygon_count, + unsigned short min_vertex_index, + unsigned short vertex_count) +{ + DX8Wrapper::Draw_Triangles(start_index, polygon_count, min_vertex_index, vertex_count); +} + +void DX8Backend::Draw_Triangles(unsigned int buffer_type, + unsigned short start_index, + unsigned short polygon_count, + unsigned short min_vertex_index, + unsigned short vertex_count) +{ + DX8Wrapper::Draw_Triangles(buffer_type, start_index, polygon_count, min_vertex_index, vertex_count); +} + +void DX8Backend::Draw_Strip(unsigned short start_index, + unsigned short index_count, + unsigned short min_vertex_index, + unsigned short vertex_count) +{ + DX8Wrapper::Draw_Strip(start_index, index_count, min_vertex_index, vertex_count); +} + +// -- Programmable pipeline --------------------------------------------------- + +void DX8Backend::Set_Vertex_Shader(unsigned long vertex_shader) +{ + DX8Wrapper::Set_Vertex_Shader(static_cast(vertex_shader)); +} + +void DX8Backend::Set_Pixel_Shader(unsigned long pixel_shader) +{ + DX8Wrapper::Set_Pixel_Shader(static_cast(pixel_shader)); +} + +void DX8Backend::Set_Vertex_Shader_Constant(int reg, const void * data, int count) +{ + DX8Wrapper::Set_Vertex_Shader_Constant(reg, data, count); +} + +void DX8Backend::Set_Pixel_Shader_Constant(int reg, const void * data, int count) +{ + DX8Wrapper::Set_Pixel_Shader_Constant(reg, data, count); +} + +// -- Render targets ---------------------------------------------------------- + +TextureClass * DX8Backend::Create_Render_Target(int width, int height, WW3DFormat format) +{ + return DX8Wrapper::Create_Render_Target(width, height, format); +} + +void DX8Backend::Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture) +{ + DX8Wrapper::Set_Render_Target_With_Z(texture, ztexture); +} + +bool DX8Backend::Is_Render_To_Texture() +{ + return DX8Wrapper::Is_Render_To_Texture(); +} + +void DX8Backend::Set_Shadow_Map(int idx, ZTextureClass * ztex) +{ + DX8Wrapper::Set_Shadow_Map(idx, ztex); +} + +ZTextureClass * DX8Backend::Get_Shadow_Map(int idx) +{ + return DX8Wrapper::Get_Shadow_Map(idx); +} diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h new file mode 100644 index 00000000000..a6a93299456 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h @@ -0,0 +1,123 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 Electronic Arts Inc. +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend is the reference +// implementation of IRenderBackend that forwards every virtual method to the +// existing DX8Wrapper static facade. It adds zero new rendering logic and +// performs zero behavior changes — it is pure adaptation so the rest of the +// engine can start talking to an IRenderBackend pointer while still running +// on the established DX8 path. See RENDER_BACKEND.md. + +#pragma once + +#include "IRenderBackend.h" + +class DX8Backend : public IRenderBackend +{ +public: + DX8Backend(); + virtual ~DX8Backend(); + + // -- Device state queries ------------------------------------------------- + + virtual bool Is_Device_Lost() const; + virtual bool Has_Stencil(); + virtual WW3DFormat Get_Back_Buffer_Format(); + virtual SurfaceClass * Get_Back_Buffer(unsigned int num); + virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit); + + // -- Frame lifecycle ------------------------------------------------------ + + virtual void Begin_Scene(); + virtual void End_Scene(bool flip_frame); + virtual void Flip_To_Primary(); + virtual void Clear(bool clear_color, bool clear_z_stencil, + const Vector3 & color, + float dest_alpha, float z, unsigned int stencil); + virtual void Set_Viewport(const RenderBackendViewport & viewport); + + // -- Vertex / index buffers ----------------------------------------------- + + virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream); + virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba); + virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset); + virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset); + virtual void Set_Index_Buffer_Index_Offset(unsigned int offset); + + // -- State: shaders, materials, textures --------------------------------- + + virtual void Set_Shader(const ShaderClass & shader); + virtual void Get_Shader(ShaderClass & shader); + virtual void Set_Material(const VertexMaterialClass * material); + virtual void Set_Texture(unsigned int stage, TextureBaseClass * texture); + virtual void Apply_Render_State_Changes(); + virtual void Apply_Default_State(); + virtual void Invalidate_Cached_Render_States(); + + // -- Transforms ----------------------------------------------------------- + + virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m); + virtual void Set_Transform(TransformKind transform, const Matrix3D & m); + virtual void Get_Transform(TransformKind transform, Matrix4x4 & m); + virtual void Set_World_Identity(); + virtual void Set_View_Identity(); + virtual bool Is_World_Identity(); + virtual bool Is_View_Identity(); + virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar); + + // -- Lighting and fog ----------------------------------------------------- + + virtual void Set_Light(unsigned int index, const LightClass & light); + virtual void Set_Ambient(const Vector3 & color); + virtual const Vector3 & Get_Ambient() const; + virtual void Set_Fog(bool enable, const Vector3 & color, float start, float end); + virtual bool Get_Fog_Enable() const; + virtual void Set_Light_Environment(LightEnvironmentClass * light_env); + virtual LightEnvironmentClass * Get_Light_Environment() const; + + // -- Draw calls ----------------------------------------------------------- + + virtual void Draw_Triangles(unsigned short start_index, + unsigned short polygon_count, + unsigned short min_vertex_index, + unsigned short vertex_count); + virtual void Draw_Triangles(unsigned int buffer_type, + unsigned short start_index, + unsigned short polygon_count, + unsigned short min_vertex_index, + unsigned short vertex_count); + virtual void Draw_Strip(unsigned short start_index, + unsigned short index_count, + unsigned short min_vertex_index, + unsigned short vertex_count); + + // -- Programmable pipeline ------------------------------------------------ + + virtual void Set_Vertex_Shader(unsigned long vertex_shader); + virtual void Set_Pixel_Shader(unsigned long pixel_shader); + virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count); + virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count); + + // -- Render targets ------------------------------------------------------- + + virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format); + virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture); + virtual bool Is_Render_To_Texture(); + virtual void Set_Shadow_Map(int idx, ZTextureClass * ztex); + virtual ZTextureClass * Get_Shadow_Map(int idx); +}; From b6dc7bd32a0138dfcd84cc3b7508d0defc7e1eda Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 10 Apr 2026 14:48:34 -0400 Subject: [PATCH 03/17] feat(ww3d2): add global g_renderBackend pointer and lifecycle wiring --- .../Source/WWVegas/WW3D2/CMakeLists.txt | 2 + .../Source/WWVegas/WW3D2/RenderBackend.cpp | 48 +++++++++++++++++++ .../Source/WWVegas/WW3D2/RenderBackend.h | 42 ++++++++++++++++ .../Source/WWVegas/WW3D2/dx8wrapper.cpp | 11 +++++ 4 files changed, 103 insertions(+) create mode 100644 Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp create mode 100644 Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index 5ef2ef11e0c..18267191c25 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -158,6 +158,8 @@ set(WW3D2_SRC proto.h proxy.h rddesc.h + RenderBackend.cpp + RenderBackend.h #render2d.cpp #render2d.h render2dsentence.cpp diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp new file mode 100644 index 00000000000..cf4535832f2 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp @@ -0,0 +1,48 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 Electronic Arts Inc. +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 Render backend global +// owner. Holds the single g_renderBackend pointer and constructs/destroys +// the concrete backend instance. See RENDER_BACKEND.md. + +#include "RenderBackend.h" +#include "DX8Backend.h" + +IRenderBackend * g_renderBackend = nullptr; + +void Init_Render_Backend() +{ + if (g_renderBackend != nullptr) + { + return; + } + + // Phase 1: the DX8 backend is the only option. Phase 2 will introduce + // a compile-time flag to pick between DX8, bgfx, and Diligent. + g_renderBackend = new DX8Backend(); +} + +void Shutdown_Render_Backend() +{ + if (g_renderBackend == nullptr) + { + return; + } + delete g_renderBackend; + g_renderBackend = nullptr; +} diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h new file mode 100644 index 00000000000..7c72d195783 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h @@ -0,0 +1,42 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2025 Electronic Arts Inc. +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 Backend-agnostic access point +// for the global IRenderBackend instance. Engine-side code should include +// this header (not IRenderBackend.h or DX8Backend.h directly) to use the +// render backend. See RENDER_BACKEND.md. + +#pragma once + +#include "IRenderBackend.h" + +// The active rendering backend. Set by Init_Render_Backend() during +// WW3D device initialization and cleared by Shutdown_Render_Backend() +// during device teardown. Never null between those two calls. +extern IRenderBackend * g_renderBackend; + +// Create the render backend. Called by DX8Wrapper::Do_Onetime_Device_Dependent_Inits +// after the D3D device has been successfully created. +// +// Phase 1 always creates a DX8Backend. Phase 2 will add a compile-time +// option to select between DX8Backend, BgfxBackend, and DiligentBackend. +void Init_Render_Backend(); + +// Destroy the render backend. Called by DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns +// before the D3D device is released. +void Shutdown_Render_Backend(); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index ba897a753a5..46d0ae95102 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -56,6 +56,7 @@ #include "dx8vertexbuffer.h" #include "dx8indexbuffer.h" #include "dx8renderer.h" +#include "RenderBackend.h" #include "ww3d.h" #include "camera.h" #include "WWLib/wwstring.h" @@ -390,6 +391,11 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Inits() TextureLoader::Init(); Set_Default_Global_Render_States(); + + // TheSuperHackers @refactor bobtista 10/04/2026 Construct the global + // IRenderBackend instance now that the D3D device is ready. See + // Core/Libraries/Source/WWVegas/WW3D2/RENDER_BACKEND.md. + Init_Render_Backend(); } inline DWORD F2DW(float f) { return *((unsigned*)&f); } @@ -450,6 +456,11 @@ void DX8Wrapper::Invalidate_Cached_Render_States() void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns() { + // TheSuperHackers @refactor bobtista 10/04/2026 Tear down the render + // backend before the D3D device is released so any backend-owned + // resources get released first. See RENDER_BACKEND.md. + Shutdown_Render_Backend(); + /* ** Shutdown ww3d systems */ From 3d80c67437e766d7139845b8431c6728ca9f9d2e Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 18 Apr 2026 02:01:27 -0400 Subject: [PATCH 04/17] fix(ww3d2): Update copyright headers to TheSuperHackers for new files --- Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp | 2 +- Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h | 2 +- Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h | 2 +- Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp | 2 +- Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp index 542a776a22d..c6fd25950c2 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp @@ -1,6 +1,6 @@ /* ** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. +** Copyright 2026 TheSuperHackers ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h index a6a93299456..916f6b76954 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h @@ -1,6 +1,6 @@ /* ** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. +** Copyright 2026 TheSuperHackers ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index 2071d987b55..80e9f4fdb60 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -1,6 +1,6 @@ /* ** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. +** Copyright 2026 TheSuperHackers ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp index cf4535832f2..0ec35c51022 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp @@ -1,6 +1,6 @@ /* ** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. +** Copyright 2026 TheSuperHackers ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h index 7c72d195783..ee4627d5717 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h @@ -1,6 +1,6 @@ /* ** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. +** Copyright 2026 TheSuperHackers ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by From 9db0eb6b5061ff5eb188e7c506e28d376f6dbcaf Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 31 May 2026 11:46:02 +1000 Subject: [PATCH 05/17] refactor(ww3d2): trim redundant comments from render backend interface --- .../Source/WWVegas/WW3D2/DX8Backend.cpp | 18 ---- .../Source/WWVegas/WW3D2/DX8Backend.h | 24 +---- .../Source/WWVegas/WW3D2/IRenderBackend.h | 99 +++---------------- .../Source/WWVegas/WW3D2/RenderBackend.cpp | 8 +- .../Source/WWVegas/WW3D2/RenderBackend.h | 19 ++-- .../Source/WWVegas/WW3D2/dx8wrapper.cpp | 5 +- 6 files changed, 26 insertions(+), 147 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp index c6fd25950c2..7ddbe267aef 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp @@ -38,8 +38,6 @@ DX8Backend::~DX8Backend() { } -// -- Device state queries ---------------------------------------------------- - bool DX8Backend::Is_Device_Lost() const { return DX8Wrapper::Is_Device_Lost(); @@ -65,8 +63,6 @@ void DX8Backend::Set_Gamma(float gamma, float bright, float contrast, bool calib DX8Wrapper::Set_Gamma(gamma, bright, contrast, calibrate, uselimit); } -// -- Frame lifecycle --------------------------------------------------------- - void DX8Backend::Begin_Scene() { DX8Wrapper::Begin_Scene(); @@ -101,8 +97,6 @@ void DX8Backend::Set_Viewport(const RenderBackendViewport & viewport) DX8Wrapper::Set_Viewport(&vp); } -// -- Vertex / index buffers -------------------------------------------------- - void DX8Backend::Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) { DX8Wrapper::Set_Vertex_Buffer(vb, stream); @@ -128,8 +122,6 @@ void DX8Backend::Set_Index_Buffer_Index_Offset(unsigned int offset) DX8Wrapper::Set_Index_Buffer_Index_Offset(offset); } -// -- State: shaders, materials, textures ------------------------------------ - void DX8Backend::Set_Shader(const ShaderClass & shader) { DX8Wrapper::Set_Shader(shader); @@ -165,8 +157,6 @@ void DX8Backend::Invalidate_Cached_Render_States() DX8Wrapper::Invalidate_Cached_Render_States(); } -// -- Transforms -------------------------------------------------------------- - void DX8Backend::Set_Transform(TransformKind transform, const Matrix4x4 & m) { DX8Wrapper::Set_Transform(static_cast(transform), m); @@ -207,8 +197,6 @@ void DX8Backend::Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, DX8Wrapper::Set_Projection_Transform_With_Z_Bias(matrix, znear, zfar); } -// -- Lighting and fog -------------------------------------------------------- - void DX8Backend::Set_Light(unsigned int index, const LightClass & light) { DX8Wrapper::Set_Light(index, light); @@ -244,8 +232,6 @@ LightEnvironmentClass * DX8Backend::Get_Light_Environment() const return DX8Wrapper::Get_Light_Environment(); } -// -- Draw calls -------------------------------------------------------------- - void DX8Backend::Draw_Triangles(unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, @@ -271,8 +257,6 @@ void DX8Backend::Draw_Strip(unsigned short start_index, DX8Wrapper::Draw_Strip(start_index, index_count, min_vertex_index, vertex_count); } -// -- Programmable pipeline --------------------------------------------------- - void DX8Backend::Set_Vertex_Shader(unsigned long vertex_shader) { DX8Wrapper::Set_Vertex_Shader(static_cast(vertex_shader)); @@ -293,8 +277,6 @@ void DX8Backend::Set_Pixel_Shader_Constant(int reg, const void * data, int count DX8Wrapper::Set_Pixel_Shader_Constant(reg, data, count); } -// -- Render targets ---------------------------------------------------------- - TextureClass * DX8Backend::Create_Render_Target(int width, int height, WW3DFormat format) { return DX8Wrapper::Create_Render_Target(width, height, format); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h index 916f6b76954..7e1cdbb8a20 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h @@ -18,10 +18,7 @@ // TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend is the reference // implementation of IRenderBackend that forwards every virtual method to the -// existing DX8Wrapper static facade. It adds zero new rendering logic and -// performs zero behavior changes — it is pure adaptation so the rest of the -// engine can start talking to an IRenderBackend pointer while still running -// on the established DX8 path. See RENDER_BACKEND.md. +// existing DX8Wrapper static facade. Pure adaptation, no new rendering logic. #pragma once @@ -33,16 +30,12 @@ class DX8Backend : public IRenderBackend DX8Backend(); virtual ~DX8Backend(); - // -- Device state queries ------------------------------------------------- - virtual bool Is_Device_Lost() const; virtual bool Has_Stencil(); virtual WW3DFormat Get_Back_Buffer_Format(); virtual SurfaceClass * Get_Back_Buffer(unsigned int num); virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit); - // -- Frame lifecycle ------------------------------------------------------ - virtual void Begin_Scene(); virtual void End_Scene(bool flip_frame); virtual void Flip_To_Primary(); @@ -51,16 +44,12 @@ class DX8Backend : public IRenderBackend float dest_alpha, float z, unsigned int stencil); virtual void Set_Viewport(const RenderBackendViewport & viewport); - // -- Vertex / index buffers ----------------------------------------------- - virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream); virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba); virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset); virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset); virtual void Set_Index_Buffer_Index_Offset(unsigned int offset); - // -- State: shaders, materials, textures --------------------------------- - virtual void Set_Shader(const ShaderClass & shader); virtual void Get_Shader(ShaderClass & shader); virtual void Set_Material(const VertexMaterialClass * material); @@ -69,8 +58,6 @@ class DX8Backend : public IRenderBackend virtual void Apply_Default_State(); virtual void Invalidate_Cached_Render_States(); - // -- Transforms ----------------------------------------------------------- - virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m); virtual void Set_Transform(TransformKind transform, const Matrix3D & m); virtual void Get_Transform(TransformKind transform, Matrix4x4 & m); @@ -80,8 +67,6 @@ class DX8Backend : public IRenderBackend virtual bool Is_View_Identity(); virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar); - // -- Lighting and fog ----------------------------------------------------- - virtual void Set_Light(unsigned int index, const LightClass & light); virtual void Set_Ambient(const Vector3 & color); virtual const Vector3 & Get_Ambient() const; @@ -90,8 +75,6 @@ class DX8Backend : public IRenderBackend virtual void Set_Light_Environment(LightEnvironmentClass * light_env); virtual LightEnvironmentClass * Get_Light_Environment() const; - // -- Draw calls ----------------------------------------------------------- - virtual void Draw_Triangles(unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, @@ -106,15 +89,12 @@ class DX8Backend : public IRenderBackend unsigned short min_vertex_index, unsigned short vertex_count); - // -- Programmable pipeline ------------------------------------------------ - + // The shader id is treated as an opaque unsigned long. virtual void Set_Vertex_Shader(unsigned long vertex_shader); virtual void Set_Pixel_Shader(unsigned long pixel_shader); virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count); virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count); - // -- Render targets ------------------------------------------------------- - virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format); virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture); virtual bool Is_Render_To_Texture(); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index 80e9f4fdb60..88137f49b8d 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -16,25 +16,16 @@ ** along with this program. If not, see . */ -// TheSuperHackers @refactor bobtista 10/04/2026 Introduce IRenderBackend -// abstract interface so WW3D2 rendering can be re-targeted to modern backends -// (bgfx, Diligent, etc.) while the existing DX8 path stays functional as the -// reference implementation. See Core/Libraries/Source/WWVegas/WW3D2/RENDER_BACKEND.md. +// TheSuperHackers @refactor bobtista 10/04/2026 Abstract W3D-facing rendering +// interface so WW3D2 rendering can be re-targeted to other backends while the +// existing DX8 path stays as the reference implementation. #pragma once #include "ww3dformat.h" -// ----------------------------------------------------------------------------- -// Forward declarations -// ----------------------------------------------------------------------------- -// -// Kept lightweight deliberately. IRenderBackend.h must be includable without -// dragging in the full WW3D2 header graph, so callers only pay for the types -// they actually use. -// -// All W3D classes passed through this interface are referenced by pointer or -// reference; none of them need a full definition in this header. +// Forward declarations keep this header includable without pulling in the full +// WW3D2 header graph. All W3D types below are passed by pointer or reference. class ShaderClass; class VertexMaterialClass; @@ -52,15 +43,9 @@ class Matrix4x4; class Matrix3D; class Vector3; -// ----------------------------------------------------------------------------- -// POD types owned by the interface -// ----------------------------------------------------------------------------- - enum TransformKind { - // Values chosen so they can be mapped directly to D3DTS_* inside the - // DX8Backend without a branch. A modern backend ignores these indices - // and uses whichever matrix storage is convenient for it. + // Values match D3DTS_* so DX8Backend can map them without a branch. RB_TRANSFORM_VIEW = 2, // D3DTS_VIEW RB_TRANSFORM_PROJECTION = 3, // D3DTS_PROJECTION RB_TRANSFORM_WORLD = 256 // D3DTS_WORLD @@ -76,52 +61,25 @@ struct RenderBackendViewport float max_z; }; -// ----------------------------------------------------------------------------- -// IRenderBackend — abstract W3D-facing rendering interface -// ----------------------------------------------------------------------------- -// -// This interface exposes the *high-level* subset of DX8Wrapper's public API: -// the calls that take and return W3D types (ShaderClass, TextureBaseClass, -// Matrix4x4, etc.) and are backend-neutral by construction. The low-level -// D3D8-specific entry points on DX8Wrapper (Set_DX8_Render_State, -// _Create_DX8_Texture, _Get_D3D_Device8, etc.) are NOT exposed here and -// remain reachable only through DX8Wrapper's static methods. Code that -// needs them is DX8-only and must be migrated during later phases. +// Exposes the high-level subset of DX8Wrapper's public API: the calls that take +// and return W3D types (ShaderClass, TextureBaseClass, Matrix4x4, etc.). The +// low-level D3D8-specific entry points on DX8Wrapper are not exposed here and +// remain reachable only through DX8Wrapper's static methods. // -// **Method names intentionally match the existing DX8Wrapper names** so -// that migrating callers is a mechanical `DX8Wrapper::X(...)` → -// `g_renderBackend->X(...)` rewrite with minimal diff noise. -// -// **This header is included from VC6-compiled translation units** (the -// DX8 reference path and the tools). Keep it C++98-compatible: -// - No , no , no or other STL in signatures -// - No `override`, `= default`, `= delete`, `auto`, `constexpr` -// - `nullptr` is OK (the project has a VC6 shim) -// - POD structs for parameter bundles -// - Forward-declare W3D types rather than including their headers -// -// Implementations (DX8Backend.cpp, future BgfxBackend.cpp, etc.) can use -// whatever C++ features the project's main build allows. +// Method names intentionally match the existing DX8Wrapper names so migrating a +// caller is a mechanical DX8Wrapper::X(...) -> g_renderBackend->X(...) rewrite. class IRenderBackend { public: virtual ~IRenderBackend() {} - // ------------------------------------------------------------------------- - // Device state queries - // ------------------------------------------------------------------------- - virtual bool Is_Device_Lost() const = 0; virtual bool Has_Stencil() = 0; virtual WW3DFormat Get_Back_Buffer_Format() = 0; virtual SurfaceClass * Get_Back_Buffer(unsigned int num) = 0; virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) = 0; - // ------------------------------------------------------------------------- - // Frame lifecycle - // ------------------------------------------------------------------------- - virtual void Begin_Scene() = 0; virtual void End_Scene(bool flip_frame) = 0; virtual void Flip_To_Primary() = 0; @@ -130,20 +88,12 @@ class IRenderBackend float dest_alpha, float z, unsigned int stencil) = 0; virtual void Set_Viewport(const RenderBackendViewport & viewport) = 0; - // ------------------------------------------------------------------------- - // Vertex / index buffers - // ------------------------------------------------------------------------- - virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) = 0; virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba) = 0; virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) = 0; virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) = 0; virtual void Set_Index_Buffer_Index_Offset(unsigned int offset) = 0; - // ------------------------------------------------------------------------- - // State: shaders, materials, textures - // ------------------------------------------------------------------------- - virtual void Set_Shader(const ShaderClass & shader) = 0; virtual void Get_Shader(ShaderClass & shader) = 0; virtual void Set_Material(const VertexMaterialClass * material) = 0; @@ -153,10 +103,6 @@ class IRenderBackend virtual void Apply_Default_State() = 0; virtual void Invalidate_Cached_Render_States() = 0; - // ------------------------------------------------------------------------- - // Transforms - // ------------------------------------------------------------------------- - virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m) = 0; virtual void Set_Transform(TransformKind transform, const Matrix3D & m) = 0; virtual void Get_Transform(TransformKind transform, Matrix4x4 & m) = 0; @@ -167,10 +113,6 @@ class IRenderBackend virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar) = 0; - // ------------------------------------------------------------------------- - // Lighting and fog - // ------------------------------------------------------------------------- - virtual void Set_Light(unsigned int index, const LightClass & light) = 0; virtual void Set_Ambient(const Vector3 & color) = 0; virtual const Vector3 & Get_Ambient() const = 0; @@ -179,10 +121,6 @@ class IRenderBackend virtual void Set_Light_Environment(LightEnvironmentClass * light_env) = 0; virtual LightEnvironmentClass * Get_Light_Environment() const = 0; - // ------------------------------------------------------------------------- - // Draw calls - // ------------------------------------------------------------------------- - virtual void Draw_Triangles(unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, @@ -199,23 +137,12 @@ class IRenderBackend unsigned short min_vertex_index, unsigned short vertex_count) = 0; - // ------------------------------------------------------------------------- - // Programmable pipeline (GPU vertex / pixel shaders) - // ------------------------------------------------------------------------- - // - // These correspond to DX8's programmable shader slots. Modern backends - // will re-interpret the handles internally; the interface treats the - // shader id as an opaque unsigned long. - + // The shader id is treated as an opaque unsigned long. virtual void Set_Vertex_Shader(unsigned long vertex_shader) = 0; virtual void Set_Pixel_Shader(unsigned long pixel_shader) = 0; virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count) = 0; virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count) = 0; - // ------------------------------------------------------------------------- - // Render targets - // ------------------------------------------------------------------------- - virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format) = 0; virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture) = 0; virtual bool Is_Render_To_Texture() = 0; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp index 0ec35c51022..70190545323 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp @@ -16,9 +16,9 @@ ** along with this program. If not, see . */ -// TheSuperHackers @refactor bobtista 10/04/2026 Render backend global -// owner. Holds the single g_renderBackend pointer and constructs/destroys -// the concrete backend instance. See RENDER_BACKEND.md. +// TheSuperHackers @refactor bobtista 10/04/2026 Render backend global owner. +// Holds the single g_renderBackend pointer and constructs/destroys the +// concrete backend instance. #include "RenderBackend.h" #include "DX8Backend.h" @@ -32,8 +32,6 @@ void Init_Render_Backend() return; } - // Phase 1: the DX8 backend is the only option. Phase 2 will introduce - // a compile-time flag to pick between DX8, bgfx, and Diligent. g_renderBackend = new DX8Backend(); } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h index ee4627d5717..39386ee5dd0 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h @@ -17,26 +17,19 @@ */ // TheSuperHackers @refactor bobtista 10/04/2026 Backend-agnostic access point -// for the global IRenderBackend instance. Engine-side code should include -// this header (not IRenderBackend.h or DX8Backend.h directly) to use the -// render backend. See RENDER_BACKEND.md. +// for the global IRenderBackend instance. Engine-side code should include this +// header (not IRenderBackend.h or DX8Backend.h directly) to use the backend. #pragma once #include "IRenderBackend.h" -// The active rendering backend. Set by Init_Render_Backend() during -// WW3D device initialization and cleared by Shutdown_Render_Backend() -// during device teardown. Never null between those two calls. +// The active rendering backend. Set by Init_Render_Backend() and cleared by +// Shutdown_Render_Backend(); never null between those two calls. extern IRenderBackend * g_renderBackend; -// Create the render backend. Called by DX8Wrapper::Do_Onetime_Device_Dependent_Inits -// after the D3D device has been successfully created. -// -// Phase 1 always creates a DX8Backend. Phase 2 will add a compile-time -// option to select between DX8Backend, BgfxBackend, and DiligentBackend. +// Create the render backend. Must be called after the render device is ready. void Init_Render_Backend(); -// Destroy the render backend. Called by DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns -// before the D3D device is released. +// Destroy the render backend. Must be called before the render device is released. void Shutdown_Render_Backend(); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 46d0ae95102..846c1736a3b 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -393,8 +393,7 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Inits() Set_Default_Global_Render_States(); // TheSuperHackers @refactor bobtista 10/04/2026 Construct the global - // IRenderBackend instance now that the D3D device is ready. See - // Core/Libraries/Source/WWVegas/WW3D2/RENDER_BACKEND.md. + // IRenderBackend instance now that the D3D device is ready. Init_Render_Backend(); } @@ -458,7 +457,7 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns() { // TheSuperHackers @refactor bobtista 10/04/2026 Tear down the render // backend before the D3D device is released so any backend-owned - // resources get released first. See RENDER_BACKEND.md. + // resources get released first. Shutdown_Render_Backend(); /* From 294ce4fa9e075e20b374a1b691fe4c749846406a Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 31 May 2026 11:46:29 +1000 Subject: [PATCH 06/17] refactor(ww3d2): move backend implementations into Backend subfolder --- .../Source/WWVegas/WW3D2/{ => Backend}/DX8Backend.cpp | 0 .../Source/WWVegas/WW3D2/{ => Backend}/DX8Backend.h | 0 .../Source/WWVegas/WW3D2/{ => Backend}/RenderBackend.cpp | 0 .../Source/WWVegas/WW3D2/{ => Backend}/RenderBackend.h | 0 Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt | 8 ++++---- Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename Core/Libraries/Source/WWVegas/WW3D2/{ => Backend}/DX8Backend.cpp (100%) rename Core/Libraries/Source/WWVegas/WW3D2/{ => Backend}/DX8Backend.h (100%) rename Core/Libraries/Source/WWVegas/WW3D2/{ => Backend}/RenderBackend.cpp (100%) rename Core/Libraries/Source/WWVegas/WW3D2/{ => Backend}/RenderBackend.h (100%) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp similarity index 100% rename from Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.cpp rename to Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp diff --git a/Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h similarity index 100% rename from Core/Libraries/Source/WWVegas/WW3D2/DX8Backend.h rename to Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp similarity index 100% rename from Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.cpp rename to Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp diff --git a/Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h similarity index 100% rename from Core/Libraries/Source/WWVegas/WW3D2/RenderBackend.h rename to Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index 18267191c25..c64f17b1ebc 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -43,8 +43,10 @@ set(WW3D2_SRC distlod.cpp distlod.h dllist.h - DX8Backend.cpp - DX8Backend.h + Backend/DX8Backend.cpp + Backend/DX8Backend.h + Backend/RenderBackend.cpp + Backend/RenderBackend.h dx8caps.cpp dx8caps.h dx8fvf.cpp @@ -158,8 +160,6 @@ set(WW3D2_SRC proto.h proxy.h rddesc.h - RenderBackend.cpp - RenderBackend.h #render2d.cpp #render2d.h render2dsentence.cpp diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 846c1736a3b..17f74c18f79 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -56,7 +56,7 @@ #include "dx8vertexbuffer.h" #include "dx8indexbuffer.h" #include "dx8renderer.h" -#include "RenderBackend.h" +#include "Backend/RenderBackend.h" #include "ww3d.h" #include "camera.h" #include "WWLib/wwstring.h" From b1574282f89e100f05da5cca46000fa290ab9295 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 31 May 2026 11:47:38 +1000 Subject: [PATCH 07/17] feat(ww3d2): add IRenderBackend Initialize and Shutdown lifecycle hooks --- Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h | 7 +++++++ Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index 88137f49b8d..4b80eb18151 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -74,6 +74,13 @@ class IRenderBackend public: virtual ~IRenderBackend() {} + // Optional device lifecycle. DX8Wrapper owns the render device and calls + // these after the backend is constructed and before it is destroyed. A + // backend that drives its own device creates it in Initialize and releases + // it in Shutdown; the DX8 reference backend leaves them as no-ops. + virtual void Initialize(void * window, int width, int height) {} + virtual void Shutdown() {} + virtual bool Is_Device_Lost() const = 0; virtual bool Has_Stencil() = 0; virtual WW3DFormat Get_Back_Buffer_Format() = 0; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 17f74c18f79..450663190c4 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -393,8 +393,10 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Inits() Set_Default_Global_Render_States(); // TheSuperHackers @refactor bobtista 10/04/2026 Construct the global - // IRenderBackend instance now that the D3D device is ready. + // IRenderBackend instance now that the D3D device is ready, then let it + // bring up any device of its own. Init_Render_Backend(); + g_renderBackend->Initialize(_Hwnd, ResolutionWidth, ResolutionHeight); } inline DWORD F2DW(float f) { return *((unsigned*)&f); } @@ -458,6 +460,7 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns() // TheSuperHackers @refactor bobtista 10/04/2026 Tear down the render // backend before the D3D device is released so any backend-owned // resources get released first. + g_renderBackend->Shutdown(); Shutdown_Render_Backend(); /* From 3568db1ffe7a0ac72b86fe5931f98f51ea7134e2 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 5 Jun 2026 07:50:33 +1000 Subject: [PATCH 08/17] build(ww3d2): sort Backend render sources alphabetically in CMakeLists --- Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index c64f17b1ebc..decac0ea6f3 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -13,6 +13,10 @@ set(WW3D2_SRC #assetmgr.h assetstatus.cpp assetstatus.h + Backend/DX8Backend.cpp + Backend/DX8Backend.h + Backend/RenderBackend.cpp + Backend/RenderBackend.h bitmaphandler.cpp bitmaphandler.h bmp2d.cpp @@ -43,10 +47,6 @@ set(WW3D2_SRC distlod.cpp distlod.h dllist.h - Backend/DX8Backend.cpp - Backend/DX8Backend.h - Backend/RenderBackend.cpp - Backend/RenderBackend.h dx8caps.cpp dx8caps.h dx8fvf.cpp From 0644f79a65474ba60de548ae0d6b12a61b128285 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 19 Jul 2026 13:55:21 +0400 Subject: [PATCH 09/17] fix(ww3d2): guard against null render backend in device dependent shutdown --- Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 450663190c4..66105d1055d 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -460,7 +460,10 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns() // TheSuperHackers @refactor bobtista 10/04/2026 Tear down the render // backend before the D3D device is released so any backend-owned // resources get released first. - g_renderBackend->Shutdown(); + if (g_renderBackend != nullptr) + { + g_renderBackend->Shutdown(); + } Shutdown_Render_Backend(); /* From 89ba40d0685fc0084d98f60558ec6ad6c4cfed56 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 19 Jul 2026 13:55:53 +0400 Subject: [PATCH 10/17] refactor(ww3d2): decouple TransformKind values from D3D transform state constants --- .../WWVegas/WW3D2/Backend/DX8Backend.cpp | 20 ++++++++++++++++--- .../Source/WWVegas/WW3D2/IRenderBackend.h | 7 +++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp index 7ddbe267aef..c5e5b6f5c97 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -157,19 +157,33 @@ void DX8Backend::Invalidate_Cached_Render_States() DX8Wrapper::Invalidate_Cached_Render_States(); } +static D3DTRANSFORMSTATETYPE To_D3D_Transform(TransformKind transform) +{ + switch (transform) + { + case RB_TRANSFORM_VIEW: + return D3DTS_VIEW; + case RB_TRANSFORM_PROJECTION: + return D3DTS_PROJECTION; + case RB_TRANSFORM_WORLD: + default: + return D3DTS_WORLD; + } +} + void DX8Backend::Set_Transform(TransformKind transform, const Matrix4x4 & m) { - DX8Wrapper::Set_Transform(static_cast(transform), m); + DX8Wrapper::Set_Transform(To_D3D_Transform(transform), m); } void DX8Backend::Set_Transform(TransformKind transform, const Matrix3D & m) { - DX8Wrapper::Set_Transform(static_cast(transform), m); + DX8Wrapper::Set_Transform(To_D3D_Transform(transform), m); } void DX8Backend::Get_Transform(TransformKind transform, Matrix4x4 & m) { - DX8Wrapper::Get_Transform(static_cast(transform), m); + DX8Wrapper::Get_Transform(To_D3D_Transform(transform), m); } void DX8Backend::Set_World_Identity() diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index 4b80eb18151..87eb9e3f8e1 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -45,10 +45,9 @@ class Vector3; enum TransformKind { - // Values match D3DTS_* so DX8Backend can map them without a branch. - RB_TRANSFORM_VIEW = 2, // D3DTS_VIEW - RB_TRANSFORM_PROJECTION = 3, // D3DTS_PROJECTION - RB_TRANSFORM_WORLD = 256 // D3DTS_WORLD + RB_TRANSFORM_WORLD, + RB_TRANSFORM_VIEW, + RB_TRANSFORM_PROJECTION }; struct RenderBackendViewport From 97a60340beec0112a0b57e12100d7e0b5c120a4a Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 19 Jul 2026 13:56:20 +0400 Subject: [PATCH 11/17] refactor(ww3d2): add override specifiers to DX8Backend declarations --- .../Source/WWVegas/WW3D2/Backend/DX8Backend.h | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h index 7e1cdbb8a20..645154f17a7 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h @@ -28,76 +28,76 @@ class DX8Backend : public IRenderBackend { public: DX8Backend(); - virtual ~DX8Backend(); + virtual ~DX8Backend() override; - virtual bool Is_Device_Lost() const; - virtual bool Has_Stencil(); - virtual WW3DFormat Get_Back_Buffer_Format(); - virtual SurfaceClass * Get_Back_Buffer(unsigned int num); - virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit); + virtual bool Is_Device_Lost() const override; + virtual bool Has_Stencil() override; + virtual WW3DFormat Get_Back_Buffer_Format() override; + virtual SurfaceClass * Get_Back_Buffer(unsigned int num) override; + virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) override; - virtual void Begin_Scene(); - virtual void End_Scene(bool flip_frame); - virtual void Flip_To_Primary(); + virtual void Begin_Scene() override; + virtual void End_Scene(bool flip_frame) override; + virtual void Flip_To_Primary() override; virtual void Clear(bool clear_color, bool clear_z_stencil, const Vector3 & color, - float dest_alpha, float z, unsigned int stencil); - virtual void Set_Viewport(const RenderBackendViewport & viewport); + float dest_alpha, float z, unsigned int stencil) override; + virtual void Set_Viewport(const RenderBackendViewport & viewport) override; - virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream); - virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba); - virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset); - virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset); - virtual void Set_Index_Buffer_Index_Offset(unsigned int offset); + virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) override; + virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba) override; + virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) override; + virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) override; + virtual void Set_Index_Buffer_Index_Offset(unsigned int offset) override; - virtual void Set_Shader(const ShaderClass & shader); - virtual void Get_Shader(ShaderClass & shader); - virtual void Set_Material(const VertexMaterialClass * material); - virtual void Set_Texture(unsigned int stage, TextureBaseClass * texture); - virtual void Apply_Render_State_Changes(); - virtual void Apply_Default_State(); - virtual void Invalidate_Cached_Render_States(); + virtual void Set_Shader(const ShaderClass & shader) override; + virtual void Get_Shader(ShaderClass & shader) override; + virtual void Set_Material(const VertexMaterialClass * material) override; + virtual void Set_Texture(unsigned int stage, TextureBaseClass * texture) override; + virtual void Apply_Render_State_Changes() override; + virtual void Apply_Default_State() override; + virtual void Invalidate_Cached_Render_States() override; - virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m); - virtual void Set_Transform(TransformKind transform, const Matrix3D & m); - virtual void Get_Transform(TransformKind transform, Matrix4x4 & m); - virtual void Set_World_Identity(); - virtual void Set_View_Identity(); - virtual bool Is_World_Identity(); - virtual bool Is_View_Identity(); - virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar); + virtual void Set_Transform(TransformKind transform, const Matrix4x4 & m) override; + virtual void Set_Transform(TransformKind transform, const Matrix3D & m) override; + virtual void Get_Transform(TransformKind transform, Matrix4x4 & m) override; + virtual void Set_World_Identity() override; + virtual void Set_View_Identity() override; + virtual bool Is_World_Identity() override; + virtual bool Is_View_Identity() override; + virtual void Set_Projection_Transform_With_Z_Bias(const Matrix4x4 & matrix, float znear, float zfar) override; - virtual void Set_Light(unsigned int index, const LightClass & light); - virtual void Set_Ambient(const Vector3 & color); - virtual const Vector3 & Get_Ambient() const; - virtual void Set_Fog(bool enable, const Vector3 & color, float start, float end); - virtual bool Get_Fog_Enable() const; - virtual void Set_Light_Environment(LightEnvironmentClass * light_env); - virtual LightEnvironmentClass * Get_Light_Environment() const; + virtual void Set_Light(unsigned int index, const LightClass & light) override; + virtual void Set_Ambient(const Vector3 & color) override; + virtual const Vector3 & Get_Ambient() const override; + virtual void Set_Fog(bool enable, const Vector3 & color, float start, float end) override; + virtual bool Get_Fog_Enable() const override; + virtual void Set_Light_Environment(LightEnvironmentClass * light_env) override; + virtual LightEnvironmentClass * Get_Light_Environment() const override; virtual void Draw_Triangles(unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, - unsigned short vertex_count); + unsigned short vertex_count) override; virtual void Draw_Triangles(unsigned int buffer_type, unsigned short start_index, unsigned short polygon_count, unsigned short min_vertex_index, - unsigned short vertex_count); + unsigned short vertex_count) override; virtual void Draw_Strip(unsigned short start_index, unsigned short index_count, unsigned short min_vertex_index, - unsigned short vertex_count); + unsigned short vertex_count) override; // The shader id is treated as an opaque unsigned long. - virtual void Set_Vertex_Shader(unsigned long vertex_shader); - virtual void Set_Pixel_Shader(unsigned long pixel_shader); - virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count); - virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count); + virtual void Set_Vertex_Shader(unsigned long vertex_shader) override; + virtual void Set_Pixel_Shader(unsigned long pixel_shader) override; + virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count) override; + virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count) override; - virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format); - virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture); - virtual bool Is_Render_To_Texture(); - virtual void Set_Shadow_Map(int idx, ZTextureClass * ztex); - virtual ZTextureClass * Get_Shadow_Map(int idx); + virtual TextureClass * Create_Render_Target(int width, int height, WW3DFormat format) override; + virtual void Set_Render_Target_With_Z(TextureClass * texture, ZTextureClass * ztexture) override; + virtual bool Is_Render_To_Texture() override; + virtual void Set_Shadow_Map(int idx, ZTextureClass * ztex) override; + virtual ZTextureClass * Get_Shadow_Map(int idx) override; }; From 2422827e2da0d90825e9ddbe8621148a6801f657 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 19 Jul 2026 13:56:53 +0400 Subject: [PATCH 12/17] chore(ww3d2): use qualified include paths in render backend files --- .../Source/WWVegas/WW3D2/Backend/DX8Backend.cpp | 12 ++++++------ .../Source/WWVegas/WW3D2/Backend/DX8Backend.h | 2 +- .../Source/WWVegas/WW3D2/Backend/RenderBackend.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp index c5e5b6f5c97..6d9cecc3e57 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -23,12 +23,12 @@ #include "DX8Backend.h" -#include "dx8wrapper.h" -#include "vector3.h" -#include "matrix4.h" -#include "matrix3d.h" -#include "light.h" -#include "lightenvironment.h" +#include "WW3D2/dx8wrapper.h" +#include "WWMath/vector3.h" +#include "WWMath/matrix4.h" +#include "WWMath/matrix3d.h" +#include "WW3D2/light.h" +#include "WW3D2/lightenvironment.h" DX8Backend::DX8Backend() { diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h index 645154f17a7..97ad9775a65 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h @@ -22,7 +22,7 @@ #pragma once -#include "IRenderBackend.h" +#include "WW3D2/IRenderBackend.h" class DX8Backend : public IRenderBackend { diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h index 39386ee5dd0..fcba202f908 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h @@ -22,7 +22,7 @@ #pragma once -#include "IRenderBackend.h" +#include "WW3D2/IRenderBackend.h" // The active rendering backend. Set by Init_Render_Backend() and cleared by // Shutdown_Render_Backend(); never null between those two calls. From 4d2aeeb081c44f7619b35c4efd342248b1872e15 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 7 Aug 2026 13:04:55 +0100 Subject: [PATCH 13/17] fix(ww3d2): Use a fixed width type for render backend shader ids --- Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp | 4 ++-- Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h | 5 ++--- Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h | 7 ++++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp index 6d9cecc3e57..da8f4c2dba3 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -271,12 +271,12 @@ void DX8Backend::Draw_Strip(unsigned short start_index, DX8Wrapper::Draw_Strip(start_index, index_count, min_vertex_index, vertex_count); } -void DX8Backend::Set_Vertex_Shader(unsigned long vertex_shader) +void DX8Backend::Set_Vertex_Shader(unsigned int vertex_shader) { DX8Wrapper::Set_Vertex_Shader(static_cast(vertex_shader)); } -void DX8Backend::Set_Pixel_Shader(unsigned long pixel_shader) +void DX8Backend::Set_Pixel_Shader(unsigned int pixel_shader) { DX8Wrapper::Set_Pixel_Shader(static_cast(pixel_shader)); } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h index 97ad9775a65..dab3e756b0f 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h @@ -89,9 +89,8 @@ class DX8Backend : public IRenderBackend unsigned short min_vertex_index, unsigned short vertex_count) override; - // The shader id is treated as an opaque unsigned long. - virtual void Set_Vertex_Shader(unsigned long vertex_shader) override; - virtual void Set_Pixel_Shader(unsigned long pixel_shader) override; + virtual void Set_Vertex_Shader(unsigned int vertex_shader) override; + virtual void Set_Pixel_Shader(unsigned int pixel_shader) override; virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count) override; virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count) override; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index 87eb9e3f8e1..abbf82eb957 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -143,9 +143,10 @@ class IRenderBackend unsigned short min_vertex_index, unsigned short vertex_count) = 0; - // The shader id is treated as an opaque unsigned long. - virtual void Set_Vertex_Shader(unsigned long vertex_shader) = 0; - virtual void Set_Pixel_Shader(unsigned long pixel_shader) = 0; + // Legacy fixed function vertex format code or shader handle. Always 32 bits + // wide; unsigned long would be 64 bits on targets where long is 64-bit. + virtual void Set_Vertex_Shader(unsigned int vertex_shader) = 0; + virtual void Set_Pixel_Shader(unsigned int pixel_shader) = 0; virtual void Set_Vertex_Shader_Constant(int reg, const void * data, int count) = 0; virtual void Set_Pixel_Shader_Constant(int reg, const void * data, int count) = 0; From 8acd5f0dc527eb04533d74df66561984fad8caac Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 7 Aug 2026 13:05:54 +0100 Subject: [PATCH 14/17] refactor(ww3d2): Widen render backend draw and index ranges to unsigned int --- .../WWVegas/WW3D2/Backend/DX8Backend.cpp | 56 +++++++++++-------- .../Source/WWVegas/WW3D2/Backend/DX8Backend.h | 28 +++++----- .../Source/WWVegas/WW3D2/IRenderBackend.h | 34 ++++++----- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp index da8f4c2dba3..455c0947f98 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -107,14 +107,14 @@ void DX8Backend::Set_Vertex_Buffer(const DynamicVBAccessClass & vba) DX8Wrapper::Set_Vertex_Buffer(vba); } -void DX8Backend::Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) +void DX8Backend::Set_Index_Buffer(const IndexBufferClass * ib, unsigned int index_base_offset) { - DX8Wrapper::Set_Index_Buffer(ib, index_base_offset); + DX8Wrapper::Set_Index_Buffer(ib, static_cast(index_base_offset)); } -void DX8Backend::Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) +void DX8Backend::Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned int index_base_offset) { - DX8Wrapper::Set_Index_Buffer(iba, index_base_offset); + DX8Wrapper::Set_Index_Buffer(iba, static_cast(index_base_offset)); } void DX8Backend::Set_Index_Buffer_Index_Offset(unsigned int offset) @@ -246,29 +246,39 @@ LightEnvironmentClass * DX8Backend::Get_Light_Environment() const return DX8Wrapper::Get_Light_Environment(); } -void DX8Backend::Draw_Triangles(unsigned short start_index, - unsigned short polygon_count, - unsigned short min_vertex_index, - unsigned short vertex_count) +void DX8Backend::Draw_Triangles(unsigned int start_index, + unsigned int polygon_count, + unsigned int min_vertex_index, + unsigned int vertex_count) { - DX8Wrapper::Draw_Triangles(start_index, polygon_count, min_vertex_index, vertex_count); + DX8Wrapper::Draw_Triangles(static_cast(start_index), + static_cast(polygon_count), + static_cast(min_vertex_index), + static_cast(vertex_count)); } void DX8Backend::Draw_Triangles(unsigned int buffer_type, - unsigned short start_index, - unsigned short polygon_count, - unsigned short min_vertex_index, - unsigned short vertex_count) -{ - DX8Wrapper::Draw_Triangles(buffer_type, start_index, polygon_count, min_vertex_index, vertex_count); -} - -void DX8Backend::Draw_Strip(unsigned short start_index, - unsigned short index_count, - unsigned short min_vertex_index, - unsigned short vertex_count) -{ - DX8Wrapper::Draw_Strip(start_index, index_count, min_vertex_index, vertex_count); + unsigned int start_index, + unsigned int polygon_count, + unsigned int min_vertex_index, + unsigned int vertex_count) +{ + DX8Wrapper::Draw_Triangles(buffer_type, + static_cast(start_index), + static_cast(polygon_count), + static_cast(min_vertex_index), + static_cast(vertex_count)); +} + +void DX8Backend::Draw_Strip(unsigned int start_index, + unsigned int index_count, + unsigned int min_vertex_index, + unsigned int vertex_count) +{ + DX8Wrapper::Draw_Strip(static_cast(start_index), + static_cast(index_count), + static_cast(min_vertex_index), + static_cast(vertex_count)); } void DX8Backend::Set_Vertex_Shader(unsigned int vertex_shader) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h index dab3e756b0f..bb2728e0b2b 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h @@ -46,8 +46,8 @@ class DX8Backend : public IRenderBackend virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) override; virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba) override; - virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) override; - virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) override; + virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned int index_base_offset) override; + virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned int index_base_offset) override; virtual void Set_Index_Buffer_Index_Offset(unsigned int offset) override; virtual void Set_Shader(const ShaderClass & shader) override; @@ -75,19 +75,19 @@ class DX8Backend : public IRenderBackend virtual void Set_Light_Environment(LightEnvironmentClass * light_env) override; virtual LightEnvironmentClass * Get_Light_Environment() const override; - virtual void Draw_Triangles(unsigned short start_index, - unsigned short polygon_count, - unsigned short min_vertex_index, - unsigned short vertex_count) override; + virtual void Draw_Triangles(unsigned int start_index, + unsigned int polygon_count, + unsigned int min_vertex_index, + unsigned int vertex_count) override; virtual void Draw_Triangles(unsigned int buffer_type, - unsigned short start_index, - unsigned short polygon_count, - unsigned short min_vertex_index, - unsigned short vertex_count) override; - virtual void Draw_Strip(unsigned short start_index, - unsigned short index_count, - unsigned short min_vertex_index, - unsigned short vertex_count) override; + unsigned int start_index, + unsigned int polygon_count, + unsigned int min_vertex_index, + unsigned int vertex_count) override; + virtual void Draw_Strip(unsigned int start_index, + unsigned int index_count, + unsigned int min_vertex_index, + unsigned int vertex_count) override; virtual void Set_Vertex_Shader(unsigned int vertex_shader) override; virtual void Set_Pixel_Shader(unsigned int pixel_shader) override; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index abbf82eb957..2f8d97d39aa 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -96,8 +96,8 @@ class IRenderBackend virtual void Set_Vertex_Buffer(const VertexBufferClass * vb, unsigned int stream) = 0; virtual void Set_Vertex_Buffer(const DynamicVBAccessClass & vba) = 0; - virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned short index_base_offset) = 0; - virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned short index_base_offset) = 0; + virtual void Set_Index_Buffer(const IndexBufferClass * ib, unsigned int index_base_offset) = 0; + virtual void Set_Index_Buffer(const DynamicIBAccessClass & iba, unsigned int index_base_offset) = 0; virtual void Set_Index_Buffer_Index_Offset(unsigned int offset) = 0; virtual void Set_Shader(const ShaderClass & shader) = 0; @@ -127,21 +127,25 @@ class IRenderBackend virtual void Set_Light_Environment(LightEnvironmentClass * light_env) = 0; virtual LightEnvironmentClass * Get_Light_Environment() const = 0; - virtual void Draw_Triangles(unsigned short start_index, - unsigned short polygon_count, - unsigned short min_vertex_index, - unsigned short vertex_count) = 0; + // Ranges are unsigned int rather than the DX8 era unsigned short so the + // interface does not pin every future backend to 16-bit draw counts. The DX8 + // reference backend narrows on the way through to DX8Wrapper. + + virtual void Draw_Triangles(unsigned int start_index, + unsigned int polygon_count, + unsigned int min_vertex_index, + unsigned int vertex_count) = 0; virtual void Draw_Triangles(unsigned int buffer_type, - unsigned short start_index, - unsigned short polygon_count, - unsigned short min_vertex_index, - unsigned short vertex_count) = 0; - - virtual void Draw_Strip(unsigned short start_index, - unsigned short index_count, - unsigned short min_vertex_index, - unsigned short vertex_count) = 0; + unsigned int start_index, + unsigned int polygon_count, + unsigned int min_vertex_index, + unsigned int vertex_count) = 0; + + virtual void Draw_Strip(unsigned int start_index, + unsigned int index_count, + unsigned int min_vertex_index, + unsigned int vertex_count) = 0; // Legacy fixed function vertex format code or shader handle. Always 32 bits // wide; unsigned long would be 64 bits on targets where long is 64-bit. From bdd6d93894ce605a8d30e346096a1b38e54d0dff Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 7 Aug 2026 13:06:08 +0100 Subject: [PATCH 15/17] refactor(ww3d2): Remove the SurfaceClass back buffer accessor from the render backend interface --- Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp | 5 ----- Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h | 1 - Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h | 2 -- 3 files changed, 8 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp index 455c0947f98..e0c693294d5 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -53,11 +53,6 @@ WW3DFormat DX8Backend::Get_Back_Buffer_Format() return DX8Wrapper::getBackBufferFormat(); } -SurfaceClass * DX8Backend::Get_Back_Buffer(unsigned int num) -{ - return DX8Wrapper::_Get_DX8_Back_Buffer(num); -} - void DX8Backend::Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) { DX8Wrapper::Set_Gamma(gamma, bright, contrast, calibrate, uselimit); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h index bb2728e0b2b..e6e4e955529 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h @@ -33,7 +33,6 @@ class DX8Backend : public IRenderBackend virtual bool Is_Device_Lost() const override; virtual bool Has_Stencil() override; virtual WW3DFormat Get_Back_Buffer_Format() override; - virtual SurfaceClass * Get_Back_Buffer(unsigned int num) override; virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) override; virtual void Begin_Scene() override; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h index 2f8d97d39aa..fe87944800e 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -32,7 +32,6 @@ class VertexMaterialClass; class TextureBaseClass; class TextureClass; class ZTextureClass; -class SurfaceClass; class VertexBufferClass; class IndexBufferClass; class DynamicVBAccessClass; @@ -83,7 +82,6 @@ class IRenderBackend virtual bool Is_Device_Lost() const = 0; virtual bool Has_Stencil() = 0; virtual WW3DFormat Get_Back_Buffer_Format() = 0; - virtual SurfaceClass * Get_Back_Buffer(unsigned int num) = 0; virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) = 0; virtual void Begin_Scene() = 0; From 2bbc25f643ca9ea732f3e6c16a9b7ad878b5c7ed Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 7 Aug 2026 13:06:27 +0100 Subject: [PATCH 16/17] refactor(ww3d2): Separate render backend object lifetime from device lifetime --- .../Source/WWVegas/WW3D2/Backend/RenderBackend.cpp | 6 ++++++ .../Source/WWVegas/WW3D2/Backend/RenderBackend.h | 6 ++++-- Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp | 14 ++++++-------- Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp | 9 +++++++++ 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp index 70190545323..ad5b83cfcf1 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp @@ -23,10 +23,16 @@ #include "RenderBackend.h" #include "DX8Backend.h" +#include "WWDebug/wwdebug.h" + IRenderBackend * g_renderBackend = nullptr; void Init_Render_Backend() { + // Construction is single shot. WW3D::Init pairs with WW3D::Shutdown, which + // destroys the backend again, so arriving here with a live backend means the + // library lifecycle is unbalanced. + WWASSERT(g_renderBackend == nullptr); if (g_renderBackend != nullptr) { return; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h index fcba202f908..93d337c6d2a 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h @@ -28,8 +28,10 @@ // Shutdown_Render_Backend(); never null between those two calls. extern IRenderBackend * g_renderBackend; -// Create the render backend. Must be called after the render device is ready. +// Create the render backend. Called once from WW3D::Init, before any render +// device exists, and exactly once per Shutdown_Render_Backend(). void Init_Render_Backend(); -// Destroy the render backend. Must be called before the render device is released. +// Destroy the render backend. Called from WW3D::Shutdown, after the render +// device has been released. void Shutdown_Render_Backend(); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp index 66105d1055d..869a001cd40 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp @@ -392,10 +392,9 @@ void DX8Wrapper::Do_Onetime_Device_Dependent_Inits() Set_Default_Global_Render_States(); - // TheSuperHackers @refactor bobtista 10/04/2026 Construct the global - // IRenderBackend instance now that the D3D device is ready, then let it - // bring up any device of its own. - Init_Render_Backend(); + // TheSuperHackers @refactor bobtista 10/04/2026 The backend object is created + // in WW3D::Init and outlives every device cycle. Only its device dependent + // state is brought up here, now that the D3D device is ready. g_renderBackend->Initialize(_Hwnd, ResolutionWidth, ResolutionHeight); } @@ -457,14 +456,13 @@ void DX8Wrapper::Invalidate_Cached_Render_States() void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns() { - // TheSuperHackers @refactor bobtista 10/04/2026 Tear down the render - // backend before the D3D device is released so any backend-owned - // resources get released first. + // TheSuperHackers @refactor bobtista 10/04/2026 Release the backend's device + // dependent state before the D3D device goes away. The backend object itself + // is destroyed later, in WW3D::Shutdown. if (g_renderBackend != nullptr) { g_renderBackend->Shutdown(); } - Shutdown_Render_Backend(); /* ** Shutdown ww3d systems diff --git a/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp b/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp index 226c8a63c98..7547c17f889 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp @@ -104,6 +104,7 @@ #include "dazzle.h" #include "meshmdl.h" #include "dx8renderer.h" +#include "Backend/RenderBackend.h" #include "render2d.h" #include "WWLib/bound.h" #include "rddesc.h" @@ -278,6 +279,12 @@ WW3DErrorType WW3D::Init(void *hwnd, char *defaultpal, bool lite) if (!DX8Wrapper::Init(_Hwnd, lite)) { return(WW3D_ERROR_INITIALIZATION_FAILED); } + + // TheSuperHackers @refactor bobtista 07/08/2026 The backend object is created + // once here and destroyed in WW3D::Shutdown, so it survives the device + // release and create cycles that drive its Initialize and Shutdown calls. + Init_Render_Backend(); + WWDEBUG_SAY(("Allocate Debug Resources")); Allocate_Debug_Resources(); @@ -368,6 +375,8 @@ WW3DErrorType WW3D::Shutdown() DX8Wrapper::Shutdown(); } + Shutdown_Render_Backend(); + /* ** Clear the default static sort lists */ From c03cc182a72c484d893615387a23f808d9e71740 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Wed, 12 Aug 2026 09:45:23 -0400 Subject: [PATCH 17/17] refactor(ww3d2): Select render backend through factory --- Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp | 6 ++++++ .../Source/WWVegas/WW3D2/Backend/RenderBackend.cpp | 3 +-- Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp index e0c693294d5..7cac76073bb 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -22,6 +22,7 @@ // should change in DX8Wrapper, not here. #include "DX8Backend.h" +#include "RenderBackend.h" #include "WW3D2/dx8wrapper.h" #include "WWMath/vector3.h" @@ -38,6 +39,11 @@ DX8Backend::~DX8Backend() { } +IRenderBackend *Create_Render_Backend() +{ + return new DX8Backend(); +} + bool DX8Backend::Is_Device_Lost() const { return DX8Wrapper::Is_Device_Lost(); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp index ad5b83cfcf1..1a908c1c196 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.cpp @@ -21,7 +21,6 @@ // concrete backend instance. #include "RenderBackend.h" -#include "DX8Backend.h" #include "WWDebug/wwdebug.h" @@ -38,7 +37,7 @@ void Init_Render_Backend() return; } - g_renderBackend = new DX8Backend(); + g_renderBackend = Create_Render_Backend(); } void Shutdown_Render_Backend() diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h index 93d337c6d2a..5dceab05cc7 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h @@ -28,6 +28,10 @@ // Shutdown_Render_Backend(); never null between those two calls. extern IRenderBackend * g_renderBackend; +// Construct the backend selected by the build. Exactly one backend +// implementation must define this function. +IRenderBackend *Create_Render_Backend(); + // Create the render backend. Called once from WW3D::Init, before any render // device exists, and exactly once per Shutdown_Render_Backend(). void Init_Render_Backend();