2015-09-28 22:51:32 +02:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "BufferUtils.h"
|
|
|
|
|
|
|
|
|
|
#define MIN2(x, y) ((x) < (y)) ? (x) : (y)
|
|
|
|
|
#define MAX2(x, y) ((x) > (y)) ? (x) : (y)
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_t index, const rsx::data_array_format_info &vertex_array_desc)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-12-23 22:25:02 +01:00
|
|
|
assert(vertex_array_desc.size > 0);
|
2015-10-14 19:47:09 +02:00
|
|
|
|
|
|
|
|
if (vertex_array_desc.frequency > 1)
|
|
|
|
|
LOG_ERROR(RSX, "%s: frequency is not null (%d, index=%d)", __FUNCTION__, vertex_array_desc.frequency, index);
|
|
|
|
|
|
|
|
|
|
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
|
|
|
|
|
u32 address = rsx::get_address(offset & 0x7fffffff, offset >> 31);
|
|
|
|
|
|
|
|
|
|
u32 type_size = rsx::get_vertex_type_size(vertex_array_desc.type);
|
|
|
|
|
u32 element_size = type_size * vertex_array_desc.size;
|
|
|
|
|
|
|
|
|
|
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
|
|
|
|
|
u32 base_index = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX];
|
|
|
|
|
|
|
|
|
|
for (u32 i = 0; i < count; ++i)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-14 19:47:09 +02:00
|
|
|
auto src = vm::ps3::_ptr<const u8>(address + base_offset + vertex_array_desc.stride * (first + i + base_index));
|
|
|
|
|
u8* dst = (u8*)buffer + i * element_size;
|
|
|
|
|
|
|
|
|
|
switch (type_size)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-14 19:47:09 +02:00
|
|
|
case 1:
|
|
|
|
|
memcpy(dst, src, vertex_array_desc.size);
|
|
|
|
|
break;
|
2015-10-11 01:07:47 +02:00
|
|
|
|
2015-10-14 19:47:09 +02:00
|
|
|
case 2:
|
|
|
|
|
{
|
|
|
|
|
auto* c_src = (const be_t<u16>*)src;
|
|
|
|
|
u16* c_dst = (u16*)dst;
|
2015-09-28 22:51:32 +02:00
|
|
|
|
2015-10-14 19:47:09 +02:00
|
|
|
for (u32 j = 0; j < vertex_array_desc.size; ++j)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-14 19:47:09 +02:00
|
|
|
*c_dst++ = *c_src++;
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
2015-10-14 19:47:09 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2015-09-28 22:51:32 +02:00
|
|
|
|
2015-10-14 19:47:09 +02:00
|
|
|
case 4:
|
|
|
|
|
{
|
|
|
|
|
auto* c_src = (const be_t<u32>*)src;
|
|
|
|
|
u32* c_dst = (u32*)dst;
|
2015-09-28 22:51:32 +02:00
|
|
|
|
2015-10-14 19:47:09 +02:00
|
|
|
for (u32 j = 0; j < vertex_array_desc.size; ++j)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-14 19:47:09 +02:00
|
|
|
*c_dst++ = *c_src++;
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
2015-10-14 19:47:09 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 01:19:04 +01:00
|
|
|
namespace
|
|
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
template<typename IndexType>
|
2015-12-17 18:31:27 +01:00
|
|
|
void uploadAsIt(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index)
|
2015-10-15 23:06:14 +02:00
|
|
|
{
|
|
|
|
|
for (u32 i = 0; i < indexCount; ++i)
|
|
|
|
|
{
|
|
|
|
|
IndexType index = vm::ps3::_ref<IndexType>(address + i * sizeof(IndexType));
|
2015-11-10 22:34:57 +01:00
|
|
|
if (is_primitive_restart_enabled && index == (IndexType)primitive_restart_index)
|
|
|
|
|
index = (IndexType)-1;
|
2015-10-15 23:06:14 +02:00
|
|
|
(IndexType&)dst[i * sizeof(IndexType)] = index;
|
|
|
|
|
if (is_primitive_restart_enabled && index == (IndexType)-1) // Cut
|
|
|
|
|
continue;
|
|
|
|
|
max_index = MAX2(max_index, index);
|
|
|
|
|
min_index = MIN2(min_index, index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 22:34:57 +01:00
|
|
|
// FIXME: expanded primitive type may not support primitive restart correctly
|
|
|
|
|
|
2015-10-15 23:06:14 +02:00
|
|
|
template<typename IndexType>
|
2015-12-17 18:31:27 +01:00
|
|
|
void expandIndexedTriangleFan(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
|
|
|
|
for (unsigned i = 0; i < indexCount - 2; i++)
|
|
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
IndexType index0 = vm::ps3::_ref<IndexType>(address);
|
2015-11-10 22:34:57 +01:00
|
|
|
if (index0 == (IndexType)primitive_restart_index)
|
|
|
|
|
index0 = (IndexType)-1;
|
2015-10-15 23:06:14 +02:00
|
|
|
IndexType index1 = vm::ps3::_ref<IndexType>(address + (i + 2 - 1) * sizeof(IndexType));
|
2015-11-10 22:34:57 +01:00
|
|
|
if (index1 == (IndexType)primitive_restart_index)
|
|
|
|
|
index1 = (IndexType)-1;
|
2015-10-15 23:06:14 +02:00
|
|
|
IndexType index2 = vm::ps3::_ref<IndexType>(address + (i + 2) * sizeof(IndexType));
|
2015-11-10 22:34:57 +01:00
|
|
|
if (index2 == (IndexType)primitive_restart_index)
|
|
|
|
|
index2 = (IndexType)-1;
|
|
|
|
|
|
|
|
|
|
(IndexType&)dst[(3 * i) * sizeof(IndexType)] = index0;
|
|
|
|
|
(IndexType&)dst[(3 * i + 1) * sizeof(IndexType)] = index1;
|
2015-10-15 23:06:14 +02:00
|
|
|
(IndexType&)dst[(3 * i + 2) * sizeof(IndexType)] = index2;
|
|
|
|
|
|
|
|
|
|
if (!is_primitive_restart_enabled || index0 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index0);
|
|
|
|
|
max_index = MAX2(max_index, index0);
|
|
|
|
|
}
|
|
|
|
|
if (!is_primitive_restart_enabled || index1 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index1);
|
|
|
|
|
max_index = MAX2(max_index, index1);
|
|
|
|
|
}
|
|
|
|
|
if (!is_primitive_restart_enabled || index2 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index2);
|
|
|
|
|
max_index = MAX2(max_index, index2);
|
|
|
|
|
}
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-15 23:06:14 +02:00
|
|
|
template<typename IndexType>
|
2015-12-17 18:31:27 +01:00
|
|
|
void expandIndexedQuads(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
|
|
|
|
for (unsigned i = 0; i < indexCount / 4; i++)
|
|
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
IndexType index0 = vm::ps3::_ref<IndexType>(address + 4 * i * sizeof(IndexType));
|
2015-11-10 22:34:57 +01:00
|
|
|
if (is_primitive_restart_enabled && index0 == (IndexType)primitive_restart_index)
|
|
|
|
|
index0 = (IndexType)-1;
|
2015-10-15 23:06:14 +02:00
|
|
|
IndexType index1 = vm::ps3::_ref<IndexType>(address + (4 * i + 1) * sizeof(IndexType));
|
2015-11-10 22:34:57 +01:00
|
|
|
if (is_primitive_restart_enabled && index1 == (IndexType)primitive_restart_index)
|
|
|
|
|
index1 = (IndexType)-1;
|
2015-10-15 23:06:14 +02:00
|
|
|
IndexType index2 = vm::ps3::_ref<IndexType>(address + (4 * i + 2) * sizeof(IndexType));
|
2015-11-10 22:34:57 +01:00
|
|
|
if (is_primitive_restart_enabled && index2 == (IndexType)primitive_restart_index)
|
|
|
|
|
index2 = (IndexType)-1;
|
|
|
|
|
IndexType index3 = vm::ps3::_ref<IndexType>(address + (4 * i + 3) * sizeof(IndexType));
|
|
|
|
|
if (is_primitive_restart_enabled &&index3 == (IndexType)primitive_restart_index)
|
|
|
|
|
index3 = (IndexType)-1;
|
|
|
|
|
|
|
|
|
|
// First triangle
|
|
|
|
|
(IndexType&)dst[(6 * i) * sizeof(IndexType)] = index0;
|
|
|
|
|
(IndexType&)dst[(6 * i + 1) * sizeof(IndexType)] = index1;
|
2015-10-15 23:06:14 +02:00
|
|
|
(IndexType&)dst[(6 * i + 2) * sizeof(IndexType)] = index2;
|
2015-09-28 22:51:32 +02:00
|
|
|
// Second triangle
|
2015-10-15 23:06:14 +02:00
|
|
|
(IndexType&)dst[(6 * i + 3) * sizeof(IndexType)] = index2;
|
|
|
|
|
(IndexType&)dst[(6 * i + 4) * sizeof(IndexType)] = index3;
|
|
|
|
|
(IndexType&)dst[(6 * i + 5) * sizeof(IndexType)] = index0;
|
|
|
|
|
|
|
|
|
|
if (!is_primitive_restart_enabled || index0 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index0);
|
|
|
|
|
max_index = MAX2(max_index, index0);
|
|
|
|
|
}
|
|
|
|
|
if (!is_primitive_restart_enabled || index1 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index1);
|
|
|
|
|
max_index = MAX2(max_index, index1);
|
|
|
|
|
}
|
|
|
|
|
if (!is_primitive_restart_enabled || index2 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index2);
|
|
|
|
|
max_index = MAX2(max_index, index2);
|
|
|
|
|
}
|
|
|
|
|
if (!is_primitive_restart_enabled || index3 != (IndexType)-1) // Cut
|
|
|
|
|
{
|
|
|
|
|
min_index = MIN2(min_index, index3);
|
|
|
|
|
max_index = MAX2(max_index, index3);
|
|
|
|
|
}
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-10-27 01:19:04 +01:00
|
|
|
}
|
2015-09-28 22:51:32 +02:00
|
|
|
|
|
|
|
|
// Only handle quads and triangle fan now
|
2015-12-17 18:31:27 +01:00
|
|
|
bool is_primitive_native(unsigned m_draw_mode)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
|
|
|
|
switch (m_draw_mode)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_POINTS:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_LINES:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_LINE_LOOP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_LINE_STRIP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLES:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
|
|
|
|
return true;
|
2015-12-08 23:42:06 +01:00
|
|
|
case CELL_GCM_PRIMITIVE_POLYGON:
|
2015-09-28 22:51:32 +02:00
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_QUADS:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-08 23:42:06 +01:00
|
|
|
/** We assume that polygon is convex in polygon mode (constraints in OpenGL)
|
|
|
|
|
*In such case polygon triangulation equates to triangle fan with arbitrary start vertex
|
|
|
|
|
* see http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/polygon-triangulation-r3334
|
|
|
|
|
*/
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
size_t get_index_count(unsigned m_draw_mode, unsigned initial_index_count)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
|
|
|
|
// Index count
|
2015-10-27 01:19:04 +01:00
|
|
|
if (is_primitive_native(m_draw_mode))
|
2015-09-28 22:51:32 +02:00
|
|
|
return initial_index_count;
|
|
|
|
|
|
|
|
|
|
switch (m_draw_mode)
|
|
|
|
|
{
|
2015-12-08 23:42:06 +01:00
|
|
|
case CELL_GCM_PRIMITIVE_POLYGON:
|
2015-09-28 22:51:32 +02:00
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
|
|
|
|
return (initial_index_count - 2) * 3;
|
|
|
|
|
case CELL_GCM_PRIMITIVE_QUADS:
|
|
|
|
|
return (6 * initial_index_count) / 4;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
size_t get_index_type_size(u32 type)
|
2015-10-27 01:19:04 +01:00
|
|
|
{
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: return 2;
|
|
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: return 4;
|
|
|
|
|
default: return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, unsigned draw_mode, unsigned first, unsigned count)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
unsigned short *typedDst = (unsigned short *)(dst);
|
|
|
|
|
switch (draw_mode)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
2015-12-08 23:42:06 +01:00
|
|
|
case CELL_GCM_PRIMITIVE_POLYGON:
|
2015-10-15 23:06:14 +02:00
|
|
|
for (unsigned i = 0; i < (count - 2); i++)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
typedDst[3 * i] = first;
|
|
|
|
|
typedDst[3 * i + 1] = i + 2 - 1;
|
|
|
|
|
typedDst[3 * i + 2] = i + 2;
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
2015-10-15 23:06:14 +02:00
|
|
|
return;
|
|
|
|
|
case CELL_GCM_PRIMITIVE_QUADS:
|
|
|
|
|
for (unsigned i = 0; i < count / 4; i++)
|
|
|
|
|
{
|
|
|
|
|
// First triangle
|
|
|
|
|
typedDst[6 * i] = 4 * i + first;
|
|
|
|
|
typedDst[6 * i + 1] = 4 * i + 1 + first;
|
|
|
|
|
typedDst[6 * i + 2] = 4 * i + 2 + first;
|
|
|
|
|
// Second triangle
|
|
|
|
|
typedDst[6 * i + 3] = 4 * i + 2 + first;
|
|
|
|
|
typedDst[6 * i + 4] = 4 * i + 3 + first;
|
|
|
|
|
typedDst[6 * i + 5] = 4 * i + first;
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
2015-10-15 23:06:14 +02:00
|
|
|
return;
|
2015-09-28 22:51:32 +02:00
|
|
|
}
|
2015-10-15 23:06:14 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count, unsigned &min_index, unsigned &max_index)
|
2015-10-15 23:06:14 +02:00
|
|
|
{
|
|
|
|
|
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
|
|
|
|
|
u32 type = rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4;
|
|
|
|
|
|
|
|
|
|
u32 type_size = type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 ? sizeof(u32) : sizeof(u16);
|
|
|
|
|
|
|
|
|
|
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
|
|
|
|
|
u32 base_index = 0;//rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX];
|
|
|
|
|
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
|
2015-11-10 22:34:57 +01:00
|
|
|
u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
|
2015-10-15 23:06:14 +02:00
|
|
|
|
|
|
|
|
switch (m_draw_mode)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
case CELL_GCM_PRIMITIVE_POINTS:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_LINES:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_LINE_LOOP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_LINE_STRIP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLES:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
|
|
|
|
case CELL_GCM_PRIMITIVE_POLYGON:
|
|
|
|
|
switch (type)
|
2015-09-28 22:51:32 +02:00
|
|
|
{
|
2015-10-15 23:06:14 +02:00
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
2015-11-10 22:34:57 +01:00
|
|
|
uploadAsIt<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
|
2015-09-28 22:51:32 +02:00
|
|
|
return;
|
2015-10-15 23:06:14 +02:00
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
2015-11-10 22:34:57 +01:00
|
|
|
uploadAsIt<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
|
2015-10-15 23:06:14 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
2015-11-10 22:34:57 +01:00
|
|
|
expandIndexedTriangleFan<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
|
2015-10-15 23:06:14 +02:00
|
|
|
return;
|
|
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
2015-11-10 22:34:57 +01:00
|
|
|
expandIndexedTriangleFan<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
|
2015-10-15 23:06:14 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case CELL_GCM_PRIMITIVE_QUADS:
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
2015-11-10 22:34:57 +01:00
|
|
|
expandIndexedQuads<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
|
2015-10-15 23:06:14 +02:00
|
|
|
return;
|
|
|
|
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
2015-11-10 22:34:57 +01:00
|
|
|
expandIndexedQuads<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
|
2015-09-28 22:51:32 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-31 18:08:49 +01:00
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
void stream_vector(void *dst, u32 x, u32 y, u32 z, u32 w)
|
2015-10-31 18:08:49 +01:00
|
|
|
{
|
|
|
|
|
__m128i vector = _mm_set_epi32(w, z, y, x);
|
|
|
|
|
_mm_stream_si128((__m128i*)dst, vector);
|
2015-10-31 18:19:45 +01:00
|
|
|
}
|
|
|
|
|
|
2015-12-17 18:31:27 +01:00
|
|
|
void stream_vector_from_memory(void *dst, void *src)
|
2015-10-31 18:19:45 +01:00
|
|
|
{
|
|
|
|
|
const __m128i &vector = _mm_loadu_si128((__m128i*)src);
|
|
|
|
|
_mm_stream_si128((__m128i*)dst, vector);
|
2015-12-17 18:31:27 +01:00
|
|
|
}
|