mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Improved rendering performance for indexed and system memory primitives
This commit is contained in:
parent
ca9404ec6f
commit
bff7253ecd
@ -2,11 +2,11 @@
|
||||
#include <winternl.h>
|
||||
#include <../km/d3dkmthk.h>
|
||||
|
||||
#include "Common/HResultException.h"
|
||||
#include "D3dDdi/Adapter.h"
|
||||
#include "D3dDdi/Device.h"
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/Resource.h"
|
||||
#include <Common/HResultException.h>
|
||||
#include <D3dDdi/Adapter.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/DeviceFuncs.h>
|
||||
#include <D3dDdi/Resource.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -24,8 +24,7 @@ namespace D3dDdi
|
||||
, m_renderTarget(nullptr)
|
||||
, m_renderTargetSubResourceIndex(0)
|
||||
, m_sharedPrimary(nullptr)
|
||||
, m_streamSourceData{}
|
||||
, m_streamSource(nullptr)
|
||||
, m_drawPrimitive(*this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -66,6 +65,13 @@ namespace D3dDdi
|
||||
{
|
||||
Resource resource(*this, data);
|
||||
m_resources.emplace(resource, std::move(resource));
|
||||
if (data.Flags.VertexBuffer &&
|
||||
D3DDDIPOOL_SYSTEMMEM == data.Pool &&
|
||||
data.pSurfList[0].pSysMem)
|
||||
{
|
||||
m_drawPrimitive.addSysMemVertexBuffer(data.hResource,
|
||||
static_cast<BYTE*>(const_cast<void*>(data.pSurfList[0].pSysMem)), data.Fvf);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
catch (const HResultException& e)
|
||||
@ -115,57 +121,27 @@ namespace D3dDdi
|
||||
g_gdiResourceHandle = nullptr;
|
||||
g_gdiResource = nullptr;
|
||||
}
|
||||
if (resource == m_streamSource)
|
||||
{
|
||||
m_streamSource = nullptr;
|
||||
}
|
||||
m_drawPrimitive.removeSysMemVertexBuffer(resource);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT Device::drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE* data)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable.pfnDrawIndexedPrimitive(m_device, data);
|
||||
}
|
||||
|
||||
HRESULT Device::drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2* data,
|
||||
UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer)
|
||||
{
|
||||
if (2 != indicesSize)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
prepareForRendering();
|
||||
return m_origVtable.pfnDrawIndexedPrimitive2(m_device, data, indicesSize, indexBuffer, flagBuffer);
|
||||
return m_drawPrimitive.drawIndexed(*data, indexBuffer, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE* data, const UINT* flagBuffer)
|
||||
{
|
||||
if (m_streamSource && 0 != m_streamSourceData.Stride)
|
||||
{
|
||||
m_streamSource->fixVertexData(m_streamSourceData.Offset + data->VStart * m_streamSourceData.Stride,
|
||||
data->PrimitiveCount, m_streamSourceData.Stride);
|
||||
}
|
||||
prepareForRendering();
|
||||
return m_origVtable.pfnDrawPrimitive(m_device, data, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2* data)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable.pfnDrawPrimitive2(m_device, data);
|
||||
}
|
||||
|
||||
HRESULT Device::drawRectPatch(const D3DDDIARG_DRAWRECTPATCH* data, const D3DDDIRECTPATCH_INFO* info,
|
||||
const FLOAT* patch)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable.pfnDrawRectPatch(m_device, data, info, patch);
|
||||
}
|
||||
|
||||
HRESULT Device::drawTriPatch(const D3DDDIARG_DRAWTRIPATCH* data, const D3DDDITRIPATCH_INFO* info,
|
||||
const FLOAT* patch)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable.pfnDrawTriPatch(m_device, data, info, patch);
|
||||
return m_drawPrimitive.draw(*data, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::flush()
|
||||
@ -234,24 +210,12 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Device::setStreamSource(const D3DDDIARG_SETSTREAMSOURCE* data)
|
||||
{
|
||||
HRESULT result = m_origVtable.pfnSetStreamSource(m_device, data);
|
||||
if (SUCCEEDED(result) && 0 == data->Stream)
|
||||
{
|
||||
m_streamSourceData = *data;
|
||||
m_streamSource = getResource(data->hVertexBuffer);
|
||||
}
|
||||
return result;
|
||||
return m_drawPrimitive.setStreamSource(*data);
|
||||
}
|
||||
|
||||
HRESULT Device::setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM* data, const void* umBuffer)
|
||||
{
|
||||
HRESULT result = m_origVtable.pfnSetStreamSourceUm(m_device, data, umBuffer);
|
||||
if (SUCCEEDED(result) && 0 == data->Stream)
|
||||
{
|
||||
m_streamSourceData = {};
|
||||
m_streamSource = nullptr;
|
||||
}
|
||||
return result;
|
||||
return m_drawPrimitive.setStreamSourceUm(*data, umBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::unlock(const D3DDDIARG_UNLOCK* data)
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <d3dnthal.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
#include <D3dDdi/DrawPrimitive.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class Adapter;
|
||||
@ -23,15 +25,9 @@ namespace D3dDdi
|
||||
HRESULT createResource(D3DDDIARG_CREATERESOURCE* data);
|
||||
HRESULT createResource2(D3DDDIARG_CREATERESOURCE2* data);
|
||||
HRESULT destroyResource(HANDLE resource);
|
||||
HRESULT drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE* data);
|
||||
HRESULT drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2* data,
|
||||
UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer);
|
||||
HRESULT drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE* data, const UINT* flagBuffer);
|
||||
HRESULT drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2* data);
|
||||
HRESULT drawRectPatch(const D3DDDIARG_DRAWRECTPATCH* data, const D3DDDIRECTPATCH_INFO* info,
|
||||
const FLOAT* patch);
|
||||
HRESULT drawTriPatch(const D3DDDIARG_DRAWTRIPATCH* data, const D3DDDITRIPATCH_INFO* info,
|
||||
const FLOAT* patch);
|
||||
HRESULT flush();
|
||||
HRESULT flush1(UINT FlushFlags);
|
||||
HRESULT lock(D3DDDIARG_LOCK* data);
|
||||
@ -74,8 +70,7 @@ namespace D3dDdi
|
||||
Resource* m_renderTarget;
|
||||
UINT m_renderTargetSubResourceIndex;
|
||||
HANDLE m_sharedPrimary;
|
||||
D3DDDIARG_SETSTREAMSOURCE m_streamSourceData;
|
||||
Resource* m_streamSource;
|
||||
DrawPrimitive m_drawPrimitive;
|
||||
|
||||
static std::map<HANDLE, Device> s_devices;
|
||||
static bool s_isFlushEnabled;
|
||||
|
@ -11,12 +11,8 @@ namespace
|
||||
|
||||
HRESULT APIENTRY destroyDevice(HANDLE hDevice)
|
||||
{
|
||||
HRESULT result = D3dDdi::DeviceFuncs::s_origVtablePtr->pfnDestroyDevice(hDevice);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
D3dDdi::Device::remove(hDevice);
|
||||
}
|
||||
return result;
|
||||
D3dDdi::Device::remove(hDevice);
|
||||
return D3dDdi::DeviceFuncs::s_origVtablePtr->pfnDestroyDevice(hDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,12 +34,8 @@ namespace D3dDdi
|
||||
vtable.pfnCreateResource2 = &DEVICE_FUNC(createResource2);
|
||||
vtable.pfnDestroyDevice = &destroyDevice;
|
||||
vtable.pfnDestroyResource = &DEVICE_FUNC(destroyResource);
|
||||
vtable.pfnDrawIndexedPrimitive = &DEVICE_FUNC(drawIndexedPrimitive);
|
||||
vtable.pfnDrawIndexedPrimitive2 = &DEVICE_FUNC(drawIndexedPrimitive2);
|
||||
vtable.pfnDrawPrimitive = &DEVICE_FUNC(drawPrimitive);
|
||||
vtable.pfnDrawPrimitive2 = &DEVICE_FUNC(drawPrimitive2);
|
||||
vtable.pfnDrawRectPatch = &DEVICE_FUNC(drawRectPatch);
|
||||
vtable.pfnDrawTriPatch = &DEVICE_FUNC(drawTriPatch);
|
||||
vtable.pfnFlush = &DEVICE_FUNC(flush);
|
||||
vtable.pfnFlush1 = &DEVICE_FUNC(flush1);
|
||||
vtable.pfnLock = &DEVICE_FUNC(lock);
|
||||
|
329
DDrawCompat/D3dDdi/DrawPrimitive.cpp
Normal file
329
DDrawCompat/D3dDdi/DrawPrimitive.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include <D3dDdi/DrawPrimitive.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/Resource.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class VertexRhwFixer
|
||||
{
|
||||
public:
|
||||
VertexRhwFixer(D3DTLVERTEX* vertex)
|
||||
{
|
||||
if (vertex && 0.0f == vertex->rhw)
|
||||
{
|
||||
vertex->rhw = 1.0f;
|
||||
m_vertex = vertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VertexRhwFixer(void* vertex)
|
||||
: VertexRhwFixer(static_cast<D3DTLVERTEX*>(vertex))
|
||||
{
|
||||
}
|
||||
|
||||
~VertexRhwFixer()
|
||||
{
|
||||
if (m_vertex)
|
||||
{
|
||||
m_vertex->rhw = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
D3DTLVERTEX* m_vertex;
|
||||
};
|
||||
|
||||
UINT getVertexCount(D3DPRIMITIVETYPE primitiveType, UINT primitiveCount)
|
||||
{
|
||||
switch (primitiveType)
|
||||
{
|
||||
case D3DPT_POINTLIST:
|
||||
return primitiveCount;
|
||||
case D3DPT_LINELIST:
|
||||
return primitiveCount * 2;
|
||||
case D3DPT_LINESTRIP:
|
||||
return primitiveCount + 1;
|
||||
case D3DPT_TRIANGLELIST:
|
||||
return primitiveCount * 3;
|
||||
case D3DPT_TRIANGLESTRIP:
|
||||
case D3DPT_TRIANGLEFAN:
|
||||
return primitiveCount + 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT roundUpToNearestMultiple(UINT num, UINT mul)
|
||||
{
|
||||
return (num + mul - 1) / mul * mul;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
DrawPrimitive::Buffer::Buffer(HANDLE device, const D3DDDI_DEVICEFUNCS& origVtable, D3DDDIFORMAT format, UINT size)
|
||||
: m_device(device)
|
||||
, m_origVtable(origVtable)
|
||||
, m_resource(nullptr, [=](HANDLE vb) { origVtable.pfnDestroyResource(device, vb); })
|
||||
, m_format(format)
|
||||
, m_initialSize(size)
|
||||
, m_size(0)
|
||||
, m_stride(0)
|
||||
, m_pos(0)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
HANDLE DrawPrimitive::Buffer::getHandle() const
|
||||
{
|
||||
return m_resource.get();
|
||||
}
|
||||
|
||||
void* DrawPrimitive::Buffer::lock(UINT size)
|
||||
{
|
||||
D3DDDIARG_LOCK lock = {};
|
||||
lock.hResource = m_resource.get();
|
||||
lock.Range.Offset = m_pos;
|
||||
lock.Range.Size = size;
|
||||
lock.Flags.RangeValid = 1;
|
||||
|
||||
if (0 == m_pos)
|
||||
{
|
||||
lock.Flags.Discard = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lock.Flags.WriteOnly = 1;
|
||||
lock.Flags.NoOverwrite = 1;
|
||||
}
|
||||
|
||||
m_origVtable.pfnLock(m_device, &lock);
|
||||
return lock.pSurfData;
|
||||
}
|
||||
|
||||
UINT DrawPrimitive::Buffer::load(const void* src, UINT count, UINT stride)
|
||||
{
|
||||
if (stride != m_stride)
|
||||
{
|
||||
m_stride = stride;
|
||||
m_pos = roundUpToNearestMultiple(m_pos, stride);
|
||||
}
|
||||
|
||||
UINT size = count * m_stride;
|
||||
if (m_pos + size > m_size)
|
||||
{
|
||||
m_pos = 0;
|
||||
if (size > m_size)
|
||||
{
|
||||
if (!resize(roundUpToNearestMultiple(size, m_initialSize)))
|
||||
{
|
||||
return UINT_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto dst = lock(size);
|
||||
if (!dst)
|
||||
{
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
memcpy(dst, src, size);
|
||||
unlock();
|
||||
|
||||
UINT pos = m_pos;
|
||||
m_pos += size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool DrawPrimitive::Buffer::resize(UINT size)
|
||||
{
|
||||
if (0 == size)
|
||||
{
|
||||
m_resource.reset();
|
||||
m_size = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
D3DDDI_SURFACEINFO surfaceInfo = {};
|
||||
surfaceInfo.Width = size;
|
||||
surfaceInfo.Height = 1;
|
||||
|
||||
D3DDDIARG_CREATERESOURCE2 cr = {};
|
||||
cr.Format = m_format;
|
||||
cr.Pool = D3DDDIPOOL_VIDEOMEMORY;
|
||||
cr.pSurfList = &surfaceInfo;
|
||||
cr.SurfCount = 1;
|
||||
cr.Flags.Dynamic = 1;
|
||||
cr.Flags.WriteOnly = 1;
|
||||
if (D3DDDIFMT_VERTEXDATA == m_format)
|
||||
{
|
||||
cr.Flags.VertexBuffer = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cr.Flags.IndexBuffer = 1;
|
||||
}
|
||||
|
||||
if (FAILED(m_origVtable.pfnCreateResource2
|
||||
? m_origVtable.pfnCreateResource2(m_device, &cr)
|
||||
: m_origVtable.pfnCreateResource(m_device, reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&cr))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_resource.reset(cr.hResource);
|
||||
m_size = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawPrimitive::Buffer::unlock()
|
||||
{
|
||||
D3DDDIARG_UNLOCK unlock = {};
|
||||
unlock.hResource = m_resource.get();
|
||||
m_origVtable.pfnUnlock(m_device, &unlock);
|
||||
}
|
||||
|
||||
DrawPrimitive::DrawPrimitive(Device& device)
|
||||
: m_device(device)
|
||||
, m_origVtable(device.getOrigVtable())
|
||||
, m_vertexBuffer(m_device, m_origVtable, D3DDDIFMT_VERTEXDATA, 1024 * 1024)
|
||||
, m_indexBuffer(m_device, m_origVtable, D3DDDIFMT_INDEX16, 256 * 1024)
|
||||
, m_streamSource{}
|
||||
{
|
||||
if (m_indexBuffer.getHandle())
|
||||
{
|
||||
D3DDDIARG_SETINDICES si = {};
|
||||
si.hIndexBuffer = m_indexBuffer.getHandle();
|
||||
si.Stride = 2;
|
||||
m_origVtable.pfnSetIndices(m_device, &si);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPrimitive::addSysMemVertexBuffer(HANDLE resource, BYTE* vertices, UINT fvf)
|
||||
{
|
||||
m_sysMemVertexBuffers[resource] = { vertices, fvf };
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::draw(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer)
|
||||
{
|
||||
auto firstVertexPtr = m_streamSource.vertices + data.VStart * m_streamSource.stride;
|
||||
VertexRhwFixer fixer((m_streamSource.fvf & D3DFVF_XYZRHW) ? firstVertexPtr : nullptr);
|
||||
|
||||
if (m_streamSource.vertices && m_vertexBuffer.getHandle())
|
||||
{
|
||||
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
|
||||
auto vbOffset = m_vertexBuffer.load(firstVertexPtr, vertexCount, m_streamSource.stride);
|
||||
if (UINT_MAX == vbOffset)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
D3DDDIARG_DRAWPRIMITIVE dp = data;
|
||||
dp.VStart = vbOffset / m_streamSource.stride;
|
||||
return m_origVtable.pfnDrawPrimitive(m_device, &dp, flagBuffer);
|
||||
}
|
||||
|
||||
return m_origVtable.pfnDrawPrimitive(m_device, &data, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::drawIndexed(
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const void* 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);
|
||||
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.getHandle())
|
||||
{
|
||||
data.BaseVertexOffset = m_vertexBuffer.load(firstVertexPtr, data.NumVertices, m_streamSource.stride);
|
||||
if (UINT_MAX == data.BaseVertexOffset)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
data.BaseVertexOffset -= data.MinIndex * m_streamSource.stride;
|
||||
}
|
||||
|
||||
if (m_indexBuffer.getHandle() && !flagBuffer)
|
||||
{
|
||||
D3DDDIARG_DRAWINDEXEDPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = data.PrimitiveType;
|
||||
dp.BaseVertexIndex = data.BaseVertexOffset / m_streamSource.stride;
|
||||
dp.MinIndex = data.MinIndex;
|
||||
dp.NumVertices = data.NumVertices;
|
||||
dp.StartIndex = m_indexBuffer.load(firstIndexPtr, indexCount, 2) / 2;
|
||||
dp.PrimitiveCount = data.PrimitiveCount;
|
||||
return m_origVtable.pfnDrawIndexedPrimitive(m_device, &dp);
|
||||
}
|
||||
|
||||
return m_origVtable.pfnDrawIndexedPrimitive2(m_device, &data, 2, indices, flagBuffer);
|
||||
}
|
||||
|
||||
void DrawPrimitive::removeSysMemVertexBuffer(HANDLE resource)
|
||||
{
|
||||
m_sysMemVertexBuffers.erase(resource);
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::setStreamSource(BYTE* vertices, UINT stride, UINT fvf)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (m_vertexBuffer.getHandle())
|
||||
{
|
||||
if (!m_streamSource.vertices || stride != m_streamSource.stride)
|
||||
{
|
||||
D3DDDIARG_SETSTREAMSOURCE ss = {};
|
||||
ss.hVertexBuffer = m_vertexBuffer.getHandle();
|
||||
ss.Stride = stride;
|
||||
result = m_origVtable.pfnSetStreamSource(m_device, &ss);
|
||||
}
|
||||
}
|
||||
else if (vertices != m_streamSource.vertices || stride != m_streamSource.stride)
|
||||
{
|
||||
D3DDDIARG_SETSTREAMSOURCEUM ss = {};
|
||||
ss.Stride = stride;
|
||||
result = m_origVtable.pfnSetStreamSourceUm(m_device, &ss, vertices);
|
||||
}
|
||||
|
||||
m_streamSource.vertices = vertices;
|
||||
m_streamSource.stride = stride;
|
||||
m_streamSource.fvf = fvf;
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& data)
|
||||
{
|
||||
if (0 != data.Stride)
|
||||
{
|
||||
auto it = m_sysMemVertexBuffers.find(data.hVertexBuffer);
|
||||
if (it != m_sysMemVertexBuffers.end())
|
||||
{
|
||||
return setStreamSource(it->second.vertices + data.Offset, data.Stride, it->second.fvf);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT result = m_origVtable.pfnSetStreamSource(m_device, &data);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
m_streamSource = {};
|
||||
m_streamSource.stride = data.Stride;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT DrawPrimitive::setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer)
|
||||
{
|
||||
return setStreamSource(static_cast<BYTE*>(const_cast<void*>(umBuffer)), data.Stride, 0);
|
||||
}
|
||||
}
|
74
DDrawCompat/D3dDdi/DrawPrimitive.h
Normal file
74
DDrawCompat/D3dDdi/DrawPrimitive.h
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <d3d.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class Device;
|
||||
|
||||
class DrawPrimitive
|
||||
{
|
||||
public:
|
||||
DrawPrimitive(Device& device);
|
||||
|
||||
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 setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& data);
|
||||
HRESULT setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer);
|
||||
|
||||
private:
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer(HANDLE device, const D3DDDI_DEVICEFUNCS& origVtable, D3DDDIFORMAT format, UINT size);
|
||||
|
||||
HANDLE getHandle() const;
|
||||
UINT load(const void* src, UINT count, UINT stride);
|
||||
|
||||
private:
|
||||
void* lock(UINT size);
|
||||
bool resize(UINT size);
|
||||
void unlock();
|
||||
|
||||
HANDLE m_device = nullptr;
|
||||
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
||||
std::unique_ptr<void, std::function<void(HANDLE)>> m_resource;
|
||||
D3DDDIFORMAT m_format;
|
||||
UINT m_initialSize;
|
||||
UINT m_size;
|
||||
UINT m_stride;
|
||||
UINT m_pos;
|
||||
};
|
||||
|
||||
struct StreamSource
|
||||
{
|
||||
BYTE* vertices;
|
||||
UINT stride;
|
||||
UINT fvf;
|
||||
};
|
||||
|
||||
struct SysMemVertexBuffer
|
||||
{
|
||||
BYTE* vertices;
|
||||
UINT fvf;
|
||||
};
|
||||
|
||||
HRESULT setStreamSource(BYTE* vertices, UINT stride, UINT fvf);
|
||||
|
||||
HANDLE m_device;
|
||||
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
||||
Buffer m_vertexBuffer;
|
||||
Buffer m_indexBuffer;
|
||||
StreamSource m_streamSource;
|
||||
std::map<HANDLE, SysMemVertexBuffer> m_sysMemVertexBuffers;
|
||||
};
|
||||
}
|
@ -143,15 +143,6 @@ namespace D3dDdi
|
||||
, m_lockBuffer(nullptr, &heapFree)
|
||||
, m_lockResource(nullptr, ResourceDeleter(device))
|
||||
{
|
||||
if (D3DDDIFMT_VERTEXDATA == data.Format &&
|
||||
data.Flags.VertexBuffer &&
|
||||
data.Flags.MightDrawFromLocked &&
|
||||
D3DDDIPOOL_SYSTEMMEM != data.Pool)
|
||||
{
|
||||
const HRESULT D3DERR_NOTAVAILABLE = 0x8876086A;
|
||||
throw HResultException(D3DERR_NOTAVAILABLE);
|
||||
}
|
||||
|
||||
fixResourceData(device, reinterpret_cast<D3DDDIARG_CREATERESOURCE&>(m_fixedData));
|
||||
m_formatInfo = getFormatInfo(m_fixedData.Format);
|
||||
|
||||
@ -477,31 +468,6 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::fixVertexData(UINT offset, UINT count, UINT stride)
|
||||
{
|
||||
if (!m_fixedData.Flags.MightDrawFromLocked ||
|
||||
!m_fixedData.pSurfList[0].pSysMem ||
|
||||
!(m_fixedData.Fvf & D3DFVF_XYZRHW))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char* data = static_cast<unsigned char*>(const_cast<void*>(m_fixedData.pSurfList[0].pSysMem)) + offset;
|
||||
if (0.0f != reinterpret_cast<D3DTLVERTEX*>(data)->rhw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < count; ++i)
|
||||
{
|
||||
if (0.0f == reinterpret_cast<D3DTLVERTEX*>(data)->rhw)
|
||||
{
|
||||
reinterpret_cast<D3DTLVERTEX*>(data)->rhw = 1.0f;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void* Resource::getLockPtr(UINT subResourceIndex)
|
||||
{
|
||||
return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <d3d.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
#include "D3dDdi/FormatInfo.h"
|
||||
#include <D3dDdi/FormatInfo.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
@ -30,7 +30,6 @@ namespace D3dDdi
|
||||
HRESULT blt(D3DDDIARG_BLT data);
|
||||
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
||||
void endGdiAccess(bool isReadOnly);
|
||||
void fixVertexData(UINT offset, UINT count, UINT stride);
|
||||
void* getLockPtr(UINT subResourceIndex);
|
||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||
void prepareForRendering(UINT subResourceIndex, bool isReadOnly);
|
||||
|
@ -154,6 +154,7 @@
|
||||
<ClInclude Include="D3dDdi\Device.h" />
|
||||
<ClInclude Include="D3dDdi\DeviceCallbacks.h" />
|
||||
<ClInclude Include="D3dDdi\DeviceFuncs.h" />
|
||||
<ClInclude Include="D3dDdi\DrawPrimitive.h" />
|
||||
<ClInclude Include="D3dDdi\FormatInfo.h" />
|
||||
<ClInclude Include="D3dDdi\Hooks.h" />
|
||||
<ClInclude Include="D3dDdi\KernelModeThunks.h" />
|
||||
@ -243,6 +244,7 @@
|
||||
<ClCompile Include="D3dDdi\Device.cpp" />
|
||||
<ClCompile Include="D3dDdi\DeviceCallbacks.cpp" />
|
||||
<ClCompile Include="D3dDdi\DeviceFuncs.cpp" />
|
||||
<ClCompile Include="D3dDdi\DrawPrimitive.cpp" />
|
||||
<ClCompile Include="D3dDdi\FormatInfo.cpp" />
|
||||
<ClCompile Include="D3dDdi\Hooks.cpp" />
|
||||
<ClCompile Include="D3dDdi\KernelModeThunks.cpp" />
|
||||
|
@ -387,6 +387,9 @@
|
||||
<ClInclude Include="D3dDdi\Log\CommonLog.h">
|
||||
<Filter>Header Files\D3dDdi\Log</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\DrawPrimitive.h">
|
||||
<Filter>Header Files\D3dDdi</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -593,5 +596,8 @@
|
||||
<ClCompile Include="D3dDdi\Log\CommonLog.cpp">
|
||||
<Filter>Source Files\D3dDdi\Log</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3dDdi\DrawPrimitive.cpp">
|
||||
<Filter>Source Files\D3dDdi</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user