Пример #1
0
u32 GLGSRender::get_zcull_stats(u32 type)
{
	if (g_cfg.video.disable_zcull_queries)
		return 0u;

	if (zcull_task_queue.active_query &&
		zcull_task_queue.active_query->active &&
		current_zcull_stats.zpass_pixel_cnt == 0 &&
		type == CELL_GCM_ZPASS_PIXEL_CNT)
	{
		//The zcull unit is still bound as the read is happening and there are no results ready
		check_zcull_status(false, true);  //close current query
		check_zcull_status(false, false); //start new query since stat counting is still active
	}

	switch (type)
	{
	case CELL_GCM_ZPASS_PIXEL_CNT:
	{
		if (current_zcull_stats.zpass_pixel_cnt > 0)
			return UINT16_MAX;

		synchronize_zcull_stats(true);
		return (current_zcull_stats.zpass_pixel_cnt > 0)? UINT16_MAX : 0;
	}
	case CELL_GCM_ZCULL_STATS:
	case CELL_GCM_ZCULL_STATS1:
	case CELL_GCM_ZCULL_STATS2:
		//TODO
		return UINT16_MAX;
	case CELL_GCM_ZCULL_STATS3:
	{
		//Some kind of inverse value
		if (current_zcull_stats.zpass_pixel_cnt > 0)
			return 0;
		
		synchronize_zcull_stats(true);
		return (current_zcull_stats.zpass_pixel_cnt > 0) ? 0 : UINT16_MAX;
	}
	default:
		LOG_ERROR(RSX, "Unknown zcull stat type %d", type);
		return 0;
	}
}
Пример #2
0
void GLGSRender::clear_zcull_stats(u32 type)
{
	if (g_cfg.video.disable_zcull_queries)
		return;

	if (type == CELL_GCM_ZPASS_PIXEL_CNT)
	{
		if (zcull_task_queue.active_query &&
			zcull_task_queue.active_query->active &&
			zcull_task_queue.active_query->num_draws > 0)
		{
			//discard active query results
			check_zcull_status(false, true);
			zcull_task_queue.active_query->pending = false;

			//re-enable cull stats if stats are enabled
			check_zcull_status(false, false);
		}

		current_zcull_stats.clear();
	}
}
Пример #3
0
u32 GLGSRender::get_zcull_stats(u32 type)
{
	if (g_cfg.video.disable_zcull_queries)
		return 0u;

	if (zcull_task_queue.active_query &&
		zcull_task_queue.active_query->active &&
		current_zcull_stats.zpass_pixel_cnt == 0)
	{
		//The zcull unit is still bound as the read is happening and there are no results ready
		check_zcull_status(false, true);
	}

	switch (type)
	{
	case CELL_GCM_ZPASS_PIXEL_CNT:
	{
		if (current_zcull_stats.zpass_pixel_cnt > 0)
			return UINT32_MAX;

		//If we have no results, we might as well synchronize here and wait for results to become available
		synchronize_zcull_stats(true);
		return (current_zcull_stats.zpass_pixel_cnt > 0)? UINT32_MAX: 0;
	}
	case CELL_GCM_ZCULL_STATS:
	case CELL_GCM_ZCULL_STATS1:
	case CELL_GCM_ZCULL_STATS2:
		//TODO
		return UINT32_MAX;
	case CELL_GCM_ZCULL_STATS3:
	{
		//Some kind of inverse value
		if (current_zcull_stats.zpass_pixel_cnt > 0)
			return 0;
		
		synchronize_zcull_stats(true);
		return (current_zcull_stats.zpass_pixel_cnt > 0) ? 0 : UINT32_MAX;
	}
	default:
		LOG_ERROR(RSX, "Unknown zcull stat type %d", type);
		return 0;
	}
}
Пример #4
0
void GLGSRender::init_buffers(bool skip_reading)
{
	if (draw_fbo && !m_rtts_dirty)
	{
		set_viewport();
		return;
	}

	//We are about to change buffers, flush any pending requests for the old buffers
	synchronize_buffers();

	m_rtts_dirty = false;
	zcull_surface_active = false;

	const u16 clip_horizontal = rsx::method_registers.surface_clip_width();
	const u16 clip_vertical = rsx::method_registers.surface_clip_height();

	if (clip_horizontal == 0 || clip_vertical == 0)
	{
		LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_horizontal, clip_vertical);
		framebuffer_status_valid = false;
		return;
	}

	const auto pitchs = get_pitchs();
	const auto surface_format = rsx::method_registers.surface_color();
	const auto depth_format = rsx::method_registers.surface_depth_fmt();

	const auto surface_addresses = get_color_surface_addresses();
	const auto depth_address = get_zeta_surface_address();

	m_rtts.prepare_render_target(nullptr, surface_format, depth_format,  clip_horizontal, clip_vertical,
		rsx::method_registers.surface_color_target(),
		surface_addresses, depth_address);

	draw_fbo.recreate();

	for (int i = 0; i < rsx::limits::color_buffers_count; ++i)
	{
		if (std::get<0>(m_rtts.m_bound_render_targets[i]))
		{
			__glcheck draw_fbo.color[i] = *std::get<1>(m_rtts.m_bound_render_targets[i]);

			std::get<1>(m_rtts.m_bound_render_targets[i])->set_rsx_pitch(pitchs[i]);
			surface_info[i] = { surface_addresses[i], pitchs[i], false, surface_format, depth_format, clip_horizontal, clip_vertical };

			//Verify pitch given is correct if pitch <= 64 (especially 64)
			if (pitchs[i] <= 64)
			{	
				const u16 native_pitch = std::get<1>(m_rtts.m_bound_render_targets[i])->get_native_pitch();
				if (native_pitch > pitchs[i])
				{
					LOG_TRACE(RSX, "Bad color surface pitch given: surface_width=%d, format=%d, pitch=%d, native_pitch=%d",
						clip_horizontal, (u32)surface_format, pitchs[i], native_pitch);

					//Will not transfer this surface between cell and rsx due to misalignment
					//TODO: Verify correct behaviour
					surface_info[i].pitch = 0;
				}
			}
		}
		else
			surface_info[i] = {};
	}

	if (std::get<0>(m_rtts.m_bound_depth_stencil))
	{
		if (depth_format == rsx::surface_depth_format::z24s8)
			__glcheck draw_fbo.depth_stencil = *std::get<1>(m_rtts.m_bound_depth_stencil);
		else
			__glcheck draw_fbo.depth = *std::get<1>(m_rtts.m_bound_depth_stencil);

		const u32 depth_surface_pitch = rsx::method_registers.surface_z_pitch();
		std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
		depth_surface_info = { depth_address, depth_surface_pitch, true, surface_format, depth_format, clip_horizontal, clip_vertical };

		//Verify pitch given is correct if pitch <= 64 (especially 64)
		if (depth_surface_pitch <= 64)
		{
			const u16 native_pitch = std::get<1>(m_rtts.m_bound_depth_stencil)->get_native_pitch();
			if (native_pitch > depth_surface_pitch)
			{
				LOG_TRACE(RSX, "Bad depth surface pitch given: surface_width=%d, format=%d, pitch=%d, native_pitch=%d",
					clip_horizontal, (u32)depth_format, depth_surface_pitch, native_pitch);

				//Will not transfer this surface between cell and rsx due to misalignment
				//TODO: Verify correct behaviour
				depth_surface_info.pitch = 0;
			}
		}
	}
	else
		depth_surface_info = {};

	framebuffer_status_valid = draw_fbo.check();
	if (!framebuffer_status_valid) return;

	check_zcull_status(true, false);

	draw_fbo.bind();
	set_viewport();

	switch (rsx::method_registers.surface_color_target())
	{
	case rsx::surface_target::none: break;

	case rsx::surface_target::surface_a:
		__glcheck draw_fbo.draw_buffer(draw_fbo.color[0]);
		__glcheck draw_fbo.read_buffer(draw_fbo.color[0]);
		break;

	case rsx::surface_target::surface_b:
		__glcheck draw_fbo.draw_buffer(draw_fbo.color[1]);
		__glcheck draw_fbo.read_buffer(draw_fbo.color[1]);
		break;

	case rsx::surface_target::surfaces_a_b:
		__glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1] });
		__glcheck draw_fbo.read_buffer(draw_fbo.color[0]);
		break;

	case rsx::surface_target::surfaces_a_b_c:
		__glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2] });
		__glcheck draw_fbo.read_buffer(draw_fbo.color[0]);
		break;

	case rsx::surface_target::surfaces_a_b_c_d:
		__glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2], draw_fbo.color[3] });
		__glcheck draw_fbo.read_buffer(draw_fbo.color[0]);
		break;
	}

	//Mark buffer regions as NO_ACCESS on Cell visible side
	if (g_cfg.video.write_color_buffers)
	{
		auto color_format = rsx::internals::surface_color_format_to_gl(surface_format);

		for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i)
		{
			if (!surface_info[i].address || !surface_info[i].pitch) continue;

			const u32 range = surface_info[i].pitch * surface_info[i].height;
			m_gl_texture_cache.lock_rtt_region(surface_info[i].address, range, surface_info[i].width, surface_info[i].height, surface_info[i].pitch,
				color_format.format, color_format.type, color_format.swap_bytes, *std::get<1>(m_rtts.m_bound_render_targets[i]));
		}
	}

	if (g_cfg.video.write_depth_buffer)
	{
		if (depth_surface_info.address && depth_surface_info.pitch)
		{
			auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(depth_format);

			u32 pitch = depth_surface_info.width * 2;
			if (depth_surface_info.depth_format != rsx::surface_depth_format::z16) pitch *= 2;

			const u32 range = pitch * depth_surface_info.height;

			//TODO: Verify that depth surface pitch variance affects results
			if (pitch != depth_surface_info.pitch)
				LOG_WARNING(RSX, "Depth surface pitch does not match computed pitch, %d vs %d", depth_surface_info.pitch, pitch);

			m_gl_texture_cache.lock_rtt_region(depth_surface_info.address, range, depth_surface_info.width, depth_surface_info.height, pitch,
				depth_format_gl.format, depth_format_gl.type, true, *std::get<1>(m_rtts.m_bound_depth_stencil));
		}
	}
}
Пример #5
0
void GLGSRender::notify_zcull_info_changed()
{
	check_zcull_status(false, false);
}