Commit b5f925ca authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Implement half float vertex buffer conversion.

parent 6598589e
......@@ -277,6 +277,8 @@ static void CreateVBO(IWineD3DVertexBufferImpl *object) {
WARN("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error);
goto error;
}
object->vbo_size = object->resource.size;
object->vbo_usage = glUsage;
LEAVE_GL();
......
......@@ -201,10 +201,6 @@ void primitiveDeclarationConvertToStridedData(
if((UINT_PTR)data < -This->stateBlock->loadBaseVertexIndex * stride) {
FIXME("System memory vertex data load offset is negative!\n");
}
} else if(vertexDeclaration->half_float_conv_needed) {
WARN("Half float vertex data used, but GL_NV_half_float is not supported. Not using vbos\n");
streamVBO = 0;
data = ((IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[element->Stream])->resource.allocatedMemory;
}
if(fixup) {
......@@ -574,24 +570,6 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
checkGLcall("glEnd and previous calls");
}
/* See GL_NV_half_float for reference */
static inline float float_16_to_32(const unsigned short *in) {
const unsigned short s = ((*in) & 0x8000);
const unsigned short e = ((*in) & 0x7C00) >> 10;
const unsigned short m = (*in) & 0x3FF;
const float sgn = (s ? -1.0 : 1.0);
if(e == 0) {
if(m == 0) return sgn * 0.0; /* +0.0 or -0.0 */
else return sgn * pow(2, -14.0) * ( (float) m / 1024.0);
} else if(e < 31) {
return sgn * pow(2, (float) e-15.0) * (1.0 + ((float) m / 1024.0));
} else {
if(m == 0) return sgn / 0.0; /* +INF / -INF */
else return 0.0 / 0.0; /* NAN */
}
}
static inline void send_attribute(IWineD3DDeviceImpl *This, const DWORD type, const UINT index, const void *ptr) {
switch(type) {
case WINED3DDECLTYPE_FLOAT1:
......@@ -1103,19 +1081,21 @@ void drawPrimitive(IWineD3DDevice *iface,
if (This->useDrawStridedSlow || emulation) {
/* Immediate mode drawing */
drawStridedSlow(iface, strided, calculatedNumberOfindices,
glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
if(use_vs(This)) {
FIXME("Using immediate mode with vertex shaders for half float emulation\n");
drawStridedSlowVs(iface, strided, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
} else {
drawStridedSlow(iface, strided, calculatedNumberOfindices,
glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
}
} else if(This->instancedDraw) {
/* Instancing emulation with mixing immediate mode and arrays */
drawStridedInstanced(iface, &This->strided_streams, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
} else if(!((IWineD3DVertexDeclarationImpl *) This->stateBlock->vertexDecl)->half_float_conv_needed) {
} else {
drawStridedFast(iface, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
} else {
FIXME("Using immediate mode with vertex shaders for half float emulation\n");
drawStridedSlowVs(iface, strided, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
}
}
......
......@@ -2880,15 +2880,11 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi
GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
int i;
UINT *offset = stateblock->streamOffset;
IWineD3DVertexBufferImpl *vb;
/* Default to no instancing */
stateblock->wineD3DDevice->instancedDraw = FALSE;
if(((IWineD3DVertexDeclarationImpl *)stateblock->vertexDecl)->half_float_conv_needed) {
/* This will be handled using drawStridedSlow */
return;
}
for (i = 0; i < MAX_ATTRIBS; i++) {
if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
......@@ -2909,12 +2905,37 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi
checkGLcall("glBindBufferARB");
curVBO = strided->u.input[i].VBO;
}
GL_EXTCALL(glVertexAttribPointerARB(i,
WINED3D_ATR_SIZE(strided->u.input[i].dwType),
WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
strided->u.input[i].dwStride,
strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
/* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
* user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
* vbo we won't be load converted attributes anyway
*/
if(curVBO && vb->conv_shift) {
TRACE("Loading attribute from shifted buffer\n");
TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
GL_EXTCALL(glVertexAttribPointerARB(i,
WINED3D_ATR_SIZE(strided->u.input[i].dwType),
WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
vb->conv_stride,
strided->u.input[i].lpData + vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData] +
stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
offset[strided->u.input[i].streamNo]));
} else {
GL_EXTCALL(glVertexAttribPointerARB(i,
WINED3D_ATR_SIZE(strided->u.input[i].dwType),
WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
strided->u.input[i].dwStride,
strided->u.input[i].lpData +
stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
offset[strided->u.input[i].streamNo]) );
}
GL_EXTCALL(glEnableVertexAttribArrayARB(i));
} else {
/* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
......@@ -2922,7 +2943,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi
*/
BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
if(strided->u.input[i].VBO) {
IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
ptr += (long) vb->resource.allocatedMemory;
}
GL_EXTCALL(glDisableVertexAttribArrayARB(i));
......@@ -3360,10 +3381,16 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer
}
if(useVertexShaderFunction) {
TRACE("Loading numbered arrays\n");
loadNumberedArrays(stateblock, dataLocations);
device->useDrawStridedSlow = FALSE;
context->numberedArraysLoaded = TRUE;
if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
device->useDrawStridedSlow = TRUE;
context->numberedArraysLoaded = FALSE;
} else {
TRACE("Loading numbered arrays\n");
loadNumberedArrays(stateblock, dataLocations);
device->useDrawStridedSlow = FALSE;
context->numberedArraysLoaded = TRUE;
}
} else if (fixup ||
(dataLocations->u.s.pSize.lpData == NULL &&
dataLocations->u.s.diffuse.lpData == NULL &&
......
......@@ -121,6 +121,24 @@ void init_type_lookup(WineD3D_GL_Info *gl_info);
#define WINED3D_ATR_NORMALIZED(type) GLINFO_LOCATION.glTypeLookup[type].normalized
#define WINED3D_ATR_TYPESIZE(type) GLINFO_LOCATION.glTypeLookup[type].typesize
/* See GL_NV_half_float for reference */
static inline float float_16_to_32(const unsigned short *in) {
const unsigned short s = ((*in) & 0x8000);
const unsigned short e = ((*in) & 0x7C00) >> 10;
const unsigned short m = (*in) & 0x3FF;
const float sgn = (s ? -1.0 : 1.0);
if(e == 0) {
if(m == 0) return sgn * 0.0; /* +0.0 or -0.0 */
else return sgn * pow(2, -14.0) * ( (float) m / 1024.0);
} else if(e < 31) {
return sgn * pow(2, (float) e-15.0) * (1.0 + ((float) m / 1024.0));
} else {
if(m == 0) return sgn / 0.0; /* +INF / -INF */
else return 0.0 / 0.0; /* NAN */
}
}
/**
* Settings
*/
......@@ -826,6 +844,8 @@ typedef struct IWineD3DVertexBufferImpl
GLuint vbo;
BYTE Flags;
LONG bindCount;
LONG vbo_size;
GLenum vbo_usage;
UINT dirtystart, dirtyend;
LONG lockcount;
......@@ -835,6 +855,10 @@ typedef struct IWineD3DVertexBufferImpl
WineDirect3DVertexStridedData strided;
BOOL last_was_vshader;
BOOL last_was_converted;
/* Extra load offsets, for FLOAT16 conversion */
DWORD *conv_shift;
DWORD conv_stride;
} IWineD3DVertexBufferImpl;
extern const IWineD3DVertexBufferVtbl IWineD3DVertexBuffer_Vtbl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment