Skip to content

Conversation

@xezon
Copy link

@xezon xezon commented Jan 17, 2026

This change reduces the cost of

  • W3DRadar::renderObjectList by around 80%, from 0.5 ms to 0.1 ms (tested with many radar objects)
  • W3DRadar::buildTerrainTexture by around 25%, from 0.0127 ms to 0.0164 ms
  • W3DRadar::clearShroud - not measured because not important

This is achieved by locking the radar surface only once instead of many times in loops.

W3DRadar::renderObjectList is called every 6 logic frames, and the jump from 0.5 ms to 0.1 ms is nice to improve overall performance (measured on modern machine).

Functions SurfaceClass::DrawPixel and SurfaceClass::DrawHLine were renamed to better fit the WWVegas style.

The NULL's in W3DRadar were changed to nullptr, which was added by #2072.

…adar::buildTerrainTexture (by 25%), W3DRadar::clearShroud by locking radar surface only once
@xezon xezon added Major Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Gen Relates to Generals ZH Relates to Zero Hour Rendering Is Rendering related labels Jan 17, 2026
@greptile-apps
Copy link

greptile-apps bot commented Jan 17, 2026

Greptile Summary

Refactored radar surface drawing to lock surfaces once per batch operation instead of per-pixel, achieving significant performance improvements:

  • renderObjectList: ~80% faster (0.5ms → 0.1ms)
  • buildTerrainTexture: ~25% faster (0.0164ms → 0.0127ms)
  • clearShroud: Performance improved (unmeasured)

Key Changes

  • Modified SurfaceClass::Draw_Pixel, Draw_H_Line, and Get_Pixel to accept pre-locked surface parameters (bytesPerPixel, pBits, pitch)
  • Added SurfaceClass::Get_Bytes_Per_Pixel() helper method
  • Updated all radar rendering functions to lock surfaces once at the beginning and unlock at the end
  • Simplified pixel writing using memcpy instead of switch statements
  • Changed NULL to nullptr throughout W3DRadar for consistency
  • Updated all call sites including W3DWater and commented-out MapUtil code

The optimization is well-implemented and follows the existing codebase patterns. The performance gains are substantial for frequently-called rendering operations.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The refactoring is clean, well-tested (performance measured), and follows established patterns. All surface lock/unlock pairs are properly balanced. The change is mechanical and consistent across all call sites. Previous thread issues were already addressed.
  • No files require special attention

Important Files Changed

Filename Overview
Core/Libraries/Source/WWVegas/WW3D2/surfaceclass.h Added Get_Bytes_Per_Pixel() helper and updated Draw_Pixel, Draw_H_Line, Get_Pixel to accept pre-locked surface parameters for performance optimization
Core/Libraries/Source/WWVegas/WW3D2/surfaceclass.cpp Refactored Draw_Pixel, Draw_H_Line, and Get_Pixel to use memcpy and accept locked surface pointers, eliminating repeated lock/unlock cycles
Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp Optimized radar rendering by locking surfaces once per function (renderObjectList, buildTerrainTexture, clearShroud, refreshObjects, setShroudLevel) instead of per-pixel, achieving 80% and 25% performance improvements

Sequence Diagram

sequenceDiagram
    participant Radar as W3DRadar
    participant Surface as SurfaceClass
    participant D3D as Direct3D Surface
    
    Note over Radar,D3D: Before Optimization (per-pixel locking)
    Radar->>Surface: DrawPixel(x1, y1, color1)
    Surface->>D3D: Lock()
    D3D-->>Surface: pBits
    Surface->>D3D: Write pixel
    Surface->>D3D: Unlock()
    Radar->>Surface: DrawPixel(x2, y2, color2)
    Surface->>D3D: Lock()
    D3D-->>Surface: pBits
    Surface->>D3D: Write pixel
    Surface->>D3D: Unlock()
    Note over Radar,D3D: Repeated for each pixel (expensive)
    
    Note over Radar,D3D: After Optimization (single lock per batch)
    Radar->>Surface: Lock(&pitch)
    Surface->>D3D: Lock()
    D3D-->>Surface: pBits, pitch
    Surface-->>Radar: pBits, pitch
    Radar->>Surface: Get_Bytes_Per_Pixel()
    Surface-->>Radar: bytesPerPixel
    loop For each pixel
        Radar->>Surface: Draw_Pixel(x, y, color, bytesPerPixel, pBits, pitch)
        Surface->>Surface: memcpy to locked memory (no lock/unlock)
    end
    Radar->>Surface: Unlock()
    Surface->>D3D: Unlock()
    Note over Radar,D3D: 80% faster for renderObjectList
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@xezon
Copy link
Author

xezon commented Jan 17, 2026

@greptileai

@bobtista
Copy link

Code LGTM, good find!

I left some nits about commented out code, but looks good to go

Copy link

@bobtista bobtista left a comment

Choose a reason for hiding this comment

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

LGTM

* 1/10/2025 TheSuperHackers : Added bits and pitch to argument list for better performance *
*=============================================================================================*/
void SurfaceClass::DrawPixel(const unsigned int x,const unsigned int y, unsigned int color)
void SurfaceClass::Draw_Pixel(const unsigned int x, const unsigned int y, unsigned int color,
Copy link

Choose a reason for hiding this comment

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

Might want to add a comment to these that the surface needs to be externally locked and unlocked before using this.

Copy link
Author

Choose a reason for hiding this comment

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

Hmm ok I can add it in the header file. I thought it was kind of implied by the new argument requirement.

Copy link
Author

Choose a reason for hiding this comment

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

Instead of comment, I added a typedef LockedSurfacePtr for the void pointer, which acts as a means to document the related types in this class.

@xezon xezon changed the title perf(radar): Reduce cost of W3DRadar::renderObjectList (by 80%), W3DRadar::buildTerrainTexture (by 25%), W3DRadar::clearShroud by locking radar surface only once perf(radar): Reduce cost of W3DRadar::renderObjectList (by 80%), W3DRadar::buildTerrainTexture (by 25%) and W3DRadar::clearShroud Jan 20, 2026
@xezon xezon merged commit 25b1735 into TheSuperHackers:main Jan 20, 2026
25 checks passed
@xezon xezon deleted the xezon/optimize-radar-drawpixel-2 branch January 20, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gen Relates to Generals Major Severity: Minor < Major < Critical < Blocker Performance Is a performance concern Rendering Is Rendering related ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants