Prevent invalid g_Xbox_MultiSampleType values using a setter

This avoids zero-dectection later on
Some tooling functions to top it off.
This commit is contained in:
patrickvl 2020-05-08 12:05:29 +02:00
parent fec845f6f8
commit ba2d18d17f
3 changed files with 137 additions and 69 deletions

View File

@ -2830,6 +2830,89 @@ ConvertedIndexBuffer& CxbxUpdateActiveIndexBuffer
return CacheEntry;
}
#define CXBX_D3DMULTISAMPLE_XSCALE(type) (((type) & XTL::X_D3DMULTISAMPLE_XSCALE_MASK) >> XTL::X_D3DMULTISAMPLE_XSCALE_SHIFT)
#define CXBX_D3DMULTISAMPLE_YSCALE(type) (((type) & XTL::X_D3DMULTISAMPLE_YSCALE_MASK) >> XTL::X_D3DMULTISAMPLE_YSCALE_SHIFT)
void SetXboxMultiSampleType(XTL::X_D3DMULTISAMPLE_TYPE value)
{
// Validate & correct input, to detect test cases and avoid trouble when using g_Xbox_MultiSampleType :
if (value == 0) {
LOG_TEST_CASE("Correcting zero to X_D3DMULTISAMPLE_NONE");
value = XTL::X_D3DMULTISAMPLE_NONE;
}
if (value & ~XTL::X_D3DMULTISAMPLE_KNOWN_MASK) {
LOG_TEST_CASE("Removing unknown X_D3DMULTISAMPLE bits");
value &= XTL::X_D3DMULTISAMPLE_KNOWN_MASK;
}
if (CXBX_D3DMULTISAMPLE_XSCALE(value) == 0) {
LOG_TEST_CASE("Correcting XSCALE 0 to 1");
value |= 1 << XTL::X_D3DMULTISAMPLE_XSCALE_SHIFT;
}
if (CXBX_D3DMULTISAMPLE_YSCALE(value) == 0) {
LOG_TEST_CASE("Correcting YSCALE 0 to 1");
value |= 1 << XTL::X_D3DMULTISAMPLE_YSCALE_SHIFT;
}
if ((CXBX_D3DMULTISAMPLE_XSCALE(value) == 1) && (CXBX_D3DMULTISAMPLE_YSCALE(value) == 1)) {
if (value & XTL::X_D3DMULTISAMPLE_ALGO_MASK) {
LOG_TEST_CASE("Removing algorithm for 1 by 1 scale");
value &= ~XTL::X_D3DMULTISAMPLE_ALGO_MASK;
}
if (value & XTL::X_D3DMULTISAMPLE_SAMPLING_MASK) {
LOG_TEST_CASE("Removing sampling for 1 by 1 scale");
value &= ~XTL::X_D3DMULTISAMPLE_SAMPLING_MASK;
}
}
if (value == XTL::X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN) {
LOG_TEST_CASE("X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN"); // This used to use scale 1.5f
}
// Set the now-validated g_Xbox_MultiSampleType value :
g_Xbox_MultiSampleType = value;
}
static inline float GetMultiSampleOffsetDelta()
{
// TODO : What impact does X_D3DMULTISAMPLE_SAMPLING_SUPER have on offset?
return (g_Xbox_MultiSampleType & XTL::X_D3DMULTISAMPLE_SAMPLING_MULTI) ? 0.0f : 0.5f;
}
static inline void GetMultiSampleOffset(float& xOffset, float& yOffset)
{
xOffset = yOffset = GetMultiSampleOffsetDelta();
}
static inline void GetMultiSampleScale(float& xScale, float& yScale)
{
xScale = (float)CXBX_D3DMULTISAMPLE_XSCALE(g_Xbox_MultiSampleType);
yScale = (float)CXBX_D3DMULTISAMPLE_YSCALE(g_Xbox_MultiSampleType);
}
void GetMultiSampleOffsetAndScale(float& xScale, float& yScale, float& xOffset, float& yOffset)
{
GetMultiSampleScale(xScale, yScale);
GetMultiSampleOffset(xOffset, yOffset);
}
static void ApplyXboxMultiSampleOffset(float& x, float& y)
{
float d = GetMultiSampleOffsetDelta();
x += d;
y += d;
}
static void ApplyXboxMultiSampleScale(float& x, float& y)
{
float xs, ys;
GetMultiSampleScale(xs, ys);
x *= xs;
y *= ys;
}
void ApplyXboxMultiSampleOffsetAndScale(float& x, float& y)
{
ApplyXboxMultiSampleScale(x, y);
ApplyXboxMultiSampleOffset(x, y);
}
void Direct3D_CreateDevice_Start
(
XTL::X_D3DPRESENT_PARAMETERS *pPresentationParameters
@ -2843,7 +2926,7 @@ void Direct3D_CreateDevice_Start
CxbxKrnlCleanup("Failed to init XboxTextureStates");
}
g_Xbox_MultiSampleType = pPresentationParameters->MultiSampleType;
SetXboxMultiSampleType(pPresentationParameters->MultiSampleType);
// create default device *before* calling Xbox Direct3D_CreateDevice trampline
// to avoid hitting EMUPATCH'es that need a valid g_pD3DDevice
@ -3085,7 +3168,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_Reset)
// Instead, it simply re-creates the backbuffer with a new configuration
// Store the new multisampling configuration
g_Xbox_MultiSampleType = pPresentationParameters->MultiSampleType;
SetXboxMultiSampleType(pPresentationParameters->MultiSampleType);
// Since Reset will call create a new backbuffer surface, we can clear our current association
// NOTE: We don't actually free the Xbox data, the Xbox side will do this for us when we call the trampoline below.
@ -3751,44 +3834,6 @@ float GetZScaleForSurface(XTL::X_D3DSurface* pSurface)
return 1;
}
void GetMultiSampleOffsetAndScale(float& xScale, float& yScale, float& xOffset, float& yOffset)
{
// Default values
xScale = 1.0f;
yScale = 1.0f;
xOffset = 0.5f;
yOffset = 0.5f;
// NOTE: Can be 0, so we need to check for that too
if (g_Xbox_MultiSampleType > 0) {
switch (g_Xbox_MultiSampleType)
{
case XTL::X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR:
case XTL::X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_QUINCUNX:
case XTL::X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_LINEAR:
case XTL::X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_GAUSSIAN:
xOffset = yOffset = 0.0f;
break;
case XTL::X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN:
xOffset = yOffset = 0.0f;
LOG_TEST_CASE("X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN");
break;
}
#define MULTISAMPLE_XSCALE_MASK 0x00f0
#define MULTISAMPLE_XSCALE_SHIFT 4
#define MULTISAMPLE_YSCALE_MASK 0x000f
#define MULTISAMPLE_YSCALE_SHIFT 0
#define MULTISAMPLE_XSCALE(type) ((type & MULTISAMPLE_XSCALE_MASK) >> MULTISAMPLE_XSCALE_SHIFT)
#define MULTISAMPLE_YSCALE(type) ((type & MULTISAMPLE_YSCALE_MASK) >> MULTISAMPLE_YSCALE_SHIFT)
xScale = (float)MULTISAMPLE_XSCALE(g_Xbox_MultiSampleType);
yScale = (float)MULTISAMPLE_YSCALE(g_Xbox_MultiSampleType);
}
}
void GetViewPortOffsetAndScale(float (&vOffset)[4], float(&vScale)[4])
{
// Store viewport offset and scale in constant registers
@ -3801,8 +3846,11 @@ void GetViewPortOffsetAndScale(float (&vOffset)[4], float(&vScale)[4])
float xScale, yScale;
float xOffset, yOffset;
GetMultiSampleOffsetAndScale(xScale, yScale, xOffset, yOffset);
ViewPort.Width /= xScale;
ViewPort.Height /= yScale;
// Since Width and Height are DWORD, subtracting MultiSampleOffset 0.0f or 0.5f makes no sense
//ViewPort.Width -= xOffset;
//ViewPort.Height -= yOffset;
ViewPort.Width /= (DWORD)xScale;
ViewPort.Height /= (DWORD)yScale;
// Calculate Width/Height scale & offset
float scaleWidth = (2.0f / ViewPort.Width) * g_RenderScaleFactor;
@ -3929,12 +3977,12 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetViewport)
}
}
// Apply MSAA scale
// Apply MSAA scale and offset
float xScale, yScale;
float xOffset, yOffset;
GetMultiSampleOffsetAndScale(xScale, yScale, xOffset, yOffset);
HostViewPort.Width *= xScale;
HostViewPort.Height *= yScale;
GetMultiSampleScale(xScale, yScale);
HostViewPort.Width *= (DWORD)xScale;
HostViewPort.Height *= (DWORD)yScale;
// Since Width and Height are DWORD, adding GetMultiSampleOffset 0.0f or 0.5f makes no sense
HRESULT hRet = g_pD3DDevice->SetViewport(&HostViewPort);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetViewport");
@ -5036,8 +5084,7 @@ DWORD WINAPI XTL::EMUPATCH(D3DDevice_Swap)
// We also need to account for any MSAA which may have enlarged the Xbox Backbuffer
float xScale, yScale;
float xOffset, yOffset;
GetMultiSampleOffsetAndScale(xScale, yScale, xOffset, yOffset);
GetMultiSampleScale(xScale, yScale);
xScale = (float)BackBufferDesc.Width / ((float)XboxBackBufferWidth / xScale);
yScale = (float)BackBufferDesc.Height / ((float)XboxBackBufferHeight / yScale);

View File

@ -463,18 +463,43 @@ struct X_D3DResource
#define X_D3DLOCK_TILED 0x00000040 // Xbox extension
#define X_D3DLOCK_READONLY 0x00000080
const int X_D3DMULTISAMPLE_NONE = 0x0011;
const int X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR = 0x1021;
const int X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_QUINCUNX = 0x1121;
// Multisample modes
const int X_D3DMULTISAMPLE_NONE = 0x0011;
const int X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR = 0x1021;
const int X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_QUINCUNX = 0x1121;
const int X_D3DMULTISAMPLE_2_SAMPLES_SUPERSAMPLE_HORIZONTAL_LINEAR = 0x2021;
const int X_D3DMULTISAMPLE_2_SAMPLES_SUPERSAMPLE_VERTICAL_LINEAR = 0x2012;
const int X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_LINEAR = 0x1022;
const int X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_GAUSSIAN = 0x1222;
const int X_D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_LINEAR = 0x2022;
const int X_D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_GAUSSIAN = 0x2222;
const int X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN = 0x1233;
const int X_D3DMULTISAMPLE_9_SAMPLES_SUPERSAMPLE_GAUSSIAN = 0x2233;
const int X_D3DMULTISAMPLE_2_SAMPLES_SUPERSAMPLE_VERTICAL_LINEAR = 0x2012;
const int X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_LINEAR = 0x1022;
const int X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_GAUSSIAN = 0x1222;
const int X_D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_LINEAR = 0x2022;
const int X_D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_GAUSSIAN = 0x2222;
const int X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN = 0x1233;
const int X_D3DMULTISAMPLE_9_SAMPLES_SUPERSAMPLE_GAUSSIAN = 0x2233;
// Multisample masks (Cxbx additions)
const int X_D3DMULTISAMPLE_YSCALE_MASK = 0x0003;
const int X_D3DMULTISAMPLE_YSCALE_SHIFT = 0;
const int X_D3DMULTISAMPLE_XSCALE_MASK = 0x0030;
const int X_D3DMULTISAMPLE_XSCALE_SHIFT = 4;
const int X_D3DMULTISAMPLE_ALGO_LINEAR = 0x0000;
const int X_D3DMULTISAMPLE_ALGO_QUINCUNX = 0x0100;
const int X_D3DMULTISAMPLE_ALGO_GAUSSIAN = 0x0200;
const int X_D3DMULTISAMPLE_ALGO_MASK = 0x0300;
const int X_D3DMULTISAMPLE_SAMPLING_NONE = 0x0000;
const int X_D3DMULTISAMPLE_SAMPLING_MULTI = 0x1000;
const int X_D3DMULTISAMPLE_SAMPLING_SUPER = 0x2000;
const int X_D3DMULTISAMPLE_SAMPLING_MASK = 0x3000;
const int X_D3DMULTISAMPLE_KNOWN_MASK = 0
| X_D3DMULTISAMPLE_YSCALE_MASK
| X_D3DMULTISAMPLE_XSCALE_MASK
| X_D3DMULTISAMPLE_ALGO_MASK
| X_D3DMULTISAMPLE_SAMPLING_MASK
;
struct X_D3DVertexBuffer : public X_D3DResource
{

View File

@ -61,12 +61,13 @@ XTL::X_STREAMINPUT g_Xbox_SetStreamSource[X_VSH_MAX_STREAMS] = { 0 }; // Note :
extern XTL::X_D3DSurface* g_pXbox_RenderTarget;
extern XTL::X_D3DSurface* g_pXbox_BackBufferSurface;
extern XTL::X_D3DMULTISAMPLE_TYPE g_Xbox_MultiSampleType;
extern XTL::X_D3DMULTISAMPLE_TYPE g_Xbox_MultiSampleType;
void *GetDataFromXboxResource(XTL::X_D3DResource *pXboxResource);
bool GetHostRenderTargetDimensions(DWORD* pHostWidth, DWORD* pHostHeight, IDirect3DSurface* pHostRenderTarget = nullptr);
uint32_t GetPixelContainerWidth(XTL::X_D3DPixelContainer* pPixelContainer);
uint32_t GetPixelContainerHeight(XTL::X_D3DPixelContainer* pPixelContainer);
void GetMultiSampleOffsetAndScale(float& xScale, float& yScale, float& xOffset, float& yOffset);
void ApplyXboxMultiSampleOffsetAndScale(float& x, float& y);
void CxbxPatchedStream::Activate(CxbxDrawContext *pDrawContext, UINT uiStream) const
{
@ -669,7 +670,7 @@ void CxbxVertexBufferConverter::ConvertStream
HostRenderTarget_Height = XboxRenderTarget_Height;
}
bool bNeedRHWTransform = g_Xbox_MultiSampleType > 0 || (XboxRenderTarget_Width < HostRenderTarget_Width && XboxRenderTarget_Height < HostRenderTarget_Height);
bool bNeedRHWTransform = (g_Xbox_MultiSampleType > XTL::X_D3DMULTISAMPLE_NONE) || (XboxRenderTarget_Width < HostRenderTarget_Width && XboxRenderTarget_Height < HostRenderTarget_Height);
for (uint32_t uiVertex = 0; uiVertex < uiVertexCount; uiVertex++) {
FLOAT *pVertexDataAsFloat = (FLOAT*)(&pHostVertexData[uiVertex * uiHostVertexStride]);
@ -682,12 +683,7 @@ void CxbxVertexBufferConverter::ConvertStream
pVertexDataAsFloat[0] *= g_RenderScaleFactor;
pVertexDataAsFloat[1] *= g_RenderScaleFactor;
// Apply MSAA scale
float xScale, yScale;
float xOffset, yOffset;
GetMultiSampleOffsetAndScale(xScale, yScale, xOffset, yOffset);
pVertexDataAsFloat[0] *= xScale;
pVertexDataAsFloat[1] *= yScale;
ApplyXboxMultiSampleOffsetAndScale(pVertexDataAsFloat[0], pVertexDataAsFloat[1]);
}
#if 0