コード例 #1
0
void DX11SpriteBatch::Draw(const POINT& center, float width, float height, XMCOLOR color)
{
	Sprite sprite;
	sprite.SrcRect  = CD3D11_RECT(0, 0, mTexWidth, mTexHeight);;
	sprite.DestRect = CD3D11_RECT(center.x - (LONG)(0.5*width), center.y - (LONG)(0.5*width), center.x + (LONG)(0.5*width), center.y + (LONG)(0.5*height));
	sprite.Color    = color;

	mSpriteList.push_back(sprite);
}
コード例 #2
0
void DX11SpriteBatch::Draw(const POINT& position, XMCOLOR color)
{
	Sprite sprite;
	sprite.SrcRect  = CD3D11_RECT(0, 0, mTexWidth, mTexHeight);
	sprite.DestRect = CD3D11_RECT(position.x, position.y, position.x + mTexWidth, position.y + mTexHeight);
	sprite.Color    = color;

	mSpriteList.push_back(sprite);
}
コード例 #3
0
void DX11SpriteBatch::DrawConsoleCommand(DX11FontSheet& fs, char (&text)[COMMAND_MAX_LENGTH], const POINT& pos)
{
	BeginBatch(fs.GetFontSheetSRV());

	int posX = pos.x;
	int posY = pos.y;

	XMCOLOR color = 0xffffffff;
	
	for(u32 i = 0; i < COMMAND_MAX_LENGTH; ++i)
	{
		WCHAR character = text[i];

		if(character == ' ')
			posX += fs.GetSpaceWidth();
		else if(character == '\t')
			posX += (4*fs.GetMaxCharWidth() - posX%(4*fs.GetMaxCharWidth()));
		else if(character == '\n')
		{
			posX  = pos.x;
			posY += fs.GetCharHeight();
		}
		else if(character == nullchar)
			break;
		else
		{
			if ( character < DX11FontSheet::StartChar || character > DX11FontSheet::EndChar )
				character = '?';

			const CD3D11_RECT& charRect = fs.GetCharBoundingRect(character);

			int width  = charRect.right - charRect.left;
			int height = charRect.bottom - charRect.top;

			Draw(CD3D11_RECT(posX, posY, posX + width, posY + height), charRect, color);

			// Move to the next character position.
			posX += width + 1;
		}
	}

	// We Draw the cursor
	const CD3D11_RECT& charRect = fs.GetCharBoundingRect('_');
	int width  = charRect.right - charRect.left;
	int height = charRect.bottom - charRect.top;

	Draw(CD3D11_RECT(posX, posY, posX + width, posY + height), charRect, color);

	EndBatch(mContext);
}
コード例 #4
0
void DxFont::BuildFontSheetBitmap(Gdiplus::Font & font, Gdiplus::Graphics & charGraphics, Gdiplus::Bitmap & charBitmap, Gdiplus::Graphics & fontSheetGraphics)
{
    WCHAR               charString[ 2 ] = { ' ', 0 };
    Gdiplus::SolidBrush whiteBrush( Gdiplus::Color( 255, 255, 255, 255 ) );
    UINT                fontSheetX = 0;
    UINT                fontSheetY = 0;

    for( UINT i = 0; i < NumChars; ++i )
    {
        charString[ 0 ] = static_cast<WCHAR>(StartChar + i);

        charGraphics.Clear(Gdiplus::Color(0, 0, 0, 0));
        charGraphics.DrawString(charString, 1, &font, Gdiplus::PointF(0.0f, 0.0f), &whiteBrush);

        int minX      = GetCharMinX(charBitmap);
        int maxX      = GetCharMaxX(charBitmap);
        int charWidth = maxX - minX + 1;

        if(fontSheetX + charWidth >= TexWidth)
        {
            fontSheetX = 0;
            fontSheetY += static_cast<int>(CharHeight) + 1;
        }

        CharRects[i] = CD3D11_RECT(fontSheetX, fontSheetY, fontSheetX + charWidth, fontSheetY + CharHeight);

        fontSheetGraphics.DrawImage(&charBitmap, fontSheetX, fontSheetY, minX, 0, charWidth, CharHeight, Gdiplus::UnitPixel);

        fontSheetX += charWidth + 1;
    }
}
コード例 #5
0
ファイル: Television.cpp プロジェクト: bradparks/dolphin
void Television::Render()
{
	if (g_ActiveConfig.bUseRealXFB && g_ActiveConfig.bUseXFB)
	{
		// Use real XFB mode
		// TODO: If this is the lower field, render at a vertical offset of 1
		// line down. We could even consider implementing a deinterlacing
		// algorithm.

		D3D11_RECT sourceRc = CD3D11_RECT(0, 0, int(m_curWidth), int(m_curHeight));

		D3D::stateman->SetSampler(0, m_samplerState);

		D3D::drawShadedTexQuad(
			m_yuyvTextureSRV, &sourceRc,
			MAX_XFB_WIDTH, MAX_XFB_HEIGHT,
			m_pShader,
			VertexShaderCache::GetSimpleVertexShader(),
			VertexShaderCache::GetSimpleInputLayout());
	}
	else if (g_ActiveConfig.bUseXFB)
	{
		// Use virtual XFB mode

		// TODO: Eventually, Television should render the Virtual XFB mode
		// display as well.
	}
}
コード例 #6
0
ファイル: TextureCache.cpp プロジェクト: maximovmax/Ishiiruka
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, unsigned int dstFormat, u32 dstStride,
	PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
	bool isIntensity, bool scaleByHalf, u32 cbufid,
	const float *colmat)
{
	g_renderer->ResetAPIState();
	// stretch picture with increased internal resolution
	const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)config.width, (float)config.height);
	D3D::context->RSSetViewports(1, &vp);

	// set transformation
	if (nullptr == efbcopycbuf[cbufid].get())
	{
		const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
		D3D11_SUBRESOURCE_DATA data;
		data.pSysMem = colmat;
		HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, D3D::ToAddr(efbcopycbuf[cbufid]));
		CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid);
		D3D::SetDebugObjectName(efbcopycbuf[cbufid].get(), "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
	}
	D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid].get());

	const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
	// TODO: try targetSource.asRECT();
	const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);

	// Use linear filtering if (bScaleByHalf), use point filtering otherwise
	if (scaleByHalf)
		D3D::SetLinearCopySampler();
	else
		D3D::SetPointCopySampler();

	// if texture is currently in use, it needs to be temporarily unset
	u32 textureSlotMask = D3D::stateman->UnsetTexture(texture->GetSRV());
	D3D::stateman->Apply();
	D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr);
	// Create texture copy
	D3D::drawShadedTexQuad(
		((srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(),
		&sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
		(srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
		VertexShaderCache::GetSimpleVertexShader(),
		VertexShaderCache::GetSimpleInputLayout(),
		(g_Config.iStereoMode > 0) ? GeometryShaderCache::GetCopyGeometryShader() : nullptr);

	D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());

	g_renderer->RestoreAPIState();

	if (g_ActiveConfig.bSkipEFBCopyToRam)
	{
		this->Zero(dst);
	}
	else
	{
		s_encoder->Encode(dst, this, srcFormat, srcRect, isIntensity, scaleByHalf);
	}
}
コード例 #7
0
void DX11SpriteBatch::Draw(const CD3D11_RECT& destinationRect, XMCOLOR color)
{
	Sprite sprite;
	sprite.SrcRect  = CD3D11_RECT(0, 0, mTexWidth, mTexHeight);
	sprite.DestRect = destinationRect;
	sprite.Color    = color;

	mSpriteList.push_back(sprite);
}
コード例 #8
0
void DX11SpriteBatch::Draw(const POINT& position, const CD3D11_RECT& sourceRect, XMCOLOR color)
{
	int srcWidth  = sourceRect.right - sourceRect.left;
	int srcHeight = sourceRect.bottom - sourceRect.top;

	Sprite sprite;
	sprite.SrcRect  = sourceRect;
	sprite.DestRect = CD3D11_RECT(position.x, position.y, position.x + srcWidth, position.y + srcHeight);
	sprite.Color    = color;

	mSpriteList.push_back(sprite);
}
コード例 #9
0
ファイル: TextureCache.cpp プロジェクト: Felk/dolphin
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
	bool scaleByHalf, unsigned int cbufid, const float *colmat)
{
	g_renderer->ResetAPIState();

	// stretch picture with increased internal resolution
	const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)config.width, (float)config.height);
	D3D::context->RSSetViewports(1, &vp);

	// set transformation
	if (nullptr == efbcopycbuf[cbufid])
	{
		const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
		D3D11_SUBRESOURCE_DATA data;
		data.pSysMem = colmat;
		HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]);
		CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid);
		D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
	}
	D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid]);

	const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
	// TODO: try targetSource.asRECT();
	const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);

	// Use linear filtering if (bScaleByHalf), use point filtering otherwise
	if (scaleByHalf)
		D3D::SetLinearCopySampler();
	else
		D3D::SetPointCopySampler();

	// Make sure we don't draw with the texture set as both a source and target.
	// (This can happen because we don't unbind textures when we free them.)
	D3D::stateman->UnsetTexture(texture->GetSRV());

	D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr);

	// Create texture copy
	D3D::drawShadedTexQuad(
		(srcFormat == PEControl::Z24 ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture())->GetSRV(),
		&sourcerect, Renderer::GetTargetWidth(),
		Renderer::GetTargetHeight(),
		srcFormat == PEControl::Z24 ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
		VertexShaderCache::GetSimpleVertexShader(),
		VertexShaderCache::GetSimpleInputLayout(),
		GeometryShaderCache::GetCopyGeometryShader());

	D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());

	g_renderer->RestoreAPIState();
}
コード例 #10
0
void DxSprite::DrawString(int X, int Y, const std::wstring & text, int R, int G, int B, int A, DxFont & F)
{
    float blendFactor[4] = { 1.0f };
    GetDX11Context()->OMSetBlendState(TransparentBS, blendFactor, 0xFFFFFFFF);

    BeginBatch(F.GetFontSheetSRV());

    UINT length = text.length();

    int posX = X;
    int posY = Y;

    XMCOLOR color;
    XMVECTOR Vec = XMVectorSet( R ? (float)( R / 255.0f ) : 0.0f, G ? (float)( G / 255.0f ) : 0.0f, B ? (float)( B / 255.0f ) : 0.0f, A ? (float)( A / 255.0f ) : 0.0f );
    XMStoreColor(&color, Vec);

    for(UINT i = 0; i < length; ++i)
    {
        WCHAR character = text[i];

        if(character == ' ') 
            posX += F.GetSpaceWidth();
        else if(character == '\n')
        {
            posX = X;
            posY += F.GetCharHeight();
        }
        else
        {
            const CD3D11_RECT & charRect = F.GetCharRect(character);

            int width  = charRect.right - charRect.left;
            int height = charRect.bottom - charRect.top;

            Draw(CD3D11_RECT(posX, posY, posX + width, posY + height), charRect, color);

            posX += width + 1;
        }
    }

    EndBatch();

    GetDX11Context()->OMSetBlendState(0, blendFactor, 0xFFFFFFFF);
}
コード例 #11
0
void XFBSource::CopyEFB(float Gamma)
{
	g_renderer->ResetAPIState(); // reset any game specific settings

	// Copy EFB data to XFB and restore render target again
	const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
	const D3D11_RECT rect = CD3D11_RECT(0, 0, texWidth, texHeight);

	D3D::context->RSSetViewports(1, &vp);
	D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), nullptr);
	D3D::SetPointCopySampler();

	D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &rect,
		Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(true),
		VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
		GeometryShaderCache::GetCopyGeometryShader(), Gamma);

	D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
		FramebufferManager::GetEFBDepthTexture()->GetDSV());

	g_renderer->RestoreAPIState();
}
コード例 #12
0
ファイル: TextureCache.cpp プロジェクト: gamax92/Ishiiruka
void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat src_format, const EFBRectangle& srcRect,
	bool scale_by_half, unsigned int cbuf_id, const float* colmat)
{
	// When copying at half size, in multisampled mode, resolve the color/depth buffer first.
	// This is because multisampled texture reads go through Load, not Sample, and the linear
	// filter is ignored.
	bool multisampled = (g_ActiveConfig.iMultisamples > 1);
	D3DTexture2D* efb_tex = (src_format == PEControl::Z24) ?
		FramebufferManager::GetEFBDepthTexture() :
		FramebufferManager::GetEFBColorTexture();
	if (multisampled && scale_by_half)
	{
		multisampled = false;
		efb_tex = (src_format == PEControl::Z24) ?
			FramebufferManager::GetResolvedEFBDepthTexture() :
			FramebufferManager::GetResolvedEFBColorTexture();
	}

	// stretch picture with increased internal resolution
	const D3D12_VIEWPORT vp = { 0.f, 0.f, (float)config.width, (float)config.height, D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
	D3D::current_command_list->RSSetViewports(1, &vp);

	// set transformation
	if (nullptr == s_efb_copy_buffers[cbuf_id])
	{
		CheckHR(
			D3D::device12->CreateCommittedResource(
				&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
				D3D12_HEAP_FLAG_NONE,
				&CD3DX12_RESOURCE_DESC::Buffer(28 * sizeof(float)),
				D3D12_RESOURCE_STATE_GENERIC_READ,
				nullptr,
				IID_PPV_ARGS(&s_efb_copy_buffers[cbuf_id])
				)
			);

		void* pData = nullptr;
		CheckHR(s_efb_copy_buffers[cbuf_id]->Map(0, nullptr, &pData));
		memcpy(pData, colmat, 28 * sizeof(float));
	}

	D3D::current_command_list->SetGraphicsRootConstantBufferView(DESCRIPTOR_TABLE_PS_CBVONE, s_efb_copy_buffers[cbuf_id]->GetGPUVirtualAddress());
	D3D::command_list_mgr->m_dirty_ps_cbv = true;

	const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
	// TODO: try targetSource.asRECT();
	const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);

	// Use linear filtering if (bScaleByHalf), use point filtering otherwise
	if (scale_by_half)
		D3D::SetLinearCopySampler();
	else
		D3D::SetPointCopySampler();

	// Make sure we don't draw with the texture set as both a source and target.
	// (This can happen because we don't unbind textures when we free them.)

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

	// Create texture copy
	D3D::DrawShadedTexQuad(
		efb_tex,
		&sourcerect,
		Renderer::GetTargetWidth(),
		Renderer::GetTargetHeight(),
		(src_format == PEControl::Z24) ? StaticShaderCache::GetDepthMatrixPixelShader(multisampled) : StaticShaderCache::GetColorMatrixPixelShader(multisampled),
		StaticShaderCache::GetSimpleVertexShader(),
		StaticShaderCache::GetSimpleVertexShaderInputLayout(),
		StaticShaderCache::GetCopyGeometryShader(),
		1.0f, 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();
}
コード例 #13
0
void DX11SpriteBatch::DrawInfoText(DX11FontSheet& fs, const char* text, const POINT& pos)
{
	BeginBatch(fs.GetFontSheetSRV());

	int posX         = pos.x;
	int posY         = pos.y;
	int tabIdx       = 0;
	int maxCharWidth = fs.GetMaxCharWidth();

	XMCOLOR color = Color::Black;

	u32 i = 0;
	while( true )
	{
		WCHAR character = text[i];

		if(character == ' ')
		{
			posX   += maxCharWidth;
			tabIdx += maxCharWidth;
		}
		else if(character == '\t')
		{
			posX += (4*maxCharWidth - tabIdx%(4*maxCharWidth));
			tabIdx = 0;
		}
		else if(character == '\n')
		{
			posX  = pos.x;
			posY += fs.GetCharHeight();
			tabIdx = 0;
		}
		else if(character == SCREEN_WHITE)		color = Color::White;
		else if(character == SCREEN_RED)		color = Color::Red;
		else if(character == SCREEN_GREEN)		color = Color::Lime;
		else if(character == SCREEN_BLUE)		color = Color::Blue;
		else if(character == SCREEN_YELLOW)		color = Color::Yellow;
		else if(character == SCREEN_ORANGE)		color = Color::Orange;
		else if(character == SCREEN_ROSE)		color = Color::Fuchsia;
		else if(character == SCREEN_GRAY)		color = Color::Gray;
		else if(character == SCREEN_BLACK)		color = Color::Black;
		else if(character == nullchar)			break;
		else
		{
			if ( character < DX11FontSheet::StartChar || character > DX11FontSheet::EndChar )
				character = '?';

			// Get the bounding rect of the character on the fontsheet.
			const CD3D11_RECT& charRect = fs.GetCharBoundingRect(character);

			int width  = charRect.right - charRect.left;
			int height = charRect.bottom - charRect.top;
			int delta = maxCharWidth - width;

			// Draw the character sprite.
			Draw(CD3D11_RECT(posX, posY, posX + width, posY + height), charRect, color);

			// Move to the next character position.
			posX   += width + delta;
			tabIdx += width + delta;
		}
		++i;
	}

	EndBatch(mContext);
}
コード例 #14
0
void DX11SpriteBatch::DrawString(DX11FontSheet& fs, const char text[], const POINT& pos, XMCOLOR color, TextAlignment alignment)
{
	BeginBatch(fs.GetFontSheetSRV());

	u32 length = (u32)strlen(text);

	int posX         = 0;
	int posY         = pos.y;
	int totalWidth   = 0;
	int tabIdx       = 0;
	int maxCharWidth = fs.GetMaxCharWidth();

	if (alignment == LeftAligned)
	{
		posX = pos.x;
	}
	else
	{
		// Calculate text total width to adjust with the alignment
		for(u32 i = 0; i < length; ++i)
		{
			WCHAR character = text[i];

			if(character == ' ')
			{
				totalWidth += maxCharWidth;
			}
			else
			{
				if ( character < DX11FontSheet::StartChar || character > DX11FontSheet::EndChar )
					character = '?';

				// Get the bounding rect of the character on the fontsheet.
				const CD3D11_RECT& charRect = fs.GetCharBoundingRect(character);

				int width  = charRect.right - charRect.left;
				totalWidth += width;
			}
		}

		if (alignment == RightAligned)		posX = pos.x - totalWidth;
		else								posX = pos.x - totalWidth/ 2;
	}

	for(u32 i = 0; i < length; ++i)
	{
		WCHAR character = text[i];

		if(character == ' ') 
		{
			posX   += maxCharWidth;
			tabIdx += maxCharWidth;
		}
		else if(character == '\t')
		{
			posX += (4*maxCharWidth - posX%(4*maxCharWidth));
			tabIdx = 0;
		}
		else if(character == '\n')
		{
			posX   = pos.x;
			posY  += fs.GetCharHeight();;
			tabIdx = 0;
		}
		else
		{
			if ( character < DX11FontSheet::StartChar || character > DX11FontSheet::EndChar )
				character = '?';

			// Get the bounding rect of the character on the fontsheet.
			const CD3D11_RECT& charRect = fs.GetCharBoundingRect(character);

			int width  = charRect.right - charRect.left;
			int height = charRect.bottom - charRect.top;
			int delta = maxCharWidth - width;

			// Draw the character sprite.
			Draw(CD3D11_RECT(posX, posY, posX + width, posY + height), charRect, color);

			// Move to the next character position.
			posX   += width + delta;
			tabIdx += width + delta;
		}
	}

	EndBatch(mContext);
}
コード例 #15
0
ファイル: TextureCache.cpp プロジェクト: BlockABoots/dolphin
void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
	PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
	bool isIntensity, bool scaleByHalf, unsigned int cbufid,
	const float *colmat)
{
	if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
	{
		g_renderer->ResetAPIState();

		// stretch picture with increased internal resolution
		const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtual_width, (float)virtual_height);
		D3D::context->RSSetViewports(1, &vp);

		// set transformation
		if (nullptr == efbcopycbuf[cbufid])
		{
			const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
			D3D11_SUBRESOURCE_DATA data;
			data.pSysMem = colmat;
			HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]);
			CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid);
			D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
		}
		D3D::stateman->SetPixelConstants(efbcopycbuf[cbufid]);

		const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
		// TODO: try targetSource.asRECT();
		const D3D11_RECT sourcerect = CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);

		// Use linear filtering if (bScaleByHalf), use point filtering otherwise
		if (scaleByHalf)
			D3D::SetLinearCopySampler();
		else
			D3D::SetPointCopySampler();

		// if texture is currently in use, it needs to be temporarily unset
		u32 textureSlotMask = D3D::stateman->UnsetTexture(texture->GetSRV());
		D3D::stateman->Apply();

		D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr);

		// Create texture copy
		D3D::drawShadedTexQuad(
			(srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
			&sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
			(srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
			VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());

		D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());

		g_renderer->RestoreAPIState();

		// Restore old texture in all previously used slots, if any
		D3D::stateman->SetTextureByMask(textureSlotMask, texture->GetSRV());
	}

	if (!g_ActiveConfig.bCopyEFBToTexture)
	{
		u8* dst = Memory::GetPointer(dstAddr);
		size_t encoded_size = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf);

		u64 hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);

		// Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date
		if (!g_ActiveConfig.bEFBCopyCacheEnable)
			TextureCache::MakeRangeDynamic(addr, (u32)encoded_size);
		else if (!TextureCache::Find(addr, hash))
			TextureCache::MakeRangeDynamic(addr, (u32)encoded_size);

		this->hash = hash;
	}
}