Skip to content

Conversation

@xezon
Copy link

@xezon xezon commented Jan 6, 2026

Merge with Rebase

This optimization is needed to make HeightMapRenderObjClass::oversizeTerrain faster, which is relevant later for terrain size extension on low camera pitch.

The first commit consolidates some duplicated code.

The second commit implements the performance optimization.

Cost was measured and reduced by 96%.

TODO

  • Replicate in Generals

@xezon xezon added Minor 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 6, 2026
@xezon
Copy link
Author

xezon commented Jan 7, 2026

Generals fails to compile until replicated.

Comment on lines +222 to +226
RECT rect;
rect.left = min.I;
rect.top = min.J;
rect.right = max.I;
rect.bottom = max.J;
Copy link

Choose a reason for hiding this comment

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

Suggested change
RECT rect;
rect.left = min.I;
rect.top = min.J;
rect.right = max.I;
rect.bottom = max.J;
RECT rect = { min.I, min.J, max.I, max.J };

Copy link
Author

Choose a reason for hiding this comment

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

I doubt this works in C++98

Copy link

Choose a reason for hiding this comment

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

Did you try it? VC6 seems to compile for me.

Copy link
Author

Choose a reason for hiding this comment

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

Okay. Tweaked to your suggestion.

Copy link
Author

Choose a reason for hiding this comment

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

After thinking about this a bit more I reverted that to the previous. The initializer list is totally not intuitive to read, because the list has no names. Wheras assigning to the struct names is explicit and clear.


const Int playerIndex = rts::getObservedOrLocalPlayer()->getPlayerIndex();
for (int i = 0; i < m_totalCellCount; ++i)
if (m_totalCellCount != 0)
Copy link

Choose a reason for hiding this comment

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

Maybe invert to reduce nesting?

if (m_totalCellCount == 0)
	return;

Copy link
Author

Choose a reason for hiding this comment

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

Prefer not, because it is not at the top of the function.

Copy link

Choose a reason for hiding this comment

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

Why? A few lines down is still at the top of the function.

Copy link
Author

Choose a reason for hiding this comment

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

I am not so much a fan of returns unless they are at the start of the function or the function has a single purpose and will never change (e.g. findSomethingInContainer)


Int psize;
psize=PixelSize(desc);
psize=Get_Bytes_Per_Pixel(desc.Format);
Copy link

Choose a reason for hiding this comment

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

Combine declaration and assignment?

const Int psize=Get_Bytes_Per_Pixel(desc.Format);

Copy link
Author

Choose a reason for hiding this comment

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

Could do, but for simplicity sake the refactor is enough as is.

Copy link

Choose a reason for hiding this comment

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

Okay. I had assumed minor refactors were on the table due to the changes to Core/Libraries/Source/WWVegas/WW3D2/ww3dformat.cpp.

Copy link
Author

Choose a reason for hiding this comment

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

Yes sure but can be separate refactor then. Keeping it extra simple :)

m_shroudSurface = m_shroudTexture->Get_Surface_Level();
DEBUG_ASSERTCRASH( m_shroudSurface != NULL, ("W3DRadar::beginSetShroudLevel: Can't get surface for Shroud texture") );

if (surfaceRegion != NULL)

Choose a reason for hiding this comment

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

In what situation is surfaceRegion not NULL? The only invocation I found was TheRadar->beginSetShroudLevel()

Copy link
Author

Choose a reason for hiding this comment

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

I provided the option to lock a subregion only. But it is unused, because refreshShroudForLocalPlayer needs the full region locked to touch every pixel.

Copy link
Author

Choose a reason for hiding this comment

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

After rethinking this I removed the surfaceRegion argument from this function because it would not have worked correctly when locking a subregion.

switch (m_shroudSurfacePixelSize)
{
case 1: *column = (UnsignedByte)color; break;
case 2: *reinterpret_cast<UnsignedShort*>(column) = (UnsignedShort)color; break;

Choose a reason for hiding this comment

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

Is it valid to cast Color like this? Color is AARRGGBB and casting to 2 bytes would give you GGBB and casting to 1 byte gives BB which are both zero in this case

Copy link
Author

Choose a reason for hiding this comment

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

Indeed it looks strange. I copied this style from SurfaceClass::DrawPixel, so if this is wrong then it is original game bug (out the scope of this change).

Copy link
Author

Choose a reason for hiding this comment

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

I also prepared a follow up change for this, but unclear to me if this solves anything in practice. I was unable to force surface format to non A8R8G8B8, even if texture was created with different format.

Choose a reason for hiding this comment

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

I think this was to support videocards that were DX8 capable but did not support 32 bit textures for some reason, it's a very niche situation

I was able to force m_shroudSurfacePixelSize to 2 by doing this but I don't know exactly what to look for in regards to what would happen to the graphics

diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.h b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.h
index 88a1dba2..d7e0a5fb 100644
--- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.h
+++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8caps.h
@@ -241,7 +241,12 @@ public:
 	int Get_Pixel_Shader_Minor_Version() const { return 0xff&(PixelShaderVersion); }
 	int Get_Max_Simultaneous_Textures()	const { return MaxSimultaneousTextures;}
 
-	bool Support_Texture_Format(WW3DFormat format) const { return SupportTextureFormat[format]; }
+	bool Support_Texture_Format(WW3DFormat format) const {
+		if (format == WW3D_FORMAT_A8R8G8B8) {
+			return false;
+		}
+		return SupportTextureFormat[format];
+	}
 	bool Support_Render_To_Texture_Format(WW3DFormat format) const { return SupportRenderToTextureFormat[format]; }
 	bool Support_Depth_Stencil_Format(WW3DZFormat format) const { return SupportDepthStencilFormat[format]; }

@xezon
Copy link
Author

xezon commented Jan 9, 2026

Perhaps we can combine this fix with jmarshall2323@9b1c399, which makes a lot of sense too.

@xezon
Copy link
Author

xezon commented Jan 10, 2026

Perhaps we can combine this fix with jmarshall2323@9b1c399, which makes a lot of sense too.

I prepared a follow up change that optimizes SurfaceClass::DrawPixel and SurfaceClass::DrawHLine for the other W3DRadar functions. But that change is quite big too so I will not append it here to keep it simple for reviews.

@xezon xezon force-pushed the xezon/optimize-radar-refresh-2 branch from 4843fd2 to 0be0f45 Compare January 10, 2026 20:35
@xezon
Copy link
Author

xezon commented Jan 10, 2026

Merged down the changes into the respective commit.

…er::refreshShroudForLocalPlayer by 96% (#2072)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Gen Relates to Generals Minor 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