/*
Copyright (C) 2010, Heikki Salo
All rights reserved.
Distributed under the BSD license:
http://www.opensource.org/licenses/bsd-license.php
*/
#include "stdafx.h"
#include "DPUtils.hpp"
struct FormatAndString
{
DXGI_FORMAT format;
const char* string;
UINT byteSize;
};
const FormatAndString formatMappings[] =
{
{DXGI_FORMAT_R32G32B32A32_TYPELESS, "16B", 16},
{DXGI_FORMAT_R32G32B32A32_FLOAT, "4f", 16},
{DXGI_FORMAT_R32G32B32A32_UINT, "4I", 16},
{DXGI_FORMAT_R32G32B32A32_SINT, "4i", 16},
{DXGI_FORMAT_R32G32B32_TYPELESS, "12B", 12},
{DXGI_FORMAT_R32G32B32_FLOAT, "3f", 12},
{DXGI_FORMAT_R32G32B32_UINT, "3I", 12},
{DXGI_FORMAT_R32G32B32_SINT, "3i", 12},
{DXGI_FORMAT_R16G16B16A16_TYPELESS, "8B", 8},
{DXGI_FORMAT_R16G16B16A16_FLOAT, "8B", 8}, //Short float...
{DXGI_FORMAT_R16G16B16A16_UNORM, "4H", 8},
{DXGI_FORMAT_R16G16B16A16_UINT, "4H", 8},
{DXGI_FORMAT_R16G16B16A16_SNORM, "4h", 8},
{DXGI_FORMAT_R16G16B16A16_SINT, "4h", 8},
{DXGI_FORMAT_R32G32_TYPELESS, "8B", 8},
{DXGI_FORMAT_R32G32_FLOAT, "2f", 8},
{DXGI_FORMAT_R32G32_UINT, "2I", 8},
{DXGI_FORMAT_R32G32_SINT, "2i", 8},
{DXGI_FORMAT_R32G8X24_TYPELESS, "8B", 8},
{DXGI_FORMAT_D32_FLOAT_S8X24_UINT, "f4B", 8}, //24 bit uint...
{DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, "f4B", 8}, //24 bit uint...
{DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, "8B", 8},
{DXGI_FORMAT_R8G8B8A8_TYPELESS, "4B", 4}, //XXX Three component?
{DXGI_FORMAT_R8G8B8A8_UNORM, "4B", 4},
{DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "4B", 4},
{DXGI_FORMAT_R8G8B8A8_UINT, "4B", 4},
{DXGI_FORMAT_R8G8B8A8_SNORM, "4b", 4}, //XXX Three component?
{DXGI_FORMAT_R8G8B8A8_SINT, "4b", 4}, //XXX Three component?
{DXGI_FORMAT_R10G10B10A2_TYPELESS, "4B", 4},
{DXGI_FORMAT_R10G10B10A2_UNORM, "4B", 4},
{DXGI_FORMAT_R10G10B10A2_UINT, "4B", 4},
{DXGI_FORMAT_R11G11B10_FLOAT, "4B", 4},
{DXGI_FORMAT_R16G16_TYPELESS, "4B", 4},
{DXGI_FORMAT_R16G16_FLOAT, "4B", 4},
{DXGI_FORMAT_R16G16_UNORM, "2H", 4},
{DXGI_FORMAT_R16G16_UINT, "2H", 4},
{DXGI_FORMAT_R16G16_SNORM, "2h", 4},
{DXGI_FORMAT_R16G16_SINT, "2h", 4},
{DXGI_FORMAT_R32_TYPELESS, "4B", 4},
{DXGI_FORMAT_D32_FLOAT, "f", 4},
{DXGI_FORMAT_R32_FLOAT, "f", 4},
{DXGI_FORMAT_R32_UINT, "I", 4},
{DXGI_FORMAT_R32_SINT, "i", 4},
{DXGI_FORMAT_R24G8_TYPELESS, "4B", 4},
{DXGI_FORMAT_D24_UNORM_S8_UINT, "4B", 4},
{DXGI_FORMAT_R24_UNORM_X8_TYPELESS, "4B", 4},
{DXGI_FORMAT_X24_TYPELESS_G8_UINT, "4B", 4},
{DXGI_FORMAT_R8G8_TYPELESS, "2B", 2},
{DXGI_FORMAT_R8G8_UNORM, "2B", 2},
{DXGI_FORMAT_R8G8_UINT, "2B", 2},
{DXGI_FORMAT_R8G8_SNORM, "2b", 2},
{DXGI_FORMAT_R8G8_SINT, "2b", 2},
{DXGI_FORMAT_R16_TYPELESS, "2B", 2},
{DXGI_FORMAT_R16_FLOAT, "2B", 2}, //Short float
{DXGI_FORMAT_D16_UNORM, "H", 2},
{DXGI_FORMAT_R16_UNORM, "H", 2},
{DXGI_FORMAT_R16_UINT, "H", 2},
{DXGI_FORMAT_R16_SNORM, "h", 2},
{DXGI_FORMAT_R16_SINT, "h", 2},
{DXGI_FORMAT_R8_TYPELESS, "B", 1},
{DXGI_FORMAT_R8_UNORM, "B", 1},
{DXGI_FORMAT_R8_UINT, "B", 1},
{DXGI_FORMAT_R8_SNORM, "b", 1},
{DXGI_FORMAT_R8_SINT, "b", 1},
{DXGI_FORMAT_A8_UNORM, "B", 1},
//DXGI_FORMAT_R1_UNORM - Not supported.
{DXGI_FORMAT_R9G9B9E5_SHAREDEXP, "4B", 4},
{DXGI_FORMAT_R8G8_B8G8_UNORM, "4B", 4},
{DXGI_FORMAT_G8R8_G8B8_UNORM, "4B", 4},
//Block compressed from BC1 to BC 5 - Not supported
{DXGI_FORMAT_B5G6R5_UNORM, "2B", 2},
{DXGI_FORMAT_B5G5R5A1_UNORM, "2B", 2},
{DXGI_FORMAT_B8G8R8A8_UNORM, "4B", 4},
{DXGI_FORMAT_B8G8R8X8_UNORM, "4B", 4},
{DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, "4B", 4},
{DXGI_FORMAT_B8G8R8A8_TYPELESS, "4B", 4},
{DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, "4B", 4},
{DXGI_FORMAT_B8G8R8X8_TYPELESS, "4B", 4},
{DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, "4B", 4},
};
/*
Gets the size of a given format and if the string argument is given
appends a struct-module compatible string into it.
*/
UINT GetFormatByteSize(DXGI_FORMAT format, std::string* fstr)
{
for (UINT i=0; i < sizeof(formatMappings) / sizeof(formatMappings[0]); ++i) {
if (formatMappings[i].format == format) {
if (fstr) {
//Append to the string.
*fstr += formatMappings[i].string;
}
return formatMappings[i].byteSize;
}
}
DPThrow("Unsupported format");
return 0; //Should never get in here.
}
DXGI_FORMAT GetDXGIFromString(const char* formatStr)
{
for (UINT i=0; i < sizeof(formatMappings) / sizeof(formatMappings[0]); ++i) {
if (strcmp(formatMappings[i].string, formatStr) == 0) {
return formatMappings[i].format;
}
}
DPThrow("Unsupported format");
return DXGI_FORMAT_UNKNOWN; //Should never get in here.
}
python::object CreateNamedTuple(const char* className, const char* attributes)
{
python::object collections = python::import("collections");
return collections.attr("namedtuple")(className, attributes);
}
/*
Convert a string like '4f' to DXGI_FORMAT. Only allows
vectors (element count is from 1 to 4).
*/
#ifdef DP_PYPY
DXGI_FORMAT FormatStringToDXGI(python::object arg)
{
DPThrow("Format strings not supported in PyPy");
return DXGI_FORMAT_UNKNOWN;
}
#else
DXGI_FORMAT FormatStringToDXGI(python::object arg)
{
pyunicode formatStr(arg);
const Py_ssize_t stringSize = formatStr.size();
if (stringSize < 1 || stringSize > 4)
DPThrow("Invalid format string");
std::ostringstream stream;
if (Py_UNICODE_ISDIGIT(formatStr[0])) {
//String like '3f'
int digit = Py_UNICODE_TODIGIT(formatStr[0]);
if (stringSize != 2 || digit > 4)
DPThrow("Invalid format string");
if (digit > 1) //'1B' -> 'B'
stream << digit;
stream << (char)formatStr[1];
}
else if (stringSize == 1) {
stream << (char)formatStr[0];
}
else {
//Assume 'fff' etc. - convert to '3f'
//All characters in the string must be same.
Py_UNICODE first = formatStr[0];
for (Py_ssize_t i=1; i < formatStr.size(); ++i) {
if (first != formatStr[i]) {
DPThrow("Invalid format string");
}
}
stream << formatStr.size() << (char)formatStr[0];
}
return GetDXGIFromString(stream.str().c_str());
}
#endif
/*
Converts a Python layout description list into an C++ vector
holding D3D11_INPUT_ELEMENT_DESC's.
*/
void ConvertLayoutDesc(python::object& indesc, std::vector<D3D11_INPUT_ELEMENT_DESC>* outvector)
{
outvector->clear();
UINT count = python::len(indesc);
for (UINT i=0; i < count; ++i) {
python::object current = indesc[i];
const Py_ssize_t descLen = python::len(current);
D3D11_INPUT_ELEMENT_DESC element;
//Set default values.
ZeroMemory(&element, sizeof(element));
element.AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
element.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
//SemanticName can (and probably will) end up as a invalid pointer!
//It is mostly OK though, it is only used temporarily and Buffer
//does not use it at all.
#ifdef DP_PYPY
//XXX Leaks the string, but PyPy stuff is currently very experimental.
std::string* leakSemantic = new std::string(python::extract<const char*>(current[0]));
element.SemanticName = leakSemantic->c_str();
#else
element.SemanticName = python::extract<const char*>(current[0]);
#endif
element.SemanticIndex = python::extract<UINT>(current[1]);
python::extract<UINT> pyFormat(current[2]);
if (pyFormat.check()) {
element.Format = (DXGI_FORMAT)((UINT)python::extract<UINT>(current[2])); //Assume a DXGI_FORMAT.
}
else {
element.Format = FormatStringToDXGI(current[2]); //Assume a format string ('fff' etc.).
}
//These are optional.
if (descLen > 3)
element.InputSlot = python::extract<UINT>(current[3]);
if (descLen > 4)
element.AlignedByteOffset = python::extract<UINT>(current[4]);
if (descLen > 5)
element.InputSlotClass = (D3D11_INPUT_CLASSIFICATION)(UINT)python::extract<UINT>(current[5]);
if (descLen > 6)
element.InstanceDataStepRate = python::extract<UINT>(current[6]);
if (element.AlignedByteOffset == D3D11_APPEND_ALIGNED_ELEMENT) {
//Calculate correct alignment.
if (i == 0) {
//First element.
element.AlignedByteOffset = 0;
}
else {
//Check item alignment.
const D3D11_INPUT_ELEMENT_DESC& previous = (*outvector)[i - 1];
const UINT prevByteSize = GetFormatByteSize(previous.Format);
element.AlignedByteOffset = previous.AlignedByteOffset + prevByteSize;
if (element.AlignedByteOffset % sizeof(float) != 0) {
//TODO: fix this and add support.
DPThrow("Layout description AlignedByteOffset not on a 4-byte boundary, specify alignment manually");
}
}
}
outvector->push_back(element);
}
}
python::object LayoutDescToPy(const InputElementVector& layout)
{
python::list result;
for (UINT i=0; i < layout.size(); ++i) {
const D3D11_INPUT_ELEMENT_DESC& desc = layout[i];
result.append(python::make_tuple("", desc.SemanticIndex, (DWORD)desc.Format, desc.InputSlot,
desc.AlignedByteOffset, (DWORD)desc.InputSlotClass, desc.InstanceDataStepRate));
}
return result;
}
/*
Returns the full size of a input layout description vector in bytes.
*/
UINT GetElementByteSize(const InputElementVector& elements)
{
UINT byteSize = 0;
for (UINT i=0; i < elements.size(); ++i) {
const D3D11_INPUT_ELEMENT_DESC& desc = elements[i];
if (desc.InputSlotClass == D3D11_INPUT_PER_VERTEX_DATA) {
//This is vertex data.
UINT elementSize = GetFormatByteSize(desc.Format);
byteSize = max(byteSize, desc.AlignedByteOffset + elementSize);
}
else {
DPThrow("Input layout description: InputSlotClass != INPUT_PER_VERTEX_DATA");
}
}
return byteSize;
}
/*
This converts and writes a Python object into a "raw" memory form. The
layout is used to interpret the given object. Speed is important,
converting objects for Direct3D is very common.
*/
//#define DPWRITE_TYPE(tp, dummy) *(((tp*)(bytePtr + desc.AlignedByteOffset)) + itemCounter++) = python::extract<tp>(obj[elementsWritten++])
//Faster, not so safe version:
#define DPWRITE_TYPE(tp, func) \
tmp = PySequence_ITEM(sequence, elementsWritten++); \
if (tmp) { \
*(((tp*)(bytePtr + desc.AlignedByteOffset)) + itemCounter++) = static_cast<tp>(func(tmp)); \
Py_DECREF(tmp); \
} \
if (PyErr_Occurred()) python::throw_error_already_set()
void ConvertPyToC(python::object& obj, void* writeTo, const InputElementVector& layout)
{
BYTE* bytePtr = static_cast<BYTE*>(writeTo);
UINT elementsWritten = 0;
//For faster version.
PyObject* sequence = obj.ptr();
PyObject* tmp = 0;
//Not needed if using boost-DPWRITE_TYPE().
if (!PySequence_Check(sequence))
DPThrow("Layout descriptor item must be a sequence");
for (UINT i=0; i < layout.size(); ++i) {
const D3D11_INPUT_ELEMENT_DESC& desc = layout[i];
if (desc.InputSlotClass != D3D11_INPUT_PER_VERTEX_DATA)
DPThrow("InputSlotClass != D3D11_INPUT_PER_VERTEX_DATA");
UINT itemCounter = 0;
//This switch uses several fallthroughs.
switch (desc.Format) {
//32-bit float.
case DXGI_FORMAT_R32G32B32A32_FLOAT:
DPWRITE_TYPE(float, PyFloat_AsDouble);
case DXGI_FORMAT_R32G32B32_FLOAT:
DPWRITE_TYPE(float, PyFloat_AsDouble);
case DXGI_FORMAT_R32G32_FLOAT:
DPWRITE_TYPE(float, PyFloat_AsDouble);
case DXGI_FORMAT_D32_FLOAT:
case DXGI_FORMAT_R32_FLOAT:
DPWRITE_TYPE(float, PyFloat_AsDouble);
break;
//32-bit unsigned integer.
case DXGI_FORMAT_R32G32B32A32_UINT:
DPWRITE_TYPE(UINT, PyLong_AsUnsignedLong);
case DXGI_FORMAT_R32G32B32_UINT:
DPWRITE_TYPE(UINT, PyLong_AsUnsignedLong);
case DXGI_FORMAT_R32G32_UINT:
DPWRITE_TYPE(UINT, PyLong_AsUnsignedLong);
case DXGI_FORMAT_R32_UINT:
DPWRITE_TYPE(UINT, PyLong_AsUnsignedLong);
break;
//32-bit signed integer.
case DXGI_FORMAT_R32G32B32A32_SINT:
DPWRITE_TYPE(INT, PyLong_AsLong);
case DXGI_FORMAT_R32G32B32_SINT:
DPWRITE_TYPE(INT, PyLong_AsLong);
case DXGI_FORMAT_R32G32_SINT:
DPWRITE_TYPE(INT, PyLong_AsLong);
case DXGI_FORMAT_R32_SINT:
DPWRITE_TYPE(INT, PyLong_AsLong);
break;
//16-bit unsigned integer.
case DXGI_FORMAT_R16G16B16A16_UNORM:
case DXGI_FORMAT_R16G16B16A16_UINT:
DPWRITE_TYPE(USHORT, PyLong_AsUnsignedLong);
DPWRITE_TYPE(USHORT, PyLong_AsUnsignedLong);
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_R16G16_UINT:
DPWRITE_TYPE(USHORT, PyLong_AsUnsignedLong);
case DXGI_FORMAT_D16_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16_UINT:
DPWRITE_TYPE(USHORT, PyLong_AsUnsignedLong);
break;
//16-bit signed integer.
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R16G16B16A16_SINT:
DPWRITE_TYPE(SHORT, PyLong_AsLong);
DPWRITE_TYPE(SHORT, PyLong_AsLong);
case DXGI_FORMAT_R16G16_SNORM:
case DXGI_FORMAT_R16G16_SINT:
DPWRITE_TYPE(SHORT, PyLong_AsLong);
case DXGI_FORMAT_R16_SNORM:
case DXGI_FORMAT_R16_SINT:
DPWRITE_TYPE(SHORT, PyLong_AsLong);
break;
//8-bit unsigned integer.
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8X8_UNORM:
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
DPWRITE_TYPE(BYTE, PyLong_AsUnsignedLong);
DPWRITE_TYPE(BYTE, PyLong_AsUnsignedLong);
case DXGI_FORMAT_R8G8_TYPELESS:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
DPWRITE_TYPE(BYTE, PyLong_AsUnsignedLong);
case DXGI_FORMAT_R8_TYPELESS:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_A8_UNORM:
DPWRITE_TYPE(BYTE, PyLong_AsUnsignedLong);
break;
//8-bit signed integer.
case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R8G8B8A8_SINT:
DPWRITE_TYPE(signed char, PyLong_AsLong);
DPWRITE_TYPE(signed char, PyLong_AsLong);
case DXGI_FORMAT_R8G8_SNORM:
case DXGI_FORMAT_R8G8_SINT:
DPWRITE_TYPE(signed char, PyLong_AsLong);
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT:
DPWRITE_TYPE(signed char, PyLong_AsLong);
break;
default:
DPThrow("Unsupported format");
}
}
}
/*
Convert raw memory into a Python list using the given layout.
*/
#define DPAPPEND_TYPE(tp) result.append(*((tp*)(posPtr + desc.AlignedByteOffset) + itemCounter++));
python::list ConvertCToPy(void* readFrom, const InputElementVector& layout)
{
python::list result;
BYTE* posPtr = static_cast<BYTE*>(readFrom);
for (UINT i=0; i < layout.size(); ++i) {
const D3D11_INPUT_ELEMENT_DESC& desc = layout[i];
if (desc.InputSlotClass != D3D11_INPUT_PER_VERTEX_DATA)
DPThrow("InputSlotClass != D3D11_INPUT_PER_VERTEX_DATA");
UINT itemCounter = 0;
//This switch uses several fallthroughs.
switch (desc.Format) {
//32-bit float.
case DXGI_FORMAT_R32G32B32A32_FLOAT:
DPAPPEND_TYPE(float);
case DXGI_FORMAT_R32G32B32_FLOAT:
DPAPPEND_TYPE(float);
case DXGI_FORMAT_R32G32_FLOAT:
DPAPPEND_TYPE(float);
case DXGI_FORMAT_D32_FLOAT:
case DXGI_FORMAT_R32_FLOAT:
DPAPPEND_TYPE(float);
break;
//32-bit unsigned integer.
case DXGI_FORMAT_R32G32B32A32_UINT:
DPAPPEND_TYPE(UINT);
case DXGI_FORMAT_R32G32B32_UINT:
DPAPPEND_TYPE(UINT);
case DXGI_FORMAT_R32G32_UINT:
DPAPPEND_TYPE(UINT);
case DXGI_FORMAT_R32_UINT:
DPAPPEND_TYPE(UINT);
break;
//32-bit signed integer.
case DXGI_FORMAT_R32G32B32A32_SINT:
DPAPPEND_TYPE(INT);
case DXGI_FORMAT_R32G32B32_SINT:
DPAPPEND_TYPE(INT);
case DXGI_FORMAT_R32G32_SINT:
DPAPPEND_TYPE(INT);
case DXGI_FORMAT_R32_SINT:
DPAPPEND_TYPE(INT);
break;
//16-bit unsigned integer.
case DXGI_FORMAT_R16G16B16A16_UNORM:
case DXGI_FORMAT_R16G16B16A16_UINT:
DPAPPEND_TYPE(USHORT);
DPAPPEND_TYPE(USHORT);
case DXGI_FORMAT_R16G16_UNORM:
case DXGI_FORMAT_R16G16_UINT:
DPAPPEND_TYPE(USHORT);
case DXGI_FORMAT_D16_UNORM:
case DXGI_FORMAT_R16_UNORM:
case DXGI_FORMAT_R16_UINT:
DPAPPEND_TYPE(USHORT);
break;
//16-bit signed integer.
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R16G16B16A16_SINT:
DPAPPEND_TYPE(SHORT);
DPAPPEND_TYPE(SHORT);
case DXGI_FORMAT_R16G16_SNORM:
case DXGI_FORMAT_R16G16_SINT:
DPAPPEND_TYPE(SHORT);
case DXGI_FORMAT_R16_SNORM:
case DXGI_FORMAT_R16_SINT:
DPAPPEND_TYPE(SHORT);
break;
//8-bit unsigned integer.
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_R8G8B8A8_UINT:
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8X8_UNORM:
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
DPAPPEND_TYPE(BYTE);
DPAPPEND_TYPE(BYTE);
case DXGI_FORMAT_R8G8_TYPELESS:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
DPAPPEND_TYPE(BYTE);
case DXGI_FORMAT_R8_TYPELESS:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_A8_UNORM:
DPAPPEND_TYPE(BYTE);
break;
//8-bit signed integer.
case DXGI_FORMAT_R8G8B8A8_SNORM:
case DXGI_FORMAT_R8G8B8A8_SINT:
DPAPPEND_TYPE(signed char);
DPAPPEND_TYPE(signed char);
case DXGI_FORMAT_R8G8_SNORM:
case DXGI_FORMAT_R8G8_SINT:
DPAPPEND_TYPE(signed char);
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT:
DPAPPEND_TYPE(signed char);
break;
default:
DPThrow("Unsupported format");
}
}
return result;
}
/*
Converts an input layout description into a
struct-compatible (struct is a Python module) string.
*/
std::string GetLayoutFormatStr(const InputElementVector& elements)
{
std::string tmp;
tmp.reserve(64);
for (UINT i=0; i < elements.size(); ++i) {
//Calculate possible padding.
UINT curAlign = elements[i].AlignedByteOffset;
UINT padByteCount = curAlign;
if (i > 0) {
UINT prevAlign = elements[i-1].AlignedByteOffset;
UINT prevByteSize = GetFormatByteSize(elements[i-1].Format);
padByteCount = curAlign - (prevAlign + prevByteSize);
}
if (padByteCount > 0) {
//Add padding bytes ('x').
std::ostringstream ss;
ss << padByteCount << "x";
tmp += ss.str();
}
//Append to tmp.
GetFormatByteSize(elements[i].Format, &tmp);
}
return tmp;
}
void DPWarn(const char* message)
{
if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1) == -1) {
python::throw_error_already_set();
}
}