mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Aggregate Draw(Indexed)Primitive calls
This commit is contained in:
parent
8e07040750
commit
bb8ce374e2
@ -32,6 +32,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::blt(const D3DDDIARG_BLT* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
auto it = m_resources.find(data->hDstResource);
|
||||
if (it != m_resources.end())
|
||||
{
|
||||
@ -43,6 +44,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::clear(const D3DDDIARG_CLEAR* data, UINT numRect, const RECT* rect)
|
||||
{
|
||||
flushPrimitives();
|
||||
if (data->Flags & D3DCLEAR_TARGET)
|
||||
{
|
||||
prepareForRendering();
|
||||
@ -52,6 +54,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::colorFill(const D3DDDIARG_COLORFILL* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
auto it = m_resources.find(data->hResource);
|
||||
if (it != m_resources.end())
|
||||
{
|
||||
@ -94,6 +97,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::destroyResource(HANDLE resource)
|
||||
{
|
||||
flushPrimitives();
|
||||
if (g_gdiResource && resource == *g_gdiResource)
|
||||
{
|
||||
D3DDDIARG_LOCK lock = {};
|
||||
@ -130,14 +134,10 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
HRESULT Device::drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2* data,
|
||||
UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer)
|
||||
UINT /*indicesSize*/, const void* indexBuffer, const UINT* flagBuffer)
|
||||
{
|
||||
if (2 != indicesSize)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
prepareForRendering();
|
||||
return m_drawPrimitive.drawIndexed(*data, indexBuffer, flagBuffer);
|
||||
return m_drawPrimitive.drawIndexed(*data, static_cast<const UINT16*>(indexBuffer), flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE* data, const UINT* flagBuffer)
|
||||
@ -152,6 +152,7 @@ namespace D3dDdi
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
flushPrimitives();
|
||||
return m_origVtable.pfnFlush(m_device);
|
||||
}
|
||||
|
||||
@ -161,11 +162,13 @@ namespace D3dDdi
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
flushPrimitives();
|
||||
return m_origVtable.pfnFlush1(m_device, FlushFlags);
|
||||
}
|
||||
|
||||
HRESULT Device::lock(D3DDDIARG_LOCK* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
auto it = m_resources.find(data->hResource);
|
||||
if (it != m_resources.end())
|
||||
{
|
||||
@ -186,12 +189,14 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::present(const D3DDDIARG_PRESENT* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
prepareForRendering(data->hSrcResource, data->SrcSubResourceIndex, true);
|
||||
return m_origVtable.pfnPresent(m_device, data);
|
||||
}
|
||||
|
||||
HRESULT Device::present1(D3DDDIARG_PRESENT1* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
for (UINT i = 0; i < data->SrcResources; ++i)
|
||||
{
|
||||
prepareForRendering(data->phSrcResources[i].hResource, data->phSrcResources[i].SubResourceIndex, true);
|
||||
@ -201,6 +206,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::setRenderTarget(const D3DDDIARG_SETRENDERTARGET* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
HRESULT result = m_origVtable.pfnSetRenderTarget(m_device, data);
|
||||
if (SUCCEEDED(result) && 0 == data->RenderTargetIndex)
|
||||
{
|
||||
@ -229,6 +235,7 @@ namespace D3dDdi
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
flushPrimitives();
|
||||
HRESULT result = m_origVtable.pfnSetTexture(m_device, stage, texture);
|
||||
if (SUCCEEDED(result) && stage < m_textures.size())
|
||||
{
|
||||
@ -237,6 +244,7 @@ namespace D3dDdi
|
||||
return result;
|
||||
}
|
||||
|
||||
flushPrimitives();
|
||||
return m_origVtable.pfnSetTexture(m_device, stage, texture);
|
||||
}
|
||||
|
||||
@ -247,6 +255,7 @@ namespace D3dDdi
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
flushPrimitives();
|
||||
HRESULT result = m_origVtable.pfnSetVertexShaderDecl(m_device, shader);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
@ -257,6 +266,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::unlock(const D3DDDIARG_UNLOCK* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
auto it = m_resources.find(data->hResource);
|
||||
if (it != m_resources.end())
|
||||
{
|
||||
@ -267,6 +277,7 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::updateWInfo(const D3DDDIARG_WINFO* data)
|
||||
{
|
||||
flushPrimitives();
|
||||
if (1.0f == data->WNear && 1.0f == data->WFar)
|
||||
{
|
||||
D3DDDIARG_WINFO wInfo = {};
|
||||
@ -326,11 +337,6 @@ namespace D3dDdi
|
||||
return it != m_resources.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
void Device::enableFlush(bool enable)
|
||||
{
|
||||
s_isFlushEnabled = enable;
|
||||
}
|
||||
|
||||
Resource* Device::findResource(HANDLE resource)
|
||||
{
|
||||
for (auto& device : s_devices)
|
||||
|
@ -47,6 +47,7 @@ namespace D3dDdi
|
||||
const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||
Resource* getResource(HANDLE resource);
|
||||
|
||||
void flushPrimitives() { m_drawPrimitive.flushPrimitives(); }
|
||||
void prepareForRendering(HANDLE resource, UINT subResourceIndex, bool isReadOnly);
|
||||
void prepareForRendering();
|
||||
|
||||
@ -54,7 +55,7 @@ namespace D3dDdi
|
||||
static Device& get(HANDLE device);
|
||||
static void remove(HANDLE device);
|
||||
|
||||
static void enableFlush(bool enable);
|
||||
static void enableFlush(bool enable) { s_isFlushEnabled = enable; }
|
||||
static Resource* findResource(HANDLE resource);
|
||||
static Resource* getGdiResource();
|
||||
static void setGdiResourceHandle(HANDLE resource);
|
||||
|
@ -14,6 +14,13 @@ namespace
|
||||
D3dDdi::Device::remove(hDevice);
|
||||
return D3dDdi::DeviceFuncs::s_origVtablePtr->pfnDestroyDevice(hDevice);
|
||||
}
|
||||
|
||||
template <typename DeviceMethodPtr, DeviceMethodPtr deviceMethod, typename... Params>
|
||||
HRESULT APIENTRY flushPrimitives(HANDLE hDevice, Params... params)
|
||||
{
|
||||
D3dDdi::Device::get(hDevice).flushPrimitives();
|
||||
return (D3dDdi::DeviceFuncs::s_origVtablePtr->*deviceMethod)(hDevice, params...);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEVICE_FUNC(func) deviceFunc<decltype(&Device::func), &Device::func>
|
||||
@ -49,5 +56,36 @@ namespace D3dDdi
|
||||
vtable.pfnSetVertexShaderDecl = &DEVICE_FUNC(setVertexShaderDecl);
|
||||
vtable.pfnUnlock = &DEVICE_FUNC(unlock);
|
||||
vtable.pfnUpdateWInfo = &DEVICE_FUNC(updateWInfo);
|
||||
|
||||
#define FLUSH_PRIMITIVES(func) vtable.func = &flushPrimitives<decltype(&D3DDDI_DEVICEFUNCS::func), &D3DDDI_DEVICEFUNCS::func>
|
||||
FLUSH_PRIMITIVES(pfnBufBlt);
|
||||
FLUSH_PRIMITIVES(pfnBufBlt1);
|
||||
FLUSH_PRIMITIVES(pfnDeletePixelShader);
|
||||
FLUSH_PRIMITIVES(pfnDeleteVertexShaderDecl);
|
||||
FLUSH_PRIMITIVES(pfnDeleteVertexShaderFunc);
|
||||
FLUSH_PRIMITIVES(pfnDepthFill);
|
||||
FLUSH_PRIMITIVES(pfnDiscard);
|
||||
FLUSH_PRIMITIVES(pfnGenerateMipSubLevels);
|
||||
FLUSH_PRIMITIVES(pfnSetClipPlane);
|
||||
FLUSH_PRIMITIVES(pfnSetDepthStencil);
|
||||
FLUSH_PRIMITIVES(pfnSetPalette);
|
||||
FLUSH_PRIMITIVES(pfnSetPixelShader);
|
||||
FLUSH_PRIMITIVES(pfnSetPixelShaderConst);
|
||||
FLUSH_PRIMITIVES(pfnSetPixelShaderConstB);
|
||||
FLUSH_PRIMITIVES(pfnSetPixelShaderConstI);
|
||||
FLUSH_PRIMITIVES(pfnSetRenderState);
|
||||
FLUSH_PRIMITIVES(pfnSetScissorRect);
|
||||
FLUSH_PRIMITIVES(pfnSetTextureStageState);
|
||||
FLUSH_PRIMITIVES(pfnSetVertexShaderConst);
|
||||
FLUSH_PRIMITIVES(pfnSetVertexShaderConstB);
|
||||
FLUSH_PRIMITIVES(pfnSetVertexShaderConstI);
|
||||
FLUSH_PRIMITIVES(pfnSetVertexShaderFunc);
|
||||
FLUSH_PRIMITIVES(pfnSetViewport);
|
||||
FLUSH_PRIMITIVES(pfnStateSet);
|
||||
FLUSH_PRIMITIVES(pfnTexBlt);
|
||||
FLUSH_PRIMITIVES(pfnTexBlt1);
|
||||
FLUSH_PRIMITIVES(pfnUpdatePalette);
|
||||
FLUSH_PRIMITIVES(pfnSetZRange);
|
||||
#undef FLUSH_PRIMITIVES
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,13 @@
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include <Common/Log.h>
|
||||
#include <D3dDdi/DrawPrimitive.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/Resource.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const UINT INDEX_BUFFER_SIZE = 256 * 1024;
|
||||
const UINT VERTEX_BUFFER_SIZE = 1024 * 1024;
|
||||
|
||||
class VertexRhwFixer
|
||||
{
|
||||
public:
|
||||
VertexRhwFixer(D3DTLVERTEX* vertex)
|
||||
{
|
||||
if (vertex && 0.0f == vertex->rhw)
|
||||
{
|
||||
vertex->rhw = 1.0f;
|
||||
m_vertex = vertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VertexRhwFixer(const void* vertex)
|
||||
: VertexRhwFixer(static_cast<D3DTLVERTEX*>(const_cast<void*>(vertex)))
|
||||
{
|
||||
}
|
||||
|
||||
~VertexRhwFixer()
|
||||
{
|
||||
if (m_vertex)
|
||||
{
|
||||
m_vertex->rhw = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
D3DTLVERTEX* m_vertex;
|
||||
};
|
||||
|
||||
UINT getVertexCount(D3DPRIMITIVETYPE primitiveType, UINT primitiveCount)
|
||||
{
|
||||
switch (primitiveType)
|
||||
@ -63,6 +26,22 @@ namespace
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateMax(UINT& max, UINT value)
|
||||
{
|
||||
if (value > max)
|
||||
{
|
||||
max = value;
|
||||
}
|
||||
}
|
||||
|
||||
void updateMin(UINT& min, UINT value)
|
||||
{
|
||||
if (value < min)
|
||||
{
|
||||
min = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
@ -73,6 +52,7 @@ namespace D3dDdi
|
||||
, m_vertexBuffer(device, VERTEX_BUFFER_SIZE)
|
||||
, m_indexBuffer(device, m_vertexBuffer ? INDEX_BUFFER_SIZE : 0)
|
||||
, m_streamSource{}
|
||||
, m_batched{}
|
||||
{
|
||||
LOG_ONCE("Dynamic vertex buffers are " << (m_vertexBuffer ? "" : "not ") << "available");
|
||||
LOG_ONCE("Dynamic index buffers are " << (m_indexBuffer ? "" : "not ") << "available");
|
||||
@ -91,65 +71,539 @@ namespace D3dDdi
|
||||
m_sysMemVertexBuffers[resource] = { vertices, fvf };
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::draw(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer)
|
||||
void DrawPrimitive::appendIndexedVertices(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
auto firstVertexPtr = m_streamSource.vertices + data.VStart * m_streamSource.stride;
|
||||
VertexRhwFixer fixer((m_streamSource.fvf & D3DFVF_XYZRHW) ? firstVertexPtr : nullptr);
|
||||
rebaseIndices();
|
||||
appendIndexedVerticesWithoutRebase(indices, count, baseVertexIndex, minIndex, maxIndex);
|
||||
}
|
||||
|
||||
if (m_streamSource.vertices && m_vertexBuffer)
|
||||
void DrawPrimitive::appendIndexedVerticesWithoutRebase(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
UINT vertexCount = maxIndex - minIndex + 1;
|
||||
if (vertexCount <= count)
|
||||
{
|
||||
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||
auto baseVertexIndex = loadVertices(firstVertexPtr, vertexCount);
|
||||
if (baseVertexIndex >= 0)
|
||||
INT delta = getBatchedVertexCount() - minIndex;
|
||||
for (UINT i = 0; i < count; ++i)
|
||||
{
|
||||
D3DDDIARG_DRAWPRIMITIVE dp = data;
|
||||
dp.VStart = baseVertexIndex;
|
||||
return m_origVtable.pfnDrawPrimitive(m_device, &dp, flagBuffer);
|
||||
m_batched.indices.push_back(static_cast<UINT16>(indices[i] + delta));
|
||||
}
|
||||
appendVertices(baseVertexIndex + minIndex, vertexCount);
|
||||
return;
|
||||
}
|
||||
|
||||
static UINT16 indexMap[D3DMAXNUMVERTICES] = {};
|
||||
static BYTE indexCycles[D3DMAXNUMVERTICES] = {};
|
||||
static BYTE currentCycle = 0;
|
||||
static UINT maxVertexCount = 0;
|
||||
|
||||
++currentCycle;
|
||||
if (0 == currentCycle)
|
||||
{
|
||||
memset(indexCycles, 0, maxVertexCount);
|
||||
maxVertexCount = vertexCount;
|
||||
++currentCycle;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateMax(maxVertexCount, vertexCount);
|
||||
}
|
||||
|
||||
UINT16 newIndex = static_cast<UINT16>(getBatchedVertexCount());
|
||||
for (UINT i = 0; i < count; ++i)
|
||||
{
|
||||
const UINT16 zeroBasedIndex = static_cast<UINT16>(indices[i] - minIndex);
|
||||
if (currentCycle != indexCycles[zeroBasedIndex])
|
||||
{
|
||||
appendVertices(baseVertexIndex + indices[i], 1);
|
||||
indexMap[zeroBasedIndex] = newIndex;
|
||||
indexCycles[zeroBasedIndex] = currentCycle;
|
||||
m_batched.indices.push_back(newIndex);
|
||||
++newIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_batched.indices.push_back(indexMap[zeroBasedIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendIndexRange(UINT base, UINT count)
|
||||
{
|
||||
rebaseIndices();
|
||||
appendIndexRangeWithoutRebase(base, count);
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendIndexRangeWithoutRebase(UINT base, UINT count)
|
||||
{
|
||||
for (UINT i = base; i < base + count; ++i)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i));
|
||||
}
|
||||
updateMin(m_batched.minIndex, base);
|
||||
updateMax(m_batched.maxIndex, base + count - 1);
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendIndices(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
rebaseIndices();
|
||||
for (UINT i = 0; i < count; ++i)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(baseVertexIndex + indices[i]));
|
||||
}
|
||||
updateMin(m_batched.minIndex, baseVertexIndex + minIndex);
|
||||
updateMax(m_batched.maxIndex, baseVertexIndex + maxIndex);
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendIndicesAndVertices(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
if (indices)
|
||||
{
|
||||
appendIndexedVertices(indices, count, baseVertexIndex, minIndex, maxIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_batched.indices.empty())
|
||||
{
|
||||
appendIndexRange(getBatchedVertexCount(), count);
|
||||
}
|
||||
appendVertices(baseVertexIndex + minIndex, count);
|
||||
}
|
||||
}
|
||||
else if (indices)
|
||||
{
|
||||
appendIndices(indices, count, baseVertexIndex, minIndex, maxIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendIndexRange(baseVertexIndex, count);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendLineOrTriangleList(INT baseVertexIndex, UINT primitiveCount, UINT vpp,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
if (m_streamSource.vertices ||
|
||||
indices ||
|
||||
!m_batched.indices.empty() ||
|
||||
m_batched.baseVertexIndex + static_cast<INT>(m_batched.primitiveCount * vpp) != baseVertexIndex)
|
||||
{
|
||||
appendIndicesAndVertices(indices, primitiveCount * vpp, baseVertexIndex, minIndex, maxIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawPrimitive::appendPrimitives(D3DPRIMITIVETYPE primitiveType, INT baseVertexIndex, UINT primitiveCount,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
if ((m_batched.primitiveCount + primitiveCount) * 3 > D3DMAXNUMVERTICES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (primitiveType)
|
||||
{
|
||||
case D3DPT_POINTLIST:
|
||||
if (D3DPT_POINTLIST != m_batched.primitiveType ||
|
||||
!m_streamSource.vertices &&
|
||||
m_batched.baseVertexIndex + static_cast<INT>(m_batched.primitiveCount) != baseVertexIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
appendVertices(baseVertexIndex, primitiveCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case D3DPT_LINESTRIP:
|
||||
return false;
|
||||
|
||||
case D3DPT_LINELIST:
|
||||
if (D3DPT_LINELIST != m_batched.primitiveType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
appendLineOrTriangleList(baseVertexIndex, primitiveCount, 2, indices, minIndex, maxIndex);
|
||||
break;
|
||||
|
||||
case D3DPT_TRIANGLELIST:
|
||||
if (m_batched.primitiveType < D3DPT_TRIANGLELIST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
convertToTriangleList();
|
||||
appendLineOrTriangleList(baseVertexIndex, primitiveCount, 3, indices, minIndex, maxIndex);
|
||||
break;
|
||||
|
||||
case D3DPT_TRIANGLESTRIP:
|
||||
if (m_batched.primitiveType < D3DPT_TRIANGLELIST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
appendTriangleStrip(baseVertexIndex, primitiveCount, indices, minIndex, maxIndex);
|
||||
break;
|
||||
|
||||
case D3DPT_TRIANGLEFAN:
|
||||
if (m_batched.primitiveType < D3DPT_TRIANGLELIST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
appendTriangleFan(baseVertexIndex, primitiveCount, indices, minIndex, maxIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
m_batched.primitiveCount += primitiveCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendTriangleFan(INT baseVertexIndex, UINT primitiveCount,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
convertToTriangleList();
|
||||
rebaseIndices();
|
||||
appendIndicesAndVertices(indices, primitiveCount + 2, baseVertexIndex, minIndex, maxIndex);
|
||||
convertIndexedTriangleFanToList(m_batched.primitiveCount, primitiveCount);
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendTriangleStrip(INT baseVertexIndex, UINT primitiveCount,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex)
|
||||
{
|
||||
if (D3DPT_TRIANGLESTRIP != m_batched.primitiveType)
|
||||
{
|
||||
convertToTriangleList();
|
||||
rebaseIndices();
|
||||
appendIndicesAndVertices(indices, primitiveCount + 2, baseVertexIndex, minIndex, maxIndex);
|
||||
convertIndexedTriangleStripToList(m_batched.primitiveCount, primitiveCount);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_streamSource.vertices || !m_batched.indices.empty())
|
||||
{
|
||||
rebaseIndices();
|
||||
}
|
||||
|
||||
for (UINT i = 1 + m_batched.primitiveCount % 2; i != 0; --i)
|
||||
{
|
||||
repeatLastBatchedVertex();
|
||||
m_batched.primitiveCount++;
|
||||
}
|
||||
|
||||
if (m_batched.indices.empty())
|
||||
{
|
||||
appendVertices(baseVertexIndex, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(getBatchedVertexCount()));
|
||||
}
|
||||
else if (indices)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(baseVertexIndex + indices[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(baseVertexIndex));
|
||||
}
|
||||
}
|
||||
m_batched.primitiveCount += 3;
|
||||
|
||||
appendIndicesAndVertices(indices, primitiveCount + 2, baseVertexIndex, minIndex, maxIndex);
|
||||
}
|
||||
|
||||
void DrawPrimitive::appendVertices(UINT base, UINT count)
|
||||
{
|
||||
auto vertices = m_streamSource.vertices + base * m_streamSource.stride;
|
||||
m_batched.vertices.insert(m_batched.vertices.end(), vertices, vertices + count * m_streamSource.stride);
|
||||
}
|
||||
|
||||
void DrawPrimitive::clearBatchedPrimitives()
|
||||
{
|
||||
m_batched.primitiveCount = 0;
|
||||
m_batched.vertices.clear();
|
||||
m_batched.indices.clear();
|
||||
}
|
||||
|
||||
void DrawPrimitive::convertIndexedTriangleFanToList(UINT startPrimitive, UINT primitiveCount)
|
||||
{
|
||||
const UINT totalPrimitiveCount = startPrimitive + primitiveCount;
|
||||
m_batched.indices.resize(totalPrimitiveCount * 3);
|
||||
|
||||
INT startIndexPos = startPrimitive * 3;
|
||||
INT oldIndexPos = startIndexPos + primitiveCount - 1;
|
||||
INT newIndexPos = (totalPrimitiveCount - 1) * 3;
|
||||
const UINT16 startIndex = m_batched.indices[startIndexPos];
|
||||
|
||||
while (newIndexPos > startIndexPos)
|
||||
{
|
||||
m_batched.indices[newIndexPos + 2] = startIndex;
|
||||
m_batched.indices[newIndexPos + 1] = m_batched.indices[oldIndexPos + 2];
|
||||
m_batched.indices[newIndexPos] = m_batched.indices[oldIndexPos + 1];
|
||||
newIndexPos -= 3;
|
||||
oldIndexPos--;
|
||||
}
|
||||
|
||||
m_batched.indices[newIndexPos] = m_batched.indices[oldIndexPos + 1];
|
||||
m_batched.indices[newIndexPos + 1] = m_batched.indices[oldIndexPos + 2];
|
||||
m_batched.indices[newIndexPos + 2] = startIndex;
|
||||
}
|
||||
|
||||
void DrawPrimitive::convertIndexedTriangleStripToList(UINT startPrimitive, UINT primitiveCount)
|
||||
{
|
||||
const UINT totalPrimitiveCount = startPrimitive + primitiveCount;
|
||||
m_batched.indices.resize(totalPrimitiveCount * 3);
|
||||
|
||||
INT oldIndexPos = startPrimitive * 3 + primitiveCount - 2;
|
||||
INT newIndexPos = (totalPrimitiveCount - 2) * 3;
|
||||
|
||||
if (0 != primitiveCount % 2)
|
||||
{
|
||||
m_batched.indices[newIndexPos + 5] = m_batched.indices[oldIndexPos + 3];
|
||||
m_batched.indices[newIndexPos + 4] = m_batched.indices[oldIndexPos + 2];
|
||||
m_batched.indices[newIndexPos + 3] = m_batched.indices[oldIndexPos + 1];
|
||||
newIndexPos -= 3;
|
||||
oldIndexPos--;
|
||||
}
|
||||
|
||||
while (newIndexPos >= oldIndexPos)
|
||||
{
|
||||
m_batched.indices[newIndexPos + 5] = m_batched.indices[oldIndexPos + 2];
|
||||
m_batched.indices[newIndexPos + 4] = m_batched.indices[oldIndexPos + 3];
|
||||
m_batched.indices[newIndexPos + 3] = m_batched.indices[oldIndexPos + 1];
|
||||
m_batched.indices[newIndexPos + 2] = m_batched.indices[oldIndexPos + 2];
|
||||
m_batched.indices[newIndexPos + 1] = m_batched.indices[oldIndexPos + 1];
|
||||
m_batched.indices[newIndexPos] = m_batched.indices[oldIndexPos];
|
||||
newIndexPos -= 6;
|
||||
oldIndexPos -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPrimitive::convertToTriangleList()
|
||||
{
|
||||
const bool alreadyIndexed = !m_batched.indices.empty();
|
||||
|
||||
switch (m_batched.primitiveType)
|
||||
{
|
||||
case D3DPT_TRIANGLELIST:
|
||||
return;
|
||||
|
||||
case D3DPT_TRIANGLESTRIP:
|
||||
if (alreadyIndexed)
|
||||
{
|
||||
rebaseIndices();
|
||||
convertIndexedTriangleStripToList(0, m_batched.primitiveCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
const UINT baseVertexIndex = static_cast<UINT>(m_batched.baseVertexIndex);
|
||||
UINT i = baseVertexIndex;
|
||||
for (; i < baseVertexIndex + m_batched.primitiveCount - 1; i += 2)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 1));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 2));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 1));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 3));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 2));
|
||||
}
|
||||
if (i < baseVertexIndex + m_batched.primitiveCount)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 1));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D3DPT_TRIANGLEFAN:
|
||||
if (alreadyIndexed)
|
||||
{
|
||||
rebaseIndices();
|
||||
convertIndexedTriangleFanToList(0, m_batched.primitiveCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UINT i = m_batched.baseVertexIndex; i < m_batched.baseVertexIndex + m_batched.primitiveCount; ++i)
|
||||
{
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 1));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(i + 2));
|
||||
m_batched.indices.push_back(static_cast<UINT16>(m_batched.baseVertexIndex));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_batched.primitiveType = D3DPT_TRIANGLELIST;
|
||||
if (!alreadyIndexed)
|
||||
{
|
||||
m_batched.minIndex = m_batched.baseVertexIndex;
|
||||
m_batched.maxIndex = m_batched.baseVertexIndex + m_batched.primitiveCount + 1;
|
||||
m_batched.baseVertexIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::draw(D3DDDIARG_DRAWPRIMITIVE data, const UINT* flagBuffer)
|
||||
{
|
||||
if (0 == m_batched.primitiveCount || flagBuffer ||
|
||||
!appendPrimitives(data.PrimitiveType, data.VStart, data.PrimitiveCount, nullptr, 0, 0))
|
||||
{
|
||||
flushPrimitives();
|
||||
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
appendVertices(data.VStart, vertexCount);
|
||||
m_batched.baseVertexIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_batched.baseVertexIndex = data.VStart;
|
||||
m_batched.minIndex = D3DMAXNUMVERTICES;
|
||||
m_batched.maxIndex = 0;
|
||||
}
|
||||
m_batched.primitiveType = data.PrimitiveType;
|
||||
m_batched.primitiveCount = data.PrimitiveCount;
|
||||
|
||||
if (flagBuffer)
|
||||
{
|
||||
flushPrimitives(flagBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
return m_origVtable.pfnDrawPrimitive(m_device, &data, flagBuffer);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::drawIndexed(
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const void* indices, const UINT* flagBuffer)
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const UINT16* indices, const UINT* flagBuffer)
|
||||
{
|
||||
auto firstIndexPtr = reinterpret_cast<const UINT16*>(static_cast<const BYTE*>(indices) + data.StartIndexOffset);
|
||||
auto indexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||
auto [min, max] = std::minmax_element(firstIndexPtr, firstIndexPtr + indexCount);
|
||||
auto [min, max] = std::minmax_element(indices, indices + indexCount);
|
||||
data.MinIndex = *min;
|
||||
data.NumVertices = *max - *min + 1;
|
||||
|
||||
auto firstVertexPtr = m_streamSource.vertices + data.BaseVertexOffset + data.MinIndex * m_streamSource.stride;
|
||||
VertexRhwFixer fixer((m_streamSource.fvf & D3DFVF_XYZRHW) ? firstVertexPtr : nullptr);
|
||||
|
||||
if (m_streamSource.vertices && m_vertexBuffer)
|
||||
if (0 == m_batched.primitiveCount || flagBuffer ||
|
||||
!appendPrimitives(data.PrimitiveType, data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride),
|
||||
data.PrimitiveCount, indices, *min, *max))
|
||||
{
|
||||
auto baseVertexIndex = loadVertices(firstVertexPtr, data.NumVertices);
|
||||
if (baseVertexIndex >= 0)
|
||||
flushPrimitives();
|
||||
m_batched.baseVertexIndex = data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride);
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
baseVertexIndex -= data.MinIndex;
|
||||
data.BaseVertexOffset = baseVertexIndex * static_cast<INT>(m_streamSource.stride);
|
||||
appendIndexedVerticesWithoutRebase(indices, indexCount, m_batched.baseVertexIndex, *min, *max);
|
||||
m_batched.baseVertexIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_batched.indices.assign(indices, indices + indexCount);
|
||||
m_batched.minIndex = *min;
|
||||
m_batched.maxIndex = *max;
|
||||
}
|
||||
m_batched.primitiveType = data.PrimitiveType;
|
||||
m_batched.primitiveCount = data.PrimitiveCount;
|
||||
|
||||
if (flagBuffer)
|
||||
{
|
||||
flushPrimitives(flagBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void DrawPrimitive::fixFirstVertexRhw()
|
||||
{
|
||||
auto firstVertex = reinterpret_cast<D3DTLVERTEX*>(m_batched.vertices.data());
|
||||
if ((m_streamSource.fvf & D3DFVF_XYZRHW) && 0.0f == firstVertex->rhw)
|
||||
{
|
||||
firstVertex->rhw = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::flush(const UINT* flagBuffer)
|
||||
{
|
||||
D3DDDIARG_DRAWPRIMITIVE data = {};
|
||||
data.PrimitiveType = m_batched.primitiveType;
|
||||
data.VStart = m_batched.baseVertexIndex;
|
||||
data.PrimitiveCount = m_batched.primitiveCount;
|
||||
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
fixFirstVertexRhw();
|
||||
data.VStart = loadVertices(m_batched.vertices.data(), getBatchedVertexCount());
|
||||
}
|
||||
|
||||
clearBatchedPrimitives();
|
||||
return m_origVtable.pfnDrawPrimitive(m_device, &data, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::flushIndexed(const UINT* flagBuffer)
|
||||
{
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data = {};
|
||||
data.PrimitiveType = m_batched.primitiveType;
|
||||
data.BaseVertexOffset = m_batched.baseVertexIndex * static_cast<INT>(m_streamSource.stride);
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
data.MinIndex = -m_batched.baseVertexIndex;
|
||||
data.NumVertices = getBatchedVertexCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
data.MinIndex = m_batched.minIndex;
|
||||
data.NumVertices = m_batched.maxIndex - m_batched.minIndex + 1;
|
||||
}
|
||||
data.PrimitiveCount = m_batched.primitiveCount;
|
||||
|
||||
if (m_streamSource.vertices)
|
||||
{
|
||||
fixFirstVertexRhw();
|
||||
INT baseVertexIndex = loadVertices(m_batched.vertices.data(), data.NumVertices) - data.MinIndex;
|
||||
data.BaseVertexOffset = baseVertexIndex * static_cast<INT>(m_streamSource.stride);
|
||||
}
|
||||
|
||||
INT startIndex = -1;
|
||||
if ((!m_streamSource.vertices || m_vertexBuffer) && m_indexBuffer && !flagBuffer)
|
||||
{
|
||||
auto startIndex = loadIndices(firstIndexPtr, indexCount);
|
||||
if (startIndex >= 0)
|
||||
{
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = data.PrimitiveType;
|
||||
dp.BaseVertexIndex = data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride);
|
||||
dp.MinIndex = data.MinIndex;
|
||||
dp.NumVertices = data.NumVertices;
|
||||
dp.StartIndex = startIndex;
|
||||
dp.PrimitiveCount = data.PrimitiveCount;
|
||||
return m_origVtable.pfnDrawIndexedPrimitive(m_device, &dp);
|
||||
}
|
||||
startIndex = loadIndices(m_batched.indices.data(), m_batched.indices.size());
|
||||
}
|
||||
|
||||
return m_origVtable.pfnDrawIndexedPrimitive2(m_device, &data, 2, indices, flagBuffer);
|
||||
HRESULT result = S_OK;
|
||||
if (startIndex >= 0)
|
||||
{
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = data.PrimitiveType;
|
||||
dp.BaseVertexIndex = data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride);
|
||||
dp.MinIndex = data.MinIndex;
|
||||
dp.NumVertices = data.NumVertices;
|
||||
dp.StartIndex = startIndex;
|
||||
dp.PrimitiveCount = data.PrimitiveCount;
|
||||
result = m_origVtable.pfnDrawIndexedPrimitive(m_device, &dp);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_origVtable.pfnDrawIndexedPrimitive2(m_device, &data, 2, m_batched.indices.data(), flagBuffer);
|
||||
}
|
||||
|
||||
clearBatchedPrimitives();
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::flushPrimitives(const UINT* flagBuffer)
|
||||
{
|
||||
if (0 == m_batched.primitiveCount)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
return m_batched.indices.empty() ? flush(flagBuffer) : flushIndexed(flagBuffer);
|
||||
}
|
||||
|
||||
UINT DrawPrimitive::getBatchedVertexCount() const
|
||||
{
|
||||
return m_batched.vertices.size() / m_streamSource.stride;
|
||||
}
|
||||
|
||||
INT DrawPrimitive::loadIndices(const void* indices, UINT count)
|
||||
@ -167,40 +621,79 @@ namespace D3dDdi
|
||||
|
||||
INT DrawPrimitive::loadVertices(const void* vertices, UINT count)
|
||||
{
|
||||
UINT size = count * m_streamSource.stride;
|
||||
if (size > m_vertexBuffer.getSize())
|
||||
{
|
||||
m_vertexBuffer.resize((size + VERTEX_BUFFER_SIZE - 1) / VERTEX_BUFFER_SIZE * VERTEX_BUFFER_SIZE);
|
||||
if (m_vertexBuffer)
|
||||
{
|
||||
D3DDDIARG_SETSTREAMSOURCE ss = {};
|
||||
ss.hVertexBuffer = m_vertexBuffer;
|
||||
ss.Stride = m_streamSource.stride;
|
||||
m_origVtable.pfnSetStreamSource(m_device, &ss);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ONCE("WARN: Dynamic vertex buffer resize failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (m_vertexBuffer)
|
||||
{
|
||||
INT baseVertexIndex = m_vertexBuffer.load(vertices, count);
|
||||
if (baseVertexIndex >= 0)
|
||||
UINT size = count * m_streamSource.stride;
|
||||
if (size > m_vertexBuffer.getSize())
|
||||
{
|
||||
return baseVertexIndex;
|
||||
m_vertexBuffer.resize((size + VERTEX_BUFFER_SIZE - 1) / VERTEX_BUFFER_SIZE * VERTEX_BUFFER_SIZE);
|
||||
if (m_vertexBuffer)
|
||||
{
|
||||
D3DDDIARG_SETSTREAMSOURCE ss = {};
|
||||
ss.hVertexBuffer = m_vertexBuffer;
|
||||
ss.Stride = m_streamSource.stride;
|
||||
m_origVtable.pfnSetStreamSource(m_device, &ss);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ONCE("WARN: Dynamic vertex buffer resize failed");
|
||||
}
|
||||
}
|
||||
LOG_ONCE("WARN: Dynamic vertex buffer lock failed");
|
||||
|
||||
if (m_vertexBuffer)
|
||||
{
|
||||
INT baseVertexIndex = m_vertexBuffer.load(vertices, count);
|
||||
if (baseVertexIndex >= 0)
|
||||
{
|
||||
return baseVertexIndex;
|
||||
}
|
||||
LOG_ONCE("WARN: Dynamic vertex buffer lock failed");
|
||||
}
|
||||
|
||||
m_vertexBuffer.resize(0);
|
||||
m_indexBuffer.resize(0);
|
||||
}
|
||||
|
||||
D3DDDIARG_SETSTREAMSOURCEUM ss = {};
|
||||
ss.Stride = m_streamSource.stride;
|
||||
m_origVtable.pfnSetStreamSourceUm(m_device, &ss, m_streamSource.vertices);
|
||||
m_origVtable.pfnSetStreamSourceUm(m_device, &ss, vertices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_vertexBuffer.resize(0);
|
||||
m_indexBuffer.resize(0);
|
||||
return -1;
|
||||
void DrawPrimitive::rebaseIndices()
|
||||
{
|
||||
if (0 != m_batched.baseVertexIndex || m_batched.indices.empty())
|
||||
{
|
||||
if (m_batched.indices.empty())
|
||||
{
|
||||
auto vertexCount = getVertexCount(m_batched.primitiveType, m_batched.primitiveCount);
|
||||
appendIndexRangeWithoutRebase(m_batched.baseVertexIndex, vertexCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& index : m_batched.indices)
|
||||
{
|
||||
index = static_cast<UINT16>(m_batched.baseVertexIndex + index);
|
||||
}
|
||||
m_batched.minIndex += m_batched.baseVertexIndex;
|
||||
m_batched.maxIndex += m_batched.baseVertexIndex;
|
||||
}
|
||||
m_batched.baseVertexIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPrimitive::repeatLastBatchedVertex()
|
||||
{
|
||||
if (m_batched.indices.empty())
|
||||
{
|
||||
m_batched.vertices.reserve(m_batched.vertices.size() + m_streamSource.stride);
|
||||
m_batched.vertices.insert(m_batched.vertices.end(),
|
||||
m_batched.vertices.end() - m_streamSource.stride, m_batched.vertices.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_batched.indices.push_back(m_batched.indices.back());
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPrimitive::removeSysMemVertexBuffer(HANDLE resource)
|
||||
@ -216,6 +709,7 @@ namespace D3dDdi
|
||||
return setSysMemStreamSource(it->second.vertices, data.Stride, it->second.fvf);
|
||||
}
|
||||
|
||||
flushPrimitives();
|
||||
HRESULT result = m_origVtable.pfnSetStreamSource(m_device, &data);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
@ -232,9 +726,10 @@ namespace D3dDdi
|
||||
HRESULT DrawPrimitive::setSysMemStreamSource(const BYTE* vertices, UINT stride, UINT fvf)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (m_vertexBuffer)
|
||||
if (!m_streamSource.vertices || stride != m_streamSource.stride)
|
||||
{
|
||||
if (!m_streamSource.vertices || stride != m_streamSource.stride)
|
||||
flushPrimitives();
|
||||
if (m_vertexBuffer)
|
||||
{
|
||||
D3DDDIARG_SETSTREAMSOURCE ss = {};
|
||||
ss.hVertexBuffer = m_vertexBuffer;
|
||||
@ -246,12 +741,6 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (vertices != m_streamSource.vertices || stride != m_streamSource.stride)
|
||||
{
|
||||
D3DDDIARG_SETSTREAMSOURCEUM ss = {};
|
||||
ss.Stride = stride;
|
||||
result = m_origVtable.pfnSetStreamSourceUm(m_device, &ss, vertices);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
|
@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <d3d.h>
|
||||
@ -22,12 +20,25 @@ namespace D3dDdi
|
||||
void addSysMemVertexBuffer(HANDLE resource, BYTE* vertices, UINT fvf);
|
||||
void removeSysMemVertexBuffer(HANDLE resource);
|
||||
|
||||
HRESULT draw(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer);
|
||||
HRESULT drawIndexed(D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const void* indices, const UINT* flagBuffer);
|
||||
HRESULT flushPrimitives(const UINT* flagBuffer = nullptr);
|
||||
|
||||
HRESULT draw(D3DDDIARG_DRAWPRIMITIVE data, const UINT* flagBuffer);
|
||||
HRESULT drawIndexed(D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const UINT16* indices, const UINT* flagBuffer);
|
||||
HRESULT setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& data);
|
||||
HRESULT setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer);
|
||||
|
||||
private:
|
||||
struct BatchedPrimitives
|
||||
{
|
||||
D3DPRIMITIVETYPE primitiveType;
|
||||
UINT primitiveCount;
|
||||
INT baseVertexIndex;
|
||||
UINT minIndex;
|
||||
UINT maxIndex;
|
||||
std::vector<BYTE> vertices;
|
||||
std::vector<UINT16> indices;
|
||||
};
|
||||
|
||||
struct StreamSource
|
||||
{
|
||||
const BYTE* vertices;
|
||||
@ -41,8 +52,38 @@ namespace D3dDdi
|
||||
UINT fvf;
|
||||
};
|
||||
|
||||
void appendIndexedVertices(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex);
|
||||
void appendIndexedVerticesWithoutRebase(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex);
|
||||
void appendIndexRange(UINT base, UINT count);
|
||||
void appendIndexRangeWithoutRebase(UINT base, UINT count);
|
||||
void appendIndices(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex);
|
||||
void appendIndicesAndVertices(const UINT16* indices, UINT count,
|
||||
INT baseVertexIndex, UINT minIndex, UINT maxIndex);
|
||||
void appendLineOrTriangleList(INT baseVertexIndex, UINT primitiveCount, UINT vpp,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex);
|
||||
bool appendPrimitives(D3DPRIMITIVETYPE primitiveType, INT baseVertexIndex, UINT primitiveCount,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex);
|
||||
void appendTriangleFan(INT baseVertexIndex, UINT primitiveCount,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex);
|
||||
void appendTriangleStrip(INT baseVertexIndex, UINT primitiveCount,
|
||||
const UINT16* indices, UINT minIndex, UINT maxIndex);
|
||||
void appendVertices(UINT base, UINT count);
|
||||
void clearBatchedPrimitives();
|
||||
void convertIndexedTriangleFanToList(UINT startPrimitive, UINT primitiveCount);
|
||||
void convertIndexedTriangleStripToList(UINT startPrimitive, UINT primitiveCount);
|
||||
void convertToTriangleList();
|
||||
void fixFirstVertexRhw();
|
||||
HRESULT flush(const UINT* flagBuffer);
|
||||
HRESULT flushIndexed(const UINT* flagBuffer);
|
||||
INT loadIndices(const void* indices, UINT count);
|
||||
INT loadVertices(const void* vertices, UINT count);
|
||||
UINT getBatchedVertexCount() const;
|
||||
void rebaseIndices();
|
||||
void repeatLastBatchedVertex();
|
||||
|
||||
HRESULT setSysMemStreamSource(const BYTE* vertices, UINT stride, UINT fvf);
|
||||
|
||||
HANDLE m_device;
|
||||
@ -51,5 +92,6 @@ namespace D3dDdi
|
||||
DynamicIndexBuffer m_indexBuffer;
|
||||
StreamSource m_streamSource;
|
||||
std::map<HANDLE, SysMemVertexBuffer> m_sysMemVertexBuffers;
|
||||
BatchedPrimitives m_batched;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user