Example #1
0
void ReplaceRGBATexture2D(ID3D12Resource* texture12, const u8* buffer, unsigned int width, unsigned int height, unsigned int src_pitch, unsigned int level, D3D12_RESOURCE_STATES current_resource_state)
{
	const unsigned int upload_size = AlignValue(src_pitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) * height;

	if (!s_texture_upload_stream_buffer)
	{
		s_texture_upload_stream_buffer = new D3DStreamBuffer(4 * 1024 * 1024, 64 * 1024 * 1024, nullptr);
	}

	bool current_command_list_executed = s_texture_upload_stream_buffer->AllocateSpaceInBuffer(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
	if (current_command_list_executed)
	{
		g_renderer->SetViewport();
		D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
	}

	ResourceBarrier(current_command_list, texture12, current_resource_state, D3D12_RESOURCE_STATE_COPY_DEST, level);

	D3D12_PLACED_SUBRESOURCE_FOOTPRINT upload_footprint = {};
	u32 upload_rows = 0;
	u64 upload_row_size_in_bytes = 0;
	u64 upload_total_bytes = 0;

	D3D::device12->GetCopyableFootprints(&texture12->GetDesc(), level, 1, s_texture_upload_stream_buffer->GetOffsetOfCurrentAllocation(), &upload_footprint, &upload_rows, &upload_row_size_in_bytes, &upload_total_bytes);

	u8* dest_data = reinterpret_cast<u8*>(s_texture_upload_stream_buffer->GetCPUAddressOfCurrentAllocation());
	const u8* src_data = reinterpret_cast<const u8*>(buffer);
	for (u32 y = 0; y < upload_rows; ++y)
	{
		memcpy(
			dest_data + upload_footprint.Footprint.RowPitch * y,
			src_data + src_pitch * y,
			upload_row_size_in_bytes
			);
	}

	D3D::current_command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(texture12, level), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(s_texture_upload_stream_buffer->GetBuffer(), upload_footprint), nullptr);

	ResourceBarrier(D3D::current_command_list, texture12, D3D12_RESOURCE_STATE_COPY_DEST, current_resource_state, level);
}
Example #2
0
void TextureCache::TCacheEntry::CopyRectangleFromTexture(
	const TCacheEntryBase* source,
	const MathUtil::Rectangle<int>& src_rect,
	const MathUtil::Rectangle<int>& dst_rect)
{
	const TCacheEntry* srcentry = reinterpret_cast<const TCacheEntry*>(source);
	if (src_rect.GetWidth() == dst_rect.GetWidth()
		&& src_rect.GetHeight() == dst_rect.GetHeight())
	{
		D3D12_BOX srcbox;
		srcbox.left = src_rect.left;
		srcbox.top = src_rect.top;
		srcbox.right = src_rect.right;
		srcbox.bottom = src_rect.bottom;
		srcbox.front = 0;
		srcbox.back = srcentry->config.layers;

		if (static_cast<u32>(src_rect.GetHeight()) > config.height ||
			static_cast<u32>(src_rect.GetWidth()) > config.width)
		{
			// To mimic D3D11 behavior, we're just going to drop the clear since it is invalid.
			// This invalid copy needs to be fixed above the Backend level.

			// On D3D12, instead of silently dropping this invalid clear, the runtime throws an exception
			// so we need to filter it out ourselves.

			return;
		}

		D3D12_TEXTURE_COPY_LOCATION dst_location = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0);
		D3D12_TEXTURE_COPY_LOCATION src_location = CD3DX12_TEXTURE_COPY_LOCATION(srcentry->m_texture->GetTex12(), 0);

		m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST);
		srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE);

		D3D::current_command_list->CopyTextureRegion(&dst_location, dst_rect.left, dst_rect.top, 0, &src_location, &srcbox);

		m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
		srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

		return;
	}
	else if (!config.rendertarget)
	{
		return;
	}

	D3D::SetViewportAndScissor(dst_rect.left, dst_rect.top, dst_rect.GetWidth(), dst_rect.GetHeight());

	m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
	D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr);

	D3D::SetLinearCopySampler();

	D3D12_RECT src_rc;
	src_rc.left = src_rect.left;
	src_rc.right = src_rect.right;
	src_rc.top = src_rect.top;
	src_rc.bottom = src_rect.bottom;

	D3D::DrawShadedTexQuad(srcentry->m_texture, &src_rc,
		srcentry->config.width, srcentry->config.height,
		StaticShaderCache::GetColorCopyPixelShader(false),
		StaticShaderCache::GetSimpleVertexShader(),
		StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0, 0,
		DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled());

	m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

	FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
	FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
	D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());

	g_renderer->RestoreAPIState();
}
Example #3
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();
}
Example #4
0
void TextureCache::TCacheEntry::CopyRectangleFromTexture(const TCacheEntryBase* source,
                                                         const MathUtil::Rectangle<int>& src_rect,
                                                         const MathUtil::Rectangle<int>& dst_rect)
{
  const TCacheEntry* srcentry = reinterpret_cast<const TCacheEntry*>(source);
  if (src_rect.GetWidth() == dst_rect.GetWidth() && src_rect.GetHeight() == dst_rect.GetHeight())
  {
    // These assertions should hold true unless the base code is passing us sizes too large, in
    // which case it should be fixed instead.
    _assert_msg_(VIDEO, static_cast<u32>(src_rect.GetWidth()) <= source->config.width &&
                            static_cast<u32>(src_rect.GetHeight()) <= source->config.height,
                 "Source rect is too large for CopyRectangleFromTexture");

    _assert_msg_(VIDEO, static_cast<u32>(dst_rect.GetWidth()) <= config.width &&
                            static_cast<u32>(dst_rect.GetHeight()) <= config.height,
                 "Dest rect is too large for CopyRectangleFromTexture");

    CD3DX12_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom,
                        srcentry->config.layers);
    D3D12_TEXTURE_COPY_LOCATION dst_location =
        CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0);
    D3D12_TEXTURE_COPY_LOCATION src_location =
        CD3DX12_TEXTURE_COPY_LOCATION(srcentry->m_texture->GetTex12(), 0);

    m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST);
    srcentry->m_texture->TransitionToResourceState(D3D::current_command_list,
                                                   D3D12_RESOURCE_STATE_COPY_SOURCE);
    D3D::current_command_list->CopyTextureRegion(&dst_location, dst_rect.left, dst_rect.top, 0,
                                                 &src_location, &src_box);

    m_texture->TransitionToResourceState(D3D::current_command_list,
                                         D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
    srcentry->m_texture->TransitionToResourceState(D3D::current_command_list,
                                                   D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

    return;
  }
  else if (!config.rendertarget)
  {
    return;
  }

  D3D::SetViewportAndScissor(dst_rect.left, dst_rect.top, dst_rect.GetWidth(),
                             dst_rect.GetHeight());

  m_texture->TransitionToResourceState(D3D::current_command_list,
                                       D3D12_RESOURCE_STATE_RENDER_TARGET);
  D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr);

  D3D::SetLinearCopySampler();

  D3D12_RECT src_rc;
  src_rc.left = src_rect.left;
  src_rc.right = src_rect.right;
  src_rc.top = src_rect.top;
  src_rc.bottom = src_rect.bottom;

  D3D::DrawShadedTexQuad(
      srcentry->m_texture, &src_rc, srcentry->config.width, srcentry->config.height,
      StaticShaderCache::GetColorCopyPixelShader(false), StaticShaderCache::GetSimpleVertexShader(),
      StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0, 0,
      DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled());

  m_texture->TransitionToResourceState(D3D::current_command_list,
                                       D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

  FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(
      D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
  FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(
      D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);

  g_renderer->RestoreAPIState();
}
Example #5
0
void TextureCache::TCacheEntry::CopyRectangleFromTexture(
	const TCacheEntryBase* source,
	const MathUtil::Rectangle<int>& src_rect,
	const MathUtil::Rectangle<int>& dst_rect)
{
	TCacheEntry* srcentry = (TCacheEntry*)source;
	if (src_rect.GetWidth() == dst_rect.GetWidth()
		&& src_rect.GetHeight() == dst_rect.GetHeight())
	{
		const D3D12_BOX *psrcbox = nullptr;
		D3D12_BOX srcbox;
		if (src_rect.left != 0 
			|| src_rect.top != 0 
			|| src_rect.GetWidth() != srcentry->config.width 
			|| src_rect.GetHeight() != srcentry->config.height)
		{
			srcbox.left = src_rect.left;
			srcbox.top = src_rect.top;
			srcbox.right = src_rect.right;
			srcbox.bottom = src_rect.bottom;
			srcbox.front = 0;
			srcbox.back = 1;
			psrcbox = &srcbox;
		}
		
		D3D12_TEXTURE_COPY_LOCATION dst = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0);
		D3D12_TEXTURE_COPY_LOCATION src = CD3DX12_TEXTURE_COPY_LOCATION(srcentry->m_texture->GetTex12(), 0);

		m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST);
		srcentry->m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE);

		D3D::current_command_list->CopyTextureRegion(&dst, dst_rect.left, dst_rect.top, 0, &src, psrcbox);

		return;
	}
	else if (!config.rendertarget)
	{
		return;
	}

	const D3D12_VIEWPORT vp12 = {
		float(dst_rect.left),
		float(dst_rect.top),
		float(dst_rect.GetWidth()),
		float(dst_rect.GetHeight()),
		D3D12_MIN_DEPTH,
		D3D12_MAX_DEPTH
	};
	D3D::current_command_list->RSSetViewports(1, &vp12);

	m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
	D3D::current_command_list->OMSetRenderTargets(1, &m_texture->GetRTV12(), FALSE, nullptr);

	D3D::SetLinearCopySampler();
	D3D12_RECT srcRC;
	srcRC.left = src_rect.left;
	srcRC.right = src_rect.right;
	srcRC.top = src_rect.top;
	srcRC.bottom = src_rect.bottom;
	D3D::DrawShadedTexQuad(srcentry->m_texture, &srcRC,
		srcentry->config.width, srcentry->config.height,
		StaticShaderCache::GetColorCopyPixelShader(false),
		StaticShaderCache::GetSimpleVertexShader(),
		StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), 1.0, 0,
		DXGI_FORMAT_R8G8B8A8_UNORM, false, m_texture->GetMultisampled());

	FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
	FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
	D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());

	g_renderer->RestoreAPIState();
}
Example #6
0
bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level)
{
	// EXISTINGD3D11TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs)
	static bool warn_once = true;
	if (level && warn_once)
	{
		WARN_LOG(VIDEO, "Dumping individual LOD not supported by D3D11 backend!");
		warn_once = false;
		return false;
	}

	D3D12_RESOURCE_DESC textureDesc = m_texture->GetTex12()->GetDesc();

	UINT requiredReadbackBufferSize = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT + ((textureDesc.Width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1)) * textureDesc.Height;

	if (s_texture_cache_entry_readback_buffer_size < requiredReadbackBufferSize)
	{
		s_texture_cache_entry_readback_buffer_size = requiredReadbackBufferSize;

		// We know the readback buffer won't be in use right now, since we wait on this thread 
		// for the GPU to finish execution right after copying to it.

		SAFE_RELEASE(s_texture_cache_entry_readback_buffer);
	}

	if (!s_texture_cache_entry_readback_buffer_size)
	{
		CheckHR(
			D3D::device12->CreateCommittedResource(
				&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK),
				D3D12_HEAP_FLAG_NONE,
				&CD3DX12_RESOURCE_DESC::Buffer(s_texture_cache_entry_readback_buffer_size),
				D3D12_RESOURCE_STATE_COPY_DEST,
				nullptr,
				IID_PPV_ARGS(&s_texture_cache_entry_readback_buffer)
				)
			);

		CheckHR(s_texture_cache_entry_readback_buffer->Map(0, nullptr, &s_texture_cache_entry_readback_buffer_data));
	}

	bool saved_png = false;

	m_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE);
	
	D3D12_TEXTURE_COPY_LOCATION dst_location = {};
	dst_location.pResource = s_texture_cache_entry_readback_buffer;
	dst_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
	dst_location.PlacedFootprint.Offset = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
	dst_location.PlacedFootprint.Footprint.Depth = 1;
	dst_location.PlacedFootprint.Footprint.Format = textureDesc.Format;
	dst_location.PlacedFootprint.Footprint.Width = static_cast<UINT>(textureDesc.Width);
	dst_location.PlacedFootprint.Footprint.Height = textureDesc.Height;
	dst_location.PlacedFootprint.Footprint.RowPitch = ((textureDesc.Width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1));

	D3D12_TEXTURE_COPY_LOCATION src_location = CD3DX12_TEXTURE_COPY_LOCATION(m_texture->GetTex12(), 0);

	D3D::current_command_list->CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, nullptr);

	D3D::command_list_mgr->ExecuteQueuedWork(true);

	saved_png = TextureToPng(
		static_cast<u8*>(s_texture_cache_entry_readback_buffer_data) + D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT,
		dst_location.PlacedFootprint.Footprint.RowPitch,
		filename,
		dst_location.PlacedFootprint.Footprint.Width,
		dst_location.PlacedFootprint.Footprint.Height
		);

	return saved_png;
}
Example #7
0
void D3DPostProcessor::CopyTexture(const TargetRectangle& dst_rect, uintptr_t dst_tex,
	const TargetRectangle& src_rect, uintptr_t src_tex,
	const TargetSize& src_size, int src_layer, bool is_depth_texture,
	bool force_shader_copy)
{
	D3DTexture2D* dst_texture = reinterpret_cast<D3DTexture2D*>(dst_tex);
	D3DTexture2D* src_texture = reinterpret_cast<D3DTexture2D*>(src_tex);
	// If the dimensions are the same, we can copy instead of using a shader.
	bool scaling = (dst_rect.GetWidth() != src_rect.GetWidth() || dst_rect.GetHeight() != src_rect.GetHeight());
	if (!scaling && !force_shader_copy)
	{
		D3D12_BOX srcbox = {
			static_cast<UINT>(src_rect.left),
			static_cast<UINT>(src_rect.top),
			0,
			static_cast<UINT>(src_rect.right),
			static_cast<UINT>(src_rect.bottom),
			1 };

		D3D12_TEXTURE_COPY_LOCATION dst = CD3DX12_TEXTURE_COPY_LOCATION(dst_texture->GetTex(), 0);
		D3D12_TEXTURE_COPY_LOCATION src = CD3DX12_TEXTURE_COPY_LOCATION(src_texture->GetTex(), 0);

		dst_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_DEST);
		src_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_COPY_SOURCE);

		if (src_layer < 0)
		{
			// Copy all layers
			for (unsigned int layer = 0; layer < FramebufferManager::GetEFBLayers(); layer++)
			{
				src.SubresourceIndex = D3D12CalcSubresource(0, layer, 0, 1, FramebufferManager::GetEFBLayers());
				dst.SubresourceIndex = src.SubresourceIndex;
				D3D::current_command_list->CopyTextureRegion(&dst, dst_rect.left, dst_rect.top, 0, &src, &srcbox);
			}
		}
		else
		{
			// Copy single layer to layer 0
			D3D::current_command_list->CopyTextureRegion(&dst, dst_rect.left, dst_rect.top, 0, &src, &srcbox);
		}
	}
	else
	{
		D3D::SetViewportAndScissor(dst_rect.left, dst_rect.top, dst_rect.GetWidth(), dst_rect.GetHeight());
		dst_texture->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
		D3D::current_command_list->OMSetRenderTargets(1, &dst_texture->GetRTV(), FALSE, nullptr);

		if (scaling)
			D3D::SetLinearCopySampler();
		else
			D3D::SetPointCopySampler();

		D3D12_SHADER_BYTECODE bytecode = {};

		D3D::DrawShadedTexQuad(src_texture, src_rect.AsRECT(), src_size.width, src_size.height,
			StaticShaderCache::GetColorCopyPixelShader(false),
			StaticShaderCache::GetSimpleVertexShader(),
			StaticShaderCache::GetSimpleVertexShaderInputLayout(),
			(src_layer < 0) ? StaticShaderCache::GetCopyGeometryShader() : bytecode, 0,
			dst_texture->GetFormat(), false, dst_texture->GetMultisampled());
	}
}
Example #8
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);
		}
	}
}