Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental

This commit is contained in:
Gliniak
2022-12-31 10:53:25 +01:00
38 changed files with 632 additions and 6570 deletions

View File

@@ -1038,6 +1038,36 @@ bool D3D12CommandProcessor::SetupContext() {
parameter.Descriptor.RegisterSpace = 0;
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
}
// Shared memory SRV and UAV.
D3D12_DESCRIPTOR_RANGE root_shared_memory_view_ranges[2];
{
auto& parameter =
root_parameters_bindless[kRootParameter_Bindless_SharedMemory];
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
parameter.DescriptorTable.NumDescriptorRanges =
uint32_t(xe::countof(root_shared_memory_view_ranges));
parameter.DescriptorTable.pDescriptorRanges =
root_shared_memory_view_ranges;
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
{
auto& range = root_shared_memory_view_ranges[0];
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
range.NumDescriptors = 1;
range.BaseShaderRegister =
UINT(DxbcShaderTranslator::SRVMainRegister::kSharedMemory);
range.RegisterSpace = UINT(DxbcShaderTranslator::SRVSpace::kMain);
range.OffsetInDescriptorsFromTableStart = 0;
}
{
auto& range = root_shared_memory_view_ranges[1];
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
range.NumDescriptors = 1;
range.BaseShaderRegister =
UINT(DxbcShaderTranslator::UAVRegister::kSharedMemory);
range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart = 1;
}
}
// Sampler heap.
D3D12_DESCRIPTOR_RANGE root_bindless_sampler_range;
{
@@ -1057,7 +1087,7 @@ bool D3D12CommandProcessor::SetupContext() {
root_bindless_sampler_range.OffsetInDescriptorsFromTableStart = 0;
}
// View heap.
D3D12_DESCRIPTOR_RANGE root_bindless_view_ranges[6];
D3D12_DESCRIPTOR_RANGE root_bindless_view_ranges[4];
{
auto& parameter =
root_parameters_bindless[kRootParameter_Bindless_ViewHeap];
@@ -1066,34 +1096,6 @@ bool D3D12CommandProcessor::SetupContext() {
parameter.DescriptorTable.NumDescriptorRanges = 0;
parameter.DescriptorTable.pDescriptorRanges = root_bindless_view_ranges;
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
// Shared memory SRV.
{
assert_true(parameter.DescriptorTable.NumDescriptorRanges <
xe::countof(root_bindless_view_ranges));
auto& range = root_bindless_view_ranges[parameter.DescriptorTable
.NumDescriptorRanges++];
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
range.NumDescriptors = 1;
range.BaseShaderRegister =
UINT(DxbcShaderTranslator::SRVMainRegister::kSharedMemory);
range.RegisterSpace = UINT(DxbcShaderTranslator::SRVSpace::kMain);
range.OffsetInDescriptorsFromTableStart =
UINT(SystemBindlessView::kSharedMemoryRawSRV);
}
// Shared memory UAV.
{
assert_true(parameter.DescriptorTable.NumDescriptorRanges <
xe::countof(root_bindless_view_ranges));
auto& range = root_bindless_view_ranges[parameter.DescriptorTable
.NumDescriptorRanges++];
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
range.NumDescriptors = 1;
range.BaseShaderRegister =
UINT(DxbcShaderTranslator::UAVRegister::kSharedMemory);
range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart =
UINT(SystemBindlessView::kSharedMemoryRawUAV);
}
// EDRAM.
if (render_target_cache_->GetPath() ==
RenderTargetCache::Path::kPixelShaderInterlock) {
@@ -1458,6 +1460,20 @@ bool D3D12CommandProcessor::SetupContext() {
if (bindless_resources_used_) {
// Create the system bindless descriptors once all resources are
// initialized.
// kNullRawSRV.
ui::d3d12::util::CreateBufferRawSRV(
device,
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kNullRawSRV)),
nullptr, 0);
// kNullRawUAV.
ui::d3d12::util::CreateBufferRawUAV(
device,
provider.OffsetViewDescriptor(
view_bindless_heap_cpu_start_,
uint32_t(SystemBindlessView::kNullRawUAV)),
nullptr, 0);
// kNullTexture2DArray.
D3D12_SHADER_RESOURCE_VIEW_DESC null_srv_desc;
null_srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
@@ -2731,7 +2747,8 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
used_texture_mask, normalized_depth_control, normalized_color_mask);
// Update constant buffers, descriptors and root parameters.
if (!UpdateBindings(vertex_shader, pixel_shader, root_signature)) {
if (!UpdateBindings(vertex_shader, pixel_shader, root_signature,
memexport_used)) {
return false;
}
// Must not call anything that can change the descriptor heap from now on!
@@ -3413,6 +3430,7 @@ bool D3D12CommandProcessor::BeginSubmission(bool is_guest_command) {
cbuffer_binding_float_pixel_.up_to_date = false;
cbuffer_binding_bool_loop_.up_to_date = false;
cbuffer_binding_fetch_.up_to_date = false;
current_shared_memory_binding_is_uav_.reset();
if (bindless_resources_used_) {
cbuffer_binding_descriptor_indices_vertex_.up_to_date = false;
cbuffer_binding_descriptor_indices_pixel_.up_to_date = false;
@@ -4299,9 +4317,10 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
}
}
bool D3D12CommandProcessor::UpdateBindings(
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader,
ID3D12RootSignature* root_signature) {
bool D3D12CommandProcessor::UpdateBindings(const D3D12Shader* vertex_shader,
const D3D12Shader* pixel_shader,
ID3D12RootSignature* root_signature,
bool shared_memory_is_uav) {
const ui::d3d12::D3D12Provider& provider = GetD3D12Provider();
ID3D12Device* device = provider.GetDevice();
const RegisterFile& regs = *register_file_;
@@ -4338,6 +4357,9 @@ bool D3D12CommandProcessor::UpdateBindings(
uint32_t root_parameter_bool_loop_constants =
bindless_resources_used_ ? kRootParameter_Bindless_BoolLoopConstants
: kRootParameter_Bindful_BoolLoopConstants;
uint32_t root_parameter_shared_memory_and_bindful_edram =
bindless_resources_used_ ? kRootParameter_Bindless_SharedMemory
: kRootParameter_Bindful_SharedMemoryAndEdram;
//
// Update root constant buffers that are common for bindful and bindless.
@@ -4505,6 +4527,13 @@ bool D3D12CommandProcessor::UpdateBindings(
// Update descriptors.
//
if (!current_shared_memory_binding_is_uav_.has_value() ||
current_shared_memory_binding_is_uav_.value() != shared_memory_is_uav) {
current_shared_memory_binding_is_uav_ = shared_memory_is_uav;
current_graphics_root_up_to_date_ &=
~(1u << root_parameter_shared_memory_and_bindful_edram);
}
// Get textures and samplers used by the vertex shader, check if the last used
// samplers are compatible and update them.
size_t texture_layout_uid_vertex =
@@ -4815,7 +4844,9 @@ bool D3D12CommandProcessor::UpdateBindings(
bool retval = UpdateBindings_BindfulPath(
texture_layout_uid_vertex, textures_vertex, texture_layout_uid_pixel,
textures_pixel, sampler_count_vertex, sampler_count_pixel, retflag);
if (retflag) return retval;
if (retflag) {
return retval;
}
}
// Update the root parameters.
@@ -4854,6 +4885,31 @@ bool D3D12CommandProcessor::UpdateBindings(
current_graphics_root_up_to_date_ |= 1u
<< root_parameter_bool_loop_constants;
}
if (!(current_graphics_root_up_to_date_ &
(1u << root_parameter_shared_memory_and_bindful_edram))) {
assert_true(current_shared_memory_binding_is_uav_.has_value());
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_shared_memory_and_bindful_edram;
if (bindless_resources_used_) {
gpu_handle_shared_memory_and_bindful_edram =
provider.OffsetViewDescriptor(
view_bindless_heap_gpu_start_,
uint32_t(current_shared_memory_binding_is_uav_.value()
? SystemBindlessView ::
kNullRawSRVAndSharedMemoryRawUAVStart
: SystemBindlessView ::
kSharedMemoryRawSRVAndNullRawUAVStart));
} else {
gpu_handle_shared_memory_and_bindful_edram =
current_shared_memory_binding_is_uav_.value()
? gpu_handle_shared_memory_uav_and_edram_
: gpu_handle_shared_memory_srv_and_edram_;
}
deferred_command_list_.D3DSetGraphicsRootDescriptorTable(
root_parameter_shared_memory_and_bindful_edram,
gpu_handle_shared_memory_and_bindful_edram);
current_graphics_root_up_to_date_ |=
1u << root_parameter_shared_memory_and_bindful_edram;
}
if (bindless_resources_used_) {
if (!(current_graphics_root_up_to_date_ &
(1u << kRootParameter_Bindless_DescriptorIndicesPixel))) {
@@ -4895,14 +4951,6 @@ bool D3D12CommandProcessor::UpdateBindings(
XE_COLD
XE_NOINLINE
void D3D12CommandProcessor::UpdateBindings_UpdateRootBindful() {
if (!(current_graphics_root_up_to_date_ &
(1u << kRootParameter_Bindful_SharedMemoryAndEdram))) {
deferred_command_list_.D3DSetGraphicsRootDescriptorTable(
kRootParameter_Bindful_SharedMemoryAndEdram,
gpu_handle_shared_memory_and_edram_);
current_graphics_root_up_to_date_ |=
1u << kRootParameter_Bindful_SharedMemoryAndEdram;
}
uint32_t extra_index;
extra_index = current_graphics_root_bindful_extras_.textures_pixel;
if (extra_index != RootBindfulExtraParameterIndices::kUnavailable &&
@@ -5031,7 +5079,7 @@ bool D3D12CommandProcessor::UpdateBindings_BindfulPath(
bindful_textures_written_pixel_ = false;
// If updating fully, write the shared memory SRV and UAV descriptors and,
// if needed, the EDRAM descriptor.
gpu_handle_shared_memory_and_edram_ = view_gpu_handle;
gpu_handle_shared_memory_srv_and_edram_ = view_gpu_handle;
shared_memory_->WriteRawSRVDescriptor(view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
@@ -5043,6 +5091,19 @@ bool D3D12CommandProcessor::UpdateBindings_BindfulPath(
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
}
// Null SRV + UAV + EDRAM.
gpu_handle_shared_memory_uav_and_edram_ = view_gpu_handle;
ui::d3d12::util::CreateBufferRawSRV(provider.GetDevice(), view_cpu_handle, nullptr, 0);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
shared_memory_->WriteRawUAVDescriptor(view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
if (edram_rov_used) {
render_target_cache_->WriteEdramUintPow2UAVDescriptor(view_cpu_handle, 2);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
}
current_graphics_root_up_to_date_ &=
~(1u << kRootParameter_Bindful_SharedMemoryAndEdram);
}

View File

@@ -14,6 +14,7 @@
#include <atomic>
#include <deque>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
@@ -136,11 +137,19 @@ class D3D12CommandProcessor final : public CommandProcessor {
uint32_t count, ui::d3d12::util::DescriptorCpuGpuHandlePair* handles_out);
// These are needed often, so they are always allocated.
enum class SystemBindlessView : uint32_t {
kSharedMemoryRawSRV,
// Both may be bound as one root parameter.
kSharedMemoryRawSRVAndNullRawUAVStart,
kSharedMemoryRawSRV = kSharedMemoryRawSRVAndNullRawUAVStart,
kNullRawUAV,
// Both may be bound as one root parameter.
kNullRawSRVAndSharedMemoryRawUAVStart,
kNullRawSRV = kNullRawSRVAndSharedMemoryRawUAVStart,
kSharedMemoryRawUAV,
kSharedMemoryR32UintSRV,
kSharedMemoryR32G32UintSRV,
kSharedMemoryR32G32B32A32UintSRV,
kSharedMemoryRawUAV,
kSharedMemoryR32UintUAV,
kSharedMemoryR32G32UintUAV,
kSharedMemoryR32G32B32A32UintUAV,
@@ -348,10 +357,10 @@ class D3D12CommandProcessor final : public CommandProcessor {
kRootParameter_Bindful_SystemConstants, // +2 = 6 in all.
// Pretty rarely used and rarely changed - flow control constants.
kRootParameter_Bindful_BoolLoopConstants, // +2 = 8 in all.
// Never changed except for when starting a new descriptor heap - shared
// memory byte address buffer, and, if ROV is used for EDRAM, EDRAM R32_UINT
// UAV.
// SRV/UAV descriptor table.
// Changed only when starting a new descriptor heap or when switching
// between shared memory as SRV and UAV - shared memory byte address buffer
// (as SRV and as UAV, either may be null if not used), and, if ROV is used
// for EDRAM, EDRAM R32_UINT UAV.
kRootParameter_Bindful_SharedMemoryAndEdram, // +1 = 9 in all.
kRootParameter_Bindful_Count_Base,
@@ -375,10 +384,14 @@ class D3D12CommandProcessor final : public CommandProcessor {
kRootParameter_Bindless_DescriptorIndicesVertex, // +2 = 6 in VS.
kRootParameter_Bindless_SystemConstants, // +2 = 8 in all.
kRootParameter_Bindless_BoolLoopConstants, // +2 = 10 in all.
// Changed only when switching between shared memory as SRV and UAV - shared
// memory byte address buffer (as SRV and as UAV, either may be null if not
// used).
kRootParameter_Bindless_SharedMemory, // +1 = 11 in all.
// Unbounded sampler descriptor table - changed in case of overflow.
kRootParameter_Bindless_SamplerHeap, // +1 = 11 in all.
kRootParameter_Bindless_SamplerHeap, // +1 = 12 in all.
// Unbounded SRV/UAV descriptor table - never changed.
kRootParameter_Bindless_ViewHeap, // +1 = 12 in all.
kRootParameter_Bindless_ViewHeap, // +1 = 13 in all.
kRootParameter_Bindless_Count,
};
@@ -467,7 +480,8 @@ class D3D12CommandProcessor final : public CommandProcessor {
uint32_t normalized_color_mask);
bool UpdateBindings(const D3D12Shader* vertex_shader,
const D3D12Shader* pixel_shader,
ID3D12RootSignature* root_signature);
ID3D12RootSignature* root_signature,
bool shared_memory_is_uav);
XE_COLD
XE_NOINLINE
void UpdateBindings_UpdateRootBindful();
@@ -739,6 +753,13 @@ class D3D12CommandProcessor final : public CommandProcessor {
ConstantBufferBinding cbuffer_binding_descriptor_indices_vertex_;
ConstantBufferBinding cbuffer_binding_descriptor_indices_pixel_;
// Whether the latest shared memory and EDRAM buffer binding contains the
// shared memory UAV rather than the SRV.
// Separate descriptor tables for the SRV and the UAV, even though only one is
// accessed dynamically in the shaders, are used to prevent a validation
// message about missing resource states in PIX.
std::optional<bool> current_shared_memory_binding_is_uav_;
// Pages with the descriptors currently used for handling Xenos draw calls.
uint64_t draw_view_bindful_heap_index_;
uint64_t draw_sampler_bindful_heap_index_;
@@ -771,7 +792,8 @@ class D3D12CommandProcessor final : public CommandProcessor {
std::vector<uint32_t> current_sampler_bindless_indices_pixel_;
// Latest bindful descriptor handles used for handling Xenos draw calls.
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_shared_memory_and_edram_;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_shared_memory_srv_and_edram_;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_shared_memory_uav_and_edram_;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_textures_vertex_;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_textures_pixel_;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_samplers_vertex_;

View File

@@ -1226,15 +1226,13 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
builder_->makeStructType(struct_per_vertex_members, "gl_PerVertex");
builder_->addMemberName(type_struct_per_vertex,
kOutputPerVertexMemberPosition, "gl_Position");
builder_->addMemberDecoration(type_struct_per_vertex,
kOutputPerVertexMemberPosition,
spv::DecorationInvariant);
builder_->addMemberDecoration(type_struct_per_vertex,
kOutputPerVertexMemberPosition,
spv::DecorationBuiltIn, spv::BuiltInPosition);
builder_->addDecoration(type_struct_per_vertex, spv::DecorationBlock);
output_per_vertex_ = builder_->createVariable(
spv::NoPrecision, spv::StorageClassOutput, type_struct_per_vertex, "");
builder_->addDecoration(output_per_vertex_, spv::DecorationInvariant);
main_interface_.push_back(output_per_vertex_);
}

View File

@@ -265,10 +265,9 @@ TextureGuestLayout GetGuestTextureLayout(
}
layout.mips_total_extent_bytes = 0;
const FormatInfo* const format_info = FormatInfo::Get(format);
const uint32_t bytes_per_block = format_info->bytes_per_block();
const unsigned char block_width_sh = FormatInfo::GetWidthShift(format);
const unsigned char block_height_sh = FormatInfo::GetHeightShift(format);
const FormatInfo* format_info = FormatInfo::Get(format);
uint32_t bytes_per_block = format_info->bytes_per_block();
// The loop counter can mean two things depending on whether the packed mip
// tail is stored as mip 0, because in this case, it would be ambiguous since
// both the base and the mips would be on "level 0", but stored separately and
@@ -313,13 +312,10 @@ TextureGuestLayout GetGuestTextureLayout(
z_slice_stride_texel_rows_unaligned =
std::max(xe::next_pow2(height_texels) >> level, uint32_t(1));
}
// maybe do 1 << block_width_sh instead of format_info->block_width, since
// we'll have cl loaded with the shift anyway
uint32_t row_pitch_blocks_tile_aligned =
xe::align(xe::align<uint32_t>(row_pitch_texels_unaligned,
format_info->block_width) >>
block_width_sh,
xenos::kTextureTileWidthHeight);
uint32_t row_pitch_blocks_tile_aligned = xe::align(
xe::align(row_pitch_texels_unaligned, format_info->block_width) /
format_info->block_width,
xenos::kTextureTileWidthHeight);
level_layout.row_pitch_bytes =
row_pitch_blocks_tile_aligned * bytes_per_block;
// Assuming the provided pitch is already 256-byte-aligned for linear, but
@@ -331,11 +327,10 @@ TextureGuestLayout GetGuestTextureLayout(
}
level_layout.z_slice_stride_block_rows =
dimension != xenos::DataDimension::k1D
? xe::align<uint32_t>(
xe::align<uint32_t>(z_slice_stride_texel_rows_unaligned,
format_info->block_height) >>
block_height_sh,
xenos::kTextureTileWidthHeight)
? xe::align(xe::align(z_slice_stride_texel_rows_unaligned,
format_info->block_height) /
format_info->block_height,
xenos::kTextureTileWidthHeight)
: 1;
level_layout.array_slice_stride_bytes =
level_layout.row_pitch_bytes * level_layout.z_slice_stride_block_rows;
@@ -352,90 +347,76 @@ TextureGuestLayout GetGuestTextureLayout(
// be smaller (especially in the 1280x720 linear k_8_8_8_8 case in 4E4D083E,
// for which memory exactly for 1280x720 is allocated, and aligning the
// height to 32 would cause access of an unallocated page) or bigger than
// the stride. For tiled textures, this is the dimensions aligned to 32x32x4
// blocks (or x1 for the missing dimensions).
uint32_t level_width_blocks =
xe::align<uint32_t>(std::max(width_texels >> level, uint32_t(1)),
format_info->block_width) >>
block_width_sh;
uint32_t level_height_blocks =
xe::align<uint32_t>(std::max(height_texels >> level, uint32_t(1)),
format_info->block_height) >>
block_height_sh;
uint32_t level_depth = std::max(depth >> level, uint32_t(1));
if (is_tiled) {
// the stride.
if (level == layout.packed_level) {
// Calculate the portion of the mip tail actually used by the needed mips.
// The actually used region may be significantly smaller than the full
// 32x32-texel-aligned (and, for mips, calculated from the base dimensions
// rounded to powers of two - 58410A7A has an 80x260 tiled texture with
// packed mips at level 3 containing a mip ending at Y = 36, while
// 260 >> 3 == 32, but 512 >> 3 == 64) tail. A 2x2 texture (for example,
// in 494707D4, there's a 2x2 k_8_8_8_8 linear texture with packed mips),
// for instance, would have its 2x2 base at (16, 0) and its 1x1 mip at
// (8, 0) - and we need 2 or 1 rows in these cases, not 32 - the 32 rows
// in a linear texture (with 256-byte pitch alignment) would span two 4 KB
// pages rather than one.
level_layout.x_extent_blocks = 0;
level_layout.y_extent_blocks = 0;
level_layout.z_extent = 0;
uint32_t packed_sublevel_last = is_base ? 0 : max_level;
for (uint32_t packed_sublevel = layout.packed_level;
packed_sublevel <= packed_sublevel_last; ++packed_sublevel) {
uint32_t packed_sublevel_x_blocks;
uint32_t packed_sublevel_y_blocks;
uint32_t packed_sublevel_z;
GetPackedMipOffset(width_texels, height_texels, depth, format,
packed_sublevel, packed_sublevel_x_blocks,
packed_sublevel_y_blocks, packed_sublevel_z);
level_layout.x_extent_blocks = std::max(
level_layout.x_extent_blocks,
packed_sublevel_x_blocks +
xe::align(
std::max(width_texels >> packed_sublevel, uint32_t(1)),
format_info->block_width) /
format_info->block_width);
level_layout.y_extent_blocks = std::max(
level_layout.y_extent_blocks,
packed_sublevel_y_blocks +
xe::align(
std::max(height_texels >> packed_sublevel, uint32_t(1)),
format_info->block_height) /
format_info->block_height);
level_layout.z_extent =
std::max(level_layout.z_extent,
packed_sublevel_z +
std::max(depth >> packed_sublevel, uint32_t(1)));
}
} else {
level_layout.x_extent_blocks =
xe::align(level_width_blocks, xenos::kTextureTileWidthHeight);
xe::align(std::max(width_texels >> level, uint32_t(1)),
format_info->block_width) /
format_info->block_width;
level_layout.y_extent_blocks =
xe::align(level_height_blocks, xenos::kTextureTileWidthHeight);
xe::align(std::max(height_texels >> level, uint32_t(1)),
format_info->block_height) /
format_info->block_height;
level_layout.z_extent = std::max(depth >> level, uint32_t(1));
}
if (is_tiled) {
uint32_t bytes_per_block_log2 = xe::log2_floor(bytes_per_block);
if (dimension == xenos::DataDimension::k3D) {
level_layout.z_extent =
xe::align(level_depth, xenos::kTextureTileDepth);
// 32-block-row x 4 slice portions laid out sequentially (4-slice-major,
// 32-block-row-minor), address extent within a 32x32x4 tile depends on
// the pitch. Origins of 32x32x4 tiles grow monotonically, first along
// Z, then along Y, then along X.
level_layout.array_slice_data_extent_bytes =
GetTiledAddressUpperBound3D(
level_layout.x_extent_blocks, level_layout.y_extent_blocks,
level_layout.z_extent, row_pitch_blocks_tile_aligned,
level_layout.y_extent_blocks, bytes_per_block_log2);
} else {
level_layout.z_extent = 1;
// Origins of 32x32 tiles grow monotonically, first along Y, then along
// X.
level_layout.array_slice_data_extent_bytes =
GetTiledAddressUpperBound2D(
level_layout.x_extent_blocks, level_layout.y_extent_blocks,
row_pitch_blocks_tile_aligned, bytes_per_block_log2);
}
} else {
if (level == layout.packed_level) {
// Calculate the portion of the mip tail actually used by the needed
// mips. The actually used region may be significantly smaller than the
// full 32x32-texel-aligned tail. A 2x2 texture (for example, in
// 494707D4, there's a 2x2 k_8_8_8_8 linear texture with packed mips),
// for instance, would have its 2x2 base at (16, 0) and its 1x1 mip at
// (8, 0) - and we need 2 or 1 rows in these cases, not 32 - the 32 rows
// would span two 4 KB pages rather than one, taking the 256-byte pitch
// alignment in linear textures into account.
level_layout.x_extent_blocks = 0;
level_layout.y_extent_blocks = 0;
level_layout.z_extent = 0;
uint32_t packed_sublevel_last = is_base ? 0 : max_level;
for (uint32_t packed_sublevel = layout.packed_level;
packed_sublevel <= packed_sublevel_last; ++packed_sublevel) {
uint32_t packed_sublevel_x_blocks;
uint32_t packed_sublevel_y_blocks;
uint32_t packed_sublevel_z;
GetPackedMipOffset(width_texels, height_texels, depth, format,
packed_sublevel, packed_sublevel_x_blocks,
packed_sublevel_y_blocks, packed_sublevel_z);
level_layout.x_extent_blocks = std::max<uint32_t>(
level_layout.x_extent_blocks,
packed_sublevel_x_blocks +
(xe::align<uint32_t>(
std::max(width_texels >> packed_sublevel, uint32_t(1)),
format_info->block_width) >>
block_width_sh));
level_layout.y_extent_blocks = std::max<uint32_t>(
level_layout.y_extent_blocks,
packed_sublevel_y_blocks +
(xe::align<uint32_t>(
std::max(height_texels >> packed_sublevel, uint32_t(1)),
format_info->block_height) >>
block_height_sh));
level_layout.z_extent =
std::max(level_layout.z_extent,
packed_sublevel_z +
std::max(depth >> packed_sublevel, uint32_t(1)));
}
} else {
level_layout.x_extent_blocks = level_width_blocks;
level_layout.y_extent_blocks = level_height_blocks;
level_layout.z_extent = level_depth;
}
level_layout.array_slice_data_extent_bytes =
z_stride_bytes * (level_layout.z_extent - 1) +
level_layout.row_pitch_bytes * (level_layout.y_extent_blocks - 1) +

View File

@@ -144,24 +144,27 @@ struct TextureGuestLayout {
// multiplied by the array slice count.
uint32_t array_slice_stride_bytes;
// Estimated amount of memory this level occupies, and variables involved in
// its calculation. Not aligned to kTextureSubresourceAlignmentBytes. For
// tiled textures, this will be rounded to 32x32x4 blocks (or 32x32x1
// depending on the dimension), but for the linear subresources, this may be
// significantly (including less 4 KB pages) smaller than the aligned size
// (like for 4E4D083E where aligning the height of a 1280x720 linear texture
// results in access violations). For the linear mip tail, this includes all
// the mip levels stored in it. If the width is bigger than the pitch, this
// will also be taken into account for the last row so all memory actually
// used by the texture will be loaded, and may be bigger than the distance
// between array slices or levels. The purpose of this parameter is to make
// the memory amount that needs to be resident as close to the real amount
// as possible, to make sure all the needed data will be read, but also, if
// possible, unneeded memory pages won't be accessed (since that may trigger
// an access violation on the CPU).
// The exclusive upper bound of blocks needed at this level (this level for
// non-packed levels, or all the packed levels for the packed mip tail).
uint32_t x_extent_blocks;
uint32_t y_extent_blocks;
uint32_t z_extent;
// Estimated amount of memory this level occupies. Not aligned to
// kTextureSubresourceAlignmentBytes. For tiled textures, this will be
// calculated for the extent rounded to 32x32x4 blocks (or 32x32x1 depending
// on the dimensionality), but for linear textures, as well as for mips of
// non-power-of-two tiled textures, this may be significantly (including
// less 4 KB pages) smaller than the aligned size (like for 4E4D083E where
// aligning the height of a 1280x720 linear texture results in access
// violations). For the linear mip tail, this includes all the mip levels
// stored in it. If the width is bigger than the pitch, this will also be
// taken into account for the last row so all memory actually used by the
// texture will be loaded, and may be bigger than the distance between array
// slices or levels. The purpose of this parameter is to make the memory
// amount that needs to be resident as close to the real amount as possible,
// to make sure all the needed data will be read, but also, if possible,
// unneeded memory pages won't be accessed (since that may trigger an access
// violation on the CPU).
uint32_t array_slice_data_extent_bytes;
// Including all array slices.
uint32_t level_data_extent_bytes;

View File

@@ -258,7 +258,7 @@ void TraceViewer::DrawControllerUI() {
}
ImGui::SameLine();
ImGui::SliderInt("", &target_frame, 0, player_->frame_count() - 1);
ImGui::SliderInt("##", &target_frame, 0, player_->frame_count() - 1);
if (target_frame != player_->current_frame_index() &&
!player_->is_playing_trace()) {
player_->SeekFrame(target_frame);
@@ -554,7 +554,7 @@ void TraceViewer::DrawCommandListUI() {
}
ImGui::PushItemWidth(float(column_width - 15));
ImGui::SliderInt("", &target_command, -1, command_count - 1);
ImGui::SliderInt("##", &target_command, -1, command_count - 1);
ImGui::PopItemWidth();
if (target_command != player_->current_command_index() &&
@@ -733,8 +733,8 @@ void TraceViewer::DrawTextureInfo(
ImGui::Columns(2);
if (texture) {
ImVec2 button_size(256, 256);
if (ImGui::ImageButton(ImTextureID(texture), button_size, ImVec2(0, 0),
ImVec2(1, 1))) {
if (ImGui::ImageButton("#texture_info_image", ImTextureID(texture),
button_size, ImVec2(0, 0), ImVec2(1, 1))) {
// show viewer
}
} else {
@@ -818,8 +818,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
int display_start, display_end;
ImGui::CalcListClipping(vertex_count, ImGui::GetTextLineHeight(),
&display_start, &display_end);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
(display_start)*ImGui::GetTextLineHeight());
ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
ImGui::Columns(column_count);
if (display_start <= 1) {
for (size_t el_index = 0; el_index < vertex_binding.attributes.size();
@@ -1005,8 +1004,8 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
}
}
ImGui::Columns(1);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (vertex_count - display_end) *
ImGui::GetTextLineHeight());
ImGui::Dummy(
ImVec2(0, (vertex_count - display_end) * ImGui::GetTextLineHeight()));
ImGui::PopStyleVar();
ImGui::EndChild();
}
@@ -1463,19 +1462,21 @@ void TraceViewer::DrawStateUI() {
ImVec2 button_pos = ImGui::GetCursorScreenPos();
ImVec2 button_size(256, 256);
ImTextureID tex = 0;
ImGui::PushID(i);
if (write_mask) {
auto color_target = GetColorRenderTarget(surface_pitch, surface_msaa,
color_base, color_format);
tex = ImTextureID(color_target);
if (ImGui::ImageButton(tex, button_size, ImVec2(0, 0),
if (ImGui::ImageButton("#color_image", tex, button_size, ImVec2(0, 0),
ImVec2(1, 1))) {
// show viewer
}
} else {
ImGui::ImageButton(ImTextureID(0), button_size, ImVec2(0, 0),
ImVec2(1, 1), -1, ImVec4(0, 0, 0, 0),
ImGui::ImageButton("#color_image", ImTextureID(0), button_size,
ImVec2(0, 0), ImVec2(1, 1), ImVec4(0, 0, 0, 0),
ImVec4(0, 0, 0, 0));
}
ImGui::PopID();
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Color Target %d (%s), base %.4X, pitch %d, format %s", i,
@@ -1586,8 +1587,8 @@ void TraceViewer::DrawStateUI() {
auto button_pos = ImGui::GetCursorScreenPos();
ImVec2 button_size(256, 256);
ImGui::ImageButton(ImTextureID(depth_target), button_size, ImVec2(0, 0),
ImVec2(1, 1));
ImGui::ImageButton("#depth_stencil_image", ImTextureID(depth_target),
button_size, ImVec2(0, 0), ImVec2(1, 1));
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
@@ -1640,8 +1641,7 @@ void TraceViewer::DrawStateUI() {
ImGui::CalcListClipping(int(vertices.size() / 4),
ImGui::GetTextLineHeight(), &display_start,
&display_end);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
(display_start)*ImGui::GetTextLineHeight());
ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
ImGui::Columns(int(el_size), "#vsvertices", true);
for (size_t i = display_start; i < display_end; i++) {
@@ -1662,9 +1662,8 @@ void TraceViewer::DrawStateUI() {
}
ImGui::Columns(1);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
((vertices.size() / 4) - display_end) *
ImGui::GetTextLineHeight());
ImGui::Dummy(ImVec2(0, ((vertices.size() / 4) - display_end) *
ImGui::GetTextLineHeight()));
ImGui::EndChild();
} else {
ImGui::Text("No vertex shader output");
@@ -1708,8 +1707,7 @@ void TraceViewer::DrawStateUI() {
ImGui::CalcListClipping(1 + draw_info.index_count,
ImGui::GetTextLineHeight(), &display_start,
&display_end);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
(display_start)*ImGui::GetTextLineHeight());
ImGui::Dummy(ImVec2(0, (display_start)*ImGui::GetTextLineHeight()));
ImGui::Columns(2, "#indices", true);
ImGui::SetColumnOffset(1, 60);
if (display_start <= 1) {
@@ -1744,9 +1742,8 @@ void TraceViewer::DrawStateUI() {
ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
(draw_info.index_count - display_end) *
ImGui::GetTextLineHeight());
ImGui::Dummy(ImVec2(0, (draw_info.index_count - display_end) *
ImGui::GetTextLineHeight()));
ImGui::PopStyleVar();
ImGui::EndChild();
}

View File

@@ -2546,8 +2546,6 @@ bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
// After all commands that may dispatch, copy or insert barriers, submit the
// barriers (may end the render pass), and (re)enter the render pass before
// drawing.
// TODO(Triang3l): Handle disabled variableMultisampleRate by restarting the
// render pass with no attachments if the sample count becomes different.
SubmitBarriersAndEnterRenderTargetCacheRenderPass(
render_target_cache_->last_update_render_pass(),
render_target_cache_->last_update_framebuffer());

View File

@@ -581,6 +581,7 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
primitive_processing_result.host_primitive_reset_enabled;
description_out.depth_clamp_enable =
device_features.depthClamp &&
regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable;
// TODO(Triang3l): Tessellation.
@@ -825,6 +826,10 @@ bool VulkanPipelineCache::ArePipelineRequirementsMet(
return false;
}
if (!device_features.depthClamp && description.depth_clamp_enable) {
return false;
}
if (!device_features.fillModeNonSolid &&
description.polygon_mode != PipelinePolygonMode::kFill) {
return false;
@@ -1173,9 +1178,6 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
builder.makeStructType(id_vector_temp, "gl_PerVertex");
builder.addMemberName(type_struct_out_gl_per_vertex,
member_out_gl_per_vertex_position, "gl_Position");
builder.addMemberDecoration(type_struct_out_gl_per_vertex,
member_out_gl_per_vertex_position,
spv::DecorationInvariant);
builder.addMemberDecoration(type_struct_out_gl_per_vertex,
member_out_gl_per_vertex_position,
spv::DecorationBuiltIn, spv::BuiltInPosition);
@@ -1183,9 +1185,6 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
builder.addMemberName(type_struct_out_gl_per_vertex,
member_out_gl_per_vertex_clip_distance,
"gl_ClipDistance");
builder.addMemberDecoration(type_struct_out_gl_per_vertex,
member_out_gl_per_vertex_clip_distance,
spv::DecorationInvariant);
builder.addMemberDecoration(
type_struct_out_gl_per_vertex, member_out_gl_per_vertex_clip_distance,
spv::DecorationBuiltIn, spv::BuiltInClipDistance);
@@ -1194,6 +1193,7 @@ VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
spv::Id out_gl_per_vertex =
builder.createVariable(spv::NoPrecision, spv::StorageClassOutput,
type_struct_out_gl_per_vertex, "");
builder.addDecoration(out_gl_per_vertex, spv::DecorationInvariant);
main_interface.push_back(out_gl_per_vertex);
// Begin the main function.

View File

@@ -44,9 +44,13 @@ class VulkanRenderTargetCache final : public RenderTargetCache {
// targets are different for 2x and 4x guest MSAA, pipelines because the
// sample mask will have 2 samples excluded for 2x-as-4x).
// This has effect only on the attachments, but even in cases when there
// are no attachments, it can be used to the sample count between
// are no attachments, it can be used to pass the sample count between
// subsystems, for instance, to specify the desired number of samples to
// use when there are no attachments in pipelines.
// Also, without attachments, using separate render passes for different
// sample counts ensures that if the variableMultisampleRate feature is
// not supported, no draws with different rasterization sample counts end
// up in one render pass.
xenos::MsaaSamples msaa_samples : xenos::kMsaaSamplesBits; // 2
// << 0 is depth, << 1...4 is color.
uint32_t depth_and_color_used : 1 + xenos::kMaxColorRenderTargets; // 7