[D3D12] Banjo-Kazooie/Tooie top tile clear fix (rendering still broken in Tooie)
This commit is contained in:
parent
91ef453534
commit
e819a41300
|
@ -59,6 +59,21 @@ ID3D12GraphicsCommandList1* D3D12CommandProcessor::GetCurrentCommandList1()
|
||||||
return command_lists_[current_queue_frame_]->GetCommandList1();
|
return command_lists_[current_queue_frame_]->GetCommandList1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t D3D12CommandProcessor::GetCurrentColorMask(
|
||||||
|
const D3D12Shader* pixel_shader) const {
|
||||||
|
if (pixel_shader == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto& regs = *register_file_;
|
||||||
|
uint32_t color_mask = regs[XE_GPU_REG_RB_COLOR_MASK].u32 & 0xFFFF;
|
||||||
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
|
if (!pixel_shader->writes_color_target(i)) {
|
||||||
|
color_mask &= ~(0xF << (i * 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color_mask;
|
||||||
|
}
|
||||||
|
|
||||||
void D3D12CommandProcessor::PushTransitionBarrier(
|
void D3D12CommandProcessor::PushTransitionBarrier(
|
||||||
ID3D12Resource* resource, D3D12_RESOURCE_STATES old_state,
|
ID3D12Resource* resource, D3D12_RESOURCE_STATES old_state,
|
||||||
D3D12_RESOURCE_STATES new_state, UINT subresource) {
|
D3D12_RESOURCE_STATES new_state, UINT subresource) {
|
||||||
|
@ -848,12 +863,6 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
// Doesn't actually draw.
|
// Doesn't actually draw.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
uint32_t color_mask = enable_mode == xenos::ModeControl::kColorDepth ?
|
|
||||||
regs[XE_GPU_REG_RB_COLOR_MASK].u32 & 0xFFFF : 0;
|
|
||||||
if (!color_mask && !(regs[XE_GPU_REG_RB_DEPTHCONTROL].u32 & (0x1 | 0x4))) {
|
|
||||||
// Not writing to color, depth or doing stencil test, so doesn't draw.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((regs[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32 & 0x3) == 0x3 &&
|
if ((regs[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32 & 0x3) == 0x3 &&
|
||||||
primitive_type != PrimitiveType::kPointList &&
|
primitive_type != PrimitiveType::kPointList &&
|
||||||
primitive_type != PrimitiveType::kRectangleList) {
|
primitive_type != PrimitiveType::kRectangleList) {
|
||||||
|
@ -901,11 +910,17 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t color_mask = GetCurrentColorMask(pixel_shader);
|
||||||
|
if (!color_mask && !(regs[XE_GPU_REG_RB_DEPTHCONTROL].u32 & (0x1 | 0x4))) {
|
||||||
|
// Not writing to color, depth or doing stencil test, so doesn't draw.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool new_frame = BeginFrame();
|
bool new_frame = BeginFrame();
|
||||||
auto command_list = GetCurrentCommandList();
|
auto command_list = GetCurrentCommandList();
|
||||||
|
|
||||||
// Set up the render targets - this may bind pipelines.
|
// Set up the render targets - this may bind pipelines.
|
||||||
if (!render_target_cache_->UpdateRenderTargets()) {
|
if (!render_target_cache_->UpdateRenderTargets(pixel_shader)) {
|
||||||
// Doesn't actually draw.
|
// Doesn't actually draw.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,16 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
ID3D12GraphicsCommandList* GetCurrentCommandList() const;
|
ID3D12GraphicsCommandList* GetCurrentCommandList() const;
|
||||||
ID3D12GraphicsCommandList1* GetCurrentCommandList1() const;
|
ID3D12GraphicsCommandList1* GetCurrentCommandList1() const;
|
||||||
|
|
||||||
|
// Gets the current color write mask, taking the pixel shader's write mask
|
||||||
|
// into account. If a shader doesn't write to a render target, it shouldn't be
|
||||||
|
// written to and it shouldn't be even bound - otherwise, in Halo 3, one
|
||||||
|
// render target is being destroyed by a shader not writing anything, and in
|
||||||
|
// Banjo-Tooie, the result of clearing the top tile is being ignored because
|
||||||
|
// there are 4 render targets bound with the same EDRAM base (clearly not
|
||||||
|
// correct usage), but the shader only clears 1, and then EDRAM buffer stores
|
||||||
|
// conflict with each other.
|
||||||
|
uint32_t GetCurrentColorMask(const D3D12Shader* pixel_shader) const;
|
||||||
|
|
||||||
void PushTransitionBarrier(
|
void PushTransitionBarrier(
|
||||||
ID3D12Resource* resource, D3D12_RESOURCE_STATES old_state,
|
ID3D12Resource* resource, D3D12_RESOURCE_STATES old_state,
|
||||||
D3D12_RESOURCE_STATES new_state,
|
D3D12_RESOURCE_STATES new_state,
|
||||||
|
|
|
@ -335,20 +335,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateBlendStateAndRenderTargets(
|
||||||
dirty |= regs.render_targets[i].format != render_targets[i].format;
|
dirty |= regs.render_targets[i].format != render_targets[i].format;
|
||||||
regs.render_targets[i].format = render_targets[i].format;
|
regs.render_targets[i].format = render_targets[i].format;
|
||||||
}
|
}
|
||||||
uint32_t color_mask;
|
uint32_t color_mask = command_processor_->GetCurrentColorMask(pixel_shader);
|
||||||
if (pixel_shader != nullptr) {
|
|
||||||
color_mask = register_file_->values[XE_GPU_REG_RB_COLOR_MASK].u32 & 0xFFFF;
|
|
||||||
for (uint32_t i = 0; i < 4; ++i) {
|
|
||||||
// If the pixel shader doesn't write to a render target, writing to it is
|
|
||||||
// disabled in the blend state. Otherwise, in Halo 3, one important render
|
|
||||||
// target is destroyed by a shader not writing to one of the outputs.
|
|
||||||
if (!pixel_shader->writes_color_target(i)) {
|
|
||||||
color_mask &= ~(0xF << (i * 4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
color_mask = 0;
|
|
||||||
}
|
|
||||||
dirty |= regs.color_mask != color_mask;
|
dirty |= regs.color_mask != color_mask;
|
||||||
regs.color_mask = color_mask;
|
regs.color_mask = color_mask;
|
||||||
bool blend_enable =
|
bool blend_enable =
|
||||||
|
|
|
@ -323,7 +323,7 @@ void RenderTargetCache::BeginFrame() {
|
||||||
// stable D24F==D32F comparison.
|
// stable D24F==D32F comparison.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderTargetCache::UpdateRenderTargets() {
|
bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
|
||||||
// There are two kinds of render target binding updates in this implementation
|
// There are two kinds of render target binding updates in this implementation
|
||||||
// in case something has been changed - full and partial.
|
// in case something has been changed - full and partial.
|
||||||
//
|
//
|
||||||
|
@ -416,16 +416,12 @@ bool RenderTargetCache::UpdateRenderTargets() {
|
||||||
uint32_t edram_bases[5];
|
uint32_t edram_bases[5];
|
||||||
uint32_t formats[5];
|
uint32_t formats[5];
|
||||||
bool formats_are_64bpp[5];
|
bool formats_are_64bpp[5];
|
||||||
uint32_t rb_color_mask = regs[XE_GPU_REG_RB_COLOR_MASK].u32;
|
uint32_t color_mask = command_processor_->GetCurrentColorMask(pixel_shader);
|
||||||
if (xenos::ModeControl(regs[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7) !=
|
|
||||||
xenos::ModeControl::kColorDepth) {
|
|
||||||
rb_color_mask = 0;
|
|
||||||
}
|
|
||||||
uint32_t rb_color_info[4] = {
|
uint32_t rb_color_info[4] = {
|
||||||
regs[XE_GPU_REG_RB_COLOR_INFO].u32, regs[XE_GPU_REG_RB_COLOR1_INFO].u32,
|
regs[XE_GPU_REG_RB_COLOR_INFO].u32, regs[XE_GPU_REG_RB_COLOR1_INFO].u32,
|
||||||
regs[XE_GPU_REG_RB_COLOR2_INFO].u32, regs[XE_GPU_REG_RB_COLOR3_INFO].u32};
|
regs[XE_GPU_REG_RB_COLOR2_INFO].u32, regs[XE_GPU_REG_RB_COLOR3_INFO].u32};
|
||||||
for (uint32_t i = 0; i < 4; ++i) {
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
enabled[i] = (rb_color_mask & (0xF << (i * 4))) != 0;
|
enabled[i] = (color_mask & (0xF << (i * 4))) != 0;
|
||||||
edram_bases[i] = std::min(rb_color_info[i] & 0xFFF, 2048u);
|
edram_bases[i] = std::min(rb_color_info[i] & 0xFFF, 2048u);
|
||||||
formats[i] = (rb_color_info[i] >> 16) & 0xF;
|
formats[i] = (rb_color_info[i] >> 16) & 0xF;
|
||||||
formats_are_64bpp[i] =
|
formats_are_64bpp[i] =
|
||||||
|
@ -2027,7 +2023,13 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
|
||||||
if (current_bindings_[a].edram_base < current_bindings_[b].edram_base) {
|
if (current_bindings_[a].edram_base < current_bindings_[b].edram_base) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return a < b;
|
// If EDRAM bases are the same (not really a valid usage, but happens in
|
||||||
|
// Banjo-Tooie - in case color writing was enabled for invalid render
|
||||||
|
// targets in some draw call), treat the render targets with the lowest
|
||||||
|
// index as more important (it's the primary one after all, while the
|
||||||
|
// rest are additional). Also treat the depth buffer as highest-priority
|
||||||
|
// (in the comparison, treat depth as 0 and color as 1-4).
|
||||||
|
return ((a + 1) % 5) > ((b + 1) % 5);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate the dispatch width.
|
// Calculate the dispatch width.
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "xenia/gpu/d3d12/d3d12_shader.h"
|
||||||
#include "xenia/gpu/d3d12/shared_memory.h"
|
#include "xenia/gpu/d3d12/shared_memory.h"
|
||||||
#include "xenia/gpu/d3d12/texture_cache.h"
|
#include "xenia/gpu/d3d12/texture_cache.h"
|
||||||
#include "xenia/gpu/register_file.h"
|
#include "xenia/gpu/register_file.h"
|
||||||
|
@ -209,7 +210,7 @@ class RenderTargetCache {
|
||||||
|
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
// Called in the beginning of a draw call - may bind pipelines.
|
// Called in the beginning of a draw call - may bind pipelines.
|
||||||
bool UpdateRenderTargets();
|
bool UpdateRenderTargets(const D3D12Shader* pixel_shader);
|
||||||
// Returns the host-to-guest mappings and host formats of currently bound
|
// Returns the host-to-guest mappings and host formats of currently bound
|
||||||
// render targets for pipeline creation and remapping in shaders. They are
|
// render targets for pipeline creation and remapping in shaders. They are
|
||||||
// consecutive, and format DXGI_FORMAT_UNKNOWN terminates the list. Depth
|
// consecutive, and format DXGI_FORMAT_UNKNOWN terminates the list. Depth
|
||||||
|
|
Loading…
Reference in New Issue