mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
D3D: Implement vectored efb pokes, increase util vertex buffer size to 64KiB
This commit is contained in:
@ -34,6 +34,8 @@ public:
|
||||
buf->Release();
|
||||
}
|
||||
|
||||
int GetSize() const { return max_size; }
|
||||
|
||||
// returns vertex offset to the new data
|
||||
int AppendData(void* data, int size, int vertex_size)
|
||||
{
|
||||
@ -59,6 +61,37 @@ public:
|
||||
return (offset - size) / vertex_size;
|
||||
}
|
||||
|
||||
int BeginAppendData(void** write_ptr, int size, int vertex_size)
|
||||
{
|
||||
_dbg_assert_(VIDEO, size < max_size);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
int aligned_offset = ((offset + vertex_size - 1) / vertex_size) * vertex_size; // align offset to vertex_size bytes
|
||||
if (aligned_offset + size > max_size)
|
||||
{
|
||||
// wrap buffer around and notify observers
|
||||
offset = 0;
|
||||
aligned_offset = 0;
|
||||
context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
for (bool* observer : observers)
|
||||
*observer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->Map(buf, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
|
||||
}
|
||||
|
||||
*write_ptr = reinterpret_cast<byte*>(map.pData) + aligned_offset;
|
||||
offset = aligned_offset + size;
|
||||
return aligned_offset / vertex_size;
|
||||
}
|
||||
|
||||
void EndAppendData()
|
||||
{
|
||||
context->Unmap(buf, 0);
|
||||
}
|
||||
|
||||
void AddWrapObserver(bool* observer)
|
||||
{
|
||||
observers.push_back(observer);
|
||||
@ -460,7 +493,7 @@ bool stq_observer, stsq_observer, cq_observer, clearq_observer;
|
||||
|
||||
void InitUtils()
|
||||
{
|
||||
util_vbuf = new UtilVertexBuffer(0x4000);
|
||||
util_vbuf = new UtilVertexBuffer(65536); // 64KiB
|
||||
|
||||
float border[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f);
|
||||
@ -647,6 +680,71 @@ void drawClearQuad(u32 Color, float z)
|
||||
stateman->SetGeometryShader(nullptr);
|
||||
}
|
||||
|
||||
static void InitColVertex(ColVertex* vert, float x, float y, float z, u32 col)
|
||||
{
|
||||
vert->x = x;
|
||||
vert->y = y;
|
||||
vert->z = z;
|
||||
vert->col = col;
|
||||
}
|
||||
|
||||
void DrawEFBPokeQuads(EFBAccessType type, const EfbPokeData* points, size_t num_points)
|
||||
{
|
||||
const size_t COL_QUAD_SIZE = sizeof(ColVertex) * 6;
|
||||
|
||||
// Set common state
|
||||
stateman->SetVertexShader(VertexShaderCache::GetClearVertexShader());
|
||||
stateman->SetGeometryShader(GeometryShaderCache::GetClearGeometryShader());
|
||||
stateman->SetPixelShader(PixelShaderCache::GetClearProgram());
|
||||
stateman->SetInputLayout(VertexShaderCache::GetClearInputLayout());
|
||||
stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
stateman->SetVertexBuffer(util_vbuf->GetBuffer(), sizeof(ColVertex), 0);
|
||||
stateman->Apply();
|
||||
|
||||
// if drawing a large number of points at once, this will have to be split into multiple passes.
|
||||
size_t points_per_draw = util_vbuf->GetSize() / COL_QUAD_SIZE;
|
||||
size_t current_point_index = 0;
|
||||
while (current_point_index < num_points)
|
||||
{
|
||||
size_t points_to_draw = std::min(num_points - current_point_index, points_per_draw);
|
||||
size_t required_bytes = COL_QUAD_SIZE * points_to_draw;
|
||||
|
||||
// map and reserve enough buffer space for this draw
|
||||
void* buffer_ptr;
|
||||
int base_vertex_index = util_vbuf->BeginAppendData(&buffer_ptr, (int)required_bytes, sizeof(ColVertex));
|
||||
|
||||
// generate quads for each efb point
|
||||
ColVertex* base_vertex_ptr = reinterpret_cast<ColVertex*>(buffer_ptr);
|
||||
for (size_t i = 0; i < points_to_draw; i++)
|
||||
{
|
||||
// generate quad from the single point (clip-space coordinates)
|
||||
const EfbPokeData* point = &points[current_point_index];
|
||||
float x1 = float(point->x) * 2.0f / EFB_WIDTH - 1.0f;
|
||||
float y1 = -float(point->y) * 2.0f / EFB_HEIGHT + 1.0f;
|
||||
float x2 = float(point->x + 1) * 2.0f / EFB_WIDTH - 1.0f;
|
||||
float y2 = -float(point->y + 1) * 2.0f / EFB_HEIGHT + 1.0f;
|
||||
float z = (type == POKE_Z) ? (1.0f - float(point->data & 0xFFFFFF) / 16777216.0f) : 0.0f;
|
||||
u32 col = (type == POKE_Z) ? 0 : ((point->data & 0xFF00FF00) | ((point->data >> 16) & 0xFF) | ((point->data << 16) & 0xFF0000));
|
||||
current_point_index++;
|
||||
|
||||
// quad -> triangles
|
||||
ColVertex* vertex = &base_vertex_ptr[i * 6];
|
||||
InitColVertex(&vertex[0], x1, y1, z, col);
|
||||
InitColVertex(&vertex[1], x2, y1, z, col);
|
||||
InitColVertex(&vertex[2], x1, y2, z, col);
|
||||
InitColVertex(&vertex[3], x1, y2, z, col);
|
||||
InitColVertex(&vertex[4], x2, y1, z, col);
|
||||
InitColVertex(&vertex[5], x2, y2, z, col);
|
||||
}
|
||||
|
||||
// unmap the util buffer, and issue the draw
|
||||
util_vbuf->EndAppendData();
|
||||
context->Draw(6 * (UINT)points_to_draw, base_vertex_index);
|
||||
}
|
||||
|
||||
stateman->SetGeometryShader(GeometryShaderCache::GetClearGeometryShader());
|
||||
}
|
||||
|
||||
} // namespace D3D
|
||||
|
||||
} // namespace DX11
|
||||
|
Reference in New Issue
Block a user