D3D12: Add helper method for setting both viewport and scissor rect

Simplfies making changes, as well as keeping the two in sync.
This commit is contained in:
Stenzek 2016-02-23 22:18:41 +10:00
parent 13e143de38
commit c4d79d6db3
6 changed files with 49 additions and 129 deletions

View file

@ -72,7 +72,7 @@ public:
// returns vertex offset to the new data
size_t AppendData(const void* data, size_t size, size_t vertex_size)
{
m_stream_buffer->AllocateSpaceInBuffer(size, vertex_size);
m_stream_buffer->AllocateSpaceInBuffer(size, vertex_size, false);
memcpy(static_cast<u8*>(m_stream_buffer->GetCPUAddressOfCurrentAllocation()), data, size);
@ -81,7 +81,7 @@ public:
size_t BeginAppendData(void** write_ptr, size_t size, size_t vertex_size)
{
m_stream_buffer->AllocateSpaceInBuffer(size, vertex_size);
m_stream_buffer->AllocateSpaceInBuffer(size, vertex_size, false);
*write_ptr = m_stream_buffer->GetCPUAddressOfCurrentAllocation();
@ -422,7 +422,7 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, m_texture12_gpu);
// upper bound is nchars * 6, assuming no spaces
m_vertex_buffer->AllocateSpaceInBuffer(static_cast<u32>(text.length()) * 6 * sizeof(FONT2DVERTEX), sizeof(FONT2DVERTEX));
m_vertex_buffer->AllocateSpaceInBuffer(static_cast<u32>(text.length()) * 6 * sizeof(FONT2DVERTEX), sizeof(FONT2DVERTEX), false);
FONT2DVERTEX* vertices12 = reinterpret_cast<FONT2DVERTEX*>(m_vertex_buffer->GetCPUAddressOfCurrentAllocation());
int num_triangles = 0;
@ -588,6 +588,28 @@ void SetLinearCopySampler()
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_SAMPLERS, true);
}
void SetViewportAndScissor(u32 top_left_x, u32 top_left_y, u32 width, u32 height, float min_depth, float max_depth)
{
D3D12_VIEWPORT viewport = {
static_cast<float>(top_left_x),
static_cast<float>(top_left_y),
static_cast<float>(width),
static_cast<float>(height),
min_depth,
max_depth
};
D3D12_RECT scissor = {
static_cast<LONG>(top_left_x),
static_cast<LONG>(top_left_y),
static_cast<LONG>(top_left_x + width),
static_cast<LONG>(top_left_y + height)
};
D3D::current_command_list->RSSetViewports(1, &viewport);
D3D::current_command_list->RSSetScissorRects(1, &scissor);
};
void DrawShadedTexQuad(D3DTexture2D* texture,
const D3D12_RECT* rSource,
int source_width,
@ -684,13 +706,6 @@ void DrawShadedTexQuad(D3DTexture2D* texture,
D3D::current_command_list->SetPipelineState(pso);
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, 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::current_command_list->RSSetScissorRects(1, &CD3DX12_RECT(0, 0, 131072, 131072));
D3D::current_command_list->DrawInstanced(4, 1, static_cast<UINT>(stq_offset), 0);
g_renderer->RestoreAPIState();
@ -840,13 +855,6 @@ void DrawClearQuad(u32 Color, float z, D3D12_BLEND_DESC* blend_desc, D3D12_DEPTH
D3D::current_command_list->SetPipelineState(pso);
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, 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::current_command_list->RSSetScissorRects(1, &CD3DX12_RECT(0, 0, 131072, 131072));
D3D::current_command_list->DrawInstanced(4, 1, static_cast<UINT>(clearq_offset), 0);
g_renderer->RestoreAPIState();
@ -865,7 +873,6 @@ void DrawEFBPokeQuads(EFBAccessType type,
size_t num_points,
D3D12_BLEND_DESC* blend_desc,
D3D12_DEPTH_STENCIL_DESC* depth_stencil_desc,
D3D12_VIEWPORT* viewport,
D3D12_CPU_DESCRIPTOR_HANDLE* render_target,
D3D12_CPU_DESCRIPTOR_HANDLE* depth_buffer,
bool rt_multisampled
@ -925,7 +932,6 @@ void DrawEFBPokeQuads(EFBAccessType type,
// Corresponding dirty flags set outside loop.
D3D::current_command_list->OMSetRenderTargets(1, render_target, FALSE, depth_buffer);
D3D::current_command_list->RSSetViewports(1, viewport);
D3D::current_command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D12_VERTEX_BUFFER_VIEW vb_view = {

View file

@ -74,6 +74,8 @@ void ShutdownUtils();
void SetPointCopySampler();
void SetLinearCopySampler();
void SetViewportAndScissor(u32 top_left_x, u32 top_left_y, u32 width, u32 height, float min_depth = D3D12_MIN_DEPTH, float max_depth = D3D12_MAX_DEPTH);
void DrawShadedTexQuad(D3DTexture2D* texture,
const D3D12_RECT* source,
int source_width,
@ -97,7 +99,6 @@ void DrawEFBPokeQuads(EFBAccessType type,
size_t num_points,
D3D12_BLEND_DESC* blend_desc,
D3D12_DEPTH_STENCIL_DESC* depth_stencil_desc,
D3D12_VIEWPORT* viewport,
D3D12_CPU_DESCRIPTOR_HANDLE* render_target,
D3D12_CPU_DESCRIPTOR_HANDLE* depth_buffer,
bool rt_multisampled);

View file

@ -173,9 +173,7 @@ 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);
D3D::SetViewportAndScissor(0, 0, m_target_width, m_target_height);
m_efb.resolved_depth_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D::current_command_list->OMSetRenderTargets(0, nullptr, FALSE, &m_efb.resolved_depth_tex->GetDSV12());
@ -292,10 +290,9 @@ void FramebufferManager::MapEFBColorAccessCopy()
// for non-1xIR or multisampled cases, we need to copy to an intermediate texture first
m_efb.color_access_resize_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12_VIEWPORT vp12 = { 0, 0, EFB_WIDTH, EFB_HEIGHT, D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &vp12);
D3D::current_command_list->OMSetRenderTargets(1, &m_efb.color_access_resize_tex->GetRTV12(), FALSE, nullptr);
D3D::SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
D3D::SetPointCopySampler();
D3D::current_command_list->OMSetRenderTargets(1, &m_efb.color_access_resize_tex->GetRTV12(), FALSE, nullptr);
CD3DX12_RECT src_rect(0, 0, m_target_width, m_target_height);
D3D::DrawShadedTexQuad(m_efb.color_tex, &src_rect, m_target_width, m_target_height,
@ -345,10 +342,9 @@ void FramebufferManager::MapEFBDepthAccessCopy()
// for non-1xIR or multisampled cases, we need to copy to an intermediate texture first
m_efb.depth_access_resize_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12_VIEWPORT vp12 = { 0, 0, EFB_WIDTH, EFB_HEIGHT, D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &vp12);
D3D::current_command_list->OMSetRenderTargets(1, &m_efb.depth_access_resize_tex->GetRTV12(), FALSE, nullptr);
D3D::SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
D3D::SetPointCopySampler();
D3D::current_command_list->OMSetRenderTargets(1, &m_efb.color_access_resize_tex->GetRTV12(), FALSE, nullptr);
CD3DX12_RECT src_rect(0, 0, m_target_width, m_target_height);
D3D::DrawShadedTexQuad(m_efb.depth_tex, &src_rect, m_target_width, m_target_height,
@ -425,8 +421,7 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
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);
D3D::SetViewportAndScissor(0, 0, texWidth, texHeight);
const D3D12_RECT rect = CD3DX12_RECT(0, 0, texWidth, texHeight);

View file

@ -152,8 +152,7 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
const u32 words_per_row = bytes_per_row / sizeof(u32);
D3D12_VIEWPORT vp = { 0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &vp);
D3D::SetViewportAndScissor(0, 0, words_per_row, num_blocks_y);
constexpr EFBRectangle full_src_rect(0, 0, EFB_WIDTH, EFB_HEIGHT);

View file

@ -428,7 +428,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points)
{
D3D12_VIEWPORT vp = { 0.0f, 0.0f, static_cast<float>(GetTargetWidth()), static_cast<float>(GetTargetHeight()), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::SetViewportAndScissor(0, 0, GetTargetWidth(), GetTargetHeight());
if (type == POKE_COLOR)
{
@ -439,7 +439,6 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
num_points,
&g_reset_blend_desc,
&g_reset_depth_desc,
&vp,
&FramebufferManager::GetEFBColorTexture()->GetRTV12(),
nullptr,
FramebufferManager::GetEFBColorTexture()->GetMultisampled()
@ -453,7 +452,6 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
num_points,
&s_clear_blend_descs[CLEAR_BLEND_DESC_ALL_CHANNELS_DISABLED],
&s_clear_depth_descs[CLEAR_DEPTH_DESC_DEPTH_ENABLED_WRITES_ENABLED],
&vp,
&FramebufferManager::GetEFBColorTexture()->GetRTV12(),
&FramebufferManager::GetEFBDepthTexture()->GetDSV12(),
FramebufferManager::GetEFBColorTexture()->GetMultisampled()
@ -533,19 +531,9 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
// Update the view port for clearing the picture
TargetRectangle target_rc = Renderer::ConvertEFBRectangle(rc);
D3D12_VIEWPORT vp = {
static_cast<float>(target_rc.left),
static_cast<float>(target_rc.top),
static_cast<float>(target_rc.GetWidth()),
static_cast<float>(target_rc.GetHeight()),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
D3D::current_command_list->RSSetViewports(1, &vp);
// Color is passed in bgra mode so we need to convert it to rgba
u32 rgba_color = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000);
D3D::SetViewportAndScissor(target_rc.left, target_rc.top, target_rc.GetWidth(), target_rc.GetHeight());
D3D::DrawClearQuad(rgba_color, 1.0f - (z & 0xFFFFFF) / 16777216.0f, blend_desc, depth_stencil_desc, FramebufferManager::GetEFBColorTexture()->GetMultisampled());
// Restores proper viewport/scissor settings.
@ -575,16 +563,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
return;
}
D3D12_VIEWPORT vp = {
0.f,
0.f,
static_cast<float>(g_renderer->GetTargetWidth()),
static_cast<float>(g_renderer->GetTargetHeight()),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
D3D::current_command_list->RSSetViewports(1, &vp);
D3D::SetViewportAndScissor(0, 0, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight());
FramebufferManager::GetEFBColorTempTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV12(), FALSE, nullptr);
@ -765,27 +744,13 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
float clear_color[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::current_command_list->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV12(), clear_color, 0, nullptr);
// D3D12: Because scissor-testing is always enabled, change scissor rect to backbuffer in case EFB is smaller
// than swap chain back buffer.
D3D12_RECT back_buffer_rect = { 0L, 0L, GetBackbufferWidth(), GetBackbufferHeight() };
D3D::current_command_list->RSSetScissorRects(1, &back_buffer_rect);
// activate linear filtering for the buffer copies
D3D::SetLinearCopySampler();
if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)
{
// EXISTINGD3D11TODO: Television should be used to render Virtual XFB mode as well.
D3D12_VIEWPORT vp12 = {
static_cast<float>(target_rc.left),
static_cast<float>(target_rc.top),
static_cast<float>(target_rc.GetWidth()),
static_cast<float>(target_rc.GetHeight()),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
D3D::current_command_list->RSSetViewports(1, &vp12);
D3D::SetViewportAndScissor(target_rc.left, target_rc.top, target_rc.GetWidth(), target_rc.GetHeight());
s_television.Submit(xfb_addr, fb_stride, fb_width, fb_height);
s_television.Render();
@ -933,16 +898,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
}
// Reset viewport for drawing text
D3D12_VIEWPORT vp = {
0.0f,
0.0f,
static_cast<float>(GetBackbufferWidth()),
static_cast<float>(GetBackbufferHeight()),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
D3D::current_command_list->RSSetViewports(1, &vp);
D3D::SetViewportAndScissor(0, 0, GetBackbufferWidth(), GetBackbufferHeight());
Renderer::DrawDebugText();
@ -1368,30 +1324,12 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D
TargetRectangle left_rc, right_rc;
ConvertStereoRectangle(dst, left_rc, right_rc);
D3D12_VIEWPORT left_vp = {
static_cast<float>(left_rc.left),
static_cast<float>(left_rc.top),
static_cast<float>(left_rc.GetWidth()),
static_cast<float>(left_rc.GetHeight()),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
D3D12_VIEWPORT right_vp = {
static_cast<float>(right_rc.left),
static_cast<float>(right_rc.top),
static_cast<float>(right_rc.GetWidth()),
static_cast<float>(right_rc.GetHeight()),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
// Swap chain backbuffer is never multisampled..
D3D::current_command_list->RSSetViewports(1, &left_vp);
D3D::SetViewportAndScissor(left_rc.left, left_rc.top, left_rc.GetWidth(), left_rc.GetHeight());
D3D::DrawShadedTexQuad(src_texture, src.AsRECT(), src_width, src_height, StaticShaderCache::GetColorCopyPixelShader(false), StaticShaderCache::GetSimpleVertexShader(), StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), gamma, 0, DXGI_FORMAT_R8G8B8A8_UNORM, false, false);
D3D::current_command_list->RSSetViewports(1, &right_vp);
D3D::SetViewportAndScissor(right_rc.left, right_rc.top, right_rc.GetWidth(), right_rc.GetHeight());
D3D::DrawShadedTexQuad(src_texture, src.AsRECT(), src_width, src_height, StaticShaderCache::GetColorCopyPixelShader(false), StaticShaderCache::GetSimpleVertexShader(), StaticShaderCache::GetSimpleVertexShaderInputLayout(), D3D12_SHADER_BYTECODE(), gamma, 1, DXGI_FORMAT_R8G8B8A8_UNORM, false, false);
}
else if (g_ActiveConfig.iStereoMode == STEREO_3DVISION)
@ -1433,8 +1371,7 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D
}
else
{
D3D12_VIEWPORT vp = { static_cast<float>(dst.left), static_cast<float>(dst.top), static_cast<float>(dst.GetWidth()), static_cast<float>(dst.GetHeight()), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &vp);
D3D::SetViewportAndScissor(dst.left, dst.top, dst.GetWidth(), dst.GetHeight());
D3D::DrawShadedTexQuad(
src_texture,

View file

@ -164,15 +164,7 @@ void TextureCache::TCacheEntry::CopyRectangleFromTexture(
return;
}
const D3D12_VIEWPORT vp = {
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, &vp);
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);
@ -289,18 +281,6 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
FramebufferManager::GetResolvedEFBColorTexture();
}
// stretch picture with increased internal resolution
const D3D12_VIEWPORT vp = {
0.f,
0.f,
static_cast<float>(config.width),
static_cast<float>(config.height),
D3D12_MIN_DEPTH,
D3D12_MAX_DEPTH
};
D3D::current_command_list->RSSetViewports(1, &vp);
// set transformation
if (cbuf_id != old_cbuf_id)
{
@ -311,6 +291,9 @@ void TextureCache::TCacheEntry::FromRenderTarget(u8* dst, PEControl::PixelFormat
old_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);
@ -441,14 +424,13 @@ void main(
void TextureCache::ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette, TlutFormat format)
{
// stretch picture with increased internal resolution
const D3D12_VIEWPORT vp = { 0.f, 0.f, static_cast<float>(unconverted->config.width), static_cast<float>(unconverted->config.height), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &vp);
const unsigned int palette_buffer_allocation_size = 512;
m_palette_stream_buffer->AllocateSpaceInBuffer(palette_buffer_allocation_size, 256);
memcpy(m_palette_stream_buffer->GetCPUAddressOfCurrentAllocation(), palette, palette_buffer_allocation_size);
// stretch picture with increased internal resolution
D3D::SetViewportAndScissor(0, 0, unconverted->config.width, unconverted->config.height);
// D3D12: Because the second SRV slot is occupied by this buffer, and an arbitrary texture occupies the first SRV slot,
// we need to allocate temporary space out of our descriptor heap, place the palette SRV in the second slot, then copy the
// existing texture's descriptor into the first slot.