Optimize away SpecularEnable and PointScaleEnable, by resetting the related variables on CPU.
This shaves off almost 50 vertex shader instructions (down to 705 with this).
This commit is contained in:
parent
bd76d67c78
commit
134dd70117
|
@ -6309,10 +6309,12 @@ void UpdateFixedFunctionShaderLight(int d3dLightIndex, Light* pShaderLight, D3DX
|
|||
D3DXVec3Transform(&directionV, (D3DXVECTOR3*)&d3dLight->Direction, &viewTransform3x3);
|
||||
D3DXVec3Normalize((D3DXVECTOR3*)&pShaderLight->DirectionVN, (D3DXVECTOR3*)&directionV);
|
||||
|
||||
bool SpecularEnable = XboxRenderStates.GetXboxRenderState(xbox::X_D3DRS_SPECULARENABLE) != FALSE;
|
||||
|
||||
// Map D3D light to state struct
|
||||
pShaderLight->Type = (float)((int)d3dLight->Type);
|
||||
pShaderLight->Diffuse = toVector(d3dLight->Diffuse);
|
||||
pShaderLight->Specular = toVector(d3dLight->Specular);
|
||||
pShaderLight->Specular = SpecularEnable ? toVector(d3dLight->Specular) : toVector(0);
|
||||
pShaderLight->Range = d3dLight->Range;
|
||||
pShaderLight->Falloff = d3dLight->Falloff;
|
||||
pShaderLight->Attenuation.x = d3dLight->Attenuation0;
|
||||
|
@ -6337,7 +6339,7 @@ void UpdateFixedFunctionVertexShaderState()
|
|||
{
|
||||
using namespace xbox;
|
||||
|
||||
// Preprocessing
|
||||
// Vertex blending
|
||||
// Prepare vertex blending mode variables used in transforms, below
|
||||
auto VertexBlend = XboxRenderStates.GetXboxRenderState(X_D3DRS_VERTEXBLEND);
|
||||
// Xbox and host D3DVERTEXBLENDFLAGS :
|
||||
|
@ -6376,14 +6378,10 @@ void UpdateFixedFunctionVertexShaderState()
|
|||
// Lighting
|
||||
ffShaderState.Modes.Lighting = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_LIGHTING);
|
||||
ffShaderState.Modes.TwoSidedLighting = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_TWOSIDEDLIGHTING);
|
||||
ffShaderState.Modes.SpecularEnable = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_SPECULARENABLE);
|
||||
ffShaderState.Modes.LocalViewer = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_LOCALVIEWER);
|
||||
bool ColorVertex = XboxRenderStates.GetXboxRenderState(X_D3DRS_COLORVERTEX) != FALSE;
|
||||
|
||||
D3DXVECTOR4 Ambient = toVector(XboxRenderStates.GetXboxRenderState(X_D3DRS_AMBIENT));
|
||||
D3DXVECTOR4 BackAmbient = toVector(XboxRenderStates.GetXboxRenderState(X_D3DRS_BACKAMBIENT));
|
||||
|
||||
// Material sources
|
||||
bool ColorVertex = XboxRenderStates.GetXboxRenderState(X_D3DRS_COLORVERTEX) != FALSE;
|
||||
ffShaderState.Modes.AmbientMaterialSource = (float)(ColorVertex ? XboxRenderStates.GetXboxRenderState(X_D3DRS_AMBIENTMATERIALSOURCE) : D3DMCS_MATERIAL);
|
||||
ffShaderState.Modes.DiffuseMaterialSource = (float)(ColorVertex ? XboxRenderStates.GetXboxRenderState(X_D3DRS_DIFFUSEMATERIALSOURCE) : D3DMCS_MATERIAL);
|
||||
ffShaderState.Modes.SpecularMaterialSource = (float)(ColorVertex ? XboxRenderStates.GetXboxRenderState(X_D3DRS_SPECULARMATERIALSOURCE) : D3DMCS_MATERIAL);
|
||||
|
@ -6396,14 +6394,14 @@ void UpdateFixedFunctionVertexShaderState()
|
|||
// Point sprites
|
||||
auto pointSize = XboxRenderStates.GetXboxRenderState(X_D3DRS_POINTSIZE);
|
||||
ffShaderState.PointSprite.PointSize = *reinterpret_cast<float*>(&pointSize);
|
||||
ffShaderState.PointSprite.PointScaleEnable = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_POINTSCALEENABLE);
|
||||
ffShaderState.PointSprite.RenderTargetHeight = (float)GetPixelContainerHeight(g_pXbox_RenderTarget);
|
||||
bool PointScaleEnable = XboxRenderStates.GetXboxRenderState(X_D3DRS_POINTSCALEENABLE) != FALSE;
|
||||
ffShaderState.PointSprite.RenderTargetHeight = PointScaleEnable ? (float)GetPixelContainerHeight(g_pXbox_RenderTarget) : 1.0f;
|
||||
auto scaleA = XboxRenderStates.GetXboxRenderState(X_D3DRS_POINTSCALE_A);
|
||||
ffShaderState.PointSprite.ScaleA = *reinterpret_cast<float*>(&scaleA);
|
||||
ffShaderState.PointSprite.ScaleA = PointScaleEnable ? *reinterpret_cast<float*>(&scaleA) : 1.0f;
|
||||
auto scaleB = XboxRenderStates.GetXboxRenderState(X_D3DRS_POINTSCALE_B);
|
||||
ffShaderState.PointSprite.ScaleB = *reinterpret_cast<float*>(&scaleB);
|
||||
ffShaderState.PointSprite.ScaleB = PointScaleEnable ? *reinterpret_cast<float*>(&scaleB) : 0.0f;
|
||||
auto scaleC = XboxRenderStates.GetXboxRenderState(X_D3DRS_POINTSCALE_C);
|
||||
ffShaderState.PointSprite.ScaleC = *reinterpret_cast<float*>(&scaleC);
|
||||
ffShaderState.PointSprite.ScaleC = PointScaleEnable ? *reinterpret_cast<float*>(&scaleC) : 0.0f;
|
||||
|
||||
// Fog
|
||||
// Determine how fog depth is calculated
|
||||
|
@ -6452,9 +6450,6 @@ void UpdateFixedFunctionVertexShaderState()
|
|||
ffShaderState.TexCoordComponentCount[i] = (float)GetXboxVertexDataComponentCount(vertexDataFormat);
|
||||
}
|
||||
|
||||
// Misc flags
|
||||
ffShaderState.Modes.NormalizeNormals = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_NORMALIZENORMALS);
|
||||
|
||||
// Update lights
|
||||
auto LightAmbient = D3DXVECTOR4(0.f, 0.f, 0.f, 0.f);
|
||||
D3DXMATRIX rowMajorViewTransform;
|
||||
|
@ -6463,8 +6458,14 @@ void UpdateFixedFunctionVertexShaderState()
|
|||
UpdateFixedFunctionShaderLight(d3d8LightState.EnabledLights[i], &ffShaderState.Lights[i], &LightAmbient, rowMajorViewTransform);
|
||||
}
|
||||
|
||||
ffShaderState.AmbientPlusLightAmbient = Ambient + LightAmbient;
|
||||
ffShaderState.BackAmbientPlusLightAmbient = BackAmbient + LightAmbient;
|
||||
D3DXVECTOR4 Ambient = toVector(XboxRenderStates.GetXboxRenderState(X_D3DRS_AMBIENT));
|
||||
D3DXVECTOR4 BackAmbient = toVector(XboxRenderStates.GetXboxRenderState(X_D3DRS_BACKAMBIENT));
|
||||
|
||||
ffShaderState.TotalLightsAmbient.Front = (D3DXVECTOR3)(LightAmbient + Ambient);
|
||||
ffShaderState.TotalLightsAmbient.Back = (D3DXVECTOR3)(LightAmbient + BackAmbient);
|
||||
|
||||
// Misc flags
|
||||
ffShaderState.Modes.NormalizeNormals = (float)XboxRenderStates.GetXboxRenderState(X_D3DRS_NORMALIZENORMALS);
|
||||
|
||||
// Write fixed function state to shader constants
|
||||
const int slotSize = 16;
|
||||
|
@ -7344,8 +7345,6 @@ void CxbxUpdateHostTextures()
|
|||
|
||||
void CxbxUpdateHostTextureScaling()
|
||||
{
|
||||
extern xbox::X_VERTEXATTRIBUTEFORMAT* GetXboxVertexAttributeFormat(); // TMP glue
|
||||
|
||||
// Xbox works with "Linear" and "Swizzled" texture formats
|
||||
// Linear formats are not addressed with normalized coordinates (similar to https://www.khronos.org/opengl/wiki/Rectangle_Texture?)
|
||||
// We want to use normalized coordinates in our shaders, so need to be able to scale the coordinates back
|
||||
|
|
|
@ -94,28 +94,20 @@ struct TransformInfo
|
|||
static TransformInfo View; // Vertex transformed to viewspace
|
||||
static TransformInfo Projection; // Vertex transformed to projection space
|
||||
|
||||
// Vertex lighting
|
||||
// Both frontface and backface lighting can be calculated
|
||||
struct LightingInfo
|
||||
{
|
||||
float3 Front;
|
||||
float3 Back;
|
||||
};
|
||||
|
||||
// Final lighting output
|
||||
struct LightingOutput
|
||||
{
|
||||
LightingInfo Diffuse;
|
||||
LightingInfo Specular;
|
||||
TwoSidedColor Diffuse;
|
||||
TwoSidedColor Specular;
|
||||
};
|
||||
|
||||
LightingInfo DoSpecular(const float3 toLightVN, const float3 toViewerVN, const float2 powers, const float4 lightSpecular)
|
||||
TwoSidedColor DoSpecular(const float3 toLightVN, const float3 toViewerVN, const float2 powers, const float4 lightSpecular)
|
||||
{
|
||||
LightingInfo o;
|
||||
o.Front = o.Back = float3(0, 0, 0);
|
||||
TwoSidedColor Specular;
|
||||
Specular.Front = Specular.Back = float3(0, 0, 0);
|
||||
|
||||
// Specular
|
||||
if (state.Modes.SpecularEnable)
|
||||
// Note : if (state.Modes.SpecularEnable) no longer required because when disabled, CPU sets all lightSpecular.rgb inputs to 0
|
||||
{
|
||||
// Blinn-Phong
|
||||
// https://learnopengl.com/Advanced-Lighting/Advanced-Lighting
|
||||
|
@ -126,12 +118,12 @@ LightingInfo DoSpecular(const float3 toLightVN, const float3 toViewerVN, const f
|
|||
const float3 backSpecular = pow(abs(NdotH), powers[1]) * lightSpecular.rgb;
|
||||
|
||||
if (NdotH >= 0)
|
||||
o.Front = frontSpecular;
|
||||
Specular.Front = frontSpecular;
|
||||
else
|
||||
o.Back = backSpecular;
|
||||
Specular.Back = backSpecular;
|
||||
}
|
||||
|
||||
return o;
|
||||
return Specular;
|
||||
}
|
||||
|
||||
// useful reference https://drivers.amd.com/misc/samples/dx9/FixedFuncShader.pdf
|
||||
|
@ -317,30 +309,31 @@ Material DoMaterial(const uint index, const uint diffuseReg, const uint specular
|
|||
// Get the material from material state
|
||||
Material material = state.Materials[index];
|
||||
|
||||
// Note : If X_D3DRS_COLORVERTEX is FALSE, UpdateFixedFunctionVertexShaderState has already changed all MaterialSource's into D3DMCS_MATERIAL
|
||||
// Note : if (state.Modes.ColorVertex) no longer required because when disabled, CPU sets all MaterialSource's to D3DMCS_MATERIAL
|
||||
{
|
||||
// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dmaterialcolorsource
|
||||
static const int D3DMCS_MATERIAL = 0;
|
||||
static const int D3DMCS_COLOR1 = 1;
|
||||
static const int D3DMCS_COLOR2 = 2;
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dmaterialcolorsource
|
||||
static const int D3DMCS_MATERIAL = 0;
|
||||
static const int D3DMCS_COLOR1 = 1;
|
||||
static const int D3DMCS_COLOR2 = 2;
|
||||
// If COLORVERTEX mode, AND the desired diffuse or specular colour is defined in the vertex declaration
|
||||
// Then use the vertex colour instead of the material
|
||||
|
||||
// If COLORVERTEX mode, AND the desired diffuse or specular colour is defined in the vertex declaration
|
||||
// Then use the vertex colour instead of the material
|
||||
if (!vRegisterDefaultFlags[diffuseReg]) {
|
||||
const float4 diffuseVertexColour = Get(xIn, diffuseReg);
|
||||
if (state.Modes.AmbientMaterialSource == D3DMCS_COLOR1) material.Ambient = diffuseVertexColour;
|
||||
if (state.Modes.DiffuseMaterialSource == D3DMCS_COLOR1) material.Diffuse = diffuseVertexColour;
|
||||
if (state.Modes.SpecularMaterialSource == D3DMCS_COLOR1) material.Specular = diffuseVertexColour;
|
||||
if (state.Modes.EmissiveMaterialSource == D3DMCS_COLOR1) material.Emissive = diffuseVertexColour;
|
||||
}
|
||||
|
||||
if (!vRegisterDefaultFlags[diffuseReg]) {
|
||||
const float4 diffuseVertexColour = Get(xIn, diffuseReg);
|
||||
if (state.Modes.AmbientMaterialSource == D3DMCS_COLOR1) material.Ambient = diffuseVertexColour;
|
||||
if (state.Modes.DiffuseMaterialSource == D3DMCS_COLOR1) material.Diffuse = diffuseVertexColour;
|
||||
if (state.Modes.SpecularMaterialSource == D3DMCS_COLOR1) material.Specular = diffuseVertexColour;
|
||||
if (state.Modes.EmissiveMaterialSource == D3DMCS_COLOR1) material.Emissive = diffuseVertexColour;
|
||||
}
|
||||
|
||||
if (!vRegisterDefaultFlags[specularReg]) {
|
||||
const float4 specularVertexColour = Get(xIn, specularReg);
|
||||
if (state.Modes.AmbientMaterialSource == D3DMCS_COLOR2) material.Ambient = specularVertexColour;
|
||||
if (state.Modes.DiffuseMaterialSource == D3DMCS_COLOR2) material.Diffuse = specularVertexColour;
|
||||
if (state.Modes.SpecularMaterialSource == D3DMCS_COLOR2) material.Specular = specularVertexColour;
|
||||
if (state.Modes.EmissiveMaterialSource == D3DMCS_COLOR2) material.Emissive = specularVertexColour;
|
||||
if (!vRegisterDefaultFlags[specularReg]) {
|
||||
const float4 specularVertexColour = Get(xIn, specularReg);
|
||||
if (state.Modes.AmbientMaterialSource == D3DMCS_COLOR2) material.Ambient = specularVertexColour;
|
||||
if (state.Modes.DiffuseMaterialSource == D3DMCS_COLOR2) material.Diffuse = specularVertexColour;
|
||||
if (state.Modes.SpecularMaterialSource == D3DMCS_COLOR2) material.Specular = specularVertexColour;
|
||||
if (state.Modes.EmissiveMaterialSource == D3DMCS_COLOR2) material.Emissive = specularVertexColour;
|
||||
}
|
||||
}
|
||||
|
||||
return material;
|
||||
|
@ -474,7 +467,7 @@ float DoPointSpriteSize()
|
|||
const PointSprite ps = state.PointSprite;
|
||||
float pointSize = ps.PointSize;
|
||||
|
||||
if (ps.PointScaleEnable)
|
||||
// Note : if (ps.PointScaleEnable) not required because when disabled, CPU sets RenderTargetHeight and ScaleA to 1, and ScaleB and ScaleC to 0
|
||||
{
|
||||
const float eyeDistance = length(View.Position);
|
||||
const float factor = ps.ScaleA + ps.ScaleB * eyeDistance + ps.ScaleC * (eyeDistance * eyeDistance);
|
||||
|
@ -541,50 +534,39 @@ VS_OUTPUT main(const VS_INPUT xInput)
|
|||
// Projection transform - final position
|
||||
xOut.oPos = Projection.Position;
|
||||
|
||||
// Diffuse and specular for when lighting is disabled
|
||||
xOut.oD0 = Get(xIn, diffuse);
|
||||
xOut.oD1 = Get(xIn, specular);
|
||||
xOut.oB0 = Get(xIn, backDiffuse);
|
||||
xOut.oB1 = Get(xIn, backSpecular);
|
||||
|
||||
// Vertex lighting
|
||||
if (state.Modes.Lighting || state.Modes.TwoSidedLighting)
|
||||
if (state.Modes.Lighting) // TODO : Remove this check by incorporating this boolean into the variables used below (set DiffuseMaterialSource to D3DMCS_COLOR1, SpecularMaterialSource to D3DMCS_COLOR2, all other to D3DMCS_MATERIAL and their colors and TotalLightsAmbient to zero, etc)
|
||||
{
|
||||
// Materials
|
||||
const Material material = DoMaterial(0, diffuse, specular, xIn);
|
||||
const Material backMaterial = DoMaterial(1, backDiffuse, backSpecular, xIn);
|
||||
|
||||
const float2 powers = float2(material.Power, backMaterial.Power);
|
||||
|
||||
LightingOutput lighting = CalcLighting(powers);
|
||||
Material material = DoMaterial(0, diffuse, specular, xIn);
|
||||
Material backMaterial = DoMaterial(1, backDiffuse, backSpecular, xIn);
|
||||
|
||||
// Compute each lighting component
|
||||
const float3 _ambient = material.Ambient.rgb * state.AmbientPlusLightAmbient.rgb;
|
||||
const float3 _backAmbient = backMaterial.Ambient.rgb * state.BackAmbientPlusLightAmbient.rgb;
|
||||
|
||||
const float3 _diffuse = material.Diffuse.rgb * lighting.Diffuse.Front;
|
||||
const float3 _backDiffuse = backMaterial.Diffuse.rgb * lighting.Diffuse.Back;
|
||||
|
||||
const float3 _specular = material.Specular.rgb * lighting.Specular.Front;
|
||||
const float3 _backSpecular = backMaterial.Specular.rgb * lighting.Specular.Back;
|
||||
|
||||
const float3 _emissive = material.Emissive.rgb;
|
||||
const float3 _backEmissive = backMaterial.Emissive.rgb;
|
||||
const float2 powers = float2(material.Power, backMaterial.Power);
|
||||
const LightingOutput lighting = CalcLighting(powers);
|
||||
|
||||
// Frontface
|
||||
xOut.oD0 = float4(_ambient + _diffuse + _emissive, material.Diffuse.a);
|
||||
xOut.oD1 = float4(_specular, 0);
|
||||
// Backface
|
||||
xOut.oB0 = float4(_backAmbient + _backDiffuse + _backEmissive, backMaterial.Diffuse.a);
|
||||
xOut.oB1 = float4(_backSpecular, 0);
|
||||
}
|
||||
material.Specular.rgb *= lighting.Specular.Front;
|
||||
material.Diffuse.rgb *= lighting.Diffuse.Front;
|
||||
material.Ambient.rgb *= state.TotalLightsAmbient.Front;
|
||||
xOut.oD0 = float4(material.Diffuse.rgb + material.Ambient.rgb + material.Emissive.rgb, material.Diffuse.a);
|
||||
xOut.oD1 = float4(material.Specular.rgb, 0);
|
||||
|
||||
// TODO does TwoSidedLighting imply Lighting? Verify if TwoSidedLighting can be enabled independently of Lighting
|
||||
// Diffuse and specular for when lighting is disabled
|
||||
if (!state.Modes.Lighting)
|
||||
{
|
||||
xOut.oD0 = Get(xIn, diffuse);
|
||||
xOut.oD1 = Get(xIn, specular);
|
||||
}
|
||||
|
||||
if(!state.Modes.TwoSidedLighting)
|
||||
{
|
||||
xOut.oB0 = Get(xIn, backDiffuse);
|
||||
xOut.oB1 = Get(xIn, backSpecular);
|
||||
if(state.Modes.TwoSidedLighting) // TODO : Same as above, for backface lighting variables
|
||||
{
|
||||
// Backface
|
||||
backMaterial.Specular.rgb *= lighting.Specular.Back;
|
||||
backMaterial.Diffuse.rgb *= lighting.Diffuse.Back;
|
||||
backMaterial.Ambient.rgb *= state.TotalLightsAmbient.Back;
|
||||
xOut.oB0 = float4(backMaterial.Diffuse.rgb + backMaterial.Ambient.rgb + backMaterial.Emissive.rgb, backMaterial.Diffuse.a);
|
||||
xOut.oB1 = float4(backMaterial.Specular.rgb, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Colour
|
||||
|
|
|
@ -94,9 +94,10 @@ struct Modes {
|
|||
|
||||
alignas(16) float Lighting;
|
||||
alignas(16) float TwoSidedLighting;
|
||||
alignas(16) float SpecularEnable;
|
||||
// alignas(16) float SpecularEnable;
|
||||
alignas(16) float LocalViewer;
|
||||
|
||||
/// alignas(16) float ColorVertex;
|
||||
alignas(16) float VertexBlend_NrOfMatrices;
|
||||
alignas(16) float VertexBlend_CalcLastWeight; // Could be a bool in higer shader models
|
||||
alignas(16) float NormalizeNormals;
|
||||
|
@ -104,7 +105,7 @@ struct Modes {
|
|||
|
||||
struct PointSprite {
|
||||
alignas(16) float PointSize;
|
||||
alignas(16) float PointScaleEnable;
|
||||
// alignas(16) float PointScaleEnable;
|
||||
alignas(16) float RenderTargetHeight;
|
||||
alignas(16) float ScaleA;
|
||||
alignas(16) float ScaleB;
|
||||
|
@ -122,11 +123,18 @@ struct Fog {
|
|||
alignas(16) float DepthMode;
|
||||
};
|
||||
|
||||
// Vertex lighting
|
||||
// Both frontface and backface lighting can be calculated
|
||||
struct TwoSidedColor
|
||||
{
|
||||
alignas(16) float3 Front;
|
||||
alignas(16) float3 Back;
|
||||
};
|
||||
|
||||
struct FixedFunctionVertexShaderState {
|
||||
alignas(16) Transforms Transforms;
|
||||
alignas(16) arr(Lights, Light, 8);
|
||||
alignas(16) float4 AmbientPlusLightAmbient;
|
||||
alignas(16) float4 BackAmbientPlusLightAmbient;
|
||||
alignas(16) TwoSidedColor TotalLightsAmbient;
|
||||
alignas(16) arr(Materials, Material, 2);
|
||||
alignas(16) Modes Modes;
|
||||
alignas(16) Fog Fog;
|
||||
|
|
Loading…
Reference in New Issue