rsx: Fix vertex attrib parsing

This commit is contained in:
kd-11 2018-09-25 20:29:24 +03:00 committed by kd-11
parent dab30c0051
commit f72157bcec
6 changed files with 58 additions and 8 deletions

View File

@ -218,6 +218,14 @@ void GLGSRender::end()
//Do vertex upload before RTT prep / texture lookups to give the driver time to push data
auto upload_info = set_vertex_buffer();
if (upload_info.vertex_draw_count == 0)
{
// Malformed vertex setup; abort
do_heap_cleanup();
rsx::thread::end();
return;
}
//Check if depth buffer is bound and valid
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
auto copy_rtt_contents = [this](gl::render_target *surface, bool is_depth)

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "GLGSRender.h"
#include "../rsx_methods.h"
#include "../Common/BufferUtils.h"
@ -158,7 +158,7 @@ namespace
vertex_input_state operator()(const rsx::draw_inlined_array& command)
{
const u32 vertex_count = m_vertex_layout.interleaved_blocks[0].locations.size() ? ((u32)command.inline_vertex_array.size() * sizeof(u32)) / m_vertex_layout.interleaved_blocks[0].attribute_stride : 0;
const u32 vertex_count = (u32)(command.inline_vertex_array.size() * sizeof(u32)) / m_vertex_layout.interleaved_blocks[0].attribute_stride;
if (!gl::is_primitive_native(rsx::method_registers.current_draw_clause.primitive))
{
@ -186,6 +186,9 @@ gl::vertex_upload_info GLGSRender::set_vertex_buffer()
m_vertex_layout = analyse_inputs_interleaved();
if (!m_vertex_layout.validate())
return {};
//Write index buffers and count verts
auto result = std::visit(draw_command_visitor(*m_index_ring_buffer, m_vertex_layout), get_draw_command(rsx::method_registers));

View File

@ -1776,10 +1776,6 @@ namespace rsx
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
// Check if vertex stream is enabled
if (!(input_mask & (1 << index)))
continue;
auto &vinfo = state.vertex_arrays_info[index];
if (vinfo.size() > 0)

View File

@ -204,6 +204,39 @@ namespace rsx
std::vector<u8> referenced_registers; // Volatile register data
std::array<attribute_buffer_placement, 16> attribute_placement;
vertex_input_layout()
{
attribute_placement.fill(attribute_buffer_placement::none);
}
bool validate() const
{
switch (attribute_placement[0])
{
case attribute_buffer_placement::transient:
{
if (!referenced_registers.empty() && referenced_registers.front() == 0)
{
// ATTR[0] is position which cannot be from a register
return false;
}
// The source is inline array or immediate draw push buffer
return true;
}
case attribute_buffer_placement::persistent:
{
// Attribute stride cannot be 0, proper packing stride is computed elsewhere
verify(HERE), (!interleaved_blocks.empty() && interleaved_blocks[0].attribute_stride != 0);
return true;
}
case attribute_buffer_placement::none:
{
return false;
}
}
}
};
struct framebuffer_layout

View File

@ -1364,6 +1364,13 @@ void VKGSRender::end()
std::chrono::time_point<steady_clock> vertex_end = steady_clock::now();
m_vertex_upload_time += std::chrono::duration_cast<std::chrono::microseconds>(vertex_end - vertex_start).count();
if (!upload_info.vertex_draw_count)
{
// Malformed vertex setup; abort
rsx::thread::end();
return;
}
// Load program execution environment
program_start = vertex_end;
load_program_env(upload_info);

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/Memory/vm.h"
#include "Emu/System.h"
#include "VKGSRender.h"
@ -212,7 +212,7 @@ namespace
auto &draw_clause = rsx::method_registers.current_draw_clause;
VkPrimitiveTopology prims = vk::get_appropriate_topology(draw_clause.primitive, primitives_emulated);
const u32 vertex_count = m_vertex_layout.interleaved_blocks[0].locations.size() ? ((u32)command.inline_vertex_array.size() * sizeof(u32)) / m_vertex_layout.interleaved_blocks[0].attribute_stride : 0;
const u32 vertex_count = ((u32)command.inline_vertex_array.size() * sizeof(u32)) / m_vertex_layout.interleaved_blocks[0].attribute_stride;
if (!primitives_emulated)
{
@ -235,6 +235,9 @@ vk::vertex_upload_info VKGSRender::upload_vertex_data()
{
m_vertex_layout = analyse_inputs_interleaved();
if (!m_vertex_layout.validate())
return {};
draw_command_visitor visitor(m_index_buffer_ring_info, m_vertex_layout);
auto result = std::visit(visitor, get_draw_command(rsx::method_registers));