Commit 80177879 by Jamie Madill

Move D3D9 vertex format tables to formatutils9.

Vertex format information is useful for querying format properties with the new vertex translation logic with dynamic shaders. Change-Id: I1935c75f1e3920dc1d4a364a2d6968c82692e476 Reviewed-on: https://chromium-review.googlesource.com/184520Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarNicolas Capens <nicolascapens@chromium.org>
parent 7ab02faf
...@@ -33,7 +33,6 @@ typedef void (*ColorCopyFunction)(const void *source, void *dest); ...@@ -33,7 +33,6 @@ typedef void (*ColorCopyFunction)(const void *source, void *dest);
typedef void (*VertexCopyFunction)(const void *input, size_t stride, size_t count, void *output); typedef void (*VertexCopyFunction)(const void *input, size_t stride, size_t count, void *output);
namespace rx namespace rx
{ {
......
...@@ -490,6 +490,8 @@ EGLint Renderer9::initialize() ...@@ -490,6 +490,8 @@ EGLint Renderer9::initialize()
initializeDevice(); initializeDevice();
d3d9::InitializeVertexTranslations(this);
return EGL_SUCCESS; return EGL_SUCCESS;
} }
......
...@@ -12,26 +12,18 @@ ...@@ -12,26 +12,18 @@
#include "libGLESv2/renderer/BufferStorage.h" #include "libGLESv2/renderer/BufferStorage.h"
#include "libGLESv2/VertexAttribute.h" #include "libGLESv2/VertexAttribute.h"
#include "libGLESv2/renderer/d3d9/Renderer9.h" #include "libGLESv2/renderer/d3d9/Renderer9.h"
#include "libGLESv2/renderer/d3d9/formatutils9.h"
#include "libGLESv2/Buffer.h" #include "libGLESv2/Buffer.h"
namespace rx namespace rx
{ {
bool VertexBuffer9::mTranslationsInitialized = false;
VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
{ {
mVertexBuffer = NULL; mVertexBuffer = NULL;
mBufferSize = 0; mBufferSize = 0;
mDynamicUsage = false; mDynamicUsage = false;
if (!mTranslationsInitialized)
{
initializeTranslations(renderer->getCapsDeclTypes());
mTranslationsInitialized = true;
}
} }
VertexBuffer9::~VertexBuffer9() VertexBuffer9::~VertexBuffer9()
...@@ -82,7 +74,6 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con ...@@ -82,7 +74,6 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con
int inputStride = attrib.stride(); int inputStride = attrib.stride();
int elementSize = attrib.typeSize(); int elementSize = attrib.typeSize();
const FormatConverter &converter = formatConverter(attrib);
DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
...@@ -125,13 +116,17 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con ...@@ -125,13 +116,17 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, con
input += inputStride * start; input += inputStride * start;
} }
if (converter.identity && inputStride == elementSize) gl::VertexFormat vertexFormat(attrib, currentValue.Type);
bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0;
if (!needsConversion && inputStride == elementSize)
{ {
memcpy(mapPtr, input, count * inputStride); memcpy(mapPtr, input, count * inputStride);
} }
else else
{ {
converter.convertArray(input, inputStride, count, mapPtr); VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat);
copyFunction(input, inputStride, count, mapPtr);
} }
mVertexBuffer->Unlock(); mVertexBuffer->Unlock();
...@@ -153,18 +148,15 @@ bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei ...@@ -153,18 +148,15 @@ bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei
bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
{ {
return !formatConverter(attrib).identity; gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
return (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0;
} }
bool VertexBuffer9::requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const bool VertexBuffer9::requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const
{ {
ASSERT(currentValue.Type == GL_FLOAT); ASSERT(currentValue.Type == GL_FLOAT);
return getCurrentValueFormatConverter().identity; gl::VertexFormat vertexFormat(currentValue.Type, GL_FALSE, 4, GL_FALSE);
} return (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0;
D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
{
return formatConverter(attrib).d3dDeclType;
} }
unsigned int VertexBuffer9::getBufferSize() const unsigned int VertexBuffer9::getBufferSize() const
...@@ -219,252 +211,11 @@ IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const ...@@ -219,252 +211,11 @@ IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
return mVertexBuffer; return mVertexBuffer;
} }
// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
//
// BYTE SHORT (Cast)
// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
// SHORT SHORT (Identity)
// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
// UNSIGNED_SHORT FLOAT (Cast)
// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
// FIXED (not in WebGL) FLOAT (FixedToFloat)
// FLOAT FLOAT (Identity)
// GLToCType maps from GL type (as GLenum) to the C typedef.
template <GLenum GLType> struct GLToCType { };
template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
enum D3DVertexType
{
D3DVT_FLOAT,
D3DVT_SHORT,
D3DVT_SHORT_NORM,
D3DVT_UBYTE,
D3DVT_UBYTE_NORM,
D3DVT_USHORT_NORM
};
// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
template <unsigned int D3DType> struct D3DToCType { };
template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
template <unsigned int type, int size> struct WidenRule { };
template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { };
template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { };
// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
template <unsigned int _capflag, unsigned int _declflag>
struct VertexTypeFlagsHelper
{
enum { capflag = _capflag };
enum { declflag = _declflag };
};
template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
struct VertexTypeMappingBase
{
enum { preferred = Preferred };
enum { fallback = Fallback };
};
template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
// The conversion rules themselves are defined in vertexconversion.h.
// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
template <GLenum fromType, bool normalized, unsigned int toType>
struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
// All conversions from normalized types to float use the Normalize operator.
template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
// whether it is normalized or not.
template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { };
template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
// Work out the default value rule for a D3D type (expressed as the C type) and
template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
// The fallback conversion produces an output that all D3D9 devices must support.
template <class T> struct UsePreferred { enum { type = T::preferred }; };
template <class T> struct UseFallback { enum { type = T::fallback }; };
// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
struct Converter
: VertexDataConverter<typename GLToCType<fromType>::type,
WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
ConversionRule<fromType,
normalized,
PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
{
private:
enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
public:
enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
};
// Initialize a TranslationInfo
#define TRANSLATION(type, norm, size, preferred) \
{ \
Converter<type, norm, size, preferred>::identity, \
Converter<type, norm, size, preferred>::finalSize, \
Converter<type, norm, size, preferred>::convertArray, \
static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
}
#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
{ \
Converter<type, norm, size, UsePreferred>::capflag, \
TRANSLATION(type, norm, size, UsePreferred), \
TRANSLATION(type, norm, size, UseFallback) \
}
#define TRANSLATIONS_FOR_TYPE(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
}
#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
}
const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
{
TRANSLATIONS_FOR_TYPE(GL_BYTE),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
TRANSLATIONS_FOR_TYPE(GL_SHORT),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
};
void VertexBuffer9::initializeTranslations(DWORD declTypes)
{
for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
{
for (unsigned int j = 0; j < 2; j++)
{
for (unsigned int k = 0; k < 4; k++)
{
if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
{
mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
}
else
{
mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
}
}
}
}
}
unsigned int VertexBuffer9::typeIndex(GLenum type)
{
switch (type)
{
case GL_BYTE: return 0;
case GL_UNSIGNED_BYTE: return 1;
case GL_SHORT: return 2;
case GL_UNSIGNED_SHORT: return 3;
case GL_FIXED: return 4;
case GL_FLOAT: return 5;
default: UNREACHABLE(); return 5;
}
}
const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
{
if (!attribute.mArrayEnabled)
{
return getCurrentValueFormatConverter();
}
// Pure integer attributes only supported in ES3.0
ASSERT(!attribute.mPureInteger);
return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
}
const VertexBuffer9::FormatConverter &VertexBuffer9::getCurrentValueFormatConverter()
{
return mFormatConverters[typeIndex(GL_FLOAT)][0][3];
}
bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
unsigned int *outSpaceRequired) unsigned int *outSpaceRequired)
{ {
unsigned int elementSize = formatConverter(attrib).outputElementSize; gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat);
if (attrib.mArrayEnabled) if (attrib.mArrayEnabled)
{ {
......
...@@ -33,8 +33,6 @@ class VertexBuffer9 : public VertexBuffer ...@@ -33,8 +33,6 @@ class VertexBuffer9 : public VertexBuffer
virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
virtual bool requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const; virtual bool requiresConversion(const gl::VertexAttribCurrentValueData &currentValue) const;
D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const;
virtual unsigned int getBufferSize() const; virtual unsigned int getBufferSize() const;
virtual bool setBufferSize(unsigned int size); virtual bool setBufferSize(unsigned int size);
virtual bool discard(); virtual bool discard();
...@@ -50,38 +48,6 @@ class VertexBuffer9 : public VertexBuffer ...@@ -50,38 +48,6 @@ class VertexBuffer9 : public VertexBuffer
unsigned int mBufferSize; unsigned int mBufferSize;
bool mDynamicUsage; bool mDynamicUsage;
// Attribute format conversion
enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
struct FormatConverter
{
bool identity;
std::size_t outputElementSize;
void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
D3DDECLTYPE d3dDeclType;
};
static bool mTranslationsInitialized;
static void initializeTranslations(DWORD declTypes);
// [GL types as enumerated by typeIndex()][normalized][size - 1]
static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
struct TranslationDescription
{
DWORD capsFlag;
FormatConverter preferredConversion;
FormatConverter fallbackConversion;
};
// This table is used to generate mFormatConverters.
// [GL types as enumerated by typeIndex()][normalized][size - 1]
static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
static unsigned int typeIndex(GLenum type);
static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
static const FormatConverter &getCurrentValueFormatConverter();
static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
unsigned int *outSpaceRequired); unsigned int *outSpaceRequired);
}; };
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "libGLESv2/VertexAttribute.h" #include "libGLESv2/VertexAttribute.h"
#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" #include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" #include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h"
#include "libGLESv2/renderer/d3d9/formatutils9.h"
namespace rx namespace rx
{ {
...@@ -131,9 +132,11 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl ...@@ -131,9 +132,11 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl
mAppliedVBs[stream].offset = attributes[i].offset; mAppliedVBs[stream].offset = attributes[i].offset;
} }
gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT);
element->Stream = stream; element->Stream = stream;
element->Offset = 0; element->Offset = 0;
element->Type = vertexBuffer->getDeclType(*attributes[i].attribute); element->Type = d3d9::GetNativeVertexFormat(vertexFormat);
element->Method = D3DDECLMETHOD_DEFAULT; element->Method = D3DDECLMETHOD_DEFAULT;
element->Usage = D3DDECLUSAGE_TEXCOORD; element->Usage = D3DDECLUSAGE_TEXCOORD;
element->UsageIndex = programBinary->getSemanticIndex(i); element->UsageIndex = programBinary->getSemanticIndex(i);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "libGLESv2/renderer/generatemip.h" #include "libGLESv2/renderer/generatemip.h"
#include "libGLESv2/renderer/loadimage.h" #include "libGLESv2/renderer/loadimage.h"
#include "libGLESv2/renderer/copyimage.h" #include "libGLESv2/renderer/copyimage.h"
#include "libGLESv2/renderer/vertexconversion.h"
namespace rx namespace rx
{ {
...@@ -453,6 +454,303 @@ ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, ...@@ -453,6 +454,303 @@ ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat,
return (iter != fastCopyMap.end()) ? iter->second : NULL; return (iter != fastCopyMap.end()) ? iter->second : NULL;
} }
GLenum GetDeclTypeComponentType(D3DDECLTYPE declType)
{
switch (declType)
{
case D3DDECLTYPE_FLOAT1: return GL_FLOAT;
case D3DDECLTYPE_FLOAT2: return GL_FLOAT;
case D3DDECLTYPE_FLOAT3: return GL_FLOAT;
case D3DDECLTYPE_FLOAT4: return GL_FLOAT;
case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT;
case D3DDECLTYPE_SHORT2: return GL_SHORT;
case D3DDECLTYPE_SHORT4: return GL_SHORT;
case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED;
case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED;
case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED;
case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED;
default: UNREACHABLE(); return GL_NONE;
}
}
// Attribute format conversion
enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
struct FormatConverter
{
bool identity;
std::size_t outputElementSize;
void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
D3DDECLTYPE d3dDeclType;
};
struct TranslationDescription
{
DWORD capsFlag;
FormatConverter preferredConversion;
FormatConverter fallbackConversion;
};
static unsigned int typeIndex(GLenum type);
static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
bool mTranslationsInitialized = false;
FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
//
// BYTE SHORT (Cast)
// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
// SHORT SHORT (Identity)
// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
// UNSIGNED_SHORT FLOAT (Cast)
// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
// FIXED (not in WebGL) FLOAT (FixedToFloat)
// FLOAT FLOAT (Identity)
// GLToCType maps from GL type (as GLenum) to the C typedef.
template <GLenum GLType> struct GLToCType { };
template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
enum D3DVertexType
{
D3DVT_FLOAT,
D3DVT_SHORT,
D3DVT_SHORT_NORM,
D3DVT_UBYTE,
D3DVT_UBYTE_NORM,
D3DVT_USHORT_NORM
};
// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
template <unsigned int D3DType> struct D3DToCType { };
template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
template <unsigned int type, int size> struct WidenRule { };
template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { };
template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { };
template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { };
// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
template <unsigned int _capflag, unsigned int _declflag>
struct VertexTypeFlagsHelper
{
enum { capflag = _capflag };
enum { declflag = _declflag };
};
template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
struct VertexTypeMappingBase
{
enum { preferred = Preferred };
enum { fallback = Fallback };
};
template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
// The conversion rules themselves are defined in vertexconversion.h.
// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
template <GLenum fromType, bool normalized, unsigned int toType>
struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
// All conversions from normalized types to float use the Normalize operator.
template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
// whether it is normalized or not.
template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { };
template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
// Work out the default value rule for a D3D type (expressed as the C type) and
template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
// The fallback conversion produces an output that all D3D9 devices must support.
template <class T> struct UsePreferred { enum { type = T::preferred }; };
template <class T> struct UseFallback { enum { type = T::fallback }; };
// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
struct Converter
: VertexDataConverter<typename GLToCType<fromType>::type,
WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
ConversionRule<fromType,
normalized,
PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
{
private:
enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
public:
enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
};
// Initialize a TranslationInfo
#define TRANSLATION(type, norm, size, preferred) \
{ \
Converter<type, norm, size, preferred>::identity, \
Converter<type, norm, size, preferred>::finalSize, \
Converter<type, norm, size, preferred>::convertArray, \
static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
}
#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
{ \
Converter<type, norm, size, UsePreferred>::capflag, \
TRANSLATION(type, norm, size, UsePreferred), \
TRANSLATION(type, norm, size, UseFallback) \
}
#define TRANSLATIONS_FOR_TYPE(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
}
#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
{ \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
{ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
}
const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
{
TRANSLATIONS_FOR_TYPE(GL_BYTE),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
TRANSLATIONS_FOR_TYPE(GL_SHORT),
TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
};
void InitializeVertexTranslations(const rx::Renderer9 *renderer)
{
DWORD declTypes = renderer->getCapsDeclTypes();
for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
{
for (unsigned int j = 0; j < 2; j++)
{
for (unsigned int k = 0; k < 4; k++)
{
if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
{
mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
}
else
{
mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
}
}
}
}
}
unsigned int typeIndex(GLenum type)
{
switch (type)
{
case GL_BYTE: return 0;
case GL_UNSIGNED_BYTE: return 1;
case GL_SHORT: return 2;
case GL_UNSIGNED_SHORT: return 3;
case GL_FIXED: return 4;
case GL_FLOAT: return 5;
default: UNREACHABLE(); return 5;
}
}
const FormatConverter &formatConverter(const gl::VertexFormat &vertexFormat)
{
// Pure integer attributes only supported in ES3.0
ASSERT(!vertexFormat.mPureInteger);
return mFormatConverters[typeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1];
}
VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat)
{
return formatConverter(vertexFormat).convertArray;
}
size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat)
{
return formatConverter(vertexFormat).outputElementSize;
}
VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat)
{
return (formatConverter(vertexFormat).identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU);
}
D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat)
{
return formatConverter(vertexFormat).d3dDeclType;
}
} }
namespace gl_d3d9 namespace gl_d3d9
......
...@@ -37,6 +37,17 @@ const D3DFormatSet &GetAllUsedD3DFormats(); ...@@ -37,6 +37,17 @@ const D3DFormatSet &GetAllUsedD3DFormats();
ColorReadFunction GetColorReadFunction(D3DFORMAT format); ColorReadFunction GetColorReadFunction(D3DFORMAT format);
ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType, GLuint clientVersion); ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType, GLuint clientVersion);
VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat);
size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat);
VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat);
D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat);
GLenum GetDeclTypeComponentType(D3DDECLTYPE declType);
int GetDeclTypeComponentCount(D3DDECLTYPE declType);
bool IsDeclTypeNormalized(D3DDECLTYPE declType);
void InitializeVertexTranslations(const rx::Renderer9 *renderer);
} }
namespace gl_d3d9 namespace gl_d3d9
......
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