[D3D12] Fix state of textures bound to both VS and PS

This commit is contained in:
Triang3l 2020-05-16 19:33:22 +03:00
parent fdd97fc831
commit 8341a48210
3 changed files with 32 additions and 30 deletions

View File

@ -1409,8 +1409,8 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
// Update the textures - this may bind pipelines. // Update the textures - this may bind pipelines.
texture_cache_->RequestTextures( texture_cache_->RequestTextures(
vertex_shader->GetUsedTextureMask(), vertex_shader->GetUsedTextureMask() |
pixel_shader != nullptr ? pixel_shader->GetUsedTextureMask() : 0); (pixel_shader != nullptr ? pixel_shader->GetUsedTextureMask() : 0));
// Check if early depth/stencil can be enabled. // Check if early depth/stencil can be enabled.
bool early_z; bool early_z;

View File

@ -1250,8 +1250,7 @@ void TextureCache::EndFrame() {
} }
} }
void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask, void TextureCache::RequestTextures(uint32_t used_texture_mask) {
uint32_t used_pixel_texture_mask) {
auto& regs = *register_file_; auto& regs = *register_file_;
#if FINE_GRAINED_DRAW_SCOPES #if FINE_GRAINED_DRAW_SCOPES
@ -1268,12 +1267,11 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
} }
// Update the texture keys and the textures. // Update the texture keys and the textures.
uint32_t used_texture_mask = uint32_t textures_remaining = used_texture_mask;
used_vertex_texture_mask | used_pixel_texture_mask;
uint32_t index = 0; uint32_t index = 0;
while (xe::bit_scan_forward(used_texture_mask, &index)) { while (xe::bit_scan_forward(textures_remaining, &index)) {
uint32_t index_bit = 1u << index; uint32_t index_bit = uint32_t(1) << index;
used_texture_mask &= ~index_bit; textures_remaining &= ~index_bit;
if (texture_keys_in_sync_ & index_bit) { if (texture_keys_in_sync_ & index_bit) {
continue; continue;
} }
@ -1337,34 +1335,35 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
} }
} }
// Transition the textures to the needed usage. // Transition the textures to the needed usage - always in
used_texture_mask = used_vertex_texture_mask | used_pixel_texture_mask; // NON_PIXEL_SHADER_RESOURCE | PIXEL_SHADER_RESOURCE states because barriers
while (xe::bit_scan_forward(used_texture_mask, &index)) { // between read-only stages, if needed, are discouraged (also if these were
uint32_t index_bit = 1u << index; // tracked separately, checks would be needed to make sure, if the same
used_texture_mask &= ~index_bit; // texture is bound through different fetch constants to both VS and PS, it
// would be in both states).
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATES(0); textures_remaining = used_texture_mask;
if (used_vertex_texture_mask & index_bit) { while (xe::bit_scan_forward(textures_remaining, &index)) {
state |= D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; textures_remaining &= ~(uint32_t(1) << index);
}
if (used_pixel_texture_mask & index_bit) {
state |= D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
}
TextureBinding& binding = texture_bindings_[index]; TextureBinding& binding = texture_bindings_[index];
if (binding.texture != nullptr) { if (binding.texture != nullptr) {
// Will be referenced by the command list, so mark as used. // Will be referenced by the command list, so mark as used.
MarkTextureUsed(binding.texture); MarkTextureUsed(binding.texture);
command_processor_->PushTransitionBarrier(binding.texture->resource, command_processor_->PushTransitionBarrier(
binding.texture->state, state); binding.texture->resource, binding.texture->state,
binding.texture->state = state; D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
binding.texture->state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
} }
if (binding.texture_signed != nullptr) { if (binding.texture_signed != nullptr) {
MarkTextureUsed(binding.texture_signed); MarkTextureUsed(binding.texture_signed);
command_processor_->PushTransitionBarrier( command_processor_->PushTransitionBarrier(
binding.texture_signed->resource, binding.texture_signed->state, binding.texture_signed->resource, binding.texture_signed->state,
state); D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
binding.texture_signed->state = state; D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
binding.texture_signed->state =
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
} }
} }
} }
@ -2028,6 +2027,9 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
return false; return false;
} }
MarkTextureUsed(texture); MarkTextureUsed(texture);
// The swap texture is likely to be used only for the presentation pixel
// shader, and not during emulation, where it'd be NON_PIXEL_SHADER_RESOURCE |
// PIXEL_SHADER_RESOURCE.
command_processor_->PushTransitionBarrier( command_processor_->PushTransitionBarrier(
texture->resource, texture->state, texture->resource, texture->state,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

View File

@ -109,8 +109,7 @@ class TextureCache {
// shaders and puts them in the SRV state. This may bind compute pipelines // shaders and puts them in the SRV state. This may bind compute pipelines
// (notifying the command processor about that), so this must be called before // (notifying the command processor about that), so this must be called before
// binding the actual drawing pipeline. // binding the actual drawing pipeline.
void RequestTextures(uint32_t used_vertex_texture_mask, void RequestTextures(uint32_t used_texture_mask);
uint32_t used_pixel_texture_mask);
// Returns the hash of the current bindings (must be called after // Returns the hash of the current bindings (must be called after
// RequestTextures) for the provided SRV descriptor layout. // RequestTextures) for the provided SRV descriptor layout.
@ -160,6 +159,7 @@ class TextureCache {
uint32_t first_unscaled_4kb_page, uint32_t first_unscaled_4kb_page,
uint32_t unscaled_4kb_page_count); uint32_t unscaled_4kb_page_count);
// Returns a descriptor of the front buffer in PIXEL_SHADER_RESOURCE state.
bool RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle, bool RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
TextureFormat& format_out); TextureFormat& format_out);