Esempio n. 1
0
void Television::Render()
{
#ifdef USE_D3D11
	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.

		D3D12_RECT sourceRc = CD3DX12_RECT(0, 0, int(m_curWidth), int(m_curHeight));

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

		// D3D12TODO: This uses the normal 'reset' states, which DrawShadedTexQuad is already hard-coded to.
		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.
	}
#endif
}
Esempio n. 2
0
void FramebufferManager::ResolveDepthTexture()
{
    // ResolveSubresource does not work with depth textures.
    // Instead, we use a shader that selects the minimum depth from all samples.

    const D3D12_VIEWPORT vp12 = { 0.f, 0.f, static_cast<float>(m_target_width), static_cast<float>(m_target_height), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
    D3D::current_command_list->RSSetViewports(1, &vp12);

    m_efb.resolved_depth_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
    D3D::current_command_list->OMSetRenderTargets(0, nullptr, FALSE, &m_efb.resolved_depth_tex->GetDSV12());

    FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

    D3D::SetLinearCopySampler();

    // Render a quad covering the entire target, writing SV_Depth.
    const D3D12_RECT source_rect = CD3DX12_RECT(0, 0, m_target_width, m_target_height);
    D3D::DrawShadedTexQuad(
        FramebufferManager::GetEFBDepthTexture(),
        &source_rect,
        m_target_width,
        m_target_height,
        StaticShaderCache::GetDepthCopyPixelShader(true),
        StaticShaderCache::GetSimpleVertexShader(),
        StaticShaderCache::GetSimpleVertexShaderInputLayout(),
        StaticShaderCache::GetCopyGeometryShader(),
        1.0,
        0,
        DXGI_FORMAT_D32_FLOAT
    );

    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());

    // Restores proper viewport/scissor settings.
    g_renderer->RestoreAPIState();
}
Esempio n. 3
0
void XFBSource::CopyEFB(float gamma)
{
    // Copy EFB data to XFB and restore render target again
    const D3D12_VIEWPORT vp12 = { 0.f, 0.f, static_cast<float>(texWidth), static_cast<float>(texHeight), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
    D3D::current_command_list->RSSetViewports(1, &vp12);

    const D3D12_RECT rect = CD3DX12_RECT(0, 0, texWidth, texHeight);

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

    D3D::SetPointCopySampler();

    D3D::DrawShadedTexQuad(
        FramebufferManager::GetEFBColorTexture(),
        &rect,
        Renderer::GetTargetWidth(),
        Renderer::GetTargetHeight(),
        StaticShaderCache::GetColorCopyPixelShader(true),
        StaticShaderCache::GetSimpleVertexShader(),
        StaticShaderCache::GetSimpleVertexShaderInputLayout(),
        StaticShaderCache::GetCopyGeometryShader(),
        gamma,
        0,
        DXGI_FORMAT_R8G8B8A8_UNORM,
        false,
        m_tex->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());

    // Restores proper viewport/scissor settings.
    g_renderer->RestoreAPIState();
}
Esempio n. 4
0
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();
	}

	// set transformation
	if (s_efb_copy_last_cbuf_id != cbuf_id)
	{
		s_efb_copy_stream_buffer->AllocateSpaceInBuffer(28 * sizeof(float), 256);

		memcpy(s_efb_copy_stream_buffer->GetCPUAddressOfCurrentAllocation(), colmat, 28 * sizeof(float));

		s_efb_copy_last_cbuf_id = cbuf_id;
	}

	// stretch picture with increased internal resolution
	D3D::SetViewportAndScissor(0, 0, config.width, config.height);

	D3D::current_command_list->SetGraphicsRootConstantBufferView(DESCRIPTOR_TABLE_PS_CBVONE, s_efb_copy_stream_buffer->GetGPUAddressOfCurrentAllocation());
	D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PS_CBV, true);

	const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
	// EXISTINGD3D11TODO: try targetSource.asRECT();
	const D3D12_RECT sourcerect = CD3DX12_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();
}
Esempio n. 5
0
void drawClearQuad(u32 Color, float z, D3D12_BLEND_DESC *pBlendDesc, D3D12_DEPTH_STENCIL_DESC *pDepthStencilDesc, bool rtMultisampled)
{
	ClearVertex coords[4] = {
		{-1.0f,  1.0f, z, Color},
		{ 1.0f,  1.0f, z, Color},
		{-1.0f, -1.0f, z, Color},
		{ 1.0f, -1.0f, z, Color},
	};

	if (clear_quad_data.col != Color || clear_quad_data.z != z)
	{
		clearq_offset = util_vbuf_clearq->AppendData(coords, sizeof(coords), sizeof(ClearVertex));

		clear_quad_data.col = Color;
		clear_quad_data.z = z;
	}

	D3D::currentCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	D3D::commandListMgr->currentTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;

	D3D12_VERTEX_BUFFER_VIEW vbView = {
		util_vbuf_clearq->GetBuffer12()->GetGPUVirtualAddress(), // D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
		0x10000,                                                 // UINT SizeInBytes; This is the size of the entire buffer, not just the size of the vertex data for one draw call, since the offsetting is done in the draw call itself.
		sizeof(ClearVertex)                                      // UINT StrideInBytes;
	};

	D3D::currentCommandList->IASetVertexBuffers(0, 1, &vbView);
	D3D::commandListMgr->dirtyVertexBuffer = true;

	D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {
		defaultRootSignature,                             // ID3D12RootSignature *pRootSignature;
		VertexShaderCache::GetClearVertexShader12(),      // D3D12_SHADER_BYTECODE VS;
		PixelShaderCache::GetClearProgram12(),            // D3D12_SHADER_BYTECODE PS;
		{},                                               // D3D12_SHADER_BYTECODE DS;
		{},                                               // D3D12_SHADER_BYTECODE HS;
		g_ActiveConfig.iStereoMode > 0 ?
		GeometryShaderCache::GetClearGeometryShader12() :
		D3D12_SHADER_BYTECODE(),                          // D3D12_SHADER_BYTECODE GS;
		{},                                               // D3D12_STREAM_OUTPUT_DESC StreamOutput
		*pBlendDesc,                                      // D3D12_BLEND_DESC BlendState;
		UINT_MAX,                                         // UINT SampleMask;
		resetraststate12,                                 // D3D12_RASTERIZER_DESC RasterizerState
		*pDepthStencilDesc,                               // D3D12_DEPTH_STENCIL_DESC DepthStencilState
		VertexShaderCache::GetClearInputLayout12(),       // D3D12_INPUT_LAYOUT_DESC InputLayout
		D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF,        // D3D12_INDEX_BUFFER_PROPERTIES IndexBufferProperties
		D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,           // D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType
		1,                                                // UINT NumRenderTargets
		{ DXGI_FORMAT_R8G8B8A8_UNORM },                   // DXGI_FORMAT RTVFormats[8]
		DXGI_FORMAT_D24_UNORM_S8_UINT,                    // DXGI_FORMAT DSVFormat
		{ 1 /* UINT Count */, 0 /* UINT Quality */ }      // DXGI_SAMPLE_DESC SampleDesc
	};

	if (rtMultisampled)
	{
		psoDesc.SampleDesc.Count = g_ActiveConfig.iMultisamples;
	}

	ID3D12PipelineState *pPso = nullptr;
	CheckHR(DX12::gx_state_cache.GetPipelineStateObjectFromCache(&psoDesc, &pPso));

	D3D::currentCommandList->SetPipelineState(pPso);
	D3D::commandListMgr->dirtyPso = true;

	// In D3D11, the 'resetraststate' has ScissorEnable disabled. In D3D12, scissor testing is always enabled.
	// Thus, set the scissor rect to the max texture size, then reset it to the current scissor rect to avoid
	// dirtying state.

	// 2 ^ D3D12_MAX_TEXTURE_DIMENSION_2_TO_EXP = 131072	
	D3D::currentCommandList->RSSetScissorRects(1, &CD3DX12_RECT(0, 0, 131072, 131072));

	D3D::currentCommandList->DrawInstanced(4, 1, clearq_offset, 0);

	g_renderer->SetScissorRect(((Renderer*)g_renderer)->GetScissorRect());
}
Esempio n. 6
0
void drawShadedTexQuad(D3DTexture2D* texture,
	const D3D11_RECT* rSource,
	int SourceWidth,
	int SourceHeight,
	D3D12_SHADER_BYTECODE PShader12,
	D3D12_SHADER_BYTECODE VShader12,
	D3D12_INPUT_LAYOUT_DESC layout12,
	D3D12_SHADER_BYTECODE GShader12,
	float Gamma,
	u32 slice,
	DXGI_FORMAT rtFormat,
	bool inheritSRVbinding,
	bool rtMultisampled
	)
{
	float sw = 1.0f / (float)SourceWidth;
	float sh = 1.0f / (float)SourceHeight;
	float u1 = ((float)rSource->left) * sw;
	float u2 = ((float)rSource->right) * sw;
	float v1 = ((float)rSource->top) * sh;
	float v2 = ((float)rSource->bottom) * sh;
	float S = (float)slice;
	float G = 1.0f / Gamma;

	STQVertex coords[4] = {
		{ -1.0f, 1.0f, 0.0f, u1, v1, S, G },
		{ 1.0f, 1.0f, 0.0f, u2, v1, S, G },
		{ -1.0f, -1.0f, 0.0f, u1, v2, S, G },
		{ 1.0f, -1.0f, 0.0f, u2, v2, S, G },
	};

	// only upload the data to VRAM if it changed
	if (tex_quad_data.u1 != u1 || tex_quad_data.v1 != v1 ||
		tex_quad_data.u2 != u2 || tex_quad_data.v2 != v2 ||
		tex_quad_data.S != S || tex_quad_data.G != G)
	{
		stq_offset = util_vbuf_stq->AppendData(coords, sizeof(coords), sizeof(STQVertex));

		tex_quad_data.u1 = u1;
		tex_quad_data.v1 = v1;
		tex_quad_data.u2 = u2;
		tex_quad_data.v2 = v2;
		tex_quad_data.S = S;
		tex_quad_data.G = G;
	}

	UINT stride = sizeof(STQVertex);
	UINT offset = 0;

	D3D::currentCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	D3D::commandListMgr->currentTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;

	D3D12_VERTEX_BUFFER_VIEW vbView = {
		util_vbuf_stq->GetBuffer12()->GetGPUVirtualAddress(), // D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
		0x10000,                                              // UINT SizeInBytes; This is the size of the entire buffer, not just the size of the vertex data for one draw call, since the offsetting is done in the draw call itself.
		stride                                                // UINT StrideInBytes;
	};

	D3D::currentCommandList->IASetVertexBuffers(0, 1, &vbView);
	D3D::commandListMgr->dirtyVertexBuffer = true;

	if (!inheritSRVbinding)
	{
		texture->TransitionToResourceState(D3D::currentCommandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
		D3D::currentCommandList->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, texture->GetSRV12gpu());
	}

	D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {
		defaultRootSignature,                             // ID3D12RootSignature *pRootSignature;
		VShader12,                                        // D3D12_SHADER_BYTECODE VS;
		PShader12,                                        // D3D12_SHADER_BYTECODE PS;
		{},                                               // D3D12_SHADER_BYTECODE DS;
		{},                                               // D3D12_SHADER_BYTECODE HS;
		GShader12,                                        // D3D12_SHADER_BYTECODE GS;
		{},                                               // D3D12_STREAM_OUTPUT_DESC StreamOutput
		resetblendstate12,                                // D3D12_BLEND_DESC BlendState;
		UINT_MAX,                                         // UINT SampleMask;
		resetraststate12,                                 // D3D12_RASTERIZER_DESC RasterizerState
		resetdepthstate12,                                // D3D12_DEPTH_STENCIL_DESC DepthStencilState
		layout12,                                         // D3D12_INPUT_LAYOUT_DESC InputLayout
		D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF,        // D3D12_INDEX_BUFFER_PROPERTIES IndexBufferProperties
		D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,           // D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType
		1,                                                // UINT NumRenderTargets
		{ rtFormat },                                     // DXGI_FORMAT RTVFormats[8]
		DXGI_FORMAT_D24_UNORM_S8_UINT,                    // DXGI_FORMAT DSVFormat
		{ 1 /* UINT Count */, 0 /* UINT Quality */ }      // DXGI_SAMPLE_DESC SampleDesc
	};

	if (rtMultisampled)
	{
		psoDesc.SampleDesc.Count = g_ActiveConfig.iMultisamples;
	}

	ID3D12PipelineState *pPso = nullptr;
	CheckHR(DX12::gx_state_cache.GetPipelineStateObjectFromCache(&psoDesc, &pPso));
	
	D3D::currentCommandList->SetPipelineState(pPso);
	D3D::commandListMgr->dirtyPso = true;

	// In D3D11, the 'resetraststate' has ScissorEnable disabled. In D3D12, scissor testing is always enabled.
	// Thus, set the scissor rect to the max texture size, then reset it to the current scissor rect to avoid
	// dirtying state.

	// 2 ^ D3D12_MAX_TEXTURE_DIMENSION_2_TO_EXP = 131072
	D3D::currentCommandList->RSSetScissorRects(1, &CD3DX12_RECT(0, 0, 131072, 131072));

	D3D::currentCommandList->DrawInstanced(4, 1, stq_offset, 0);

	g_renderer->SetScissorRect(((Renderer*)g_renderer)->GetScissorRect());
}