D3D : Many more renames from WIP_LessVertexPatching branch, and now also most of it's vertex buffer conversion (not everything, yet)

This commit is contained in:
patrickvl 2018-03-18 15:33:37 +01:00
parent a13ee28307
commit a9e28964f1
4 changed files with 450 additions and 441 deletions

View File

@ -7059,7 +7059,7 @@ void XTL::CxbxDrawIndexed(CxbxDrawContext &DrawContext, INDEX16 *pIndexData)
CxbxUpdateActiveIndexBuffer(pIndexData, DrawContext.dwVertexCount);
CxbxVertexBufferConverter VertexBufferConverter;
VertexBufferConverter.Apply(&DrawContext, NULL);
VertexBufferConverter.Apply(&DrawContext);
if (DrawContext.XboxPrimitiveType == X_D3DPT_QUADLIST) {
UINT uiStartIndex = 0;
int iNumVertices = (int)DrawContext.dwVertexCount;
@ -7141,7 +7141,7 @@ void XTL::CxbxDrawPrimitiveUP(CxbxDrawContext &DrawContext)
assert(DrawContext.uiXboxVertexStreamZeroStride > 0);
CxbxVertexBufferConverter VertexBufferConverter;
VertexBufferConverter.Apply(&DrawContext, NULL);
VertexBufferConverter.Apply(&DrawContext);
if (DrawContext.XboxPrimitiveType == X_D3DPT_QUADLIST) {
// LOG_TEST_CASE("X_D3DPT_QUADLIST"); // X-Marbles and XDK Sample PlayField hits this case
// Draw quadlists using a single 'quad-to-triangle mapping' index buffer :
@ -7319,7 +7319,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DrawVertices)
}
CxbxVertexBufferConverter VertexBufferConverter;
VertexBufferConverter.Apply(&DrawContext, NULL);
VertexBufferConverter.Apply(&DrawContext);
if (DrawContext.XboxPrimitiveType == X_D3DPT_QUADLIST) {
// LOG_TEST_CASE("X_D3DPT_QUADLIST"); // ?X-Marbles and XDK Sample (Cartoon, ?maybe PlayField?) hits this case
// Draw quadlists using a single 'quad-to-triangle mapping' index buffer :
@ -7529,7 +7529,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DrawIndexedVerticesUP)
DrawContext.hVertexShader = g_CurrentXboxVertexShaderHandle;
CxbxVertexBufferConverter VertexBufferConverter;
VertexBufferConverter.Apply(&DrawContext, NULL);
VertexBufferConverter.Apply(&DrawContext);
if (DrawContext.XboxPrimitiveType == X_D3DPT_QUADLIST) {
// Indexed quadlist can be drawn using unpatched indexes via multiple draws of 2 'strip' triangles :
// Those 4 vertices are just enough for two triangles (a fan starts with 3 vertices for 1 triangle,

View File

@ -145,11 +145,43 @@ bool GetCachedVertexBufferObject(DWORD pXboxDataPtr, DWORD size, XTL::IDirect3DV
return true;
}
void ActivatePatchedStream
(
XTL::CxbxDrawContext *pDrawContext,
UINT uiStream,
XTL::CxbxPatchedStream *pPatchedStream,
bool bRelease
)
{
//LOG_INIT // Allows use of DEBUG_D3DRESULT
// Use the cached stream values on the host
if (pPatchedStream->bCacheIsStreamZeroDrawUP) {
// Set the UserPointer variables in the drawing context
pDrawContext->pHostVertexStreamZeroData = pPatchedStream->pCachedHostVertexStreamZeroData;
pDrawContext->uiHostVertexStreamZeroStride = pPatchedStream->uiCachedHostVertexStride;
}
else {
HRESULT hRet = g_pD3DDevice8->SetStreamSource(uiStream, pPatchedStream->pCachedHostVertexBuffer, pPatchedStream->uiCachedHostVertexStride);
//DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->SetStreamSource");
if (FAILED(hRet)) {
CxbxKrnlCleanup("Failed to set the type patched buffer as the new stream source!\n");
// TODO : Cartoon hits the above case when the vertex cache size is 0.
}
// TODO : The following doesn't fix that - find our why and fix it for real
if (bRelease) {
// Always release to prevent leaks when it wasn't read from cache:
pPatchedStream->pCachedHostVertexBuffer->Release();
// NOTE : Even this doesn't prevent Cartoon breaking : g_pD3DDevice8->ResourceManagerDiscardBytes(0);
}
}
}
XTL::CxbxVertexBufferConverter::CxbxVertexBufferConverter()
{
this->m_uiNbrStreams = 0;
ZeroMemory(this->m_pStreams, sizeof(PATCHEDSTREAM) * MAX_NBR_STREAMS);
this->m_bPatched = false;
ZeroMemory(this->m_PatchedStreams, sizeof(CxbxPatchedStream) * MAX_NBR_STREAMS);
this->m_bAllocatedStreamZeroData = false;
this->m_pNewVertexStreamZeroData = NULL;
this->m_pVertexShaderDynamicPatch = NULL;
@ -194,15 +226,15 @@ int CountActiveD3DStreams()
return lastStreamIndex + 1;
}
UINT XTL::CxbxVertexBufferConverter::GetNbrStreams(CxbxDrawContext *pPatchDesc)
UINT XTL::CxbxVertexBufferConverter::GetNbrStreams(CxbxDrawContext *pDrawContext)
{
// Draw..Up always have one stream
if (pPatchDesc->pXboxVertexStreamZeroData != nullptr) {
if (pDrawContext->pXboxVertexStreamZeroData != nullptr) {
return 1;
}
if(VshHandleIsVertexShader(pPatchDesc->hVertexShader)) {
CxbxVertexShaderDynamicPatch *pDynamicPatch = VshGetVertexDynamicPatch(pPatchDesc->hVertexShader);
if(VshHandleIsVertexShader(pDrawContext->hVertexShader)) {
CxbxVertexShaderDynamicPatch *pDynamicPatch = VshGetVertexDynamicPatch(pDrawContext->hVertexShader);
if (pDynamicPatch) {
return pDynamicPatch->NbrStreams;
}
@ -210,115 +242,138 @@ UINT XTL::CxbxVertexBufferConverter::GetNbrStreams(CxbxDrawContext *pPatchDesc)
return CountActiveD3DStreams();
}
if (pPatchDesc->hVertexShader) {
if (pDrawContext->hVertexShader) {
return CountActiveD3DStreams();
}
return 0;
}
bool XTL::CxbxVertexBufferConverter::PatchStream(CxbxDrawContext *pDrawContext,
UINT uiStream)
bool XTL::CxbxVertexBufferConverter::ConvertStream
(
CxbxDrawContext *pDrawContext,
UINT uiStream
)
{
bool bVshHandleIsFVF = VshHandleIsFVF(pDrawContext->hVertexShader);
bool bNeedTextureNormalization = false;
struct { bool bTexIsLinear; int Width; int Height; } pActivePixelContainer[X_D3DTS_STAGECOUNT] = { 0 };
// FVF buffers doesn't have Xbox extensions, but texture coordinates may
// need normalization if used with linear textures.
if(bVshHandleIsFVF)
{
if(pDrawContext->hVertexShader & D3DFVF_TEXCOUNT_MASK)
{
return NormalizeTexCoords(pDrawContext, uiStream);
}
else
{
return false;
if (bVshHandleIsFVF) {
DWORD dwTexN = (pDrawContext->hVertexShader & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
// Check for active linear textures.
//X_D3DBaseTexture *pLinearBaseTexture[X_D3DTS_STAGECOUNT];
for (uint i = 0; i < X_D3DTS_STAGECOUNT; i++) {
// Only normalize coordinates used by the FVF shader :
pActivePixelContainer[i].bTexIsLinear = false;
if (i + 1 <= dwTexN) {
// TODO : Use GetXboxBaseTexture()
X_D3DBaseTexture *pXboxBaseTexture = EmuD3DActiveTexture[i];
if (pXboxBaseTexture != xbnullptr) {
// TODO : Use GetXboxPixelContainerFormat
XTL::X_D3DFORMAT XBFormat = (XTL::X_D3DFORMAT)((pXboxBaseTexture->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT);
if (EmuXBFormatIsLinear(XBFormat)) {
// This is often hit by the help screen in XDK samples.
bNeedTextureNormalization = true;
// Remember linearity, width and height :
pActivePixelContainer[i].bTexIsLinear = true;
// TODO : Use DecodeD3DSize
pActivePixelContainer[i].Width = (pXboxBaseTexture->Size & X_D3DSIZE_WIDTH_MASK) + 1;
pActivePixelContainer[i].Height = ((pXboxBaseTexture->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
}
}
}
}
}
#if 0
if(!m_pVertexShaderDynamicPatch || m_pVertexShaderDynamicPatch->NbrStreams <= uiStream || !m_pVertexShaderDynamicPatch->pStreamPatches[uiStream].NeedPatch)
{
return false;
}
#endif
// Do some groovy patchin'
XTL::X_D3DVertexBuffer *pXboxVertexBuffer;
UINT uiXboxVertexStride;
IDirect3DVertexBuffer *pHostVertexBuffer;
uint08 *pXboxVertexData;
uint08 *pHostVertexData;
UINT uiVertexCount;
//UINT uiHostVertexStride;
UINT uiLength;
PATCHEDSTREAM *pStream = &m_pStreams[uiStream];
CxbxStreamDynamicPatch *pStreamDynamicPatch = (m_pVertexShaderDynamicPatch != nullptr) ? (&m_pVertexShaderDynamicPatch->pStreamPatches[uiStream]) : nullptr;
bool bNeedVertexPatching = (pStreamDynamicPatch != nullptr && pStreamDynamicPatch->NeedPatch);
bool bNeedRHWReset = bVshHandleIsFVF && ((pDrawContext->hVertexShader & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW);
bool bNeedStreamCopy = bNeedVertexPatching || bNeedRHWReset;
bool bNeedStreamCopy = bNeedTextureNormalization || bNeedVertexPatching || bNeedRHWReset;
uint08 *pXboxVertexData;
UINT uiXboxVertexStride;
UINT uiXboxVertexDataSize;
UINT uiVertexCount;
UINT uiHostVertexStride;
DWORD dwHostVertexDataSize;
uint08 *pHostVertexData;
IDirect3DVertexBuffer8 *pNewHostVertexBuffer = nullptr;
if(!pDrawContext->pXboxVertexStreamZeroData)
{
pXboxVertexBuffer = g_D3DStreams[uiStream];
uiXboxVertexStride = g_D3DStreamStrides[uiStream];
uiLength = pDrawContext->uiSize;
// Set a new (exact) vertex count
uiVertexCount = uiLength / uiXboxVertexStride;
// Dxbx addition : Don't update pDrawContext.dwVertexCount because an indexed draw
// can (and will) use less vertices than the supplied nr of indexes. Thix fixes
// the missing parts in the CompressedVertices sample (in Vertex shader mode).
pStreamDynamicPatch->ConvertedStride = std::max((uint32_t)pStreamDynamicPatch->ConvertedStride, (uint32_t)uiXboxVertexStride); // ??
dwHostVertexDataSize = uiVertexCount * pStreamDynamicPatch->ConvertedStride;
pXboxVertexData = (uint08*)GetDataFromXboxResource(pXboxVertexBuffer);
GetCachedVertexBufferObject(pXboxVertexBuffer->Data, dwHostVertexDataSize, &pHostVertexBuffer);
if(FAILED(pHostVertexBuffer->Lock(0, 0, &pHostVertexData, D3DLOCK_DISCARD)))
{
CxbxKrnlCleanup("Couldn't lock the new buffer");
}
if(!pStream->pOriginalStream)
{
// The stream was not previously patched, we'll need this when restoring
pStream->pOriginalStream = pXboxVertexBuffer;
}
}
else
{
if (pDrawContext->pXboxVertexStreamZeroData != xbnullptr) {
// There should only be one stream (stream zero) in this case
if(uiStream != 0)
{
if (uiStream != 0) {
CxbxKrnlCleanup("Trying to patch a Draw..UP with more than stream zero!");
}
uiXboxVertexStride = pDrawContext->uiXboxVertexStreamZeroStride;
pStreamDynamicPatch->ConvertedStride = std::max((uint32_t)pStreamDynamicPatch->ConvertedStride, (uint32_t)uiXboxVertexStride); // ??
pXboxVertexData = (uint08 *)pDrawContext->pXboxVertexStreamZeroData;
uiLength = pDrawContext->uiSize;
uiVertexCount = uiLength / uiXboxVertexStride;
// TODO : uiHostVertexStride = (bNeedVertexPatching) ? pStreamDynamicPatch->ConvertedStride : uiXboxVertexStride;
dwHostVertexDataSize = uiVertexCount * pStreamDynamicPatch->ConvertedStride;
pHostVertexBuffer = NULL;
pXboxVertexData = (uint08 *)pDrawContext->pXboxVertexStreamZeroData;
uiXboxVertexStride = pDrawContext->uiXboxVertexStreamZeroStride;
// pStreamDynamicPatch->ConvertedStride = std::max((uint32_t)pStreamDynamicPatch->ConvertedStride, (uint32_t)uiXboxVertexStride); // ??
uiXboxVertexDataSize = pDrawContext->uiSize;
uiVertexCount = uiXboxVertexDataSize / uiXboxVertexStride;
uiHostVertexStride = (bNeedVertexPatching) ? pStreamDynamicPatch->ConvertedStride : uiXboxVertexStride;
dwHostVertexDataSize = uiVertexCount * uiHostVertexStride;
if (bNeedStreamCopy) {
pHostVertexData = (uint08*)g_VMManager.Allocate(dwHostVertexDataSize);
if(!pHostVertexData)
{
if (pHostVertexData == nullptr) {
CxbxKrnlCleanup("Couldn't allocate the new stream zero buffer");
}
}
else {
pHostVertexData = pXboxVertexData;
}
}
else {
XTL::X_D3DVertexBuffer *pXboxVertexBuffer = g_D3DStreams[uiStream];
pXboxVertexData = (uint08*)GetDataFromXboxResource(pXboxVertexBuffer);
if (pXboxVertexData == NULL) {
HRESULT hRet = g_pD3DDevice->SetStreamSource(uiStream, nullptr, 0);
// DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetStreamSource");
if (FAILED(hRet)) {
CxbxKrnlCleanup("g_pD3DDevice->SetStreamSource(uiStream, nullptr, 0)\n");
}
for (uint32 uiVertex = 0; uiVertex < uiVertexCount; uiVertex++)
{
return false;
}
uiXboxVertexStride = g_D3DStreamStrides[uiStream];
uiXboxVertexDataSize = pDrawContext->uiSize;
// Set a new (exact) vertex count
uiVertexCount = uiXboxVertexDataSize / uiXboxVertexStride;
// Dxbx note : Don't overwrite pDrawContext.dwVertexCount with uiVertexCount, because an indexed draw
// can (and will) use less vertices than the supplied nr of indexes. Thix fixes
// the missing parts in the CompressedVertices sample (in Vertex shader mode).
uiHostVertexStride = (bNeedVertexPatching) ? pStreamDynamicPatch->ConvertedStride : uiXboxVertexStride;
//pStreamDynamicPatch->ConvertedStride = std::max((uint32_t)pStreamDynamicPatch->ConvertedStride, (uint32_t)uiXboxVertexStride); // ??
dwHostVertexDataSize = uiVertexCount * uiHostVertexStride;
GetCachedVertexBufferObject(pXboxVertexBuffer->Data, dwHostVertexDataSize, &pNewHostVertexBuffer);
if (FAILED(pNewHostVertexBuffer->Lock(0, 0, &pHostVertexData, D3DLOCK_DISCARD))) {
CxbxKrnlCleanup("Couldn't lock the new buffer");
}
bNeedStreamCopy = true;
}
if (bNeedVertexPatching) {
// assert(bNeedStreamCopy || "bNeedVertexPatching implies bNeedStreamCopy (but copies via conversions");
for (uint32 uiVertex = 0; uiVertex < uiVertexCount; uiVertex++) {
uint08 *pOrigVertex = &pXboxVertexData[uiVertex * uiXboxVertexStride];
uint08 *pNewDataPos = &pHostVertexData[uiVertex * pStreamDynamicPatch->ConvertedStride];
for (UINT uiType = 0; uiType < pStreamDynamicPatch->NbrTypes; uiType++)
{
uint08 *pNewDataPos = &pHostVertexData[uiVertex * uiHostVertexStride];
for (UINT uiType = 0; uiType < pStreamDynamicPatch->NbrTypes; uiType++) {
// Dxbx note : The following code handles only the D3DVSDT enums that need conversion;
// All other cases are catched by the memcpy in the default-block.
switch (pStreamDynamicPatch->pTypes[uiType])
{
switch (pStreamDynamicPatch->pTypes[uiType]) {
case X_D3DVSDT_NORMPACKED3: { // 0x16: // Make it FLOAT3
// Hit by Dashboard
int32 iPacked = ((int32 *)pOrigVertex)[0];
@ -371,15 +426,16 @@ bool XTL::CxbxVertexBufferConverter::PatchStream(CxbxDrawContext *pDrawContext,
break;
}
case X_D3DVSDT_NORMSHORT1: { // 0x11: // Make it FLOAT1
// UNTESTED - Need test-case!
LOG_TEST_CASE("X_D3DVSDT_NORMSHORT1"); // UNTESTED - Need test-case!
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
//((FLOAT *)pNewDataPos)[1] = 0.0f; // Would be needed for FLOAT2
pOrigVertex += 1 * sizeof(SHORT);
break;
}
#if !CXBX_USE_D3D9 // No need for patching in D3D9
#if !DXBX_USE_D3D9 // No need for patching in D3D9
case X_D3DVSDT_NORMSHORT2: { // 0x21: // Make it FLOAT2
// UNTESTED - Need test-case!
LOG_TEST_CASE("X_D3DVSDT_NORMSHORT2"); // UNTESTED - Need test-case!
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)pOrigVertex)[1]) / 32767.0f;
pOrigVertex += 2 * sizeof(SHORT);
@ -387,16 +443,16 @@ bool XTL::CxbxVertexBufferConverter::PatchStream(CxbxDrawContext *pDrawContext,
}
#endif
case X_D3DVSDT_NORMSHORT3: { // 0x31: // Make it FLOAT3
// UNTESTED - Need test-case!
LOG_TEST_CASE("X_D3DVSDT_NORMSHORT3"); // UNTESTED - Need test-case!
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)pOrigVertex)[1]) / 32767.0f;
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((SHORT*)pOrigVertex)[2]) / 32767.0f;
pOrigVertex += 3 * sizeof(SHORT);
break;
}
#if !CXBX_USE_D3D9 // No need for patching in D3D9
#if !DXBX_USE_D3D9 // No need for patching in D3D9
case X_D3DVSDT_NORMSHORT4: { // 0x41: // Make it FLOAT4
// UNTESTED - Need test-case!
LOG_TEST_CASE("X_D3DVSDT_NORMSHORT4"); // UNTESTED - Need test-case!
((FLOAT *)pNewDataPos)[0] = ((FLOAT)((SHORT*)pOrigVertex)[0]) / 32767.0f;
((FLOAT *)pNewDataPos)[1] = ((FLOAT)((SHORT*)pOrigVertex)[1]) / 32767.0f;
((FLOAT *)pNewDataPos)[2] = ((FLOAT)((SHORT*)pOrigVertex)[2]) / 32767.0f;
@ -432,28 +488,26 @@ bool XTL::CxbxVertexBufferConverter::PatchStream(CxbxDrawContext *pDrawContext,
pNewDataPos += pStreamDynamicPatch->pSizes[uiType];
}
}
#if 0
if (!pDrawContext->pXboxVertexStreamZeroData)
{
//if(pNewVertexBuffer != nullptr) // Dxbx addition
pHostVertexBuffer->Unlock();
pNewHostVertexBuffer->Unlock();
HRESULT hr = g_pD3DDevice->SetStreamSource(
uiStream,
pHostVertexBuffer,
#ifdef CXBX_USE_D3D9
0, // OffsetInBytes
#endif
pStreamDynamicPatch->ConvertedStride);
if (FAILED(hr))
if (FAILED(g_pD3DDevice->SetStreamSource(uiStream, pNewHostVertexBuffer, pStreamDynamicPatch->ConvertedStride)))
{
CxbxKrnlCleanup("Failed to set the type patched buffer as the new stream source!\n");
}
pStream->pPatchedStream = pHostVertexBuffer;
pPatchedStream->pPatchedStream = pNewHostVertexBuffer;
}
else
{
#endif
}
else {
if (bNeedStreamCopy) {
memcpy(pHostVertexData, pXboxVertexData, dwHostVertexDataSize);
}
#if 0
pDrawContext->pXboxVertexStreamZeroData = pHostVertexData;
pDrawContext->uiXboxVertexStreamZeroStride = pStreamDynamicPatch->ConvertedStride;
if (!m_bAllocatedStreamZeroData)
@ -462,51 +516,32 @@ bool XTL::CxbxVertexBufferConverter::PatchStream(CxbxDrawContext *pDrawContext,
m_bAllocatedStreamZeroData = true;
m_pNewVertexStreamZeroData = pHostVertexData;
}
#endif
}
pStream->uiOrigStride = uiXboxVertexStride;
pStream->uiNewStride = pStreamDynamicPatch->ConvertedStride;
m_bPatched = true;
return true;
}
bool XTL::CxbxVertexBufferConverter::NormalizeTexCoords(CxbxDrawContext *pPatchDesc, UINT uiStream)
// Xbox FVF shaders are identical to host Direct3D 8.1, however
// texture coordinates may need normalization if used with linear textures.
if (bNeedTextureNormalization || bNeedRHWReset)
{
// Check for active linear textures.
bool bHasLinearTex = false, bTexIsLinear[4] = { false };
X_D3DBaseTexture *pLinearBaseTexture[4];
for(uint08 i = 0; i < 4; i++)
{
X_D3DBaseTexture *pBaseTexture = EmuD3DActiveTexture[i];
if (pBaseTexture)
{
XTL::X_D3DFORMAT XBFormat = (XTL::X_D3DFORMAT)((pBaseTexture->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT);
if (EmuXBFormatIsLinear(XBFormat))
{
bHasLinearTex = bTexIsLinear[i] = true;
pLinearBaseTexture[i] = pBaseTexture;
}
}
}
if(!bHasLinearTex)
return false;
// assert(bVshHandleIsFVF);
#if 0
XTL::X_D3DVertexBuffer *pOrigVertexBuffer;
IDirect3DVertexBuffer *pNewVertexBuffer;
PATCHEDSTREAM *pStream;
CxbxPatchedStream *pStream;
uint08 *pData, *pUVData;
uint uiStride, uiVertexCount;
#endif
if(pPatchDesc->pXboxVertexStreamZeroData)
UINT uiUVOffset = 0;
#if 0
if (pDrawContext->pXboxVertexStreamZeroData)
{
// In-place patching of inline buffer.
pNewVertexBuffer = 0;
pData = (uint08 *)pPatchDesc->pXboxVertexStreamZeroData;
uiStride = pPatchDesc->uiXboxVertexStreamZeroStride;
DWORD uiLength = pPatchDesc->uiSize;
pData = (uint08 *)pDrawContext->pXboxVertexStreamZeroData;
uiStride = pDrawContext->uiXboxVertexStreamZeroStride;
DWORD uiLength = pDrawContext->uiSize;
uiVertexCount = uiLength / uiStride;
}
else
@ -514,7 +549,7 @@ bool XTL::CxbxVertexBufferConverter::NormalizeTexCoords(CxbxDrawContext *pPatchD
// Copy stream for patching and caching.
pOrigVertexBuffer = g_D3DStreams[uiStream];
uiStride = g_D3DStreamStrides[uiStream];
UINT uiLength = pPatchDesc->uiSize;
UINT uiLength = pDrawContext->uiSize;
uiVertexCount = uiLength / uiStride;
@ -527,143 +562,122 @@ bool XTL::CxbxVertexBufferConverter::NormalizeTexCoords(CxbxDrawContext *pPatchD
}
memcpy(pData, pOrigData, uiLength);
pStream = &m_pStreams[uiStream];
if(!pStream->pOriginalStream)
{
pStream->pOriginalStream = pOrigVertexBuffer;
pStream = &m_PatchedStreams[uiStream];
}
}
#endif
// Locate texture coordinate offset in vertex structure.
uint uiOffset = 0;
if(pPatchDesc->hVertexShader & D3DFVF_XYZRHW)
uiOffset += (sizeof(FLOAT) * 4);
else
{
if(pPatchDesc->hVertexShader & D3DFVF_XYZ)
uiOffset += (sizeof(FLOAT) * 3 );
else if(pPatchDesc->hVertexShader & D3DFVF_XYZB1)
uiOffset += (sizeof(FLOAT) *4 );
else if(pPatchDesc->hVertexShader & D3DFVF_XYZB2)
uiOffset += (sizeof(FLOAT) * 5);
else if(pPatchDesc->hVertexShader & D3DFVF_XYZB3)
uiOffset += (sizeof(FLOAT) * 6);
else if(pPatchDesc->hVertexShader & D3DFVF_XYZB4)
uiOffset += (sizeof(FLOAT) * 7);
if(pPatchDesc->hVertexShader & D3DFVF_NORMAL)
uiOffset += (sizeof(FLOAT) * 3);
if (bNeedTextureNormalization) {
uiUVOffset = XTL::DxbxFVFToVertexSizeInBytes(pDrawContext->hVertexShader, /*bIncludeTextures=*/false);
}
if(pPatchDesc->hVertexShader & D3DFVF_DIFFUSE)
uiOffset += sizeof(DWORD);
if(pPatchDesc->hVertexShader & D3DFVF_SPECULAR)
uiOffset += sizeof(DWORD);
for (uint32 uiVertex = 0; uiVertex < uiVertexCount; uiVertex++) {
FLOAT *pVertexDataAsFloat = (FLOAT*)(&pHostVertexData[uiVertex * uiHostVertexStride]);
DWORD dwTexN = (pPatchDesc->hVertexShader & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
// Normalize texture coordinates.
for(uint32 uiVertex = 0; uiVertex < uiVertexCount; uiVertex++)
{
pUVData = pData + (uiVertex * uiStride) + uiOffset;
if(dwTexN >= 1)
{
if(bTexIsLinear[0])
{
((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[0]->Size & X_D3DSIZE_WIDTH_MASK) + 1;
((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[0]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
}
pUVData += sizeof(FLOAT) * 2;
// Handle pre-transformed vertices (which bypass the vertex shader pipeline)
if (bNeedRHWReset) {
// Check Z. TODO : Why reset Z from 0.0 to 1.0 ? (Maybe fog-related?)
if (pVertexDataAsFloat[2] == 0.0f) {
// LOG_TEST_CASE("D3DFVF_XYZRHW (Z)"); // Test-case : Many XDK Samples (AlphaFog, PointSprites)
pVertexDataAsFloat[2] = 1.0f;
}
if(dwTexN >= 2)
{
if(bTexIsLinear[1])
{
((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[1]->Size & X_D3DSIZE_WIDTH_MASK) + 1;
((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[1]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
}
pUVData += sizeof(FLOAT) * 2;
}
if(dwTexN >= 3)
{
if(bTexIsLinear[2])
{
((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[2]->Size & X_D3DSIZE_WIDTH_MASK) + 1;
((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[2]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
}
pUVData += sizeof(FLOAT) * 2;
}
if((dwTexN >= 4) && bTexIsLinear[3])
{
((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[3]->Size & X_D3DSIZE_WIDTH_MASK) + 1;
((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[3]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
// Check RHW. TODO : Why reset from 0.0 to 1.0 ? (Maybe 1.0 indicates that the vertices are not to be transformed)
if (pVertexDataAsFloat[3] == 0.0f) {
// LOG_TEST_CASE("D3DFVF_XYZRHW (RHW)"); // Test-case : Many XDK Samples (AlphaFog, PointSprites)
pVertexDataAsFloat[3] = 1.0f;
}
}
// Normalize texture coordinates in FVF stream if needed
if (uiUVOffset > 0) { // uiUVOffset > 0 implies bNeedTextureNormalization (using one is more efficient than both)
FLOAT *pVertexUVData = (FLOAT*)((uintptr_t)pVertexDataAsFloat + uiUVOffset);
for (uint i = 0; i < X_D3DTS_STAGECOUNT; i++) {
if (pActivePixelContainer[i].bTexIsLinear) {
pVertexUVData[(i * 2) + 0] /= pActivePixelContainer[i].Width;
pVertexUVData[(i * 2) + 1] /= pActivePixelContainer[i].Height;
}
}
}
}
#if 0
if (pNewVertexBuffer)
{
pNewVertexBuffer->Unlock();
HRESULT hr = g_pD3DDevice->SetStreamSource(
uiStream,
pNewVertexBuffer,
#ifdef CXBX_USE_D3D9
0, // OffsetInBytes
#endif
uiStride);
if (FAILED(hr))
if (FAILED(g_pD3DDevice->SetStreamSource(uiStream, pNewVertexBuffer, uiStride)))
{
CxbxKrnlCleanup("Failed to set the texcoord patched FVF buffer as the new stream source.");
}
pStream->pPatchedStream = pNewVertexBuffer;
pStream->uiOrigStride = uiStride;
pStream->uiNewStride = uiStride;
m_bPatched = true;
pStream->uiCachedXboxVertexStride = uiStride;
pStream->uiCachedHostVertexStride = uiStride;
}
#endif
}
return m_bPatched;
CxbxPatchedStream *pPatchedStream = &m_PatchedStreams[uiStream];
#if 0 // new
pPatchedStream->pCachedXboxVertexData = pXboxVertexData;
#endif
pPatchedStream->uiCachedXboxVertexStride = uiXboxVertexStride;
#if 0 // new
pPatchedStream->uiCachedXboxVertexDataSize = uiXboxVertexDataSize;
#endif
pPatchedStream->uiCachedHostVertexStride = uiHostVertexStride;
pPatchedStream->bCacheIsStreamZeroDrawUP = (pDrawContext->pXboxVertexStreamZeroData != NULL);
if (pPatchedStream->bCacheIsStreamZeroDrawUP) {
pPatchedStream->pCachedHostVertexStreamZeroData = pHostVertexData;
#if 0 // new
pPatchedStream->bCachedHostVertexStreamZeroDataIsAllocated = bNeedStreamCopy;
}
else {
assert(pNewHostVertexBuffer != nullptr);
pNewHostVertexBuffer->Unlock();
pPatchedStream->pCachedHostVertexBuffer = pNewHostVertexBuffer;
#endif
}
bool XTL::CxbxVertexBufferConverter::Apply(CxbxDrawContext *pPatchDesc, bool *pbFatalError)
ActivatePatchedStream(pDrawContext, uiStream, pPatchedStream,
/*Release=*/!bNeedStreamCopy); // Release when it won't get cached
return bNeedStreamCopy;
}
void XTL::CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
{
CxbxDrawContext *pDrawContext = pPatchDesc; // Temporary alias to help porting over code from PatrickvL WIP_LessVertexPatching
if ((pDrawContext->XboxPrimitiveType < X_D3DPT_POINTLIST) || (pDrawContext->XboxPrimitiveType > X_D3DPT_POLYGON))
CxbxKrnlCleanup("Unknown primitive type: 0x%.02X\n", pDrawContext->XboxPrimitiveType);
bool Patched = false;
// Get the number of streams
m_uiNbrStreams = GetNbrStreams(pPatchDesc);
m_uiNbrStreams = GetNbrStreams(pDrawContext);
if(VshHandleIsVertexShader(pPatchDesc->hVertexShader))
{
m_pVertexShaderDynamicPatch = &((CxbxVertexShader *)VshHandleGetVertexShader(pPatchDesc->hVertexShader)->Handle)->VertexShaderDynamicPatch;
if (VshHandleIsVertexShader(pDrawContext->hVertexShader)) {
m_pVertexShaderDynamicPatch = &((CxbxVertexShader *)VshHandleGetVertexShader(pDrawContext->hVertexShader)->Handle)->VertexShaderDynamicPatch;
}
for(UINT uiStream = 0; uiStream < m_uiNbrStreams; uiStream++)
{
bool LocalPatched = false;
pPatchDesc->uiSize = GetVertexBufferSize(
pPatchDesc->dwVertexCount,
pPatchDesc->pXboxVertexStreamZeroData == nullptr ? g_D3DStreamStrides[uiStream] : pPatchDesc->uiXboxVertexStreamZeroStride,
pPatchDesc->pIndexData,
pPatchDesc->dwStartVertex,
pPatchDesc->dwIndexBase
for(UINT uiStream = 0; uiStream < m_uiNbrStreams; uiStream++) {
pDrawContext->uiSize = GetVertexBufferSize(
pDrawContext->dwVertexCount,
pDrawContext->pXboxVertexStreamZeroData == nullptr ? g_D3DStreamStrides[uiStream] : pDrawContext->uiXboxVertexStreamZeroStride,
pDrawContext->pIndexData,
pDrawContext->dwStartVertex,
pDrawContext->dwIndexBase
);
// TODO: Check for cached vertex buffer, and use it if possible
LocalPatched |= PatchStream(pPatchDesc, uiStream);
Patched |= LocalPatched;
if (!Patched && pPatchDesc->pXboxVertexStreamZeroData == nullptr) {
if (ConvertStream(pDrawContext, uiStream)) {
// success
}
else
if (pDrawContext->pXboxVertexStreamZeroData == nullptr) {
// Fetch or Create the host Vertex Buffer
XTL::IDirect3DVertexBuffer* pHostVertexBuffer;
GetCachedVertexBufferObject(g_D3DStreams[uiStream]->Data, pPatchDesc->uiSize, &pHostVertexBuffer);
GetCachedVertexBufferObject(g_D3DStreams[uiStream]->Data, pDrawContext->uiSize, &pHostVertexBuffer);
// Copy xbox data to the host vertex buffer
BYTE* pVertexDataData;
@ -671,7 +685,7 @@ bool XTL::CxbxVertexBufferConverter::Apply(CxbxDrawContext *pPatchDesc, bool *pb
CxbxKrnlCleanup("Couldn't lock Vertex Buffer");
}
memcpy(pVertexDataData, GetDataFromXboxResource(g_D3DStreams[uiStream]), pPatchDesc->uiSize);
memcpy(pVertexDataData, GetDataFromXboxResource(g_D3DStreams[uiStream]), pDrawContext->uiSize);
pHostVertexBuffer->Unlock();
// Set the buffer as a stream source
@ -708,8 +722,6 @@ bool XTL::CxbxVertexBufferConverter::Apply(CxbxDrawContext *pPatchDesc, bool *pb
// No need to set : pDrawContext->XboxPrimitiveType = X_D3DPT_TRIANGLEFAN;
LOG_TEST_CASE("X_D3DPT_POLYGON");
}
return Patched;
}
VOID XTL::EmuFlushIVB()

View File

@ -59,13 +59,14 @@ typedef struct _CxbxDrawContext
}
CxbxDrawContext;
typedef struct _PATCHEDSTREAM
typedef struct _CxbxPatchedStream
{
XTL::X_D3DVertexBuffer *pOriginalStream;
XTL::IDirect3DVertexBuffer *pPatchedStream;
UINT uiOrigStride;
UINT uiNewStride;
} PATCHEDSTREAM;
UINT uiCachedXboxVertexStride;
UINT uiCachedHostVertexStride;
bool bCacheIsStreamZeroDrawUP;
void *pCachedHostVertexStreamZeroData;
XTL::IDirect3DVertexBuffer *pCachedHostVertexBuffer;
} CxbxPatchedStream;
class CxbxVertexBufferConverter
{
@ -73,15 +74,14 @@ class CxbxVertexBufferConverter
CxbxVertexBufferConverter();
~CxbxVertexBufferConverter();
bool Apply(CxbxDrawContext *pPatchDesc, bool *pbFatalError);
void Apply(CxbxDrawContext *pPatchDesc);
private:
UINT m_uiNbrStreams;
PATCHEDSTREAM m_pStreams[MAX_NBR_STREAMS];
CxbxPatchedStream m_PatchedStreams[MAX_NBR_STREAMS];
PVOID m_pNewVertexStreamZeroData;
bool m_bPatched;
bool m_bAllocatedStreamZeroData;
CxbxVertexShaderDynamicPatch *m_pVertexShaderDynamicPatch;
@ -90,10 +90,7 @@ class CxbxVertexBufferConverter
UINT GetNbrStreams(CxbxDrawContext *pPatchDesc);
// Patches the types of the stream
bool PatchStream(CxbxDrawContext *pPatchDesc, UINT uiStream);
// Normalize texture coordinates in FVF stream if needed
bool NormalizeTexCoords(CxbxDrawContext *pPatchDesc, UINT uiStream);
bool ConvertStream(CxbxDrawContext *pPatchDesc, UINT uiStream);
};
// inline vertex buffer emulation

View File

@ -1604,30 +1604,30 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
// * Vertex shader declaration recompiler
// ****************************************************************************
typedef struct _VSH_TYPE_PATCH_DATA
typedef struct _CxbxVertexShaderTypePatchData
{
DWORD NbrTypes;
UINT Types[256];
UINT NewSizes[256];
}
VSH_TYPE_PATCH_DATA;
CxbxVertexShaderTypePatchData;
typedef struct _VSH_STREAM_PATCH_DATA
typedef struct _CxbxVertexStreamPatchData
{
DWORD NbrStreams;
XTL::CxbxStreamDynamicPatch pStreamPatches[256];
}
VSH_STREAM_PATCH_DATA;
CxbxVertexStreamPatchData;
typedef struct _VSH_PATCH_DATA
typedef struct _CxbxVertexShaderPatchData
{
boolean NeedPatching;
WORD CurrentStreamNumber;
DWORD ConvertedStride;
VSH_TYPE_PATCH_DATA TypePatchData;
VSH_STREAM_PATCH_DATA StreamPatchData;
CxbxVertexShaderTypePatchData TypePatchData;
CxbxVertexStreamPatchData StreamPatchData;
}
VSH_PATCH_DATA;
CxbxVertexShaderPatchData;
// VERTEX SHADER
#define DEF_VSH_END 0xFFFFFFFF
@ -1861,7 +1861,7 @@ static void VshConverToken_TESSELATOR(DWORD *pToken,
}
}
static boolean VshAddStreamPatch(VSH_PATCH_DATA *pPatchData)
static boolean VshAddStreamPatch(CxbxVertexShaderPatchData *pPatchData)
{
int CurrentStream = pPatchData->CurrentStreamNumber;
@ -1875,8 +1875,8 @@ static boolean VshAddStreamPatch(VSH_PATCH_DATA *pPatchData)
pStreamPatch->NbrTypes = pPatchData->TypePatchData.NbrTypes;
pStreamPatch->NeedPatch = pPatchData->NeedPatching;
// 2010/01/12 - revel8n - fixed allocated data size and type
pStreamPatch->pTypes = (UINT *)malloc(pPatchData->TypePatchData.NbrTypes * sizeof(UINT)); //VSH_TYPE_PATCH_DATA));
memcpy(pStreamPatch->pTypes, pPatchData->TypePatchData.Types, pPatchData->TypePatchData.NbrTypes * sizeof(UINT)); //VSH_TYPE_PATCH_DATA));
pStreamPatch->pTypes = (UINT *)malloc(pPatchData->TypePatchData.NbrTypes * sizeof(UINT)); //CxbxVertexShaderTypePatchData));
memcpy(pStreamPatch->pTypes, pPatchData->TypePatchData.Types, pPatchData->TypePatchData.NbrTypes * sizeof(UINT)); //CxbxVertexShaderTypePatchData));
// 2010/12/06 - PatrickvL - do the same for new sizes :
pStreamPatch->pSizes = (UINT *)malloc(pPatchData->TypePatchData.NbrTypes * sizeof(UINT));
memcpy(pStreamPatch->pSizes, pPatchData->TypePatchData.NewSizes, pPatchData->TypePatchData.NbrTypes * sizeof(UINT));
@ -1887,7 +1887,7 @@ static boolean VshAddStreamPatch(VSH_PATCH_DATA *pPatchData)
}
static void VshConvertToken_STREAM(DWORD *pToken,
VSH_PATCH_DATA *pPatchData)
CxbxVertexShaderPatchData *pPatchData)
{
// D3DVSD_STREAM_TESS
if(*pToken & D3DVSD_STREAMTESSMASK)
@ -1942,7 +1942,7 @@ static void VshConvertToken_STREAMDATA_SKIPBYTES(DWORD *pToken)
static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
boolean IsFixedFunction,
VSH_PATCH_DATA *pPatchData)
CxbxVertexShaderPatchData *pPatchData)
{
using namespace XTL;
@ -2103,7 +2103,7 @@ static void VshConvertToken_STREAMDATA_REG(DWORD *pToken,
static void VshConvertToken_STREAMDATA(DWORD *pToken,
boolean IsFixedFunction,
VSH_PATCH_DATA *pPatchData)
CxbxVertexShaderPatchData *pPatchData)
{
using namespace XTL;
if (*pToken & D3DVSD_MASK_SKIP)
@ -2123,7 +2123,7 @@ static void VshConvertToken_STREAMDATA(DWORD *pToken,
static DWORD VshRecompileToken(DWORD *pToken,
boolean IsFixedFunction,
VSH_PATCH_DATA *pPatchData)
CxbxVertexShaderPatchData *pPatchData)
{
using namespace XTL;
@ -2188,7 +2188,7 @@ DWORD XTL::EmuRecompileVshDeclaration
*pDeclarationSize = DeclarationSize;
// TODO: Put these in one struct
VSH_PATCH_DATA PatchData = { 0 };
CxbxVertexShaderPatchData PatchData = { 0 };
DbgVshPrintf("DWORD dwVSHDecl[] =\n{\n");