mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 06:51:26 +12:00
Remove RSXVertexArray
This commit is contained in:
parent
73535e0c04
commit
60bccf0f10
8 changed files with 206 additions and 210 deletions
|
@ -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);
|
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;
|
std::vector<VertexBufferFormat> Result;
|
||||||
for (size_t i = 0; i < rsx::limits::vertex_count; ++i)
|
for (size_t i = 0; i < rsx::limits::vertex_count; ++i)
|
||||||
{
|
{
|
||||||
const RSXVertexData &vertexData = m_vertex_data[i];
|
const rsx::data_array_format_info &vertexData = vertex_array_desc[i];
|
||||||
if (!vertexData.IsEnabled()) continue;
|
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
|
// If there is a single element, stride is 0, use the size of element instead
|
||||||
size_t stride = vertexData.stride;
|
size_t stride = vertexData.stride;
|
||||||
size_t elementSize = rsx::get_vertex_type_size(vertexData.type);
|
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;
|
size_t end = start + elementSize * vertexData.size + (elementCount - 1) * stride - 1;
|
||||||
std::pair<size_t, size_t> range = std::make_pair(start, end);
|
std::pair<size_t, size_t> range = std::make_pair(start, end);
|
||||||
assert(start < end);
|
assert(start < end);
|
||||||
|
@ -53,21 +55,24 @@ std::vector<VertexBufferFormat> FormatVertexData(const RSXVertexData *m_vertex_d
|
||||||
return Result;
|
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 (int vertex = 0; vertex < vbf.elementCount; vertex++)
|
||||||
{
|
{
|
||||||
for (size_t attributeId : vbf.attributeId)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
size_t offset = (size_t)vertexData[attributeId].addr + baseOffset - vbf.range.first;
|
size_t offset = (size_t)addr + baseOffset - vbf.range.first;
|
||||||
size_t tsize = rsx::get_vertex_type_size(vertexData[attributeId].type);
|
size_t tsize = rsx::get_vertex_type_size(vertex_array_desc[attributeId].type);
|
||||||
size_t size = vertexData[attributeId].size;
|
size_t size = vertex_array_desc[attributeId].size;
|
||||||
auto src = vm::get_ptr<const u8>(vertexData[attributeId].addr + (u32)baseOffset + (u32)vbf.stride * vertex);
|
auto src = vm::get_ptr<const u8>(addr + (u32)baseOffset + (u32)vbf.stride * vertex);
|
||||||
char* dst = (char*)bufferMap + offset + vbf.stride * vertex;
|
char* dst = (char*)bufferMap + offset + vbf.stride * vertex;
|
||||||
|
|
||||||
switch (tsize)
|
switch (tsize)
|
||||||
|
|
|
@ -17,12 +17,12 @@ struct VertexBufferFormat
|
||||||
* Detect buffer containing interleaved vertex attribute.
|
* Detect buffer containing interleaved vertex attribute.
|
||||||
* This minimizes memory upload size.
|
* 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.
|
* 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.
|
* If primitive mode is not supported and need to be emulated (using an index buffer) returns false.
|
||||||
|
|
|
@ -92,7 +92,7 @@ DXGI_FORMAT getFormat(u8 type, u8 size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
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;
|
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)
|
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 = {};
|
D3D12_INPUT_ELEMENT_DESC IAElement = {};
|
||||||
IAElement.SemanticName = "TEXCOORD";
|
IAElement.SemanticName = "TEXCOORD";
|
||||||
IAElement.SemanticIndex = (UINT)attributeId;
|
IAElement.SemanticIndex = (UINT)attributeId;
|
||||||
IAElement.InputSlot = (UINT)inputSlot;
|
IAElement.InputSlot = (UINT)inputSlot;
|
||||||
IAElement.Format = getFormat(vertexData.type - 1, vertexData.size);
|
IAElement.Format = getFormat(vertexData.type - 1, vertexData.size);
|
||||||
IAElement.AlignedByteOffset = (UINT)(vertexData.addr + baseOffset - vertexBufferFormat[inputSlot].range.first);
|
IAElement.AlignedByteOffset = (UINT)(addr + baseOffset - vertexBufferFormat[inputSlot].range.first);
|
||||||
IAElement.InputSlotClass = (vertexData.addr > 0) ? D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA : D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
IAElement.InputSlotClass = (addr > 0) ? D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA : D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
|
||||||
IAElement.InstanceDataStepRate = (vertexData.addr > 0) ? 0 : 0;
|
IAElement.InstanceDataStepRate = (addr > 0) ? 0 : 1;
|
||||||
result.push_back(IAElement);
|
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.
|
* Suballocate a new vertex buffer with attributes from vbf using vertexIndexHeap as storage heap.
|
||||||
*/
|
*/
|
||||||
static
|
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;
|
size_t subBufferSize = vbf.range.second - vbf.range.first + 1;
|
||||||
// Make multiple of stride
|
// Make multiple of stride
|
||||||
|
@ -134,7 +136,7 @@ D3D12_GPU_VIRTUAL_ADDRESS createVertexBuffer(const VertexBufferFormat &vbf, cons
|
||||||
void *buffer;
|
void *buffer;
|
||||||
ThrowIfFailed(vertexIndexHeap.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
ThrowIfFailed(vertexIndexHeap.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
||||||
void *bufferMap = (char*)buffer + heapOffset;
|
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));
|
vertexIndexHeap.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize));
|
||||||
return vertexIndexHeap.m_heap->GetGPUVirtualAddress() + heapOffset;
|
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> D3D12GSRender::UploadVertexBuffers(bool indexed_draw)
|
||||||
{
|
{
|
||||||
std::vector<D3D12_VERTEX_BUFFER_VIEW> result;
|
std::vector<D3D12_VERTEX_BUFFER_VIEW> result;
|
||||||
const std::vector<VertexBufferFormat> &vertexBufferFormat = FormatVertexData(m_vertex_data, m_vertexBufferSize, 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, m_vertex_data, 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;
|
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)
|
if (vbf.stride)
|
||||||
subBufferSize = ((subBufferSize + vbf.stride - 1) / vbf.stride) * 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;
|
m_timers.m_bufferUploadSize += subBufferSize;
|
||||||
|
|
||||||
D3D12_VERTEX_BUFFER_VIEW vertexBufferView = {};
|
D3D12_VERTEX_BUFFER_VIEW vertexBufferView = {};
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/RSX/RSXThread.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
|
#endif
|
|
@ -404,22 +404,22 @@ void D3D12GSRender::end()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
||||||
{
|
{
|
||||||
if (!m_vertex_data[i].IsEnabled()) continue;
|
if (!vertex_arrays_info[i].size) continue;
|
||||||
if (!m_vertex_data[i].addr) continue;
|
if (!vertex_arrays_info[i].array) continue;
|
||||||
|
|
||||||
const u32 tsize = rsx::get_vertex_type_size(m_vertex_data[i].type);
|
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 * m_vertex_data[i].size;
|
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
|
else
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
||||||
{
|
{
|
||||||
if (!m_vertex_data[i].IsEnabled()) continue;
|
if (!vertex_arrays_info[i].size) continue;
|
||||||
if (!m_vertex_data[i].addr) continue;
|
if (!vertex_arrays_info[i].array) continue;
|
||||||
|
|
||||||
const u32 tsize = rsx::get_vertex_type_size(m_vertex_data[i].type);
|
const u32 tsize = rsx::get_vertex_type_size(vertex_arrays_info[i].type);
|
||||||
m_vertexBufferSize[i] = (draw_array_first + draw_array_count) * tsize * m_vertex_data[i].size;
|
m_vertexBufferSize[i] = (draw_array_first + draw_array_count) * tsize * vertex_arrays_info[i].size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -840,14 +840,14 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
|
||||||
|
|
||||||
offset_list[i] = cur_offset;
|
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 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 size_t data_size = m_vertex_data[i].data.size() - data_offset * item_size;
|
||||||
const u32 pos = m_vdata.size();
|
const u32 pos = m_vdata.size();
|
||||||
|
|
||||||
cur_offset += data_size;
|
cur_offset += data_size;
|
||||||
m_vdata.resize(m_vdata.size() + 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();
|
m_vao.Create();
|
||||||
|
@ -872,7 +872,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
|
||||||
|
|
||||||
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
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
|
#if DUMP_VERTEX_DATA
|
||||||
dump.Write(wxString::Format("VertexData[%d]:\n", i));
|
dump.Write(wxString::Format("VertexData[%d]:\n", i));
|
||||||
|
@ -958,7 +958,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
|
||||||
GL_FALSE,
|
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);
|
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");
|
checkForGlError("glEnableVertexAttribArray");
|
||||||
glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, reinterpret_cast<void*>(offset_list[i]));
|
glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, reinterpret_cast<void*>(offset_list[i]));
|
||||||
checkForGlError("glVertexAttribPointer");
|
checkForGlError("glVertexAttribPointer");
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,7 +1014,7 @@ void GLGSRender::DisableVertexData()
|
||||||
m_vdata.clear();
|
m_vdata.clear();
|
||||||
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
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);
|
glDisableVertexAttribArray(i);
|
||||||
checkForGlError("glDisableVertexAttribArray");
|
checkForGlError("glDisableVertexAttribArray");
|
||||||
}
|
}
|
||||||
|
@ -1647,7 +1647,7 @@ void GLGSRender::end()
|
||||||
if (!m_indexed_array.m_count && !draw_array_count)
|
if (!m_indexed_array.m_count && !draw_array_count)
|
||||||
{
|
{
|
||||||
u32 min_vertex_size = ~0;
|
u32 min_vertex_size = ~0;
|
||||||
for (auto &i : m_vertex_data)
|
/* for (auto &i : m_vertex_data)
|
||||||
{
|
{
|
||||||
if (!i.size)
|
if (!i.size)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1656,7 +1656,7 @@ void GLGSRender::end()
|
||||||
|
|
||||||
if (min_vertex_size > vertex_size)
|
if (min_vertex_size > vertex_size)
|
||||||
min_vertex_size = vertex_size;
|
min_vertex_size = vertex_size;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
draw_array_count = min_vertex_size;
|
draw_array_count = min_vertex_size;
|
||||||
draw_array_first = 0;
|
draw_array_first = 0;
|
||||||
|
|
|
@ -28,6 +28,91 @@ namespace rsx
|
||||||
{
|
{
|
||||||
u32 method_registers[0x10000 >> 2];
|
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 linear_to_swizzle(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
|
||||||
{
|
{
|
||||||
u32 offset = 0;
|
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)
|
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);
|
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;
|
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
|
// Vertex data
|
||||||
case_range(16, NV4097_SET_VERTEX_DATA4UB_M, 4);
|
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);
|
||||||
const u32 a0 = ARGS(0);
|
bind_16(0, NV4097_SET_VERTEX_DATA4F_M, 16, rsx::nv4097::set_vertex_data4f_m);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_OFFSET, 4);
|
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;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4);
|
case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4);
|
||||||
{
|
{
|
||||||
const u32 a0 = ARGS(0);
|
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];
|
rsx::data_array_format_info &cv = vertex_arrays_info[index];
|
||||||
cv.frequency = frequency;
|
cv.unpack(a0);
|
||||||
cv.stride = stride;
|
cv.array = cv.size > 0;
|
||||||
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);
|
|
||||||
|
|
||||||
break;
|
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)
|
if (!m_indexed_array.m_count && !draw_array_count)
|
||||||
{
|
{
|
||||||
u32 min_vertex_size = ~0;
|
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)
|
if (!i.size)
|
||||||
continue;
|
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)
|
if (min_vertex_size > vertex_size)
|
||||||
min_vertex_size = vertex_size;
|
min_vertex_size = vertex_size;
|
||||||
|
@ -2183,9 +2171,9 @@ void RSXThread::End()
|
||||||
{
|
{
|
||||||
end();
|
end();
|
||||||
|
|
||||||
for (auto &vdata : m_vertex_data)
|
for (auto &vdata : vertex_arrays)
|
||||||
{
|
{
|
||||||
vdata.data.clear();
|
vdata.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_indexed_array.Reset();
|
m_indexed_array.Reset();
|
||||||
|
|
|
@ -59,6 +59,23 @@ namespace rsx
|
||||||
height = 1 << (u32(log2width) + 1);
|
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
|
enum Method
|
||||||
|
@ -69,24 +86,6 @@ enum Method
|
||||||
CELL_GCM_METHOD_FLAG_RETURN = 0x00020000,
|
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
|
struct RSXIndexArrayData
|
||||||
{
|
{
|
||||||
std::vector<u8> m_data;
|
std::vector<u8> m_data;
|
||||||
|
@ -149,7 +148,9 @@ public:
|
||||||
GcmZcullInfo zculls[rsx::limits::zculls_count];
|
GcmZcullInfo zculls[rsx::limits::zculls_count];
|
||||||
rsx::texture textures[rsx::limits::textures_count];
|
rsx::texture textures[rsx::limits::textures_count];
|
||||||
rsx::vertex_texture m_vertex_textures[rsx::limits::vertex_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;
|
RSXIndexArrayData m_indexed_array;
|
||||||
std::vector<RSXTransformConstant> m_fragment_constants;
|
std::vector<RSXTransformConstant> m_fragment_constants;
|
||||||
std::vector<RSXTransformConstant> m_transform_constants;
|
std::vector<RSXTransformConstant> m_transform_constants;
|
||||||
|
@ -603,9 +604,9 @@ protected:
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < rsx::limits::vertex_count; ++i)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue