Ejemplo n.º 1
0
void D3D12GSRender::clear_surface(u32 arg)
{
	// Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE
	if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
	
	std::chrono::time_point<std::chrono::system_clock> start_duration = std::chrono::system_clock::now();

	std::chrono::time_point<std::chrono::system_clock> rtt_duration_start = std::chrono::system_clock::now();
	prepare_render_targets(get_current_resource_storage().command_list.Get());

	std::chrono::time_point<std::chrono::system_clock> rtt_duration_end = std::chrono::system_clock::now();
	m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();

	if (arg & 0x1 || arg & 0x2)
	{
		get_current_resource_storage().depth_stencil_descriptor_heap_index++;

		if (arg & 0x1)
		{
			u32 clear_depth = rsx::method_registers.z_clear_value();
			u32 max_depth_value = get_max_depth_value(rsx::method_registers.surface_depth_fmt());
			get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
				1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
		}

		if (arg & 0x2)
			get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers.stencil_clear_value()),
				1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
	}

	if (arg & 0xF0)
	{
		CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle);
		size_t rtt_index = get_num_rtt(rsx::method_registers.surface_color_target());
		get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
		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,
		};
		for (unsigned i = 0; i < rtt_index; i++)
			get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, m_descriptor_stride_rtv), clear_color.data(),
				1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));
	}

	std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now();
	m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
	m_timers.draw_calls_count++;

	if (g_cfg_rsx_debug_output)
	{
		CHECK_HRESULT(get_current_resource_storage().command_list->Close());
		m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
		get_current_resource_storage().set_new_command_list();
	}
}
Ejemplo n.º 2
0
void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
{
	size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(256);

	// Scale offset buffer
	// Separate constant buffer
	void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 256));
	fill_scale_offset_data(mapped_buffer);
	int is_alpha_tested = rsx::method_registers.alpha_test_enabled();
	u8 alpha_ref_raw = rsx::method_registers.alpha_ref();
	float alpha_ref = alpha_ref_raw / 255.f;
	memcpy((char*)mapped_buffer + 16 * sizeof(float), &is_alpha_tested, sizeof(int));
	memcpy((char*)mapped_buffer + 17 * sizeof(float), &alpha_ref, sizeof(float));
	f32 fogp0 = rsx::method_registers.fog_params_0();
	f32 fogp1 = rsx::method_registers.fog_params_1();
	memcpy((char*)mapped_buffer + 18 * sizeof(float), &fogp0, sizeof(float));
	memcpy((char*)mapped_buffer + 19 * sizeof(float), &fogp1, sizeof(float));

	m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256));

	D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
		m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
		256
	};
	m_device->CreateConstantBufferView(&constant_buffer_view_desc,
		CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
		.Offset((INT)descriptorIndex, m_descriptor_stride_srv_cbv_uav));
}
Ejemplo n.º 3
0
void D3D12GSRender::upload_and_bind_vertex_shader_constants(size_t descriptor_index)
{
	size_t buffer_size = 512 * 4 * sizeof(float);

	size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);

	void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
	fill_vertex_program_constants_data(mapped_buffer);
	m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));

	D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
		m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
		(UINT)buffer_size
	};
	m_device->CreateConstantBufferView(&constant_buffer_view_desc,
		CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
		.Offset((INT)descriptor_index, m_descriptor_stride_srv_cbv_uav));
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_index)
{
	// Get constant from fragment program
	size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(m_fragment_program);
	// Multiple of 256 never 0
	buffer_size = (buffer_size + 255) & ~255;

	size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);

	size_t offset = 0;
	float *mapped_buffer = m_buffer_data.map<float>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
	m_pso_cache.fill_fragment_constans_buffer({ mapped_buffer, gsl::narrow<int>(buffer_size) }, m_fragment_program);
	m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));

	D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
		m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
		(UINT)buffer_size
	};
	m_device->CreateConstantBufferView(&constant_buffer_view_desc,
		CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
		.Offset((INT)descriptor_index, m_descriptor_stride_srv_cbv_uav));
}
Ejemplo n.º 6
0
void D3D12GSRender::load_program()
{
	auto rtt_lookup_func = [this](u32 texaddr, rsx::fragment_texture&, bool is_depth) -> std::tuple<bool, u16>
	{
		ID3D12Resource *surface = nullptr;
		if (!is_depth)
			surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
		else
			surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);

		if (!surface) return std::make_tuple(false, 0);
		
		D3D12_RESOURCE_DESC desc = surface->GetDesc();
		u16 native_pitch = get_dxgi_texel_size(desc.Format) * (u16)desc.Width;
		return std::make_tuple(true, native_pitch);
	};

	get_current_vertex_program({}, true);
	get_current_fragment_program_legacy(rtt_lookup_func);

	if (!current_fragment_program.valid)
		return;

	D3D12PipelineProperties prop = {};
	prop.Topology = get_primitive_topology_type(rsx::method_registers.current_draw_clause.primitive);

	static D3D12_BLEND_DESC CD3D12_BLEND_DESC =
	{
		FALSE,
		FALSE,
		{
			FALSE,FALSE,
			D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
		D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
		D3D12_LOGIC_OP_NOOP,
		D3D12_COLOR_WRITE_ENABLE_ALL,
		}
	};
	prop.Blend = CD3D12_BLEND_DESC;

	if (rsx::method_registers.blend_enabled())
	{
		//We can use the d3d blend factor as long as !(rgb_factor == alpha && a_factor == color)
		rsx::blend_factor sfactor_rgb = rsx::method_registers.blend_func_sfactor_rgb();
		rsx::blend_factor dfactor_rgb = rsx::method_registers.blend_func_dfactor_rgb();
		rsx::blend_factor sfactor_a = rsx::method_registers.blend_func_sfactor_a();
		rsx::blend_factor dfactor_a = rsx::method_registers.blend_func_dfactor_a();

		D3D12_BLEND d3d_sfactor_rgb = get_blend_factor(sfactor_rgb);
		D3D12_BLEND d3d_dfactor_rgb = get_blend_factor(dfactor_rgb);;
		D3D12_BLEND d3d_sfactor_alpha = get_blend_factor_alpha(sfactor_a);
		D3D12_BLEND d3d_dfactor_alpha = get_blend_factor_alpha(dfactor_a);
		
		auto BlendColor = rsx::get_constant_blend_colors();
		bool color_blend_possible = true;

		if (sfactor_rgb == rsx::blend_factor::constant_alpha ||
			dfactor_rgb == rsx::blend_factor::constant_alpha)
		{
			if (sfactor_rgb == rsx::blend_factor::constant_color ||
				dfactor_rgb == rsx::blend_factor::constant_color)
			{
				//Color information will be destroyed
				color_blend_possible = false;
			}
			else
			{
				//All components are alpha.
				//If an alpha factor refers to constant_color, it only refers to the alpha component, so no need to replace it
				BlendColor[0] = BlendColor[1] = BlendColor[2] = BlendColor[3];
			}
		}

		if (!color_blend_possible)
		{
			LOG_ERROR(RSX, "The constant_color blend factor combination defined is not supported");
			
			auto flatten_d3d12_factor = [](D3D12_BLEND in) -> D3D12_BLEND
			{
				switch (in)
				{
				case D3D12_BLEND_BLEND_FACTOR:
					return D3D12_BLEND_ONE;
				case D3D12_BLEND_INV_BLEND_FACTOR:
					return D3D12_BLEND_ZERO;
				}

				LOG_ERROR(RSX, "No suitable conversion defined for blend factor 0x%X" HERE, (u32)in);
				return in;
			};

			d3d_sfactor_rgb = flatten_d3d12_factor(d3d_sfactor_rgb);
			d3d_dfactor_rgb = flatten_d3d12_factor(d3d_dfactor_rgb);;
			d3d_sfactor_alpha = flatten_d3d12_factor(d3d_sfactor_alpha);
			d3d_dfactor_alpha = flatten_d3d12_factor(d3d_dfactor_alpha);
		}
		else
		{
			get_current_resource_storage().command_list->OMSetBlendFactor(BlendColor.data());
		}

		prop.Blend.RenderTarget[0].BlendEnable = true;

		if (rsx::method_registers.blend_enabled_surface_1())
			prop.Blend.RenderTarget[1].BlendEnable = true;
		if (rsx::method_registers.blend_enabled_surface_2())
			prop.Blend.RenderTarget[2].BlendEnable = true;
		if (rsx::method_registers.blend_enabled_surface_3())
			prop.Blend.RenderTarget[3].BlendEnable = true;

		prop.Blend.RenderTarget[0].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
		prop.Blend.RenderTarget[0].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());

		if (rsx::method_registers.blend_enabled_surface_1())
		{
			prop.Blend.RenderTarget[1].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
			prop.Blend.RenderTarget[1].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
		}

		if (rsx::method_registers.blend_enabled_surface_2())
		{
			prop.Blend.RenderTarget[2].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
			prop.Blend.RenderTarget[2].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
		}

		if (rsx::method_registers.blend_enabled_surface_3())
		{
			prop.Blend.RenderTarget[3].BlendOp = get_blend_op(rsx::method_registers.blend_equation_rgb());
			prop.Blend.RenderTarget[3].BlendOpAlpha = get_blend_op(rsx::method_registers.blend_equation_a());
		}

		prop.Blend.RenderTarget[0].SrcBlend = d3d_sfactor_rgb;
		prop.Blend.RenderTarget[0].DestBlend = d3d_dfactor_rgb;
		prop.Blend.RenderTarget[0].SrcBlendAlpha = d3d_sfactor_alpha;
		prop.Blend.RenderTarget[0].DestBlendAlpha = d3d_dfactor_alpha;

		if (rsx::method_registers.blend_enabled_surface_1())
		{
			prop.Blend.RenderTarget[1].SrcBlend = d3d_sfactor_rgb;
			prop.Blend.RenderTarget[1].DestBlend = d3d_dfactor_rgb;
			prop.Blend.RenderTarget[1].SrcBlendAlpha = d3d_sfactor_alpha;
			prop.Blend.RenderTarget[1].DestBlendAlpha = d3d_dfactor_alpha;
		}

		if (rsx::method_registers.blend_enabled_surface_2())
		{
			prop.Blend.RenderTarget[2].SrcBlend = d3d_sfactor_rgb;
			prop.Blend.RenderTarget[2].DestBlend = d3d_dfactor_rgb;
			prop.Blend.RenderTarget[2].SrcBlendAlpha = d3d_sfactor_alpha;
			prop.Blend.RenderTarget[2].DestBlendAlpha = d3d_dfactor_alpha;
		}

		if (rsx::method_registers.blend_enabled_surface_3())
		{
			prop.Blend.RenderTarget[3].SrcBlend = d3d_sfactor_rgb;
			prop.Blend.RenderTarget[3].DestBlend = d3d_dfactor_rgb;
			prop.Blend.RenderTarget[3].SrcBlendAlpha = d3d_sfactor_alpha;
			prop.Blend.RenderTarget[3].DestBlendAlpha = d3d_dfactor_alpha;
		}
	}

	if (rsx::method_registers.logic_op_enabled())
	{
		prop.Blend.RenderTarget[0].LogicOpEnable = true;
		prop.Blend.RenderTarget[0].LogicOp = get_logic_op(rsx::method_registers.logic_operation());
	}

	prop.DepthStencilFormat = get_depth_stencil_surface_format(rsx::method_registers.surface_depth_fmt());
	prop.RenderTargetsFormat = get_color_surface_format(rsx::method_registers.surface_color());

	switch (rsx::method_registers.surface_color_target())
	{
	case rsx::surface_target::surface_a:
	case rsx::surface_target::surface_b:
		prop.numMRT = 1;
		break;
	case rsx::surface_target::surfaces_a_b:
		prop.numMRT = 2;
		break;
	case rsx::surface_target::surfaces_a_b_c:
		prop.numMRT = 3;
		break;
	case rsx::surface_target::surfaces_a_b_c_d:
		prop.numMRT = 4;
		break;
	default:
		break;
	}
	if (rsx::method_registers.depth_test_enabled())
	{
		prop.DepthStencil.DepthEnable = TRUE;
		prop.DepthStencil.DepthFunc = get_compare_func(rsx::method_registers.depth_func());
	}
	else
		prop.DepthStencil.DepthEnable = FALSE;

	prop.DepthStencil.DepthWriteMask = rsx::method_registers.depth_write_enabled() ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;

	if (rsx::method_registers.stencil_test_enabled())
	{
		prop.DepthStencil.StencilEnable = TRUE;
		prop.DepthStencil.StencilReadMask = rsx::method_registers.stencil_func_mask();
		prop.DepthStencil.StencilWriteMask = rsx::method_registers.stencil_mask();
		prop.DepthStencil.FrontFace.StencilPassOp = get_stencil_op(rsx::method_registers.stencil_op_zpass());
		prop.DepthStencil.FrontFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers.stencil_op_zfail());
		prop.DepthStencil.FrontFace.StencilFailOp = get_stencil_op(rsx::method_registers.stencil_op_fail());
		prop.DepthStencil.FrontFace.StencilFunc = get_compare_func(rsx::method_registers.stencil_func());

		if (rsx::method_registers.two_sided_stencil_test_enabled())
		{
			prop.DepthStencil.BackFace.StencilFailOp = get_stencil_op(rsx::method_registers.back_stencil_op_fail());
			prop.DepthStencil.BackFace.StencilFunc = get_compare_func(rsx::method_registers.back_stencil_func());
			prop.DepthStencil.BackFace.StencilPassOp = get_stencil_op(rsx::method_registers.back_stencil_op_zpass());
			prop.DepthStencil.BackFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers.back_stencil_op_zfail());
		}
		else
		{
			prop.DepthStencil.BackFace.StencilPassOp = get_stencil_op(rsx::method_registers.stencil_op_zpass());
			prop.DepthStencil.BackFace.StencilDepthFailOp = get_stencil_op(rsx::method_registers.stencil_op_zfail());
			prop.DepthStencil.BackFace.StencilFailOp = get_stencil_op(rsx::method_registers.stencil_op_fail());
			prop.DepthStencil.BackFace.StencilFunc = get_compare_func(rsx::method_registers.stencil_func());
		}
	}

	// Sensible default value
	static D3D12_RASTERIZER_DESC CD3D12_RASTERIZER_DESC =
	{
		D3D12_FILL_MODE_SOLID,
		D3D12_CULL_MODE_NONE,
		FALSE,
		D3D12_DEFAULT_DEPTH_BIAS,
		D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
		D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
		TRUE,
		FALSE,
		FALSE,
		0,
		D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
	};
	prop.Rasterization = CD3D12_RASTERIZER_DESC;
	prop.Rasterization.DepthClipEnable = rsx::method_registers.depth_clip_enabled();

	if (rsx::method_registers.cull_face_enabled())
	{
		prop.Rasterization.CullMode = get_cull_face(rsx::method_registers.cull_face_mode());
	}

	prop.Rasterization.FrontCounterClockwise = get_front_face_ccw(rsx::method_registers.front_face_mode());

	UINT8 mask = 0;
	mask |= rsx::method_registers.color_mask_r() ? D3D12_COLOR_WRITE_ENABLE_RED : 0;
	mask |= rsx::method_registers.color_mask_g() ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0;
	mask |= rsx::method_registers.color_mask_b() ? D3D12_COLOR_WRITE_ENABLE_BLUE : 0;
	mask |= rsx::method_registers.color_mask_a() ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0;
	for (unsigned i = 0; i < prop.numMRT; i++)
		prop.Blend.RenderTarget[i].RenderTargetWriteMask = mask;

	if (rsx::method_registers.restart_index_enabled())
	{
		rsx::index_array_type index_type = rsx::method_registers.current_draw_clause.is_immediate_draw?
			rsx::index_array_type::u32:
			rsx::method_registers.index_type();

		if (index_type == rsx::index_array_type::u32)
		{
			prop.CutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
		}
		if (index_type == rsx::index_array_type::u16)
		{
			prop.CutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF;
		}
	}

	m_current_pso = m_pso_cache.get_graphics_pipeline(current_vertex_program, current_fragment_program, prop, false, m_device.Get(), m_shared_root_signature.Get());
	return;
}
Ejemplo n.º 7
0
void D3D12GSRender::flip(int buffer)
{
	ID3D12Resource *resource_to_flip;
	float viewport_w, viewport_h;

	if (!is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
	{
		resource_storage &storage = get_current_resource_storage();
		assert(storage.ram_framebuffer == nullptr);

		size_t w = 0, h = 0, row_pitch = 0;

		size_t offset = 0;
		if (false)
		{
			CellGcmDisplayInfo* buffers = nullptr;// = vm::ps3::_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr);
			u32 addr = rsx::get_address(gcm_buffers[gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL);
			w = gcm_buffers[gcm_current_buffer].width;
			h = gcm_buffers[gcm_current_buffer].height;
			u8 *src_buffer = vm::ps3::_ptr<u8>(addr);

			row_pitch = align(w * 4, 256);
			size_t texture_size = row_pitch * h; // * 4 for mipmap levels
			size_t heap_offset = m_buffer_data.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(texture_size);

			void *mapped_buffer = m_buffer_data.map<void>(heap_offset);
			for (unsigned row = 0; row < h; row++)
				memcpy((char*)mapped_buffer + row * row_pitch, (char*)src_buffer + row * w * 4, w * 4);
			m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + texture_size));
			offset = heap_offset;
		}

		CHECK_HRESULT(
			m_device->CreateCommittedResource(
				&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
				D3D12_HEAP_FLAG_NONE,
				&CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, (UINT)w, (UINT)h, 1, 1),
				D3D12_RESOURCE_STATE_COPY_DEST,
				nullptr,
				IID_PPV_ARGS(storage.ram_framebuffer.GetAddressOf())
				)
			);
		get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(storage.ram_framebuffer.Get(), 0), 0, 0, 0,
			&CD3DX12_TEXTURE_COPY_LOCATION(m_buffer_data.get_heap(), { offset, { DXGI_FORMAT_R8G8B8A8_UNORM, (UINT)w, (UINT)h, 1, (UINT)row_pitch } }), nullptr);

		get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(storage.ram_framebuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
		resource_to_flip = storage.ram_framebuffer.Get();
		viewport_w = (float)w, viewport_h = (float)h;
	}
	else
	{
		if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
		{
			get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[0]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
			resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0]);
		}
		else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr)
		{
			get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[1]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
			resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1]);
		}
		else
			resource_to_flip = nullptr;
	}

	get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));

	D3D12_VIEWPORT viewport =
	{
		0.f,
		0.f,
		(float)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Width,
		(float)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Height,
		0.f,
		1.f
	};
	get_current_resource_storage().command_list->RSSetViewports(1, &viewport);

	D3D12_RECT box =
	{
		0,
		0,
		(LONG)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Width,
		(LONG)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Height,
	};
	get_current_resource_storage().command_list->RSSetScissorRects(1, &box);
	get_current_resource_storage().command_list->SetGraphicsRootSignature(m_output_scaling_pass.root_signature);
	get_current_resource_storage().command_list->SetPipelineState(m_output_scaling_pass.pso);

	D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {};
	// FIXME: Not always true
	shader_resource_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
	shader_resource_view_desc.Texture2D.MipLevels = 1;
	if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
		shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
	else
		shader_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
			D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
			D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
			D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3,
			D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0
			);
	m_device->CreateShaderResourceView(resource_to_flip, &shader_resource_view_desc,
		CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.texture_descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_srv_cbv_uav));

	D3D12_SAMPLER_DESC sampler_desc = {};
	sampler_desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
	sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
	sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
	sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
	m_device->CreateSampler(&sampler_desc,
		CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.sampler_descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_samplers));

	ID3D12DescriptorHeap *descriptors_heaps[] =
	{
		m_output_scaling_pass.texture_descriptor_heap,
		m_output_scaling_pass.sampler_descriptor_heap
	};
	get_current_resource_storage().command_list->SetDescriptorHeaps(2, descriptors_heaps);
	get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0,
		CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.texture_descriptor_heap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_srv_cbv_uav));
	get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(1,
		CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.sampler_descriptor_heap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_samplers));

	get_current_resource_storage().command_list->OMSetRenderTargets(1,
		&CD3DX12_CPU_DESCRIPTOR_HANDLE(m_backbuffer_descriptor_heap[m_swap_chain->GetCurrentBackBufferIndex()]->GetCPUDescriptorHandleForHeapStart()),
		true, nullptr);
	D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view = {};
	vertex_buffer_view.BufferLocation = m_output_scaling_pass.vertex_buffer->GetGPUVirtualAddress();
	vertex_buffer_view.StrideInBytes = 4 * sizeof(float);
	vertex_buffer_view.SizeInBytes = 16 * sizeof(float);
	get_current_resource_storage().command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view);
	get_current_resource_storage().command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	if (resource_to_flip)
		get_current_resource_storage().command_list->DrawInstanced(4, 1, 0, 0);

	if (!rpcs3::config.rsx.d3d12.overlay.value())
		get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
	if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) && resource_to_flip != nullptr)
		get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(resource_to_flip, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
	CHECK_HRESULT(get_current_resource_storage().command_list->Close());
	m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());

	if(rpcs3::config.rsx.d3d12.overlay.value())
		render_overlay();

	reset_timer();

	std::chrono::time_point<std::chrono::system_clock> flip_start = std::chrono::system_clock::now();

	CHECK_HRESULT(m_swap_chain->Present(rpcs3::state.config.rsx.vsync.value() ? 1 : 0, 0));
	// Add an event signaling queue completion

	resource_storage &storage = get_non_current_resource_storage();

	m_command_queue->Signal(storage.frame_finished_fence.Get(), storage.fence_value);
	storage.frame_finished_fence->SetEventOnCompletion(storage.fence_value, storage.frame_finished_handle);
	storage.fence_value++;

	storage.in_use = true;
	storage.dirty_textures.merge(m_rtts.invalidated_resources);
	m_rtts.invalidated_resources.clear();

	// Get the put pos - 1. This way after cleaning we can set the get ptr to
	// this value, allowing heap to proceed even if we cleant before allocating
	// a new value (that's the reason of the -1)
	storage.buffer_heap_get_pos = m_buffer_data.get_current_put_pos_minus_one();
	storage.readback_heap_get_pos = m_readback_resources.get_current_put_pos_minus_one();

	// Now get ready for next frame
	resource_storage &new_storage = get_current_resource_storage();

	new_storage.wait_and_clean();
	if (new_storage.in_use)
	{
		m_buffer_data.m_get_pos = new_storage.buffer_heap_get_pos;
		m_readback_resources.m_get_pos = new_storage.readback_heap_get_pos;
	}

	m_frame->flip(nullptr);


	std::chrono::time_point<std::chrono::system_clock> flip_end = std::chrono::system_clock::now();
	m_timers.flip_duration += std::chrono::duration_cast<std::chrono::microseconds>(flip_end - flip_start).count();
}
Ejemplo n.º 8
0
void D3D12GSRender::end()
{
	std::chrono::time_point<std::chrono::system_clock> start_duration = std::chrono::system_clock::now();

	std::chrono::time_point<std::chrono::system_clock> rtt_duration_start = std::chrono::system_clock::now();
	prepare_render_targets(get_current_resource_storage().command_list.Get());

	std::chrono::time_point<std::chrono::system_clock> rtt_duration_end = std::chrono::system_clock::now();
	m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();

	std::chrono::time_point<std::chrono::system_clock> vertex_index_duration_start = std::chrono::system_clock::now();

	size_t currentDescriptorIndex = get_current_resource_storage().descriptors_heap_index;

	size_t vertex_count;
	bool indexed_draw;
	std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_views;
	std::tie(indexed_draw, vertex_count, vertex_buffer_views) = upload_and_set_vertex_index_data(get_current_resource_storage().command_list.Get());

	size_t vertex_buffer_count = vertex_buffer_views.size();

	std::chrono::time_point<std::chrono::system_clock> vertex_index_duration_end = std::chrono::system_clock::now();
	m_timers.vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count();

	std::chrono::time_point<std::chrono::system_clock> program_load_start = std::chrono::system_clock::now();
	load_program();
	std::chrono::time_point<std::chrono::system_clock> program_load_end = std::chrono::system_clock::now();
	m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();

	get_current_resource_storage().command_list->SetGraphicsRootSignature(m_root_signatures[std::get<2>(m_current_pso)][vertex_buffer_count].Get());
	get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]);

	std::chrono::time_point<std::chrono::system_clock> constants_duration_start = std::chrono::system_clock::now();

	INT offset = 0;
	for (const auto view : vertex_buffer_views)
	{
		m_device->CreateShaderResourceView(m_vertex_buffer_data.Get(), &view,
			CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
				.Offset((INT)currentDescriptorIndex + offset++, m_descriptor_stride_srv_cbv_uav));
	}

	// Constants
	upload_and_bind_scale_offset_matrix(currentDescriptorIndex + vertex_buffer_count);
	upload_and_bind_vertex_shader_constants(currentDescriptorIndex + 1 + vertex_buffer_count);
	upload_and_bind_fragment_shader_constants(currentDescriptorIndex + 2 + vertex_buffer_count);

	std::chrono::time_point<std::chrono::system_clock> constants_duration_end = std::chrono::system_clock::now();
	m_timers.constants_duration += std::chrono::duration_cast<std::chrono::microseconds>(constants_duration_end - constants_duration_start).count();

	get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get());

	std::chrono::time_point<std::chrono::system_clock> texture_duration_start = std::chrono::system_clock::now();
	size_t texture_count = std::get<2>(m_current_pso);
	if (texture_count > 0)
	{
		upload_and_bind_textures(get_current_resource_storage().command_list.Get(), texture_count);

		for (unsigned i = 0; i < texture_count; i++)
		{
			ID3D12Resource *tex_resource;
			D3D12_SHADER_RESOURCE_VIEW_DESC srv;
			std::tie(tex_resource, srv) = m_current_shader_resources[i];
			m_device->CreateShaderResourceView(tex_resource, &srv,
				CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
				.Offset((INT)currentDescriptorIndex + 3 + (INT)vertex_buffer_count + (INT)i, m_descriptor_stride_srv_cbv_uav)
				);
			m_device->CreateSampler(&m_current_samplers[i],
				CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
				.Offset((UINT)get_current_resource_storage().current_sampler_index + (UINT)i, m_descriptor_stride_samplers));
		}

		get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0,
			CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
			.Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav)
			);
		get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(1,
			CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetGPUDescriptorHandleForHeapStart())
			.Offset((INT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers)
			);

		get_current_resource_storage().current_sampler_index += std::get<2>(m_current_pso);
		get_current_resource_storage().descriptors_heap_index += std::get<2>(m_current_pso) + 3 + vertex_buffer_count;
	}
	else
	{
		get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0,
			CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
			.Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav)
			);
		get_current_resource_storage().descriptors_heap_index += 3 + vertex_buffer_count;
	}

	std::chrono::time_point<std::chrono::system_clock> texture_duration_end = std::chrono::system_clock::now();
	m_timers.texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count();
	set_rtt_and_ds(get_current_resource_storage().command_list.Get());

	int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
	int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;

	D3D12_VIEWPORT viewport =
	{
		0.f,
		0.f,
		(float)clip_w,
		(float)clip_h,
		(f32&)rsx::method_registers[NV4097_SET_CLIP_MIN],
		(f32&)rsx::method_registers[NV4097_SET_CLIP_MAX]
	};
	get_current_resource_storage().command_list->RSSetViewports(1, &viewport);

	get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));

	get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(draw_mode));

	if (indexed_draw)
		get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0);
	else
		get_current_resource_storage().command_list->DrawInstanced((UINT)vertex_count, 1, 0, 0);

	std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now();
	m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
	m_timers.draw_calls_count++;

	if (rpcs3::config.rsx.d3d12.debug_output.value())
	{
		CHECK_HRESULT(get_current_resource_storage().command_list->Close());
		m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
		get_current_resource_storage().set_new_command_list();
	}
	thread::end();
}
Ejemplo n.º 9
0
void D3D12GSRender::end()
{
	std::chrono::time_point<steady_clock> start_duration = steady_clock::now();

	std::chrono::time_point<steady_clock> rtt_duration_start = steady_clock::now();
	prepare_render_targets(get_current_resource_storage().command_list.Get());

	std::chrono::time_point<steady_clock> rtt_duration_end = steady_clock::now();
	m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();

	std::chrono::time_point<steady_clock> vertex_index_duration_start = steady_clock::now();

	size_t currentDescriptorIndex = get_current_resource_storage().descriptors_heap_index;

	size_t vertex_count;
	bool indexed_draw;
	std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_views;
	std::tie(indexed_draw, vertex_count, vertex_buffer_views) = upload_and_set_vertex_index_data(get_current_resource_storage().command_list.Get());

	UINT vertex_buffer_count = static_cast<UINT>(vertex_buffer_views.size());

	std::chrono::time_point<steady_clock> vertex_index_duration_end = steady_clock::now();
	m_timers.vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count();

	std::chrono::time_point<steady_clock> program_load_start = steady_clock::now();
	load_program();
	std::chrono::time_point<steady_clock> program_load_end = steady_clock::now();
	m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();

	get_current_resource_storage().command_list->SetGraphicsRootSignature(m_shared_root_signature.Get());
	get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers.stencil_func_ref());

	std::chrono::time_point<steady_clock> constants_duration_start = steady_clock::now();

	INT offset = 0;
	for (const auto view : vertex_buffer_views)
	{
		m_device->CreateShaderResourceView(m_vertex_buffer_data.Get(), &view,
			CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
				.Offset((INT)currentDescriptorIndex + offset++, m_descriptor_stride_srv_cbv_uav));
	}
	// Bind vertex buffer
	get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(VERTEX_BUFFERS_SLOT,
		CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
		.Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav)
		);

	// Constants
	const D3D12_CONSTANT_BUFFER_VIEW_DESC &fragment_constant_view = upload_fragment_shader_constants();
	get_current_resource_storage().command_list->SetGraphicsRootConstantBufferView(FRAGMENT_CONSTANT_BUFFERS_SLOT, fragment_constant_view.BufferLocation);

	upload_and_bind_scale_offset_matrix(currentDescriptorIndex + vertex_buffer_count);
	get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(SCALE_OFFSET_SLOT,
		CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
		.Offset((INT)currentDescriptorIndex + vertex_buffer_count, m_descriptor_stride_srv_cbv_uav)
		);

	if (m_transform_constants_dirty && !g_cfg.video.debug_output)
	{
		m_current_transform_constants_buffer_descriptor_id = (u32)currentDescriptorIndex + 1 + vertex_buffer_count;
		upload_and_bind_vertex_shader_constants(currentDescriptorIndex + 1 + vertex_buffer_count);
		m_transform_constants_dirty = false;
		get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(VERTEX_CONSTANT_BUFFERS_SLOT,
			CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
			.Offset(m_current_transform_constants_buffer_descriptor_id, m_descriptor_stride_srv_cbv_uav)
			);
	}


	std::chrono::time_point<steady_clock> constants_duration_end = steady_clock::now();
	m_timers.constants_duration += std::chrono::duration_cast<std::chrono::microseconds>(constants_duration_end - constants_duration_start).count();

	get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get());

	std::chrono::time_point<steady_clock> texture_duration_start = steady_clock::now();

	get_current_resource_storage().descriptors_heap_index += 2 + vertex_buffer_count;
	size_t texture_count = std::get<2>(m_current_pso);
	if (texture_count > 0)
	{
		if (get_current_resource_storage().current_sampler_index + 16 > 2048)
		{
			get_current_resource_storage().sampler_descriptors_heap_index = 1;
			get_current_resource_storage().current_sampler_index = 0;

			ID3D12DescriptorHeap *descriptors[] =
			{
				get_current_resource_storage().descriptors_heap.Get(),
				get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index].Get(),
			};
			get_current_resource_storage().command_list->SetDescriptorHeaps(2, descriptors);
		}

		upload_textures(get_current_resource_storage().command_list.Get(), texture_count);

		m_device->CopyDescriptorsSimple(16,
			CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
				.Offset((UINT)get_current_resource_storage().descriptors_heap_index, m_descriptor_stride_srv_cbv_uav),
			CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_texture_descriptors->GetCPUDescriptorHandleForHeapStart()),
			D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
			);

		m_device->CopyDescriptorsSimple(16,
			CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
				.Offset((UINT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers),
			CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_sampler_descriptors->GetCPUDescriptorHandleForHeapStart()),
			D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER
			);

		get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(TEXTURES_SLOT,
			CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
			.Offset((INT)get_current_resource_storage().descriptors_heap_index, m_descriptor_stride_srv_cbv_uav)
			);
		get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(SAMPLERS_SLOT,
			CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetGPUDescriptorHandleForHeapStart())
			.Offset((INT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers)
			);

		get_current_resource_storage().current_sampler_index += texture_count;
		get_current_resource_storage().descriptors_heap_index += texture_count;
	}

	std::chrono::time_point<steady_clock> texture_duration_end = steady_clock::now();
	m_timers.texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count();
	set_rtt_and_ds(get_current_resource_storage().command_list.Get());

	int clip_w = rsx::method_registers.surface_clip_width();
	int clip_h = rsx::method_registers.surface_clip_height();

	D3D12_VIEWPORT viewport =
	{
		0.f,
		0.f,
		(float)clip_w,
		(float)clip_h,
		rsx::method_registers.clip_min(),
		rsx::method_registers.clip_max(),
	};
	get_current_resource_storage().command_list->RSSetViewports(1, &viewport);

	get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(),
		rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height()));

	get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(rsx::method_registers.current_draw_clause.primitive));

	if (indexed_draw)
		get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0);
	else
		get_current_resource_storage().command_list->DrawInstanced((UINT)vertex_count, 1, 0, 0);

	std::chrono::time_point<steady_clock> end_duration = steady_clock::now();
	m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
	m_timers.draw_calls_count++;

	if (g_cfg.video.debug_output)
	{
		CHECK_HRESULT(get_current_resource_storage().command_list->Close());
		m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
		get_current_resource_storage().set_new_command_list();
	}
	thread::end();
}
Ejemplo n.º 10
0
std::array<std::vector<gsl::byte>, 2> D3D12GSRender::copy_depth_stencil_buffer_to_memory()
{
	int clip_w = rsx::method_registers.surface_clip_width();
	int clip_h = rsx::method_registers.surface_clip_height();
	return m_rtts.get_depth_stencil_data(rsx::method_registers.surface_depth_fmt(), clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
}
Ejemplo n.º 11
0
void D3D12GSRender::copy_render_target_to_dma_location()
{
	// Add all buffer write
	// Cell can't make any assumption about readyness of color/depth buffer
	// Except when a semaphore is written by RSX
	int clip_w = rsx::method_registers.surface_clip_width();
	int clip_h = rsx::method_registers.surface_clip_height();

	size_t depth_row_pitch = align(clip_w * 4, 256);
	size_t depth_buffer_offset_in_heap = 0;


	u32 address_color[] =
	{
		rsx::get_address(rsx::method_registers.surface_a_offset(), rsx::method_registers.surface_a_dma()),
		rsx::get_address(rsx::method_registers.surface_b_offset(), rsx::method_registers.surface_b_dma()),
		rsx::get_address(rsx::method_registers.surface_c_offset(), rsx::method_registers.surface_c_dma()),
		rsx::get_address(rsx::method_registers.surface_d_offset(), rsx::method_registers.surface_d_dma()),
	};
	u32 address_z = rsx::get_address(rsx::method_registers.surface_z_offset(), rsx::method_registers.surface_z_dma());

	bool need_transfer = false;

	if (rsx::method_registers.surface_z_dma() && g_cfg_rsx_write_depth_buffer)
	{
		get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
		get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { depth_buffer_offset_in_heap,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0,
			&CD3DX12_TEXTURE_COPY_LOCATION(std::get<1>(m_rtts.m_bound_depth_stencil), 0), nullptr);
		get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
		invalidate_address(address_z);

		need_transfer = true;
	}

	size_t color_buffer_offset_in_heap[4];
	if (g_cfg_rsx_write_color_buffers)
	{
		for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
		{
			if (!address_color[i])
				continue;
			color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[i]), rsx::method_registers.surface_color());
			invalidate_address(address_color[i]);
			need_transfer = true;
		}
	}
	if (need_transfer)
	{
		CHECK_HRESULT(get_current_resource_storage().command_list->Close());
		m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
		get_current_resource_storage().set_new_command_list();
	}

	//Wait for result
	wait_for_command_queue(m_device.Get(), m_command_queue.Get());

	if (address_z && g_cfg_rsx_write_depth_buffer)
	{
		auto ptr = vm::base(address_z);
		char *depth_buffer = (char*)ptr;
		u8 *mapped_buffer = m_readback_resources.map<u8>(depth_buffer_offset_in_heap);

		for (unsigned row = 0; row < (unsigned)clip_h; row++)
		{
			for (unsigned i = 0; i < (unsigned)clip_w; i++)
			{
				unsigned char c = mapped_buffer[row * depth_row_pitch + i];
				depth_buffer[4 * (row * clip_w + i)] = c;
				depth_buffer[4 * (row * clip_w + i) + 1] = c;
				depth_buffer[4 * (row * clip_w + i) + 2] = c;
				depth_buffer[4 * (row * clip_w + i) + 3] = c;
			}
		}
		m_readback_resources.unmap();
	}

	if (g_cfg_rsx_write_color_buffers)
	{
		size_t srcPitch = get_aligned_pitch(rsx::method_registers.surface_color(), clip_w);
		size_t dstPitch = get_packed_pitch(rsx::method_registers.surface_color(), clip_w);

		void *dest_buffer[] =
		{
			vm::base(address_color[0]),
			vm::base(address_color[1]),
			vm::base(address_color[2]),
			vm::base(address_color[3]),
		};

		for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target()))
		{
			if (!address_color[i])
				continue;
			copy_readback_buffer_to_dest(dest_buffer[i], m_readback_resources, color_buffer_offset_in_heap[i], srcPitch, dstPitch, clip_h);
		}
	}
}