mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-11 01:08:39 +12:00
d3d12: Avoid copying index data and use correct index range.
This fixes Braid.
This commit is contained in:
parent
bc7e30517b
commit
9f49232cac
6 changed files with 255 additions and 173 deletions
|
@ -109,34 +109,88 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IndexType, typename DstType, typename SrcType>
|
template<typename IndexType>
|
||||||
void expandIndexedTriangleFan(DstType *dst, const SrcType *src, size_t indexCount)
|
void uploadAsIt(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 &min_index, u32 &max_index)
|
||||||
{
|
{
|
||||||
IndexType *typedDst = reinterpret_cast<IndexType *>(dst);
|
for (u32 i = 0; i < indexCount; ++i)
|
||||||
const IndexType *typedSrc = reinterpret_cast<const IndexType *>(src);
|
|
||||||
for (unsigned i = 0; i < indexCount - 2; i++)
|
|
||||||
{
|
{
|
||||||
typedDst[3 * i] = typedSrc[0];
|
IndexType index = vm::ps3::_ref<IndexType>(address + i * sizeof(IndexType));
|
||||||
typedDst[3 * i + 1] = typedSrc[i + 2 - 1];
|
(IndexType&)dst[i * sizeof(IndexType)] = index;
|
||||||
typedDst[3 * i + 2] = typedSrc[i + 2];
|
if (is_primitive_restart_enabled && index == (IndexType)-1) // Cut
|
||||||
|
continue;
|
||||||
|
max_index = MAX2(max_index, index);
|
||||||
|
min_index = MIN2(min_index, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IndexType, typename DstType, typename SrcType>
|
template<typename IndexType>
|
||||||
void expandIndexedQuads(DstType *dst, const SrcType *src, size_t indexCount)
|
void expandIndexedTriangleFan(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 &min_index, u32 &max_index)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < indexCount - 2; i++)
|
||||||
|
{
|
||||||
|
IndexType index0 = vm::ps3::_ref<IndexType>(address);
|
||||||
|
(IndexType&)dst[(3 * i) * sizeof(IndexType)] = index0;
|
||||||
|
IndexType index1 = vm::ps3::_ref<IndexType>(address + (i + 2 - 1) * sizeof(IndexType));
|
||||||
|
(IndexType&)dst[(3 * i + 1) * sizeof(IndexType)] = index1;
|
||||||
|
IndexType index2 = vm::ps3::_ref<IndexType>(address + (i + 2) * sizeof(IndexType));
|
||||||
|
(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IndexType>
|
||||||
|
void expandIndexedQuads(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 &min_index, u32 &max_index)
|
||||||
{
|
{
|
||||||
IndexType *typedDst = reinterpret_cast<IndexType *>(dst);
|
|
||||||
const IndexType *typedSrc = reinterpret_cast<const IndexType *>(src);
|
|
||||||
for (unsigned i = 0; i < indexCount / 4; i++)
|
for (unsigned i = 0; i < indexCount / 4; i++)
|
||||||
{
|
{
|
||||||
// First triangle
|
// First triangle
|
||||||
typedDst[6 * i] = typedSrc[4 * i];
|
IndexType index0 = vm::ps3::_ref<IndexType>(address + 4 * i * sizeof(IndexType));
|
||||||
typedDst[6 * i + 1] = typedSrc[4 * i + 1];
|
(IndexType&)dst[(6 * i) * sizeof(IndexType)] = index0;
|
||||||
typedDst[6 * i + 2] = typedSrc[4 * i + 2];
|
IndexType index1 = vm::ps3::_ref<IndexType>(address + (4 * i + 1) * sizeof(IndexType));
|
||||||
|
(IndexType&)dst[(6 * i + 1) * sizeof(IndexType)] = index1;
|
||||||
|
IndexType index2 = vm::ps3::_ref<IndexType>(address + (4 * i + 2) * sizeof(IndexType));
|
||||||
|
(IndexType&)dst[(6 * i + 2) * sizeof(IndexType)] = index2;
|
||||||
// Second triangle
|
// Second triangle
|
||||||
typedDst[6 * i + 3] = typedSrc[4 * i + 2];
|
(IndexType&)dst[(6 * i + 3) * sizeof(IndexType)] = index2;
|
||||||
typedDst[6 * i + 4] = typedSrc[4 * i + 3];
|
IndexType index3 = vm::ps3::_ref<IndexType>(address + (4 * i + 3) * sizeof(IndexType));
|
||||||
typedDst[6 * i + 5] = typedSrc[4 * i];
|
(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,11 +232,46 @@ size_t getIndexCount(unsigned m_draw_mode, unsigned initial_index_count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, unsigned draw_mode, unsigned first, unsigned count)
|
||||||
void uploadIndexData(unsigned m_draw_mode, unsigned index_type, void* indexBuffer, void* bufferMap, unsigned element_count)
|
|
||||||
{
|
{
|
||||||
if (indexBuffer != nullptr)
|
unsigned short *typedDst = (unsigned short *)(dst);
|
||||||
|
switch (draw_mode)
|
||||||
{
|
{
|
||||||
|
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||||
|
for (unsigned i = 0; i < (count - 2); i++)
|
||||||
|
{
|
||||||
|
typedDst[3 * i] = first;
|
||||||
|
typedDst[3 * i + 1] = i + 2 - 1;
|
||||||
|
typedDst[3 * i + 2] = i + 2;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count, unsigned &min_index, unsigned &max_index)
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
|
||||||
switch (m_draw_mode)
|
switch (m_draw_mode)
|
||||||
{
|
{
|
||||||
case CELL_GCM_PRIMITIVE_POINTS:
|
case CELL_GCM_PRIMITIVE_POINTS:
|
||||||
|
@ -193,64 +282,34 @@ void uploadIndexData(unsigned m_draw_mode, unsigned index_type, void* indexBuffe
|
||||||
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
|
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
|
||||||
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
|
||||||
case CELL_GCM_PRIMITIVE_POLYGON:
|
case CELL_GCM_PRIMITIVE_POLYGON:
|
||||||
{
|
switch (type)
|
||||||
size_t indexSize = (index_type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32) ? 4 : 2;
|
|
||||||
memcpy(bufferMap, indexBuffer, indexSize * element_count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
|
||||||
switch (index_type)
|
|
||||||
{
|
{
|
||||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||||
expandIndexedTriangleFan<unsigned int>(bufferMap, indexBuffer, element_count);
|
uploadAsIt<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, min_index, max_index);
|
||||||
return;
|
return;
|
||||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||||
expandIndexedTriangleFan<unsigned short>(bufferMap, indexBuffer, element_count);
|
uploadAsIt<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, min_index, max_index);
|
||||||
return;
|
return;
|
||||||
default:
|
}
|
||||||
abort();
|
return;
|
||||||
|
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||||
|
expandIndexedTriangleFan<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, min_index, max_index);
|
||||||
|
return;
|
||||||
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||||
|
expandIndexedTriangleFan<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, min_index, max_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case CELL_GCM_PRIMITIVE_QUADS:
|
case CELL_GCM_PRIMITIVE_QUADS:
|
||||||
switch (index_type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||||
expandIndexedQuads<unsigned int>(bufferMap, indexBuffer, element_count);
|
expandIndexedQuads<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, min_index, max_index);
|
||||||
return;
|
return;
|
||||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||||
expandIndexedQuads<unsigned short>(bufferMap, indexBuffer, element_count);
|
expandIndexedQuads<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, min_index, max_index);
|
||||||
return;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned short *typedDst = static_cast<unsigned short *>(bufferMap);
|
|
||||||
switch (m_draw_mode)
|
|
||||||
{
|
|
||||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
|
||||||
for (unsigned i = 0; i < (element_count - 2); i++)
|
|
||||||
{
|
|
||||||
typedDst[3 * i] = 0;
|
|
||||||
typedDst[3 * i + 1] = i + 2 - 1;
|
|
||||||
typedDst[3 * i + 2] = i + 2;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case CELL_GCM_PRIMITIVE_QUADS:
|
|
||||||
for (unsigned i = 0; i < element_count / 4; i++)
|
|
||||||
{
|
|
||||||
// First triangle
|
|
||||||
typedDst[6 * i] = 4 * i;
|
|
||||||
typedDst[6 * i + 1] = 4 * i + 1;
|
|
||||||
typedDst[6 * i + 2] = 4 * i + 2;
|
|
||||||
// Second triangle
|
|
||||||
typedDst[6 * i + 3] = 4 * i + 2;
|
|
||||||
typedDst[6 * i + 4] = 4 * i + 3;
|
|
||||||
typedDst[6 * i + 5] = 4 * i;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,13 @@ bool isNativePrimitiveMode(unsigned m_draw_mode);
|
||||||
size_t getIndexCount(unsigned m_draw_mode, unsigned initial_index_count);
|
size_t getIndexCount(unsigned m_draw_mode, unsigned initial_index_count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write index information to bufferMap
|
* Write count indexes starting at first to dst buffer.
|
||||||
|
* Returns min/max index found during the process.
|
||||||
|
* The function expands index buffer for non native primitive type.
|
||||||
*/
|
*/
|
||||||
void uploadIndexData(unsigned m_draw_mode, unsigned index_type, void* indexBuffer, void* bufferMap, unsigned element_count);
|
void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count, unsigned &min_index, unsigned &max_index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write index data needed to emulate non indexed non native primitive mode.
|
||||||
|
*/
|
||||||
|
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count);
|
|
@ -118,13 +118,17 @@ void D3D12GSRender::load_vertex_data(u32 first, u32 count)
|
||||||
vertex_draw_count += count;
|
vertex_draw_count += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void D3D12GSRender::upload_vertex_attributes(const std::vector<std::pair<u32, u32> > &vertex_ranges)
|
||||||
void D3D12GSRender::upload_vertex_attributes()
|
|
||||||
{
|
{
|
||||||
m_vertex_buffer_views.clear();
|
m_vertex_buffer_views.clear();
|
||||||
m_IASet.clear();
|
m_IASet.clear();
|
||||||
size_t inputSlot = 0;
|
size_t inputSlot = 0;
|
||||||
|
|
||||||
|
size_t vertex_count = 0;
|
||||||
|
|
||||||
|
for (const auto &pair : vertex_ranges)
|
||||||
|
vertex_count += pair.second;
|
||||||
|
|
||||||
// First array attribute
|
// First array attribute
|
||||||
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
for (int index = 0; index < rsx::limits::vertex_count; ++index)
|
||||||
{
|
{
|
||||||
|
@ -136,14 +140,14 @@ void D3D12GSRender::upload_vertex_attributes()
|
||||||
u32 type_size = rsx::get_vertex_type_size(info.type);
|
u32 type_size = rsx::get_vertex_type_size(info.type);
|
||||||
u32 element_size = type_size * info.size;
|
u32 element_size = type_size * info.size;
|
||||||
|
|
||||||
size_t subBufferSize = element_size * vertex_draw_count;
|
size_t subBufferSize = element_size * vertex_count;
|
||||||
assert(m_vertexIndexData.canAlloc(subBufferSize));
|
assert(m_vertexIndexData.canAlloc(subBufferSize));
|
||||||
size_t heapOffset = m_vertexIndexData.alloc(subBufferSize);
|
size_t heapOffset = m_vertexIndexData.alloc(subBufferSize);
|
||||||
|
|
||||||
void *buffer;
|
void *buffer;
|
||||||
ThrowIfFailed(m_vertexIndexData.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
ThrowIfFailed(m_vertexIndexData.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
||||||
void *bufferMap = (char*)buffer + heapOffset;
|
void *bufferMap = (char*)buffer + heapOffset;
|
||||||
for (const auto &range : m_first_count_pairs)
|
for (const auto &range : vertex_ranges)
|
||||||
{
|
{
|
||||||
write_vertex_array_data_to_buffer(bufferMap, range.first, range.second, index, info);
|
write_vertex_array_data_to_buffer(bufferMap, range.first, range.second, index, info);
|
||||||
bufferMap = (char*)bufferMap + range.second * element_size;
|
bufferMap = (char*)bufferMap + range.second * element_size;
|
||||||
|
@ -210,73 +214,11 @@ void D3D12GSRender::upload_vertex_attributes()
|
||||||
IAElement.InstanceDataStepRate = 1;
|
IAElement.InstanceDataStepRate = 1;
|
||||||
m_IASet.push_back(IAElement);
|
m_IASet.push_back(IAElement);
|
||||||
}
|
}
|
||||||
m_first_count_pairs.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw)
|
void D3D12GSRender::load_vertex_index_data(u32 first, u32 count)
|
||||||
{
|
{
|
||||||
D3D12_INDEX_BUFFER_VIEW indexBufferView = {};
|
|
||||||
|
|
||||||
// No need for index buffer
|
|
||||||
if (!indexed_draw && isNativePrimitiveMode(draw_mode))
|
|
||||||
{
|
|
||||||
m_renderingInfo.m_indexed = false;
|
|
||||||
m_renderingInfo.m_count = vertex_draw_count;
|
|
||||||
m_renderingInfo.m_baseVertex = 0;
|
|
||||||
return indexBufferView;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_renderingInfo.m_indexed = true;
|
m_renderingInfo.m_indexed = true;
|
||||||
|
|
||||||
u32 indexed_type = rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4;
|
|
||||||
|
|
||||||
// Index type
|
|
||||||
size_t indexSize;
|
|
||||||
if (!indexed_draw)
|
|
||||||
{
|
|
||||||
indexBufferView.Format = DXGI_FORMAT_R16_UINT;
|
|
||||||
indexSize = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (indexed_type)
|
|
||||||
{
|
|
||||||
default: abort();
|
|
||||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
|
||||||
indexBufferView.Format = DXGI_FORMAT_R16_UINT;
|
|
||||||
indexSize = 2;
|
|
||||||
break;
|
|
||||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
|
||||||
indexBufferView.Format = DXGI_FORMAT_R32_UINT;
|
|
||||||
indexSize = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Index count
|
|
||||||
m_renderingInfo.m_count = getIndexCount(draw_mode, indexed_draw ? (u32)(vertex_index_array.size() / indexSize) : vertex_draw_count);
|
|
||||||
|
|
||||||
// Base vertex
|
|
||||||
if (!indexed_draw && isNativePrimitiveMode(draw_mode))
|
|
||||||
m_renderingInfo.m_baseVertex = 0;
|
|
||||||
else
|
|
||||||
m_renderingInfo.m_baseVertex = 0;
|
|
||||||
|
|
||||||
// Alloc
|
|
||||||
size_t subBufferSize = align(m_renderingInfo.m_count * indexSize, 64);
|
|
||||||
|
|
||||||
assert(m_vertexIndexData.canAlloc(subBufferSize));
|
|
||||||
size_t heapOffset = m_vertexIndexData.alloc(subBufferSize);
|
|
||||||
|
|
||||||
void *buffer;
|
|
||||||
ThrowIfFailed(m_vertexIndexData.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
|
||||||
void *bufferMap = (char*)buffer + heapOffset;
|
|
||||||
uploadIndexData(draw_mode, indexed_type, indexed_draw ? vertex_index_array.data() : nullptr, bufferMap, indexed_draw ? (u32)(vertex_index_array.size() / indexSize) : vertex_draw_count);
|
|
||||||
m_vertexIndexData.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize));
|
|
||||||
m_timers.m_bufferUploadSize += subBufferSize;
|
|
||||||
indexBufferView.SizeInBytes = (UINT)subBufferSize;
|
|
||||||
indexBufferView.BufferLocation = m_vertexIndexData.m_heap->GetGPUVirtualAddress() + heapOffset;
|
|
||||||
return indexBufferView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12GSRender::setScaleOffset(size_t descriptorIndex)
|
void D3D12GSRender::setScaleOffset(size_t descriptorIndex)
|
||||||
|
@ -419,4 +361,83 @@ void D3D12GSRender::FillPixelShaderConstantsBuffer(size_t descriptorIndex)
|
||||||
CD3DX12_CPU_DESCRIPTOR_HANDLE(getCurrentResourceStorage().m_descriptorsHeap->GetCPUDescriptorHandleForHeapStart())
|
CD3DX12_CPU_DESCRIPTOR_HANDLE(getCurrentResourceStorage().m_descriptorsHeap->GetCPUDescriptorHandleForHeapStart())
|
||||||
.Offset((INT)descriptorIndex, g_descriptorStrideSRVCBVUAV));
|
.Offset((INT)descriptorIndex, g_descriptorStrideSRVCBVUAV));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void D3D12GSRender::upload_vertex_index_data(ID3D12GraphicsCommandList *cmdlist)
|
||||||
|
{
|
||||||
|
// Index count
|
||||||
|
m_renderingInfo.m_count = 0;
|
||||||
|
for (const auto &pair : m_first_count_pairs)
|
||||||
|
m_renderingInfo.m_count += getIndexCount(draw_mode, pair.second);
|
||||||
|
|
||||||
|
if (!m_renderingInfo.m_indexed)
|
||||||
|
{
|
||||||
|
// Non indexed
|
||||||
|
upload_vertex_attributes(m_first_count_pairs);
|
||||||
|
cmdlist->IASetVertexBuffers(0, (UINT)m_vertex_buffer_views.size(), m_vertex_buffer_views.data());
|
||||||
|
if (isNativePrimitiveMode(draw_mode))
|
||||||
|
return;
|
||||||
|
// Handle non native primitive
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
size_t subBufferSize = align(m_renderingInfo.m_count * sizeof(u16), 64);
|
||||||
|
assert(m_vertexIndexData.canAlloc(subBufferSize));
|
||||||
|
size_t heapOffset = m_vertexIndexData.alloc(subBufferSize);
|
||||||
|
|
||||||
|
void *buffer;
|
||||||
|
ThrowIfFailed(m_vertexIndexData.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
||||||
|
void *bufferMap = (char*)buffer + heapOffset;
|
||||||
|
size_t first = 0;
|
||||||
|
for (const auto &pair : m_first_count_pairs)
|
||||||
|
{
|
||||||
|
size_t element_count = getIndexCount(draw_mode, pair.second);
|
||||||
|
write_index_array_for_non_indexed_non_native_primitive_to_buffer((char*)bufferMap, draw_mode, first, pair.second);
|
||||||
|
bufferMap = (char*)bufferMap + element_count * sizeof(u16);
|
||||||
|
first += pair.second;
|
||||||
|
}
|
||||||
|
m_vertexIndexData.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize));
|
||||||
|
D3D12_INDEX_BUFFER_VIEW indexBufferView = {
|
||||||
|
m_vertexIndexData.m_heap->GetGPUVirtualAddress() + heapOffset,
|
||||||
|
(UINT)subBufferSize,
|
||||||
|
DXGI_FORMAT_R16_UINT
|
||||||
|
};
|
||||||
|
cmdlist->IASetIndexBuffer(&indexBufferView);
|
||||||
|
m_renderingInfo.m_indexed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 indexed_type = rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4;
|
||||||
|
|
||||||
|
// Index type
|
||||||
|
size_t indexSize = (indexed_type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16) ? 2 : 4;
|
||||||
|
|
||||||
|
// Alloc
|
||||||
|
size_t subBufferSize = align(m_renderingInfo.m_count * indexSize, 64);
|
||||||
|
assert(m_vertexIndexData.canAlloc(subBufferSize));
|
||||||
|
size_t heapOffset = m_vertexIndexData.alloc(subBufferSize);
|
||||||
|
|
||||||
|
void *buffer;
|
||||||
|
ThrowIfFailed(m_vertexIndexData.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
||||||
|
void *bufferMap = (char*)buffer + heapOffset;
|
||||||
|
u32 min_index = (u32)-1, max_index = 0;
|
||||||
|
for (const auto &pair : m_first_count_pairs)
|
||||||
|
{
|
||||||
|
size_t element_count = getIndexCount(draw_mode, pair.second);
|
||||||
|
write_index_array_data_to_buffer((char*)bufferMap, draw_mode, pair.first, pair.second, min_index, max_index);
|
||||||
|
bufferMap = (char*)bufferMap + element_count * indexSize;
|
||||||
|
}
|
||||||
|
m_vertexIndexData.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize));
|
||||||
|
D3D12_INDEX_BUFFER_VIEW indexBufferView = {
|
||||||
|
m_vertexIndexData.m_heap->GetGPUVirtualAddress() + heapOffset,
|
||||||
|
(UINT)subBufferSize,
|
||||||
|
(indexed_type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT
|
||||||
|
};
|
||||||
|
m_timers.m_bufferUploadSize += subBufferSize;
|
||||||
|
cmdlist->IASetIndexBuffer(&indexBufferView);
|
||||||
|
m_renderingInfo.m_indexed = true;
|
||||||
|
|
||||||
|
upload_vertex_attributes({ std::make_pair(0, max_index + 1) });
|
||||||
|
cmdlist->IASetVertexBuffers(0, (UINT)m_vertex_buffer_views.size(), m_vertex_buffer_views.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -413,13 +413,7 @@ void D3D12GSRender::end()
|
||||||
std::chrono::time_point<std::chrono::system_clock> vertexIndexDurationStart = std::chrono::system_clock::now();
|
std::chrono::time_point<std::chrono::system_clock> vertexIndexDurationStart = std::chrono::system_clock::now();
|
||||||
|
|
||||||
if (!vertex_index_array.empty() || vertex_draw_count)
|
if (!vertex_index_array.empty() || vertex_draw_count)
|
||||||
{
|
upload_vertex_index_data(getCurrentResourceStorage().m_commandList.Get());
|
||||||
upload_vertex_attributes();
|
|
||||||
const D3D12_INDEX_BUFFER_VIEW &indexBufferView = uploadIndexBuffers(!vertex_index_array.empty());
|
|
||||||
getCurrentResourceStorage().m_commandList->IASetVertexBuffers(0, (UINT)m_vertex_buffer_views.size(), m_vertex_buffer_views.data());
|
|
||||||
if (m_renderingInfo.m_indexed)
|
|
||||||
getCurrentResourceStorage().m_commandList->IASetIndexBuffer(&indexBufferView);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::system_clock> vertexIndexDurationEnd = std::chrono::system_clock::now();
|
std::chrono::time_point<std::chrono::system_clock> vertexIndexDurationEnd = std::chrono::system_clock::now();
|
||||||
m_timers.m_vertexIndexDuration += std::chrono::duration_cast<std::chrono::microseconds>(vertexIndexDurationEnd - vertexIndexDurationStart).count();
|
m_timers.m_vertexIndexDuration += std::chrono::duration_cast<std::chrono::microseconds>(vertexIndexDurationEnd - vertexIndexDurationStart).count();
|
||||||
|
@ -595,9 +589,9 @@ void D3D12GSRender::end()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_renderingInfo.m_indexed)
|
if (m_renderingInfo.m_indexed)
|
||||||
getCurrentResourceStorage().m_commandList->DrawIndexedInstanced((UINT)m_renderingInfo.m_count, 1, 0, (UINT)m_renderingInfo.m_baseVertex, 0);
|
getCurrentResourceStorage().m_commandList->DrawIndexedInstanced((UINT)m_renderingInfo.m_count, 1, 0, 0, 0);
|
||||||
else
|
else
|
||||||
getCurrentResourceStorage().m_commandList->DrawInstanced((UINT)m_renderingInfo.m_count, 1, (UINT)m_renderingInfo.m_baseVertex, 0);
|
getCurrentResourceStorage().m_commandList->DrawInstanced((UINT)m_renderingInfo.m_count, 1, 0, 0);
|
||||||
|
|
||||||
vertex_index_array.clear();
|
vertex_index_array.clear();
|
||||||
std::chrono::time_point<std::chrono::system_clock> endDuration = std::chrono::system_clock::now();
|
std::chrono::time_point<std::chrono::system_clock> endDuration = std::chrono::system_clock::now();
|
||||||
|
@ -610,7 +604,8 @@ void D3D12GSRender::end()
|
||||||
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().m_commandList.GetAddressOf());
|
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)getCurrentResourceStorage().m_commandList.GetAddressOf());
|
||||||
getCurrentResourceStorage().setNewCommandList();
|
getCurrentResourceStorage().setNewCommandList();
|
||||||
}
|
}
|
||||||
|
m_first_count_pairs.clear();
|
||||||
|
m_renderingInfo.m_indexed = false;
|
||||||
thread::end();
|
thread::end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -417,7 +417,6 @@ private:
|
||||||
{
|
{
|
||||||
bool m_indexed; /*<! is draw call using an index buffer */
|
bool m_indexed; /*<! is draw call using an index buffer */
|
||||||
size_t m_count; /*<! draw call vertex count */
|
size_t m_count; /*<! draw call vertex count */
|
||||||
size_t m_baseVertex; /*<! Starting vertex for draw call */
|
|
||||||
} m_renderingInfo;
|
} m_renderingInfo;
|
||||||
|
|
||||||
RenderTargets m_rtts;
|
RenderTargets m_rtts;
|
||||||
|
@ -458,19 +457,19 @@ private:
|
||||||
|
|
||||||
bool LoadProgram();
|
bool LoadProgram();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create vertex and index buffers (if needed) and set them to cmdlist.
|
||||||
|
* Non native primitive type are emulated by index buffers expansion.
|
||||||
|
*/
|
||||||
|
void upload_vertex_index_data(ID3D12GraphicsCommandList *cmdlist);
|
||||||
|
|
||||||
std::vector<std::pair<u32, u32> > m_first_count_pairs;
|
std::vector<std::pair<u32, u32> > m_first_count_pairs;
|
||||||
/**
|
/**
|
||||||
* Upload all vertex attribute whose (first, count) info were previously accumulated.
|
* Upload all enabled vertex attributes for vertex in ranges described by vertex_ranges.
|
||||||
|
* A range in vertex_range is a pair whose first element is the index of the beginning of the
|
||||||
|
* range, and whose second element is the number of vertex in this range.
|
||||||
*/
|
*/
|
||||||
void upload_vertex_attributes();
|
void upload_vertex_attributes(const std::vector<std::pair<u32, u32> > &vertex_ranges);
|
||||||
|
|
||||||
/**
|
|
||||||
* Create index buffer for indexed rendering and non native primitive format if nedded, and
|
|
||||||
* update m_renderingInfo member accordingly. If m_renderingInfo::m_indexed is true,
|
|
||||||
* returns an index buffer view that can be passed to a command list.
|
|
||||||
*/
|
|
||||||
D3D12_INDEX_BUFFER_VIEW uploadIndexBuffers(bool indexed_draw = false);
|
|
||||||
|
|
||||||
|
|
||||||
void setScaleOffset(size_t descriptorIndex);
|
void setScaleOffset(size_t descriptorIndex);
|
||||||
void FillVertexShaderConstantsBuffer(size_t descriptorIndex);
|
void FillVertexShaderConstantsBuffer(size_t descriptorIndex);
|
||||||
|
@ -504,4 +503,5 @@ protected:
|
||||||
virtual void flip(int buffer) override;
|
virtual void flip(int buffer) override;
|
||||||
|
|
||||||
virtual void load_vertex_data(u32 first, u32 count) override;
|
virtual void load_vertex_data(u32 first, u32 count) override;
|
||||||
|
virtual void load_vertex_index_data(u32 first, u32 count) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -164,7 +164,7 @@ namespace rsx
|
||||||
u32 transform_program[512 * 4] = {};
|
u32 transform_program[512 * 4] = {};
|
||||||
|
|
||||||
virtual void load_vertex_data(u32 first, u32 count);
|
virtual void load_vertex_data(u32 first, u32 count);
|
||||||
void load_vertex_index_data(u32 first, u32 count);
|
virtual void load_vertex_index_data(u32 first, u32 count);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u32 ioAddress, ioSize;
|
u32 ioAddress, ioSize;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue