mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 14:31:24 +12:00
Common: Move generic vertex buffer code from d3d12 backend
This commit is contained in:
parent
62d7bf2159
commit
c7b7d1f71f
6 changed files with 313 additions and 253 deletions
242
rpcs3/Emu/RSX/Common/BufferUtils.cpp
Normal file
242
rpcs3/Emu/RSX/Common/BufferUtils.cpp
Normal file
|
@ -0,0 +1,242 @@
|
|||
#include "stdafx.h"
|
||||
#include "BufferUtils.h"
|
||||
|
||||
|
||||
#define MIN2(x, y) ((x) < (y)) ? (x) : (y)
|
||||
#define MAX2(x, y) ((x) > (y)) ? (x) : (y)
|
||||
|
||||
|
||||
inline
|
||||
bool overlaps(const std::pair<size_t, size_t> &range1, const std::pair<size_t, size_t> &range2)
|
||||
{
|
||||
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> Result;
|
||||
for (size_t i = 0; i < 32; ++i)
|
||||
{
|
||||
const RSXVertexData &vertexData = m_vertex_data[i];
|
||||
if (!vertexData.IsEnabled()) continue;
|
||||
|
||||
size_t elementCount = vertex_data_size[i] / (vertexData.size * vertexData.GetTypeSize());
|
||||
// If there is a single element, stride is 0, use the size of element instead
|
||||
size_t stride = vertexData.stride;
|
||||
size_t elementSize = vertexData.GetTypeSize();
|
||||
std::pair<size_t, size_t> range = std::make_pair(vertexData.addr + base_offset, vertexData.addr + base_offset + elementSize * vertexData.size + (elementCount - 1) * stride - 1);
|
||||
bool isMerged = false;
|
||||
|
||||
for (VertexBufferFormat &vbf : Result)
|
||||
{
|
||||
if (overlaps(vbf.range, range) && vbf.stride == stride)
|
||||
{
|
||||
// Extend buffer if necessary
|
||||
vbf.range.first = MIN2(vbf.range.first, range.first);
|
||||
vbf.range.second = MAX2(vbf.range.second, range.second);
|
||||
vbf.elementCount = MAX2(vbf.elementCount, elementCount);
|
||||
|
||||
vbf.attributeId.push_back(i);
|
||||
isMerged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMerged)
|
||||
continue;
|
||||
VertexBufferFormat newRange = { range, std::vector<size_t>{ i }, elementCount, stride };
|
||||
Result.emplace_back(newRange);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void uploadVertexData(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, size_t baseOffset, void* bufferMap)
|
||||
{
|
||||
for (int vertex = 0; vertex < vbf.elementCount; vertex++)
|
||||
{
|
||||
for (size_t attributeId : vbf.attributeId)
|
||||
{
|
||||
if (!vertexData[attributeId].addr)
|
||||
{
|
||||
memcpy(bufferMap, vertexData[attributeId].data.data(), vertexData[attributeId].data.size());
|
||||
continue;
|
||||
}
|
||||
size_t offset = (size_t)vertexData[attributeId].addr + baseOffset - vbf.range.first;
|
||||
size_t tsize = vertexData[attributeId].GetTypeSize();
|
||||
size_t size = vertexData[attributeId].size;
|
||||
auto src = vm::get_ptr<const u8>(vertexData[attributeId].addr + (u32)baseOffset + (u32)vbf.stride * vertex);
|
||||
char* dst = (char*)bufferMap + offset + vbf.stride * vertex;
|
||||
|
||||
switch (tsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
memcpy(dst, src, size);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
const u16* c_src = (const u16*)src;
|
||||
u16* c_dst = (u16*)dst;
|
||||
for (u32 j = 0; j < size; ++j) *c_dst++ = _byteswap_ushort(*c_src++);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
const u32* c_src = (const u32*)src;
|
||||
u32* c_dst = (u32*)dst;
|
||||
for (u32 j = 0; j < size; ++j) *c_dst++ = _byteswap_ulong(*c_src++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename IndexType, typename DstType, typename SrcType>
|
||||
void expandIndexedTriangleFan(DstType *dst, const SrcType *src, size_t indexCount)
|
||||
{
|
||||
IndexType *typedDst = reinterpret_cast<IndexType *>(dst);
|
||||
const IndexType *typedSrc = reinterpret_cast<const IndexType *>(src);
|
||||
for (unsigned i = 0; i < indexCount - 2; i++)
|
||||
{
|
||||
typedDst[3 * i] = typedSrc[0];
|
||||
typedDst[3 * i + 1] = typedSrc[i + 2 - 1];
|
||||
typedDst[3 * i + 2] = typedSrc[i + 2];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename IndexType, typename DstType, typename SrcType>
|
||||
void expandIndexedQuads(DstType *dst, const SrcType *src, size_t indexCount)
|
||||
{
|
||||
IndexType *typedDst = reinterpret_cast<IndexType *>(dst);
|
||||
const IndexType *typedSrc = reinterpret_cast<const IndexType *>(src);
|
||||
for (unsigned i = 0; i < indexCount / 4; i++)
|
||||
{
|
||||
// First triangle
|
||||
typedDst[6 * i] = typedSrc[4 * i];
|
||||
typedDst[6 * i + 1] = typedSrc[4 * i + 1];
|
||||
typedDst[6 * i + 2] = typedSrc[4 * i + 2];
|
||||
// Second triangle
|
||||
typedDst[6 * i + 3] = typedSrc[4 * i + 2];
|
||||
typedDst[6 * i + 4] = typedSrc[4 * i + 3];
|
||||
typedDst[6 * i + 5] = typedSrc[4 * i];
|
||||
}
|
||||
}
|
||||
|
||||
// Only handle quads and triangle fan now
|
||||
bool isNativePrimitiveMode(unsigned m_draw_mode)
|
||||
{
|
||||
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:
|
||||
case CELL_GCM_PRIMITIVE_POLYGON:
|
||||
return true;
|
||||
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
|
||||
case CELL_GCM_PRIMITIVE_QUADS:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
size_t getIndexCount(unsigned m_draw_mode, unsigned initial_index_count)
|
||||
{
|
||||
// Index count
|
||||
if (isNativePrimitiveMode(m_draw_mode))
|
||||
return initial_index_count;
|
||||
|
||||
switch (m_draw_mode)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uploadIndexData(unsigned m_draw_mode, unsigned index_type, void* indexBuffer, void* bufferMap, unsigned element_count)
|
||||
{
|
||||
if (indexBuffer != nullptr)
|
||||
{
|
||||
switch (m_draw_mode)
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
expandIndexedTriangleFan<unsigned int>(bufferMap, indexBuffer, element_count);
|
||||
return;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
expandIndexedTriangleFan<unsigned short>(bufferMap, indexBuffer, element_count);
|
||||
return;
|
||||
default:
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
case CELL_GCM_PRIMITIVE_QUADS:
|
||||
switch (index_type)
|
||||
{
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||
expandIndexedQuads<unsigned int>(bufferMap, indexBuffer, element_count);
|
||||
return;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
expandIndexedQuads<unsigned short>(bufferMap, indexBuffer, element_count);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
40
rpcs3/Emu/RSX/Common/BufferUtils.h
Normal file
40
rpcs3/Emu/RSX/Common/BufferUtils.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "../RSXThread.h"
|
||||
|
||||
|
||||
struct VertexBufferFormat
|
||||
{
|
||||
std::pair<size_t, size_t> range;
|
||||
std::vector<size_t> attributeId;
|
||||
size_t elementCount;
|
||||
size_t stride;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* Write vertex attributes to bufferMap, swapping data as required.
|
||||
*/
|
||||
void uploadVertexData(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, size_t baseOffset, void* bufferMap);
|
||||
|
||||
/*
|
||||
* If primitive mode is not supported and need to be emulated (using an index buffer) returns false.
|
||||
*/
|
||||
bool isNativePrimitiveMode(unsigned m_draw_mode);
|
||||
|
||||
/*
|
||||
* Returns a fixed index count for emulated primitive, otherwise returns initial_index_count
|
||||
*/
|
||||
size_t getIndexCount(unsigned m_draw_mode, unsigned initial_index_count);
|
||||
|
||||
/*
|
||||
* Write index information to bufferMap
|
||||
*/
|
||||
void uploadIndexData(unsigned m_draw_mode, unsigned index_type, void* indexBuffer, void* bufferMap, unsigned element_count);
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "D3D12GSRender.h"
|
||||
#include "d3dx12.h"
|
||||
#include "../Common/BufferUtils.h"
|
||||
|
||||
const int g_vertexCount = 32;
|
||||
|
||||
|
@ -90,14 +91,6 @@ DXGI_FORMAT getFormat(u8 type, u8 size)
|
|||
}
|
||||
}
|
||||
|
||||
struct VertexBufferFormat
|
||||
{
|
||||
std::pair<size_t, size_t> range;
|
||||
std::vector<size_t> attributeId;
|
||||
size_t elementCount;
|
||||
size_t stride;
|
||||
};
|
||||
|
||||
static
|
||||
std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, const std::vector<VertexBufferFormat> &vertexBufferFormat, const RSXVertexData *m_vertex_data, size_t baseOffset)
|
||||
{
|
||||
|
@ -122,89 +115,9 @@ std::vector<D3D12_INPUT_ELEMENT_DESC> getIALayout(ID3D12Device *device, const st
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename IndexType, typename DstType, typename SrcType>
|
||||
void expandIndexedTriangleFan(DstType *dst, const SrcType *src, size_t indexCount)
|
||||
{
|
||||
IndexType *typedDst = reinterpret_cast<IndexType *>(dst);
|
||||
const IndexType *typedSrc = reinterpret_cast<const IndexType *>(src);
|
||||
for (unsigned i = 0; i < indexCount - 2; i++)
|
||||
{
|
||||
typedDst[3 * i] = typedSrc[0];
|
||||
typedDst[3 * i + 1] = typedSrc[i + 2 - 1];
|
||||
typedDst[3 * i + 2] = typedSrc[i + 2];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename IndexType, typename DstType, typename SrcType>
|
||||
void expandIndexedQuads(DstType *dst, const SrcType *src, size_t indexCount)
|
||||
{
|
||||
IndexType *typedDst = reinterpret_cast<IndexType *>(dst);
|
||||
const IndexType *typedSrc = reinterpret_cast<const IndexType *>(src);
|
||||
for (unsigned i = 0; i < indexCount / 4; i++)
|
||||
{
|
||||
// First triangle
|
||||
typedDst[6 * i] = typedSrc[4 * i];
|
||||
typedDst[6 * i + 1] = typedSrc[4 * i + 1];
|
||||
typedDst[6 * i + 2] = typedSrc[4 * i + 2];
|
||||
// Second triangle
|
||||
typedDst[6 * i + 3] = typedSrc[4 * i + 2];
|
||||
typedDst[6 * i + 4] = typedSrc[4 * i + 3];
|
||||
typedDst[6 * i + 5] = typedSrc[4 * i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// D3D12GS member handling buffers
|
||||
|
||||
|
||||
|
||||
#define MIN2(x, y) ((x) < (y)) ? (x) : (y)
|
||||
#define MAX2(x, y) ((x) > (y)) ? (x) : (y)
|
||||
|
||||
static
|
||||
bool overlaps(const std::pair<size_t, size_t> &range1, const std::pair<size_t, size_t> &range2)
|
||||
{
|
||||
return !(range1.second < range2.first || range2.second < range1.first);
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<VertexBufferFormat> FormatVertexData(const RSXVertexData *m_vertex_data, size_t *vertex_data_size, size_t base_offset)
|
||||
{
|
||||
std::vector<VertexBufferFormat> Result;
|
||||
for (size_t i = 0; i < 32; ++i)
|
||||
{
|
||||
const RSXVertexData &vertexData = m_vertex_data[i];
|
||||
if (!vertexData.IsEnabled()) continue;
|
||||
|
||||
size_t elementCount = vertex_data_size[i] / (vertexData.size * vertexData.GetTypeSize());
|
||||
// If there is a single element, stride is 0, use the size of element instead
|
||||
size_t stride = vertexData.stride;
|
||||
size_t elementSize = vertexData.GetTypeSize();
|
||||
std::pair<size_t, size_t> range = std::make_pair(vertexData.addr + base_offset, vertexData.addr + base_offset + elementSize * vertexData.size + (elementCount - 1) * stride - 1);
|
||||
bool isMerged = false;
|
||||
|
||||
for (VertexBufferFormat &vbf : Result)
|
||||
{
|
||||
if (overlaps(vbf.range, range) && vbf.stride == stride)
|
||||
{
|
||||
// Extend buffer if necessary
|
||||
vbf.range.first = MIN2(vbf.range.first, range.first);
|
||||
vbf.range.second = MAX2(vbf.range.second, range.second);
|
||||
vbf.elementCount = MAX2(vbf.elementCount, elementCount);
|
||||
|
||||
vbf.attributeId.push_back(i);
|
||||
isMerged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMerged)
|
||||
continue;
|
||||
VertexBufferFormat newRange = { range, std::vector<size_t>{ i }, elementCount, stride };
|
||||
Result.emplace_back(newRange);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suballocate a new vertex buffer with attributes from vbf using vertexIndexHeap as storage heap.
|
||||
*/
|
||||
|
@ -221,63 +134,11 @@ 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;
|
||||
for (int vertex = 0; vertex < vbf.elementCount; vertex++)
|
||||
{
|
||||
for (size_t attributeId : vbf.attributeId)
|
||||
{
|
||||
if (!vertexData[attributeId].addr)
|
||||
{
|
||||
memcpy(bufferMap, vertexData[attributeId].data.data(), vertexData[attributeId].data.size());
|
||||
continue;
|
||||
}
|
||||
size_t offset = (size_t)vertexData[attributeId].addr + baseOffset - vbf.range.first;
|
||||
size_t tsize = vertexData[attributeId].GetTypeSize();
|
||||
size_t size = vertexData[attributeId].size;
|
||||
auto src = vm::get_ptr<const u8>(vertexData[attributeId].addr + (u32)baseOffset + (u32)vbf.stride * vertex);
|
||||
char* dst = (char*)bufferMap + offset + vbf.stride * vertex;
|
||||
|
||||
switch (tsize)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
memcpy(dst, src, size);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
const u16* c_src = (const u16*)src;
|
||||
u16* c_dst = (u16*)dst;
|
||||
for (u32 j = 0; j < size; ++j) *c_dst++ = _byteswap_ushort(*c_src++);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
const u32* c_src = (const u32*)src;
|
||||
u32* c_dst = (u32*)dst;
|
||||
for (u32 j = 0; j < size; ++j) *c_dst++ = _byteswap_ulong(*c_src++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uploadVertexData(vbf, vertexData, baseOffset, bufferMap);
|
||||
vertexIndexHeap.m_heap->Unmap(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize));
|
||||
return vertexIndexHeap.m_heap->GetGPUVirtualAddress() + heapOffset;
|
||||
}
|
||||
|
||||
static bool
|
||||
isContained(const std::vector<std::pair<u32, u32> > &ranges, const std::pair<u32, u32> &range)
|
||||
{
|
||||
for (auto &r : ranges)
|
||||
{
|
||||
if (r == range)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool indexed_draw)
|
||||
{
|
||||
std::vector<D3D12_VERTEX_BUFFER_VIEW> result;
|
||||
|
@ -310,29 +171,9 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool in
|
|||
D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw)
|
||||
{
|
||||
D3D12_INDEX_BUFFER_VIEW indexBufferView = {};
|
||||
// Only handle quads and triangle fan now
|
||||
bool forcedIndexBuffer = false;
|
||||
switch (m_draw_mode - 1)
|
||||
{
|
||||
default:
|
||||
case GL_POINTS:
|
||||
case GL_LINES:
|
||||
case GL_LINE_LOOP:
|
||||
case GL_LINE_STRIP:
|
||||
case GL_TRIANGLES:
|
||||
case GL_TRIANGLE_STRIP:
|
||||
case GL_QUAD_STRIP:
|
||||
case GL_POLYGON:
|
||||
forcedIndexBuffer = false;
|
||||
break;
|
||||
case GL_TRIANGLE_FAN:
|
||||
case GL_QUADS:
|
||||
forcedIndexBuffer = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// No need for index buffer
|
||||
if (!indexed_draw && !forcedIndexBuffer)
|
||||
if (!indexed_draw && isNativePrimitiveMode(m_draw_mode))
|
||||
{
|
||||
m_renderingInfo.m_indexed = false;
|
||||
m_renderingInfo.m_count = m_draw_array_count;
|
||||
|
@ -366,35 +207,10 @@ D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw)
|
|||
}
|
||||
|
||||
// Index count
|
||||
if (indexed_draw && !forcedIndexBuffer)
|
||||
m_renderingInfo.m_count = m_indexed_array.m_data.size() / indexSize;
|
||||
else if (indexed_draw && forcedIndexBuffer)
|
||||
{
|
||||
switch (m_draw_mode - 1)
|
||||
{
|
||||
case GL_TRIANGLE_FAN:
|
||||
m_renderingInfo.m_count = (m_indexed_array.m_data.size() - 2) * 3;
|
||||
break;
|
||||
case GL_QUADS:
|
||||
m_renderingInfo.m_count = 6 * m_indexed_array.m_data.size() / (4 * indexSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_draw_mode - 1)
|
||||
{
|
||||
case GL_TRIANGLE_FAN:
|
||||
m_renderingInfo.m_count = (m_draw_array_count - 2) * 3;
|
||||
break;
|
||||
case GL_QUADS:
|
||||
m_renderingInfo.m_count = m_draw_array_count * 6 / 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_renderingInfo.m_count = getIndexCount(m_draw_mode, indexed_draw ? (u32)(m_indexed_array.m_data.size() / indexSize) : m_draw_array_count);
|
||||
|
||||
// Base vertex
|
||||
if (!indexed_draw && forcedIndexBuffer)
|
||||
if (!indexed_draw && isNativePrimitiveMode(m_draw_mode))
|
||||
m_renderingInfo.m_baseVertex = m_draw_array_first;
|
||||
else
|
||||
m_renderingInfo.m_baseVertex = 0;
|
||||
|
@ -408,70 +224,9 @@ D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw)
|
|||
void *buffer;
|
||||
ThrowIfFailed(m_vertexIndexData.m_heap->Map(0, &CD3DX12_RANGE(heapOffset, heapOffset + subBufferSize), (void**)&buffer));
|
||||
void *bufferMap = (char*)buffer + heapOffset;
|
||||
if (indexed_draw && !forcedIndexBuffer)
|
||||
streamBuffer(bufferMap, m_indexed_array.m_data.data(), subBufferSize);
|
||||
else if (indexed_draw && forcedIndexBuffer)
|
||||
{
|
||||
// Only quads supported now
|
||||
switch (m_draw_mode - 1)
|
||||
{
|
||||
case GL_TRIANGLE_FAN:
|
||||
switch (m_indexed_array.m_type)
|
||||
{
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||
expandIndexedTriangleFan<unsigned int>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 4);
|
||||
break;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
expandIndexedTriangleFan<unsigned short>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GL_QUADS:
|
||||
switch (m_indexed_array.m_type)
|
||||
{
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||
expandIndexedQuads<unsigned int>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 4);
|
||||
break;
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
expandIndexedQuads<unsigned short>(bufferMap, m_indexed_array.m_data.data(), m_indexed_array.m_data.size() / 2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned short *typedDst = static_cast<unsigned short *>(bufferMap);
|
||||
switch (m_draw_mode - 1)
|
||||
{
|
||||
case GL_TRIANGLE_FAN:
|
||||
for (unsigned i = 0; i < (m_draw_array_count - 2); i++)
|
||||
{
|
||||
typedDst[3 * i] = 0;
|
||||
typedDst[3 * i + 1] = i + 2 - 1;
|
||||
typedDst[3 * i + 2] = i + 2;
|
||||
}
|
||||
break;
|
||||
case GL_QUADS:
|
||||
for (unsigned i = 0; i < m_draw_array_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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
uploadIndexData(m_draw_mode, m_indexed_array.m_type, indexed_draw ? m_indexed_array.m_data.data() : nullptr, bufferMap, indexed_draw ? (u32)(m_indexed_array.m_data.size() / indexSize) : m_draw_array_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;
|
||||
|
|
|
@ -260,6 +260,21 @@ enum
|
|||
|
||||
};
|
||||
|
||||
// GCM Primitive
|
||||
enum
|
||||
{
|
||||
CELL_GCM_PRIMITIVE_POINTS = 1,
|
||||
CELL_GCM_PRIMITIVE_LINES = 2,
|
||||
CELL_GCM_PRIMITIVE_LINE_LOOP = 3,
|
||||
CELL_GCM_PRIMITIVE_LINE_STRIP = 4,
|
||||
CELL_GCM_PRIMITIVE_TRIANGLES = 5,
|
||||
CELL_GCM_PRIMITIVE_TRIANGLE_STRIP = 6,
|
||||
CELL_GCM_PRIMITIVE_TRIANGLE_FAN = 7,
|
||||
CELL_GCM_PRIMITIVE_QUADS = 8,
|
||||
CELL_GCM_PRIMITIVE_QUAD_STRIP = 9,
|
||||
CELL_GCM_PRIMITIVE_POLYGON = 10,
|
||||
};
|
||||
|
||||
// GCM Reports
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
<ClCompile Include="Emu\IdManager.cpp" />
|
||||
<ClCompile Include="Emu\RSX\CgBinaryFragmentProgram.cpp" />
|
||||
<ClCompile Include="Emu\RSX\CgBinaryVertexProgram.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\BufferUtils.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\FragmentProgramDecompiler.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\ShaderParam.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\TextureUtils.cpp" />
|
||||
|
@ -530,10 +531,11 @@
|
|||
<ClInclude Include="Emu\Memory\Memory.h" />
|
||||
<ClInclude Include="Emu\Memory\MemoryBlock.h" />
|
||||
<ClInclude Include="Emu\RSX\CgBinaryProgram.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\BufferUtils.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\ShaderParam.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\TextureManagement.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\TextureUtils.h" />
|
||||
<ClInclude Include="Emu\RSX\Common\VertexProgramDecompiler.h" />
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12.h" />
|
||||
<ClInclude Include="Emu\RSX\D3D12\D3D12Buffer.h" />
|
||||
|
|
|
@ -992,6 +992,9 @@
|
|||
<ClCompile Include="Emu\RSX\Common\TextureUtils.cpp">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Common\BufferUtils.cpp">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
@ -1885,7 +1888,10 @@
|
|||
<ClInclude Include="Emu\RSX\D3D12\d3dx12.h">
|
||||
<Filter>Emu\GPU\RSX\D3D12</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Common\TextureManagement.h">
|
||||
<ClInclude Include="Emu\RSX\Common\TextureUtils.h">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Common\BufferUtils.h">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue