Пример #1
0
void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist)
{
	// Exit early if there is no rtt changes
	if (!m_rtts_dirty)
		return;
	m_rtts_dirty = false;

	std::array<float, 4> clear_color =
	{
		rsx::method_registers.clear_color_r() / 255.f,
		rsx::method_registers.clear_color_g() / 255.f,
		rsx::method_registers.clear_color_b() / 255.f,
		rsx::method_registers.clear_color_a() / 255.f,
	};
	m_rtts.prepare_render_target(copycmdlist,
		rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(),
		rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height(),
		rsx::method_registers.surface_color_target(),
		get_color_surface_addresses(), get_zeta_surface_address(),
		m_device.Get(), clear_color, 1.f, 0);

	// write descriptors
	DXGI_FORMAT dxgi_format = get_color_surface_format(rsx::method_registers.surface_color());
	D3D12_RENDER_TARGET_VIEW_DESC rtt_view_desc = {};
	rtt_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
	rtt_view_desc.Format = dxgi_format;

	m_rtts.current_rtts_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
		.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * m_descriptor_stride_rtv);
	size_t rtt_index = 0;
	for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
	{
		if (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
			continue;
		m_device->CreateRenderTargetView(std::get<1>(m_rtts.m_bound_render_targets[i]), &rtt_view_desc,
			CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle).Offset((INT)rtt_index * m_descriptor_stride_rtv));
		rtt_index++;
	}
	get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;

	if (std::get<1>(m_rtts.m_bound_depth_stencil) == nullptr)
		return;
	m_rtts.current_ds_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
		.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * m_descriptor_stride_dsv);
	get_current_resource_storage().depth_stencil_descriptor_heap_index += 1;
	D3D12_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {};
	depth_stencil_view_desc.Format = get_depth_stencil_surface_format(rsx::method_registers.surface_depth_fmt());
	depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
	m_device->CreateDepthStencilView(std::get<1>(m_rtts.m_bound_depth_stencil), &depth_stencil_view_desc, m_rtts.current_ds_handle);
}
Пример #2
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;

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

	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_WARNING(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_WARNING(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 = {};

	if (!draw_fbo.check())
		return;

	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_rsx_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_rsx_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));
		}
	}
}