Remove RSXVertexArray

This commit is contained in:
Vincent Lejeune 2015-10-11 01:07:47 +02:00
parent 73535e0c04
commit 60bccf0f10
8 changed files with 206 additions and 210 deletions

View file

@ -12,20 +12,22 @@ bool overlaps(const std::pair<size_t, size_t> &range1, const std::pair<size_t, s
return !(range1.second < range2.first || range2.second < range1.first);
}
std::vector<VertexBufferFormat> FormatVertexData(const RSXVertexData *m_vertex_data, size_t *vertex_data_size, size_t base_offset)
std::vector<VertexBufferFormat> FormatVertexData(const rsx::data_array_format_info *vertex_array_desc, const std::vector<u8> *vertex_data, size_t *vertex_data_size, size_t base_offset)
{
std::vector<VertexBufferFormat> Result;
for (size_t i = 0; i < rsx::limits::vertex_count; ++i)
{
const RSXVertexData &vertexData = m_vertex_data[i];
if (!vertexData.IsEnabled()) continue;
const rsx::data_array_format_info &vertexData = vertex_array_desc[i];
if (!vertexData.size) continue;
size_t elementCount = ((vertexData.addr) ? vertex_data_size[i] : m_vertex_data[i].data.size()) / (vertexData.size * rsx::get_vertex_type_size(vertexData.type));
u32 addrRegVal = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 4 * i];
u32 addr = rsx::get_address(addrRegVal & 0x7fffffff, addrRegVal >> 31);
size_t elementCount = ((vertexData.array) ? vertex_data_size[i] : vertex_data[i].size()) / (vertexData.size * rsx::get_vertex_type_size(vertexData.type));
// If there is a single element, stride is 0, use the size of element instead
size_t stride = vertexData.stride;
size_t elementSize = rsx::get_vertex_type_size(vertexData.type);
size_t start = vertexData.addr + base_offset;
size_t start = addr + base_offset;
size_t end = start + elementSize * vertexData.size + (elementCount - 1) * stride - 1;
std::pair<size_t, size_t> range = std::make_pair(start, end);
assert(start < end);
@ -53,21 +55,24 @@ std::vector<VertexBufferFormat> FormatVertexData(const RSXVertexData *m_vertex_d
return Result;
}
void uploadVertexData(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, size_t baseOffset, void* bufferMap)
void uploadVertexData(const VertexBufferFormat &vbf, const rsx::data_array_format_info *vertex_array_desc, const std::vector<u8> *vertex_data, size_t baseOffset, void* bufferMap)
{
for (int vertex = 0; vertex < vbf.elementCount; vertex++)
{
for (size_t attributeId : vbf.attributeId)
{
if (!vertexData[attributeId].addr)
u32 addrRegVal = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 4 * attributeId];
u32 addr = rsx::get_address(addrRegVal & 0x7fffffff, addrRegVal >> 31);
if (!vertex_array_desc[attributeId].array)
{
memcpy(bufferMap, vertexData[attributeId].data.data(), vertexData[attributeId].data.size());
memcpy(bufferMap, vertex_data[attributeId].data(), vertex_data[attributeId].size());
continue;
}
size_t offset = (size_t)vertexData[attributeId].addr + baseOffset - vbf.range.first;
size_t tsize = rsx::get_vertex_type_size(vertexData[attributeId].type);
size_t size = vertexData[attributeId].size;
auto src = vm::get_ptr<const u8>(vertexData[attributeId].addr + (u32)baseOffset + (u32)vbf.stride * vertex);
size_t offset = (size_t)addr + baseOffset - vbf.range.first;
size_t tsize = rsx::get_vertex_type_size(vertex_array_desc[attributeId].type);
size_t size = vertex_array_desc[attributeId].size;
auto src = vm::get_ptr<const u8>(addr + (u32)baseOffset + (u32)vbf.stride * vertex);
char* dst = (char*)bufferMap + offset + vbf.stride * vertex;
switch (tsize)

View file

@ -17,12 +17,12 @@ struct VertexBufferFormat
* Detect buffer containing interleaved vertex attribute.
* This minimizes memory upload size.
*/
std::vector<VertexBufferFormat> FormatVertexData(const RSXVertexData *m_vertex_data, size_t *vertex_data_size, size_t base_offset);
std::vector<VertexBufferFormat> FormatVertexData(const rsx::data_array_format_info *vertex_array_desc, const std::vector<u8> *vertex_data, size_t *vertex_data_size, size_t base_offset);
/*
* Write vertex attributes to bufferMap, swapping data as required.
*/
void uploadVertexData(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, size_t baseOffset, void* bufferMap);
void uploadVertexData(const VertexBufferFormat &vbf, const rsx::data_array_format_info *vertex_array_desc, const std::vector<u8> *vertex_data, size_t baseOffset, void* bufferMap);
/*
* If primitive mode is not supported and need to be emulated (using an index buffer) returns false.

View file

@ -92,7 +92,7 @@ DXGI_FORMAT getFormat(u8 type, u8 size)
}
static
std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, const std::vector<VertexBufferFormat> &vertexBufferFormat, const RSXVertexData *m_vertex_data, size_t baseOffset)
std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, const std::vector<VertexBufferFormat> &vertexBufferFormat, const rsx::data_array_format_info *m_vertex_data, size_t baseOffset)
{
std::vector<D3D12_INPUT_ELEMENT_DESC> result;
@ -100,15 +100,17 @@ std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, const st
{
for (size_t attributeId : vertexBufferFormat[inputSlot].attributeId)
{
const RSXVertexData &vertexData = m_vertex_data[attributeId];
u32 addrRegVal = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + 4 * attributeId];
u32 addr = rsx::get_address(addrRegVal & 0x7fffffff, addrRegVal >> 31);
const rsx::data_array_format_info &vertexData = m_vertex_data[attributeId];
D3D12_INPUT_ELEMENT_DESC IAElement = {};
IAElement.SemanticName = "TEXCOORD";
IAElement.SemanticIndex = (UINT)attributeId;
IAElement.InputSlot = (UINT)inputSlot;
IAElement.Format = getFormat(vertexData.type - 1, vertexData.size);
IAElement.AlignedByteOffset = (UINT)(vertexData.addr + baseOffset - vertexBufferFormat[inputSlot].range.first);
IAElement.InputSlotClass = (vertexData.addr > 0) ? D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA : D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
IAElement.InstanceDataStepRate = (vertexData.addr > 0) ? 0 : 0;
IAElement.AlignedByteOffset = (UINT)(addr + baseOffset - vertexBufferFormat[inputSlot].range.first);
IAElement.InputSlotClass = (addr > 0) ? D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA : D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
IAElement.InstanceDataStepRate = (addr > 0) ? 0 : 1;
result.push_back(IAElement);
}
}
@ -122,7 +124,7 @@ std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, const st
* Suballocate a new vertex buffer with attributes from vbf using vertexIndexHeap as storage heap.
*/
static
D3D12_GPU_VIRTUAL_ADDRESS createVertexBuffer(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, size_t baseOffset, ID3D12Device *device, DataHeap<ID3D12Resource, 65536> &vertexIndexHeap)
D3D12_GPU_VIRTUAL_ADDRESS createVertexBuffer(const VertexBufferFormat &vbf, const rsx::data_array_format_info *vertex_array_desc, const std::vector<u8> *vertex_data, size_t baseOffset, ID3D12Device *device, DataHeap<ID3D12Resource, 65536> &vertexIndexHeap)
{
size_t subBufferSize = vbf.range.second - vbf.range.first + 1;
// Make multiple of stride
@ -134,7 +136,7 @@ D3D12_GPU_VIRTUAL_ADDRESS createVertexBuffer(const VertexBufferFormat &vbf, cons
void *buffer;
ThrowIfFailed(vertexIndexHeap.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
void *bufferMap = (char*)buffer + heapOffset;
uploadVertexData(vbf, vertexData, baseOffset, bufferMap);
uploadVertexData(vbf, vertex_array_desc, vertex_data, baseOffset, bufferMap);
vertexIndexHeap.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize));
return vertexIndexHeap.m_heap->GetGPUVirtualAddress() + heapOffset;
}
@ -142,8 +144,8 @@ D3D12_GPU_VIRTUAL_ADDRESS createVertexBuffer(const VertexBufferFormat &vbf, cons
std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool indexed_draw)
{
std::vector<D3D12_VERTEX_BUFFER_VIEW> result;
const std::vector<VertexBufferFormat> &vertexBufferFormat = FormatVertexData(m_vertex_data, m_vertexBufferSize, m_vertex_data_base_offset);
m_IASet = getIALayout(m_device.Get(), vertexBufferFormat, m_vertex_data, m_vertex_data_base_offset);
const std::vector<VertexBufferFormat> &vertexBufferFormat = FormatVertexData(vertex_arrays_info, vertex_arrays, m_vertexBufferSize, m_vertex_data_base_offset);
m_IASet = getIALayout(m_device.Get(), vertexBufferFormat, vertex_arrays_info, m_vertex_data_base_offset);
const u32 data_offset = indexed_draw ? 0 : draw_array_first;
@ -155,7 +157,7 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool in
if (vbf.stride)
subBufferSize = ((subBufferSize + vbf.stride - 1) / vbf.stride) * vbf.stride;
D3D12_GPU_VIRTUAL_ADDRESS virtualAddress = createVertexBuffer(vbf, m_vertex_data, m_vertex_data_base_offset, m_device.Get(), m_vertexIndexData);
D3D12_GPU_VIRTUAL_ADDRESS virtualAddress = createVertexBuffer(vbf, vertex_arrays_info, vertex_arrays, m_vertex_data_base_offset, m_device.Get(), m_vertexIndexData);
m_timers.m_bufferUploadSize += subBufferSize;
D3D12_VERTEX_BUFFER_VIEW vertexBufferView = {};

View file

@ -4,6 +4,6 @@
#include "Emu/Memory/vm.h"
#include "Emu/RSX/RSXThread.h"
std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, bool indexedDraw, const RSXVertexData *vertexData);
std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, bool indexedDraw, const rsx::data_array_format_info *vertexData);
#endif

View file

@ -404,22 +404,22 @@ void D3D12GSRender::end()
{
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
if (!m_vertex_data[i].IsEnabled()) continue;
if (!m_vertex_data[i].addr) continue;
if (!vertex_arrays_info[i].size) continue;
if (!vertex_arrays_info[i].array) continue;
const u32 tsize = rsx::get_vertex_type_size(m_vertex_data[i].type);
m_vertexBufferSize[i] = (m_indexed_array.index_min + m_indexed_array.index_max - m_indexed_array.index_min + 1) * tsize * m_vertex_data[i].size;
const u32 tsize = rsx::get_vertex_type_size(vertex_arrays_info[i].type);
m_vertexBufferSize[i] = (m_indexed_array.index_min + m_indexed_array.index_max - m_indexed_array.index_min + 1) * tsize * vertex_arrays_info[i].size;
}
}
else
{
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
if (!m_vertex_data[i].IsEnabled()) continue;
if (!m_vertex_data[i].addr) continue;
if (!vertex_arrays_info[i].size) continue;
if (!vertex_arrays_info[i].array) continue;
const u32 tsize = rsx::get_vertex_type_size(m_vertex_data[i].type);
m_vertexBufferSize[i] = (draw_array_first + draw_array_count) * tsize * m_vertex_data[i].size;
const u32 tsize = rsx::get_vertex_type_size(vertex_arrays_info[i].type);
m_vertexBufferSize[i] = (draw_array_first + draw_array_count) * tsize * vertex_arrays_info[i].size;
}
}

View file

@ -840,14 +840,14 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
offset_list[i] = cur_offset;
if (!m_vertex_data[i].IsEnabled()) continue;
/* if (!m_vertex_data[i].IsEnabled()) continue;
const size_t item_size = rsx::get_vertex_type_size(m_vertex_data[i].type) * m_vertex_data[i].size;
const size_t data_size = m_vertex_data[i].data.size() - data_offset * item_size;
const u32 pos = m_vdata.size();
cur_offset += data_size;
m_vdata.resize(m_vdata.size() + data_size);
memcpy(&m_vdata[pos], &m_vertex_data[i].data[data_offset * item_size], data_size);
memcpy(&m_vdata[pos], &m_vertex_data[i].data[data_offset * item_size], data_size);*/
}
m_vao.Create();
@ -872,7 +872,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
if (!m_vertex_data[i].IsEnabled()) continue;
// if (!m_vertex_data[i].IsEnabled()) continue;
#if DUMP_VERTEX_DATA
dump.Write(wxString::Format("VertexData[%d]:\n", i));
@ -958,7 +958,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
GL_FALSE,
};
if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7)
/* if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7)
{
LOG_ERROR(RSX, "GLGSRender::EnableVertexData: Bad vertex data type (%d)!", m_vertex_data[i].type);
}
@ -1005,7 +1005,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
checkForGlError("glEnableVertexAttribArray");
glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, reinterpret_cast<void*>(offset_list[i]));
checkForGlError("glVertexAttribPointer");
}
}*/
}
}
@ -1014,7 +1014,7 @@ void GLGSRender::DisableVertexData()
m_vdata.clear();
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
if (!m_vertex_data[i].IsEnabled()) continue;
// if (!m_vertex_data[i].IsEnabled()) continue;
glDisableVertexAttribArray(i);
checkForGlError("glDisableVertexAttribArray");
}
@ -1647,7 +1647,7 @@ void GLGSRender::end()
if (!m_indexed_array.m_count && !draw_array_count)
{
u32 min_vertex_size = ~0;
for (auto &i : m_vertex_data)
/* for (auto &i : m_vertex_data)
{
if (!i.size)
continue;
@ -1656,7 +1656,7 @@ void GLGSRender::end()
if (min_vertex_size > vertex_size)
min_vertex_size = vertex_size;
}
}*/
draw_array_count = min_vertex_size;
draw_array_first = 0;

View file

@ -28,6 +28,91 @@ namespace rsx
{
u32 method_registers[0x10000 >> 2];
template<typename Type> struct vertex_data_type_from_element_type;
template<> struct vertex_data_type_from_element_type<float> { enum { type = CELL_GCM_VERTEX_F }; };
template<> struct vertex_data_type_from_element_type<f16> { enum { type = CELL_GCM_VERTEX_SF }; };
template<> struct vertex_data_type_from_element_type<u8> { enum { type = CELL_GCM_VERTEX_UB }; };
template<> struct vertex_data_type_from_element_type<u16> { enum { type = CELL_GCM_VERTEX_S1 }; };
namespace nv4097
{
//fire only when all data passed to rsx cmd buffer
template<u32 id, u32 index, int count, typename type>
force_inline void set_vertex_data_impl(RSXThread* rsx, u32 arg)
{
static const size_t element_size = (count * sizeof(type));
static const size_t element_size_in_words = element_size / sizeof(u32);
auto& info = rsx->vertex_arrays_info[index];
info.type = vertex_data_type_from_element_type<type>::type;
info.size = count;
info.frequency = 0;
info.stride = 0;
info.array = false;
auto& entry = rsx->vertex_arrays[index];
//find begin of data
size_t begin = id + index * element_size_in_words;
size_t position = entry.size();
entry.resize(position + element_size);
memcpy(entry.data() + position, method_registers + begin, element_size);
}
template<u32 index>
force_inline void set_vertex_data4ub_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4UB_M, index, 4, u8>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data1f_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 1, f32>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data2f_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 2, f32>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data3f_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 3, f32>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data4f_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA1F_M, index, 4, f32>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data2s_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA2S_M, index, 2, u16>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data4s_m(RSXThread* rsx, u32 arg)
{
set_vertex_data_impl<NV4097_SET_VERTEX_DATA4S_M, index, 4, u16>(rsx, arg);
}
template<u32 index>
force_inline void set_vertex_data_array_format(RSXThread* rsx, u32 arg)
{
auto& info = rsx->vertex_arrays_info[index];
info.unpack(arg);
info.array = info.size > 0;
}
}
u32 linear_to_swizzle(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
{
u32 offset = 0;
@ -120,66 +205,6 @@ namespace rsx
}
}
RSXVertexData::RSXVertexData()
: frequency(0)
, stride(0)
, size(0)
, type(0)
, addr(0)
, data()
{
}
void RSXVertexData::Reset()
{
frequency = 0;
stride = 0;
size = 0;
type = 0;
addr = 0;
data.clear();
}
void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex = 0)
{
if (!addr) return;
const u32 tsize = rsx::get_vertex_type_size(type);
data.resize((start + count) * tsize * size);
for (u32 i = start; i < start + count; ++i)
{
auto src = vm::get_ptr<const u8>(addr + baseOffset + stride * (i + baseIndex));
u8* dst = &data[i * tsize * size];
switch (tsize)
{
case 1:
{
memcpy(dst, src, size);
break;
}
case 2:
{
auto c_src = (const be_t<u16>*)src;
auto c_dst = (u16*)dst;
for (u32 j = 0; j < size; ++j) *c_dst++ = *c_src++;
break;
}
case 4:
{
auto c_src = (const be_t<u32>*)src;
auto c_dst = (u32*)dst;
for (u32 j = 0; j < size; ++j) *c_dst++ = *c_src++;
break;
}
}
}
}
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr)
{
auto args = vm::ps3::ptr<u32>::make(args_addr);
@ -440,99 +465,61 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
break;
}
#define bind_2(index, offset, step, func) \
case offset : \
func<index>(this, ARGS(0)); \
break; \
case offset + step: \
func<index + 1>(this, ARGS(0)); \
break;
#define bind_4(index, offset, step, func) \
bind_2(index, offset, step, func); \
bind_2(index + 2, offset + 2*step, step, func)
#define bind_8(index, offset, step, func) \
bind_4(index, offset, step, func); \
bind_4(index + 4, offset + 4*step, step, func)
#define bind_16(index, offset, step, func) \
bind_8(index, offset, step, func); \
bind_8(index + 8, offset + 8*step, step, func)
#define bind_32(index, offset, step, func) \
bind_16(index, offset, step, func); \
bind_16(index + 16, offset + 16*step, step, func)
#define bind_64(index, offset, step, func) \
bind_32(index, offset, step, func); \
bind_32(index + 32, offset + 32*step, step, func)
#define bind_128(index, offset, step, func) \
bind_64(index, offset, step, func); \
bind_64(index + 64, offset + 64*step, step, func)
#define bind_256(index, offset, step, func) \
bind_128(index, offset, step, func); \
bind_128(index + 128, offset + 128*step, step, func)
#define bind_512(index, offset, step, func) \
bind_256(index, offset, step, func); \
bind_256(index + 256, offset + 256*step, step, func)
// Vertex data
case_range(16, NV4097_SET_VERTEX_DATA4UB_M, 4);
{
const u32 a0 = ARGS(0);
u8 v0 = a0;
u8 v1 = a0 >> 8;
u8 v2 = a0 >> 16;
u8 v3 = a0 >> 24;
m_vertex_data[index].Reset();
m_vertex_data[index].size = 4;
m_vertex_data[index].type = CELL_GCM_VERTEX_UB;
m_vertex_data[index].data.push_back(v0);
m_vertex_data[index].data.push_back(v1);
m_vertex_data[index].data.push_back(v2);
m_vertex_data[index].data.push_back(v3);
//LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA4UB_M: index = %d, v0 = 0x%x, v1 = 0x%x, v2 = 0x%x, v3 = 0x%x", index, v0, v1, v2, v3);
break;
}
case_range(16, NV4097_SET_VERTEX_DATA2F_M, 8);
{
const u32 a0 = ARGS(0);
const u32 a1 = ARGS(1);
float v0 = (float&)a0;
float v1 = (float&)a1;
m_vertex_data[index].Reset();
m_vertex_data[index].type = CELL_GCM_VERTEX_F;
m_vertex_data[index].size = 2;
u32 pos = m_vertex_data[index].data.size();
m_vertex_data[index].data.resize(pos + sizeof(float) * 2);
(float&)m_vertex_data[index].data[pos + sizeof(float) * 0] = v0;
(float&)m_vertex_data[index].data[pos + sizeof(float) * 1] = v1;
//LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA2F_M: index = %d, v0 = %f, v1 = %f", index, v0, v1);
break;
}
case_range(16, NV4097_SET_VERTEX_DATA4F_M, 16);
{
const u32 a0 = ARGS(0);
const u32 a1 = ARGS(1);
const u32 a2 = ARGS(2);
const u32 a3 = ARGS(3);
float v0 = (float&)a0;
float v1 = (float&)a1;
float v2 = (float&)a2;
float v3 = (float&)a3;
m_vertex_data[index].Reset();
m_vertex_data[index].type = CELL_GCM_VERTEX_F;
m_vertex_data[index].size = 4;
u32 pos = m_vertex_data[index].data.size();
m_vertex_data[index].data.resize(pos + sizeof(float) * 4);
(float&)m_vertex_data[index].data[pos + sizeof(float) * 0] = v0;
(float&)m_vertex_data[index].data[pos + sizeof(float) * 1] = v1;
(float&)m_vertex_data[index].data[pos + sizeof(float) * 2] = v2;
(float&)m_vertex_data[index].data[pos + sizeof(float) * 3] = v3;
//LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA4F_M: index = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", index, v0, v1, v2, v3);
break;
}
bind_16(0, NV4097_SET_VERTEX_DATA4UB_M, 4, rsx::nv4097::set_vertex_data4ub_m);
bind_16(0, NV4097_SET_VERTEX_DATA2F_M, 8, rsx::nv4097::set_vertex_data2f_m);
bind_16(0, NV4097_SET_VERTEX_DATA4F_M, 16, rsx::nv4097::set_vertex_data4f_m);
case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_OFFSET, 4);
{
const u32 addr = rsx::get_address(ARGS(0) & 0x7fffffff, ARGS(0) >> 31);
m_vertex_data[index].addr = addr;
m_vertex_data[index].data.clear();
//LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA_ARRAY_OFFSET: num=%d, addr=0x%x", index, addr);
break;
}
case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4);
{
const u32 a0 = ARGS(0);
u16 frequency = a0 >> 16;
u8 stride = (a0 >> 8) & 0xff;
u8 size = (a0 >> 4) & 0xf;
u8 type = a0 & 0xf;
RSXVertexData& cv = m_vertex_data[index];
cv.frequency = frequency;
cv.stride = stride;
cv.size = size;
cv.type = type;
//LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA_ARRAY_FORMAT: index=%d, frequency=%d, stride=%d, size=%d, type=%d", index, frequency, stride, size, type);
rsx::data_array_format_info &cv = vertex_arrays_info[index];
cv.unpack(a0);
cv.array = cv.size > 0;
break;
}
@ -948,12 +935,13 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
if (!m_indexed_array.m_count && !draw_array_count)
{
u32 min_vertex_size = ~0;
for (auto &i : m_vertex_data)
for (unsigned id = 0; id < rsx::limits::vertex_count; id++)
{
auto &i = vertex_arrays_info[id];
if (!i.size)
continue;
u32 vertex_size = i.data.size() / (i.size * rsx::get_vertex_type_size(i.type));
u32 vertex_size = vertex_arrays[id].size() / (i.size * rsx::get_vertex_type_size(i.type));
if (min_vertex_size > vertex_size)
min_vertex_size = vertex_size;
@ -2183,9 +2171,9 @@ void RSXThread::End()
{
end();
for (auto &vdata : m_vertex_data)
for (auto &vdata : vertex_arrays)
{
vdata.data.clear();
vdata.clear();
}
m_indexed_array.Reset();

View file

@ -59,6 +59,23 @@ namespace rsx
height = 1 << (u32(log2width) + 1);
}
};
struct data_array_format_info
{
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
u8 type = CELL_GCM_VERTEX_F;
bool array = false;
void unpack(u32 data_array_format)
{
frequency = data_array_format >> 16;
stride = (data_array_format >> 8) & 0xff;
size = (data_array_format >> 4) & 0xf;
type = data_array_format & 0xf;
}
};
}
enum Method
@ -69,24 +86,6 @@ enum Method
CELL_GCM_METHOD_FLAG_RETURN = 0x00020000,
};
struct RSXVertexData
{
u32 frequency;
u32 stride;
u32 size;
u32 type;
u32 addr;
u32 constant_count;
std::vector<u8> data;
RSXVertexData();
void Reset();
bool IsEnabled() const { return size > 0; }
void Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex);
};
struct RSXIndexArrayData
{
std::vector<u8> m_data;
@ -149,7 +148,9 @@ public:
GcmZcullInfo zculls[rsx::limits::zculls_count];
rsx::texture textures[rsx::limits::textures_count];
rsx::vertex_texture m_vertex_textures[rsx::limits::vertex_textures_count];
RSXVertexData m_vertex_data[rsx::limits::vertex_count];
rsx::data_array_format_info vertex_arrays_info[rsx::limits::vertex_count];
std::vector<u8> vertex_arrays[rsx::limits::vertex_count];
RSXIndexArrayData m_indexed_array;
std::vector<RSXTransformConstant> m_fragment_constants;
std::vector<RSXTransformConstant> m_transform_constants;
@ -603,9 +604,9 @@ protected:
{
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
{
if (!m_vertex_data[i].IsEnabled()) continue;
// if (!m_vertex_data[i].IsEnabled()) continue;
m_vertex_data[i].Load(first, count, m_vertex_data_base_offset, m_vertex_data_base_index);
// m_vertex_data[i].Load(first, count, m_vertex_data_base_offset, m_vertex_data_base_index);
}
}