Beispiel #1
0
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width,
                          unsigned int height, unsigned int src_pitch, unsigned int level,
                          D3D11_USAGE usage)
{
  if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
  {
    D3D11_MAPPED_SUBRESOURCE map;
    D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
    if (src_pitch == map.RowPitch)
    {
      memcpy(map.pData, buffer, map.RowPitch * height);
    }
    else
    {
      // Source row size is aligned to texture block size. This can result in a different
      // pitch to what the driver returns, so copy whichever is smaller.
      unsigned int copy_size = std::min(src_pitch, map.RowPitch);
      for (unsigned int y = 0; y < height; ++y)
        memcpy((u8*)map.pData + y * map.RowPitch, buffer + y * src_pitch, copy_size);
    }
    D3D::context->Unmap(pTexture, level);
  }
  else
  {
    D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
    D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, src_pitch,
                                    src_pitch * height);
  }
}
Beispiel #2
0
void Television::Submit(u32 xfbAddr, u32 width, u32 height)
{
	m_curAddr = xfbAddr;
	m_curWidth = width;
	m_curHeight = height;

	// Load data from GameCube RAM to YUYV texture
	u8* yuyvSrc = Memory::GetPointer(xfbAddr);
	D3D11_BOX box = CD3D11_BOX(0, 0, 0, width, height, 1);
	D3D::context->UpdateSubresource(m_yuyvTexture, 0, &box, yuyvSrc, 2*width, 2*width*height);
}
Beispiel #3
0
void Television::Submit(u32 xfb_address, u32 stride, u32 width, u32 height)
{
	m_current_address = xfb_address;
	m_current_width = width;
	m_current_height = height;

	// Load data from GameCube RAM to YUYV texture
#ifdef USE_D3D11
	u8* yuyvSrc = Memory::GetPointer(xfbAddr);
	D3D11_BOX box = CD3D11_BOX(0, 0, 0, stride, height, 1);
	D3D::context->UpdateSubresource(m_yuyvTexture, 0, &box, yuyvSrc, 2 * stride, 2 * stride * height);
#endif
}
void D3D11CommandBuffer::CopyBuffer(Buffer& dstBuffer, std::uint64_t dstOffset, Buffer& srcBuffer, std::uint64_t srcOffset, std::uint64_t size)
{
    auto& dstBufferD3D = LLGL_CAST(D3D11Buffer&, dstBuffer);
    auto& srcBufferD3D = LLGL_CAST(D3D11Buffer&, srcBuffer);

    context_->CopySubresourceRegion(
        dstBufferD3D.GetNative(),                               // pDstResource
        0,                                                      // DstSubresource
        static_cast<UINT>(dstOffset),                           // DstX
        0,                                                      // DstY
        0,                                                      // DstZ
        srcBufferD3D.GetNative(),                               // pSrcResource
        0,                                                      // SrcSubresource
        &CD3D11_BOX(                                            // pSrcBox
            static_cast<LONG>(srcOffset), 0, 0,
            static_cast<LONG>(srcOffset + size), 1, 1
        )
    );
}
Beispiel #5
0
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage)
{
	if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
	{
		D3D11_MAPPED_SUBRESOURCE map;
		D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
		if (4 * pitch == map.RowPitch)
		{
			memcpy(map.pData, buffer, map.RowPitch * height);
		}
		else
		{
			for (unsigned int y = 0; y < height; ++y)
				memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, 4 * pitch);
		}
		D3D::context->Unmap(pTexture, level);
	}
	else
	{
		D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
		D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
	}
}
Beispiel #6
0
void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma)
{
    HRESULT hr;

    // Reset API

    g_renderer->ResetAPIState();

    // Set up all the state for XFB encoding

    D3D::stateman->SetPixelShader(m_pShader);
    D3D::stateman->SetVertexShader(m_vShader);
    D3D::stateman->SetGeometryShader(nullptr);

    D3D::stateman->PushBlendState(m_xfbEncodeBlendState);
    D3D::stateman->PushDepthState(m_xfbEncodeDepthState);
    D3D::stateman->PushRasterizerState(m_xfbEncodeRastState);

    D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width/4), FLOAT(height));
    D3D::context->RSSetViewports(1, &vp);

    D3D::stateman->SetInputLayout(m_quadLayout);
    D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
    UINT stride = sizeof(QuadVertex);
    UINT offset = 0;
    D3D::stateman->SetVertexBuffer(m_quad, stride, offset);

    TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect);

    XFBEncodeParams params = { 0 };
    params.Width = FLOAT(width/2);
    params.Height = FLOAT(height);
    params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetTargetWidth();
    params.TexTop = FLOAT(targetRect.top) / g_renderer->GetTargetHeight();
    params.TexRight = FLOAT(targetRect.right) / g_renderer->GetTargetWidth();
    params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetTargetHeight();
    params.Gamma = gamma;
    D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &params, 0, 0);

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

    ID3D11ShaderResourceView* pEFB = FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();

    D3D::stateman->SetVertexConstants(m_encodeParams);
    D3D::stateman->SetPixelConstants(m_encodeParams);
    D3D::stateman->SetTexture(0, pEFB);
    D3D::stateman->SetSampler(0, m_efbSampler);

    // Encode!

    D3D::stateman->Apply();
    D3D::context->Draw(4, 0);

    // Copy to staging buffer

    D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, width/4, height, 1);
    D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);

    // Clean up state

    D3D::context->OMSetRenderTargets(0, nullptr, nullptr);

    D3D::stateman->SetSampler(0, nullptr);
    D3D::stateman->SetTexture(0, nullptr);
    D3D::stateman->SetPixelConstants(nullptr);
    D3D::stateman->SetVertexConstants(nullptr);

    D3D::stateman->SetPixelShader(nullptr);
    D3D::stateman->SetVertexShader(nullptr);

    D3D::stateman->PopRasterizerState();
    D3D::stateman->PopDepthState();
    D3D::stateman->PopBlendState();

    // Transfer staging buffer to GameCube/Wii RAM

    D3D11_MAPPED_SUBRESOURCE map = { 0 };
    hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map);
    CHECK(SUCCEEDED(hr), "map staging buffer");

    u8* src = (u8*)map.pData;
    for (unsigned int y = 0; y < height; ++y)
    {
        memcpy(dst, src, width);
        dst += bpmem.copyMipMapStrideChannels*32;
        src += map.RowPitch;
    }

    D3D::context->Unmap(m_outStage, 0);

    // Restore API
    g_renderer->RestoreAPIState();
    D3D::stateman->Apply(); // force unbind efb texture as shader resource
    D3D::context->OMSetRenderTargets(1,
                                     &FramebufferManager::GetEFBColorTexture()->GetRTV(),
                                     FramebufferManager::GetEFBDepthTexture()->GetDSV());
}
size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
	PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect,
	bool isIntensity, bool scaleByHalf)
{
	if (!m_ready) // Make sure we initialized OK
		return 0;

	// Clamp srcRect to 640x528. BPS: The Strike tries to encode an 800x600
	// texture, which is invalid.
	EFBRectangle correctSrc = srcRect;
	correctSrc.ClampUL(0, 0, EFB_WIDTH, EFB_HEIGHT);

	// Validate source rect size
	if (correctSrc.GetWidth() <= 0 || correctSrc.GetHeight() <= 0)
		return 0;

	HRESULT hr;

	unsigned int blockW = BLOCK_WIDTHS[dstFormat];
	unsigned int blockH = BLOCK_HEIGHTS[dstFormat];

	// Round up source dims to multiple of block size
	unsigned int actualWidth = correctSrc.GetWidth() / (scaleByHalf ? 2 : 1);
	actualWidth = (actualWidth + blockW-1) & ~(blockW-1);
	unsigned int actualHeight = correctSrc.GetHeight() / (scaleByHalf ? 2 : 1);
	actualHeight = (actualHeight + blockH-1) & ~(blockH-1);

	unsigned int numBlocksX = actualWidth/blockW;
	unsigned int numBlocksY = actualHeight/blockH;

	unsigned int cacheLinesPerRow;
	if (dstFormat == 0x6) // RGBA takes two cache lines per block; all others take one
		cacheLinesPerRow = numBlocksX*2;
	else
		cacheLinesPerRow = numBlocksX;
	_assert_msg_(VIDEO, cacheLinesPerRow*32 <= MAX_BYTES_PER_BLOCK_ROW, "cache lines per row sanity check");

	unsigned int totalCacheLines = cacheLinesPerRow * numBlocksY;
	_assert_msg_(VIDEO, totalCacheLines*32 <= MAX_BYTES_PER_ENCODE, "total encode size sanity check");

	size_t encodeSize = 0;

	// Reset API
	g_renderer->ResetAPIState();

	// Set up all the state for EFB encoding

	{
		D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(cacheLinesPerRow * 8), FLOAT(numBlocksY));
		D3D::context->RSSetViewports(1, &vp);

		EFBRectangle fullSrcRect;
		fullSrcRect.left = 0;
		fullSrcRect.top = 0;
		fullSrcRect.right = EFB_WIDTH;
		fullSrcRect.bottom = EFB_HEIGHT;
		TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect);

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

		ID3D11ShaderResourceView* pEFB = (srcFormat == PEControl::Z24) ?
			FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
			// FIXME: Instead of resolving EFB, it would be better to pick out a
			// single sample from each pixel. The game may break if it isn't
			// expecting the blurred edges around multisampled shapes.
			FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();

		EFBEncodeParams params;
		params.SrcLeft = correctSrc.left;
		params.SrcTop = correctSrc.top;
		params.DestWidth = actualWidth;
		params.ScaleFactor = scaleByHalf ? 2 : 1;
		D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &params, 0, 0);
		D3D::stateman->SetPixelConstants(m_encodeParams);

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

		D3D::drawShadedTexQuad(pEFB,
			targetRect.AsRECT(),
			Renderer::GetTargetWidth(),
			Renderer::GetTargetHeight(),
			SetStaticShader(dstFormat, srcFormat, isIntensity, scaleByHalf),
			VertexShaderCache::GetSimpleVertexShader(),
			VertexShaderCache::GetSimpleInputLayout());

		// Copy to staging buffer
		D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, cacheLinesPerRow * 8, numBlocksY, 1);
		D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);

		// Transfer staging buffer to GameCube/Wii RAM
		D3D11_MAPPED_SUBRESOURCE map = { 0 };
		hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map);
		CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);

		u8* src = (u8*)map.pData;
		for (unsigned int y = 0; y < numBlocksY; ++y)
		{
			memcpy(dst, src, cacheLinesPerRow*32);
			dst += bpmem.copyMipMapStrideChannels*32;
			src += map.RowPitch;
		}

		D3D::context->Unmap(m_outStage, 0);

		encodeSize = bpmem.copyMipMapStrideChannels*32 * numBlocksY;
	}

	// Restore API
	g_renderer->RestoreAPIState();
	D3D::context->OMSetRenderTargets(1,
		&FramebufferManager::GetEFBColorTexture()->GetRTV(),
		FramebufferManager::GetEFBDepthTexture()->GetDSV());

	return encodeSize;
}
void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
                              u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
                              bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
  if (!m_ready)  // Make sure we initialized OK
    return;

  HRESULT hr;

  // Resolve MSAA targets before copying.
  // FIXME: Instead of resolving EFB, it would be better to pick out a
  // single sample from each pixel. The game may break if it isn't
  // expecting the blurred edges around multisampled shapes.
  ID3D11ShaderResourceView* pEFB = is_depth_copy ?
                                       FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
                                       FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();

  // Reset API
  g_renderer->ResetAPIState();

  // Set up all the state for EFB encoding
  {
    const u32 words_per_row = bytes_per_row / sizeof(u32);

    D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y));
    D3D::context->RSSetViewports(1, &vp);

    constexpr EFBRectangle fullSrcRect(0, 0, EFB_WIDTH, EFB_HEIGHT);
    TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect);

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

    EFBEncodeParams params;
    params.SrcLeft = src_rect.left;
    params.SrcTop = src_rect.top;
    params.DestWidth = native_width;
    params.ScaleFactor = scale_by_half ? 2 : 1;
    D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, &params, 0, 0);
    D3D::stateman->SetPixelConstants(m_encodeParams);

    // We also linear filtering for both box filtering and downsampling higher resolutions to 1x
    // TODO: This only produces perfect downsampling for 1.5x and 2x IR, other resolution will
    //       need more complex down filtering to average all pixels and produce the correct result.
    // Also, box filtering won't be correct for anything other than 1x IR
    if (scale_by_half || g_ActiveConfig.iEFBScale != SCALE_1X)
      D3D::SetLinearCopySampler();
    else
      D3D::SetPointCopySampler();

    D3D::drawShadedTexQuad(pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(),
                           g_renderer->GetTargetHeight(), GetEncodingPixelShader(format),
                           VertexShaderCache::GetSimpleVertexShader(),
                           VertexShaderCache::GetSimpleInputLayout());

    // Copy to staging buffer
    D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, words_per_row, num_blocks_y, 1);
    D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);

    // Transfer staging buffer to GameCube/Wii RAM
    D3D11_MAPPED_SUBRESOURCE map = {0};
    hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map);
    CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);

    u8* src = (u8*)map.pData;
    u32 readStride = std::min(bytes_per_row, map.RowPitch);
    for (unsigned int y = 0; y < num_blocks_y; ++y)
    {
      memcpy(dst, src, readStride);
      dst += memory_stride;
      src += map.RowPitch;
    }

    D3D::context->Unmap(m_outStage, 0);
  }

  // Restore API
  g_renderer->RestoreAPIState();
  D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
                                   FramebufferManager::GetEFBDepthTexture()->GetDSV());
}