[GPU] Move all xenos.h to gpu::xenos, disambiguate Dimension/TextureDimension

This commit is contained in:
Triang3l
2020-07-11 15:54:22 +03:00
parent 39490f3c3a
commit 4bb0ca0e09
61 changed files with 1411 additions and 1365 deletions

View File

@@ -673,7 +673,8 @@ void D3D12CommandProcessor::ReleaseScratchGPUBuffer(
}
}
void D3D12CommandProcessor::SetSamplePositions(MsaaSamples sample_positions) {
void D3D12CommandProcessor::SetSamplePositions(
xenos::MsaaSamples sample_positions) {
if (current_sample_positions_ == sample_positions) {
return;
}
@@ -696,10 +697,10 @@ void D3D12CommandProcessor::SetSamplePositions(MsaaSamples sample_positions) {
// work a little bit better for tall stairs.
// FIXME(Triang3l): This is currently even uglier than without custom
// sample positions.
if (sample_positions >= MsaaSamples::k2X) {
if (sample_positions >= xenos::MsaaSamples::k2X) {
// Sample 1 is lower-left on Xenos, but upper-right in Direct3D 12.
D3D12_SAMPLE_POSITION d3d_sample_positions[4];
if (sample_positions >= MsaaSamples::k4X) {
if (sample_positions >= xenos::MsaaSamples::k4X) {
// Upper-left.
d3d_sample_positions[0].X = -2 + 4;
d3d_sample_positions[0].Y = -6 + 4;
@@ -1657,7 +1658,7 @@ void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
}
D3D12_SHADER_RESOURCE_VIEW_DESC swap_texture_srv_desc;
TextureFormat frontbuffer_format;
xenos::TextureFormat frontbuffer_format;
ID3D12Resource* swap_texture_resource = texture_cache_->RequestSwapTexture(
swap_texture_srv_desc, frontbuffer_format);
if (swap_texture_resource) {
@@ -1667,8 +1668,8 @@ void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
// executable, which initializes the normal gamma ramp for 8_8_8_8 output
// and the PWL gamma ramp for 2_10_10_10.
bool use_pwl_gamma_ramp =
frontbuffer_format == TextureFormat::k_2_10_10_10 ||
frontbuffer_format == TextureFormat::k_2_10_10_10_AS_16_16_16_16;
frontbuffer_format == xenos::TextureFormat::k_2_10_10_10 ||
frontbuffer_format == xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16;
bool descriptors_obtained;
ui::d3d12::util::DescriptorCPUGPUHandlePair descriptor_swap_texture;
@@ -1757,7 +1758,7 @@ void D3D12CommandProcessor::OnPrimaryBufferEnd() {
}
}
Shader* D3D12CommandProcessor::LoadShader(ShaderType shader_type,
Shader* D3D12CommandProcessor::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) {
@@ -1765,7 +1766,7 @@ Shader* D3D12CommandProcessor::LoadShader(ShaderType shader_type,
dword_count);
}
bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
uint32_t index_count,
IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) {
@@ -1833,7 +1834,8 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
!pixel_shader->memexport_stream_constants().empty();
bool memexport_used = memexport_used_vertex || memexport_used_pixel;
bool primitive_two_faced = IsPrimitiveTwoFaced(tessellated, primitive_type);
bool primitive_two_faced =
xenos::IsPrimitiveTwoFaced(tessellated, primitive_type);
auto sq_program_cntl = regs.Get<reg::SQ_PROGRAM_CNTL>();
auto pa_su_sc_mode_cntl = regs.Get<reg::PA_SU_SC_MODE_CNTL>();
if (!memexport_used_vertex &&
@@ -1856,18 +1858,18 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
// Set up primitive topology.
bool indexed = index_buffer_info != nullptr && index_buffer_info->guest_base;
PrimitiveType primitive_type_converted;
xenos::PrimitiveType primitive_type_converted;
D3D_PRIMITIVE_TOPOLOGY primitive_topology;
if (tessellated) {
primitive_type_converted = primitive_type;
switch (primitive_type_converted) {
// TODO(Triang3l): Support all kinds of patches if found in games.
case PrimitiveType::kTriangleList:
case PrimitiveType::kTrianglePatch:
case xenos::PrimitiveType::kTriangleList:
case xenos::PrimitiveType::kTrianglePatch:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST;
break;
case PrimitiveType::kQuadList:
case PrimitiveType::kQuadPatch:
case xenos::PrimitiveType::kQuadList:
case xenos::PrimitiveType::kQuadPatch:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST;
break;
default:
@@ -1877,23 +1879,23 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
primitive_type_converted =
PrimitiveConverter::GetReplacementPrimitiveType(primitive_type);
switch (primitive_type_converted) {
case PrimitiveType::kPointList:
case xenos::PrimitiveType::kPointList:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
break;
case PrimitiveType::kLineList:
case xenos::PrimitiveType::kLineList:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
break;
case PrimitiveType::kLineStrip:
case xenos::PrimitiveType::kLineStrip:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
break;
case PrimitiveType::kTriangleList:
case PrimitiveType::kRectangleList:
case xenos::PrimitiveType::kTriangleList:
case xenos::PrimitiveType::kRectangleList:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
break;
case PrimitiveType::kTriangleStrip:
case xenos::PrimitiveType::kTriangleStrip:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
break;
case PrimitiveType::kQuadList:
case xenos::PrimitiveType::kQuadList:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
break;
default:
@@ -1905,7 +1907,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
deferred_command_list_->D3DIASetPrimitiveTopology(primitive_topology);
}
uint32_t line_loop_closing_index;
if (primitive_type == PrimitiveType::kLineLoop && !indexed &&
if (primitive_type == xenos::PrimitiveType::kLineLoop && !indexed &&
index_count >= 3) {
// Add a vertex to close the loop, and make the vertex shader replace its
// index (before adding the offset) with 0 to fetch the first vertex again.
@@ -1929,7 +1931,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
auto rb_colorcontrol = regs.Get<reg::RB_COLORCONTROL>();
early_z = pixel_shader->implicit_early_z_allowed() &&
(!rb_colorcontrol.alpha_test_enable ||
rb_colorcontrol.alpha_func == CompareFunction::kAlways) &&
rb_colorcontrol.alpha_func == xenos::CompareFunction::kAlways) &&
!rb_colorcontrol.alpha_to_mask_enable;
} else {
early_z = true;
@@ -1940,8 +1942,9 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
ID3D12RootSignature* root_signature;
if (!pipeline_cache_->ConfigurePipeline(
vertex_shader, pixel_shader, primitive_type_converted,
indexed ? index_buffer_info->format : IndexFormat::kInt16, early_z,
pipeline_render_targets, &pipeline_handle, &root_signature)) {
indexed ? index_buffer_info->format : xenos::IndexFormat::kInt16,
early_z, pipeline_render_targets, &pipeline_handle,
&root_signature)) {
return false;
}
if (current_cached_pipeline_ != pipeline_handle) {
@@ -1957,7 +1960,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
// Update system constants before uploading them.
UpdateSystemConstantValues(
memexport_used, primitive_two_faced, line_loop_closing_index,
indexed ? index_buffer_info->endianness : Endian::kNone,
indexed ? index_buffer_info->endianness : xenos::Endian::kNone,
used_texture_mask, early_z, GetCurrentColorMask(pixel_shader),
pipeline_render_targets);
@@ -2032,7 +2035,8 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
GetSupportedMemExportFormatSize(memexport_stream.format);
if (memexport_format_size == 0) {
XELOGE("Unsupported memexport format {}",
FormatInfo::Get(TextureFormat(uint32_t(memexport_stream.format)))
FormatInfo::Get(
xenos::TextureFormat(uint32_t(memexport_stream.format)))
->name);
return false;
}
@@ -2074,7 +2078,8 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
GetSupportedMemExportFormatSize(memexport_stream.format);
if (memexport_format_size == 0) {
XELOGE("Unsupported memexport format {}",
FormatInfo::Get(TextureFormat(uint32_t(memexport_stream.format)))
FormatInfo::Get(
xenos::TextureFormat(uint32_t(memexport_stream.format)))
->name);
return false;
}
@@ -2114,16 +2119,18 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
// Actually draw.
if (indexed) {
uint32_t index_size = index_buffer_info->format == IndexFormat::kInt32
? sizeof(uint32_t)
: sizeof(uint16_t);
uint32_t index_size =
index_buffer_info->format == xenos::IndexFormat::kInt32
? sizeof(uint32_t)
: sizeof(uint16_t);
assert_false(index_buffer_info->guest_base & (index_size - 1));
uint32_t index_base =
index_buffer_info->guest_base & 0x1FFFFFFF & ~(index_size - 1);
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
index_buffer_view.Format = index_buffer_info->format == IndexFormat::kInt32
? DXGI_FORMAT_R32_UINT
: DXGI_FORMAT_R16_UINT;
index_buffer_view.Format =
index_buffer_info->format == xenos::IndexFormat::kInt32
? DXGI_FORMAT_R32_UINT
: DXGI_FORMAT_R16_UINT;
PrimitiveConverter::ConversionResult conversion_result;
uint32_t converted_index_count;
if (tessellated) {
@@ -2455,7 +2462,7 @@ void D3D12CommandProcessor::BeginSubmission(bool is_guest_command) {
ff_scissor_update_needed_ = true;
ff_blend_factor_update_needed_ = true;
ff_stencil_ref_update_needed_ = true;
current_sample_positions_ = MsaaSamples::k1X;
current_sample_positions_ = xenos::MsaaSamples::k1X;
current_cached_pipeline_ = nullptr;
current_external_pipeline_ = nullptr;
current_graphics_root_signature_ = nullptr;
@@ -2703,9 +2710,10 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(bool primitive_two_faced) {
pixel_size_x = 1;
pixel_size_y = 1;
} else {
MsaaSamples msaa_samples = regs.Get<reg::RB_SURFACE_INFO>().msaa_samples;
pixel_size_x = msaa_samples >= MsaaSamples::k4X ? 2 : 1;
pixel_size_y = msaa_samples >= MsaaSamples::k2X ? 2 : 1;
xenos::MsaaSamples msaa_samples =
regs.Get<reg::RB_SURFACE_INFO>().msaa_samples;
pixel_size_x = msaa_samples >= xenos::MsaaSamples::k4X ? 2 : 1;
pixel_size_y = msaa_samples >= xenos::MsaaSamples::k2X ? 2 : 1;
}
if (texture_cache_->IsResolutionScale2X()) {
pixel_size_x *= 2;
@@ -2849,7 +2857,7 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(bool primitive_two_faced) {
void D3D12CommandProcessor::UpdateSystemConstantValues(
bool shared_memory_is_uav, bool primitive_two_faced,
uint32_t line_loop_closing_index, Endian index_endian,
uint32_t line_loop_closing_index, xenos::Endian index_endian,
uint32_t used_texture_mask, bool early_z, uint32_t color_mask,
const RenderTargetCache::PipelineRenderTarget render_targets[4]) {
auto& regs = *register_file_;
@@ -2990,13 +2998,13 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// Gamma writing.
for (uint32_t i = 0; i < 4; ++i) {
if (color_infos[i].color_format ==
ColorRenderTargetFormat::k_8_8_8_8_GAMMA) {
xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA) {
flags |= DxbcShaderTranslator::kSysFlag_Color0Gamma << i;
}
}
if (edram_rov_used_ && depth_stencil_enabled) {
flags |= DxbcShaderTranslator::kSysFlag_ROVDepthStencil;
if (rb_depth_info.depth_format == DepthRenderTargetFormat::kD24FS8) {
if (rb_depth_info.depth_format == xenos::DepthRenderTargetFormat::kD24FS8) {
flags |= DxbcShaderTranslator::kSysFlag_ROVDepthFloat24;
}
if (rb_depthcontrol.z_enable) {
@@ -3199,9 +3207,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// Log2 of sample count, for scaling VPOS with SSAA (without ROV) and for
// EDRAM address calculation with MSAA (with ROV).
uint32_t sample_count_log2_x =
rb_surface_info.msaa_samples >= MsaaSamples::k4X ? 1 : 0;
rb_surface_info.msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t sample_count_log2_y =
rb_surface_info.msaa_samples >= MsaaSamples::k2X ? 1 : 0;
rb_surface_info.msaa_samples >= xenos::MsaaSamples::k2X ? 1 : 0;
dirty |= system_constants_.sample_count_log2[0] != sample_count_log2_x;
dirty |= system_constants_.sample_count_log2[1] != sample_count_log2_y;
system_constants_.sample_count_log2[0] = sample_count_log2_x;
@@ -3220,7 +3228,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
if (edram_rov_used_) {
uint32_t edram_pitch_tiles =
((rb_surface_info.surface_pitch *
(rb_surface_info.msaa_samples >= MsaaSamples::k4X ? 2 : 1)) +
(rb_surface_info.msaa_samples >= xenos::MsaaSamples::k4X ? 2 : 1)) +
79) /
80;
dirty |= system_constants_.edram_pitch_tiles != edram_pitch_tiles;
@@ -3232,8 +3240,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
reg::RB_COLOR_INFO color_info = color_infos[i];
// Exponent bias is in bits 20:25 of RB_COLOR_INFO.
int32_t color_exp_bias = color_info.color_exp_bias;
if (color_info.color_format == ColorRenderTargetFormat::k_16_16 ||
color_info.color_format == ColorRenderTargetFormat::k_16_16_16_16) {
if (color_info.color_format == xenos::ColorRenderTargetFormat::k_16_16 ||
color_info.color_format ==
xenos::ColorRenderTargetFormat::k_16_16_16_16) {
// On the Xbox 360, k_16_16_EDRAM and k_16_16_16_16_EDRAM internally have
// -32...32 range and expect shaders to give -32...32 values, but they're
// emulated using normalized RG16/RGBA16 when not using the ROV, so the
@@ -4239,28 +4248,28 @@ bool D3D12CommandProcessor::UpdateBindings(
}
uint32_t D3D12CommandProcessor::GetSupportedMemExportFormatSize(
ColorFormat format) {
xenos::ColorFormat format) {
switch (format) {
case ColorFormat::k_8_8_8_8:
case ColorFormat::k_2_10_10_10:
case xenos::ColorFormat::k_8_8_8_8:
case xenos::ColorFormat::k_2_10_10_10:
// TODO(Triang3l): Investigate how k_8_8_8_8_A works - not supported in the
// texture cache currently.
// case ColorFormat::k_8_8_8_8_A:
case ColorFormat::k_10_11_11:
case ColorFormat::k_11_11_10:
case ColorFormat::k_16_16:
case ColorFormat::k_16_16_FLOAT:
case ColorFormat::k_32_FLOAT:
case ColorFormat::k_8_8_8_8_AS_16_16_16_16:
case ColorFormat::k_2_10_10_10_AS_16_16_16_16:
case ColorFormat::k_10_11_11_AS_16_16_16_16:
case ColorFormat::k_11_11_10_AS_16_16_16_16:
// case xenos::ColorFormat::k_8_8_8_8_A:
case xenos::ColorFormat::k_10_11_11:
case xenos::ColorFormat::k_11_11_10:
case xenos::ColorFormat::k_16_16:
case xenos::ColorFormat::k_16_16_FLOAT:
case xenos::ColorFormat::k_32_FLOAT:
case xenos::ColorFormat::k_8_8_8_8_AS_16_16_16_16:
case xenos::ColorFormat::k_2_10_10_10_AS_16_16_16_16:
case xenos::ColorFormat::k_10_11_11_AS_16_16_16_16:
case xenos::ColorFormat::k_11_11_10_AS_16_16_16_16:
return 1;
case ColorFormat::k_16_16_16_16:
case ColorFormat::k_16_16_16_16_FLOAT:
case ColorFormat::k_32_32_FLOAT:
case xenos::ColorFormat::k_16_16_16_16:
case xenos::ColorFormat::k_16_16_16_16_FLOAT:
case xenos::ColorFormat::k_32_32_FLOAT:
return 2;
case ColorFormat::k_32_32_32_32_FLOAT:
case xenos::ColorFormat::k_32_32_32_32_FLOAT:
return 4;
default:
break;

View File

@@ -158,7 +158,7 @@ class D3D12CommandProcessor : public CommandProcessor {
// Sets the current SSAA sample positions, needs to be done before setting
// render targets or copying to depth render targets.
void SetSamplePositions(MsaaSamples sample_positions);
void SetSamplePositions(xenos::MsaaSamples sample_positions);
// Returns a pipeline state object with deferred creation by its handle. May
// return nullptr if failed to create the pipeline state object.
@@ -206,11 +206,11 @@ class D3D12CommandProcessor : public CommandProcessor {
void OnPrimaryBufferEnd() override;
Shader* LoadShader(ShaderType shader_type, uint32_t guest_address,
Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) override;
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
bool IssueDraw(xenos::PrimitiveType primitive_type, uint32_t index_count,
IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) override;
bool IssueCopy() override;
@@ -336,7 +336,7 @@ class D3D12CommandProcessor : public CommandProcessor {
void UpdateFixedFunctionState(bool primitive_two_faced);
void UpdateSystemConstantValues(
bool shared_memory_is_uav, bool primitive_two_faced,
uint32_t line_loop_closing_index, Endian index_endian,
uint32_t line_loop_closing_index, xenos::Endian index_endian,
uint32_t used_texture_mask, bool early_z, uint32_t color_mask,
const RenderTargetCache::PipelineRenderTarget render_targets[4]);
bool UpdateBindings(const D3D12Shader* vertex_shader,
@@ -348,7 +348,7 @@ class D3D12CommandProcessor : public CommandProcessor {
// for instance).
// TODO(Triang3l): Check if any game uses memexport with formats smaller than
// 32 bits per element.
static uint32_t GetSupportedMemExportFormatSize(ColorFormat format);
static uint32_t GetSupportedMemExportFormatSize(xenos::ColorFormat format);
// Returns a buffer for reading GPU data back to the CPU. Assuming
// synchronizing immediately after use. Always in COPY_DEST state.
@@ -524,7 +524,7 @@ class D3D12CommandProcessor : public CommandProcessor {
bool ff_stencil_ref_update_needed_;
// Current SSAA sample positions (to be updated by the render target cache).
MsaaSamples current_sample_positions_;
xenos::MsaaSamples current_sample_positions_;
// Currently bound pipeline, either a graphics pipeline from the pipeline
// cache (with potentially deferred creation - current_external_pipeline_ is

View File

@@ -25,7 +25,7 @@ constexpr uint32_t D3D12Shader::kMaxTextureBindings;
constexpr uint32_t D3D12Shader::kMaxSamplerBindingIndexBits;
constexpr uint32_t D3D12Shader::kMaxSamplerBindings;
D3D12Shader::D3D12Shader(ShaderType shader_type, uint64_t data_hash,
D3D12Shader::D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count) {}

View File

@@ -14,6 +14,7 @@
#include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/shader.h"
#include "xenia/gpu/xenos.h"
#include "xenia/ui/d3d12/d3d12_provider.h"
namespace xe {
@@ -22,7 +23,7 @@ namespace d3d12 {
class D3D12Shader : public Shader {
public:
D3D12Shader(ShaderType shader_type, uint64_t data_hash,
D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count);
void SetTexturesAndSamplers(
@@ -53,7 +54,7 @@ class D3D12Shader : public Shader {
uint32_t fetch_constant;
// Stacked and 3D are separate TextureBindings, even for bindless for null
// descriptor handling simplicity.
TextureDimension dimension;
xenos::FetchOpDimension dimension;
bool is_signed;
};
// Safe to hash and compare with memcmp for layout hashing.
@@ -70,10 +71,10 @@ class D3D12Shader : public Shader {
struct SamplerBinding {
uint32_t bindless_descriptor_index;
uint32_t fetch_constant;
TextureFilter mag_filter;
TextureFilter min_filter;
TextureFilter mip_filter;
AnisoFilter aniso_filter;
xenos::TextureFilter mag_filter;
xenos::TextureFilter min_filter;
xenos::TextureFilter mip_filter;
xenos::AnisoFilter aniso_filter;
};
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
count_out = uint32_t(sampler_bindings_.size());

View File

@@ -25,16 +25,16 @@ class D3D12TraceViewer : public TraceViewer {
return std::unique_ptr<gpu::GraphicsSystem>(new D3D12GraphicsSystem());
}
uintptr_t GetColorRenderTarget(uint32_t pitch, MsaaSamples samples,
uint32_t base,
ColorRenderTargetFormat format) override {
uintptr_t GetColorRenderTarget(
uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
xenos::ColorRenderTargetFormat format) override {
// TODO(Triang3l): EDRAM viewer.
return 0;
}
uintptr_t GetDepthRenderTarget(uint32_t pitch, MsaaSamples samples,
uint32_t base,
DepthRenderTargetFormat format) override {
uintptr_t GetDepthRenderTarget(
uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
xenos::DepthRenderTargetFormat format) override {
// TODO(Triang3l): EDRAM viewer.
return 0;
}

View File

@@ -715,7 +715,7 @@ bool PipelineCache::IsCreatingPipelineStates() {
return !creation_queue_.empty() || creation_threads_busy_ != 0;
}
D3D12Shader* PipelineCache::LoadShader(ShaderType shader_type,
D3D12Shader* PipelineCache::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) {
@@ -760,7 +760,7 @@ Shader::HostVertexShaderType PipelineCache::GetHostVertexShaderTypeIfValid()
xenos::TessellationMode tessellation_mode =
regs.Get<reg::VGT_HOS_CNTL>().tess_mode;
switch (vgt_draw_initiator.prim_type) {
case PrimitiveType::kTriangleList:
case xenos::PrimitiveType::kTriangleList:
// Also supported by triangle strips and fans according to:
// https://www.khronos.org/registry/OpenGL/extensions/AMD/AMD_vertex_shader_tessellator.txt
// Would need to convert those to triangle lists, but haven't seen any
@@ -779,7 +779,7 @@ Shader::HostVertexShaderType PipelineCache::GetHostVertexShaderTypeIfValid()
break;
}
break;
case PrimitiveType::kQuadList:
case xenos::PrimitiveType::kQuadList:
switch (tessellation_mode) {
// Also supported by quad strips according to:
// https://www.khronos.org/registry/OpenGL/extensions/AMD/AMD_vertex_shader_tessellator.txt
@@ -794,11 +794,11 @@ Shader::HostVertexShaderType PipelineCache::GetHostVertexShaderTypeIfValid()
break;
}
break;
case PrimitiveType::kTrianglePatch:
case xenos::PrimitiveType::kTrianglePatch:
// - Banjo-Kazooie: Nuts & Bolts - water - adaptive.
// - Halo 3 - water - adaptive.
return Shader::HostVertexShaderType::kTriangleDomainPatchIndexed;
case PrimitiveType::kQuadPatch:
case xenos::PrimitiveType::kQuadPatch:
// - Fable II - continuous.
// - Viva Pinata - garden ground - adaptive.
return Shader::HostVertexShaderType::kQuadDomainPatchIndexed;
@@ -866,7 +866,8 @@ bool PipelineCache::EnsureShadersTranslated(
bool PipelineCache::ConfigurePipeline(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
PrimitiveType primitive_type, IndexFormat index_format, bool early_z,
xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format,
bool early_z,
const RenderTargetCache::PipelineRenderTarget render_targets[5],
void** pipeline_state_handle_out,
ID3D12RootSignature** root_signature_out) {
@@ -966,7 +967,7 @@ bool PipelineCache::TranslateShader(
}
const char* host_shader_type;
if (shader->type() == ShaderType::kVertex) {
if (shader->type() == xenos::ShaderType::kVertex) {
switch (shader->host_vertex_shader_type()) {
case Shader::HostVertexShaderType::kLineDomainCPIndexed:
host_shader_type = "control-point-indexed line domain";
@@ -1128,7 +1129,7 @@ bool PipelineCache::TranslateShader(
// Create a version of the shader with early depth/stencil forced by Xenia
// itself when it's safe to do so or when EARLY_Z_ENABLE is set in
// RB_DEPTHCONTROL.
if (shader->type() == ShaderType::kPixel && !edram_rov_used_ &&
if (shader->type() == xenos::ShaderType::kPixel && !edram_rov_used_ &&
!shader->writes_depth()) {
shader->SetForcedEarlyZShaderObject(
std::move(DxbcShaderTranslator::ForceEarlyDepthStencil(
@@ -1147,7 +1148,7 @@ bool PipelineCache::TranslateShader(
// Dump shader files if desired.
if (!cvars::dump_shaders.empty()) {
shader->Dump(cvars::dump_shaders,
(shader->type() == ShaderType::kPixel)
(shader->type() == xenos::ShaderType::kPixel)
? (edram_rov_used_ ? "d3d12_rov" : "d3d12_rtv")
: "d3d12");
}
@@ -1157,7 +1158,8 @@ bool PipelineCache::TranslateShader(
bool PipelineCache::GetCurrentStateDescription(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
PrimitiveType primitive_type, IndexFormat index_format, bool early_z,
xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format,
bool early_z,
const RenderTargetCache::PipelineRenderTarget render_targets[5],
PipelineRuntimeDescription& runtime_description_out) {
PipelineDescription& description_out = runtime_description_out.description;
@@ -1187,7 +1189,7 @@ bool PipelineCache::GetCurrentStateDescription(
if (pa_su_sc_mode_cntl.multi_prim_ib_ena) {
// Not using 0xFFFF with 32-bit indices because in index buffers it will be
// 0xFFFF0000 anyway due to endianness.
description_out.strip_cut_index = index_format == IndexFormat::kInt32
description_out.strip_cut_index = index_format == xenos::IndexFormat::kInt32
? PipelineStripCutIndex::kFFFFFFFF
: PipelineStripCutIndex::kFFFF;
} else {
@@ -1203,16 +1205,16 @@ bool PipelineCache::GetCurrentStateDescription(
description_out.host_vertex_shader_type = host_vertex_shader_type;
if (host_vertex_shader_type == Shader::HostVertexShaderType::kVertex) {
switch (primitive_type) {
case PrimitiveType::kPointList:
case xenos::PrimitiveType::kPointList:
description_out.primitive_topology_type_or_tessellation_mode =
uint32_t(PipelinePrimitiveTopologyType::kPoint);
break;
case PrimitiveType::kLineList:
case PrimitiveType::kLineStrip:
case PrimitiveType::kLineLoop:
case xenos::PrimitiveType::kLineList:
case xenos::PrimitiveType::kLineStrip:
case xenos::PrimitiveType::kLineLoop:
// Quads are emulated as line lists with adjacency.
case PrimitiveType::kQuadList:
case PrimitiveType::k2DLineStrip:
case xenos::PrimitiveType::kQuadList:
case xenos::PrimitiveType::k2DLineStrip:
description_out.primitive_topology_type_or_tessellation_mode =
uint32_t(PipelinePrimitiveTopologyType::kLine);
break;
@@ -1222,14 +1224,14 @@ bool PipelineCache::GetCurrentStateDescription(
break;
}
switch (primitive_type) {
case PrimitiveType::kPointList:
case xenos::PrimitiveType::kPointList:
description_out.geometry_shader = PipelineGeometryShader::kPointList;
break;
case PrimitiveType::kRectangleList:
case xenos::PrimitiveType::kRectangleList:
description_out.geometry_shader =
PipelineGeometryShader::kRectangleList;
break;
case PrimitiveType::kQuadList:
case xenos::PrimitiveType::kQuadList:
description_out.geometry_shader = PipelineGeometryShader::kQuadList;
break;
default:
@@ -1241,7 +1243,7 @@ bool PipelineCache::GetCurrentStateDescription(
uint32_t(regs.Get<reg::VGT_HOS_CNTL>().tess_mode);
}
bool primitive_two_faced = IsPrimitiveTwoFaced(
bool primitive_two_faced = xenos::IsPrimitiveTwoFaced(
host_vertex_shader_type != Shader::HostVertexShaderType::kVertex,
primitive_type);
@@ -1332,7 +1334,7 @@ bool PipelineCache::GetCurrentStateDescription(
// (shadows - 2^17 is not enough, 2^18 hasn't been tested, but 2^19
// eliminates the acne).
if (regs.Get<reg::RB_DEPTH_INFO>().depth_format ==
DepthRenderTargetFormat::kD24FS8) {
xenos::DepthRenderTargetFormat::kD24FS8) {
poly_offset *= float(1 << 19);
} else {
poly_offset *= float(1 << 23);
@@ -1353,8 +1355,8 @@ bool PipelineCache::GetCurrentStateDescription(
}
description_out.depth_clip = !regs.Get<reg::PA_CL_CLIP_CNTL>().clip_disable;
if (edram_rov_used_) {
description_out.rov_msaa =
regs.Get<reg::RB_SURFACE_INFO>().msaa_samples != MsaaSamples::k1X;
description_out.rov_msaa = regs.Get<reg::RB_SURFACE_INFO>().msaa_samples !=
xenos::MsaaSamples::k1X;
} else {
// Depth/stencil. No stencil, always passing depth test and no depth writing
// means depth disabled.
@@ -1364,7 +1366,7 @@ bool PipelineCache::GetCurrentStateDescription(
description_out.depth_func = rb_depthcontrol.zfunc;
description_out.depth_write = rb_depthcontrol.z_write_enable;
} else {
description_out.depth_func = CompareFunction::kAlways;
description_out.depth_func = xenos::CompareFunction::kAlways;
}
if (rb_depthcontrol.stencil_enable) {
description_out.stencil_enable = 1;
@@ -1406,13 +1408,13 @@ bool PipelineCache::GetCurrentStateDescription(
}
}
// If not binding the DSV, ignore the format in the hash.
if (description_out.depth_func != CompareFunction::kAlways ||
if (description_out.depth_func != xenos::CompareFunction::kAlways ||
description_out.depth_write || description_out.stencil_enable) {
description_out.depth_format =
regs.Get<reg::RB_DEPTH_INFO>().depth_format;
}
} else {
description_out.depth_func = CompareFunction::kAlways;
description_out.depth_func = xenos::CompareFunction::kAlways;
}
if (early_z) {
description_out.force_early_z = 1;
@@ -1495,10 +1497,10 @@ bool PipelineCache::GetCurrentStateDescription(
} else {
rt.src_blend = PipelineBlendFactor::kOne;
rt.dest_blend = PipelineBlendFactor::kZero;
rt.blend_op = BlendOp::kAdd;
rt.blend_op = xenos::BlendOp::kAdd;
rt.src_blend_alpha = PipelineBlendFactor::kOne;
rt.dest_blend_alpha = PipelineBlendFactor::kZero;
rt.blend_op_alpha = BlendOp::kAdd;
rt.blend_op_alpha = xenos::BlendOp::kAdd;
}
}
}
@@ -1725,7 +1727,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12PipelineState(
if (!edram_rov_used_) {
// Depth/stencil.
if (description.depth_func != CompareFunction::kAlways ||
if (description.depth_func != xenos::CompareFunction::kAlways ||
description.depth_write) {
state_desc.DepthStencilState.DepthEnable = TRUE;
state_desc.DepthStencilState.DepthWriteMask =
@@ -1812,10 +1814,10 @@ ID3D12PipelineState* PipelineCache::CreateD3D12PipelineState(
// Call of Duty 4 - GPU performance is better when not blending.
if (rt.src_blend != PipelineBlendFactor::kOne ||
rt.dest_blend != PipelineBlendFactor::kZero ||
rt.blend_op != BlendOp::kAdd ||
rt.blend_op != xenos::BlendOp::kAdd ||
rt.src_blend_alpha != PipelineBlendFactor::kOne ||
rt.dest_blend_alpha != PipelineBlendFactor::kZero ||
rt.blend_op_alpha != BlendOp::kAdd) {
rt.blend_op_alpha != xenos::BlendOp::kAdd) {
blend_desc.BlendEnable = TRUE;
blend_desc.SrcBlend = kBlendFactorMap[uint32_t(rt.src_blend)];
blend_desc.DestBlend = kBlendFactorMap[uint32_t(rt.dest_blend)];

View File

@@ -56,7 +56,7 @@ class PipelineCache {
void EndSubmission();
bool IsCreatingPipelineStates();
D3D12Shader* LoadShader(ShaderType shader_type, uint32_t guest_address,
D3D12Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address,
const uint32_t* host_address, uint32_t dword_count);
// Returns the host vertex shader type for the current draw if it's valid and
@@ -70,7 +70,8 @@ class PipelineCache {
bool ConfigurePipeline(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
PrimitiveType primitive_type, IndexFormat index_format, bool early_z,
xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format,
bool early_z,
const RenderTargetCache::PipelineRenderTarget render_targets[5],
void** pipeline_state_handle_out,
ID3D12RootSignature** root_signature_out);
@@ -87,7 +88,7 @@ class PipelineCache {
uint64_t ucode_data_hash;
uint32_t ucode_dword_count : 16;
ShaderType type : 1;
xenos::ShaderType type : 1;
Shader::HostVertexShaderType host_vertex_shader_type : 3;
reg::SQ_PROGRAM_CNTL sq_program_cntl;
@@ -155,15 +156,15 @@ class PipelineCache {
// Update PipelineDescription::kVersion if anything is changed!
XEPACKEDSTRUCT(PipelineRenderTarget, {
uint32_t used : 1; // 1
ColorRenderTargetFormat format : 4; // 5
PipelineBlendFactor src_blend : 4; // 9
PipelineBlendFactor dest_blend : 4; // 13
BlendOp blend_op : 3; // 16
PipelineBlendFactor src_blend_alpha : 4; // 20
PipelineBlendFactor dest_blend_alpha : 4; // 24
BlendOp blend_op_alpha : 3; // 27
uint32_t write_mask : 4; // 31
uint32_t used : 1; // 1
xenos::ColorRenderTargetFormat format : 4; // 5
PipelineBlendFactor src_blend : 4; // 9
PipelineBlendFactor dest_blend : 4; // 13
xenos::BlendOp blend_op : 3; // 16
PipelineBlendFactor src_blend_alpha : 4; // 20
PipelineBlendFactor dest_blend_alpha : 4; // 24
xenos::BlendOp blend_op_alpha : 3; // 27
uint32_t write_mask : 4; // 31
});
XEPACKEDSTRUCT(PipelineDescription, {
@@ -180,28 +181,28 @@ class PipelineCache {
// xenos::TessellationMode for a domain shader.
uint32_t primitive_topology_type_or_tessellation_mode : 2; // 7
// Zero for non-kVertex host_vertex_shader_type.
PipelineGeometryShader geometry_shader : 2; // 9
uint32_t fill_mode_wireframe : 1; // 10
PipelineCullMode cull_mode : 2; // 12
uint32_t front_counter_clockwise : 1; // 13
uint32_t depth_clip : 1; // 14
uint32_t rov_msaa : 1; // 15
DepthRenderTargetFormat depth_format : 1; // 16
CompareFunction depth_func : 3; // 19
uint32_t depth_write : 1; // 20
uint32_t stencil_enable : 1; // 21
uint32_t stencil_read_mask : 8; // 29
uint32_t force_early_z : 1; // 30
PipelineGeometryShader geometry_shader : 2; // 9
uint32_t fill_mode_wireframe : 1; // 10
PipelineCullMode cull_mode : 2; // 12
uint32_t front_counter_clockwise : 1; // 13
uint32_t depth_clip : 1; // 14
uint32_t rov_msaa : 1; // 15
xenos::DepthRenderTargetFormat depth_format : 1; // 16
xenos::CompareFunction depth_func : 3; // 19
uint32_t depth_write : 1; // 20
uint32_t stencil_enable : 1; // 21
uint32_t stencil_read_mask : 8; // 29
uint32_t force_early_z : 1; // 30
uint32_t stencil_write_mask : 8; // 8
StencilOp stencil_front_fail_op : 3; // 11
StencilOp stencil_front_depth_fail_op : 3; // 14
StencilOp stencil_front_pass_op : 3; // 17
CompareFunction stencil_front_func : 3; // 20
StencilOp stencil_back_fail_op : 3; // 23
StencilOp stencil_back_depth_fail_op : 3; // 26
StencilOp stencil_back_pass_op : 3; // 29
CompareFunction stencil_back_func : 3; // 32
uint32_t stencil_write_mask : 8; // 8
xenos::StencilOp stencil_front_fail_op : 3; // 11
xenos::StencilOp stencil_front_depth_fail_op : 3; // 14
xenos::StencilOp stencil_front_pass_op : 3; // 17
xenos::CompareFunction stencil_front_func : 3; // 20
xenos::StencilOp stencil_back_fail_op : 3; // 23
xenos::StencilOp stencil_back_depth_fail_op : 3; // 26
xenos::StencilOp stencil_back_pass_op : 3; // 29
xenos::CompareFunction stencil_back_func : 3; // 32
PipelineRenderTarget render_targets[4];
@@ -228,7 +229,8 @@ class PipelineCache {
bool GetCurrentStateDescription(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
PrimitiveType primitive_type, IndexFormat index_format, bool early_z,
xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format,
bool early_z,
const RenderTargetCache::PipelineRenderTarget render_targets[5],
PipelineRuntimeDescription& runtime_description_out);

View File

@@ -173,16 +173,16 @@ void PrimitiveConverter::BeginFrame() {
memory_regions_used_ = 0;
}
PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
PrimitiveType type) {
xenos::PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
xenos::PrimitiveType type) {
switch (type) {
case PrimitiveType::kTriangleFan:
return PrimitiveType::kTriangleList;
case PrimitiveType::kLineLoop:
return PrimitiveType::kLineStrip;
case PrimitiveType::kQuadList:
case xenos::PrimitiveType::kTriangleFan:
return xenos::PrimitiveType::kTriangleList;
case xenos::PrimitiveType::kLineLoop:
return xenos::PrimitiveType::kLineStrip;
case xenos::PrimitiveType::kQuadList:
if (cvars::d3d12_convert_quads_to_triangles) {
return PrimitiveType::kTriangleList;
return xenos::PrimitiveType::kTriangleList;
}
break;
default:
@@ -192,10 +192,10 @@ PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
}
PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
PrimitiveType source_type, uint32_t address, uint32_t index_count,
IndexFormat index_format, Endian index_endianness,
xenos::PrimitiveType source_type, uint32_t address, uint32_t index_count,
xenos::IndexFormat index_format, xenos::Endian index_endianness,
D3D12_GPU_VIRTUAL_ADDRESS& gpu_address_out, uint32_t& index_count_out) {
bool index_32bit = index_format == IndexFormat::kInt32;
bool index_32bit = index_format == xenos::IndexFormat::kInt32;
auto& regs = *register_file_;
bool reset = regs.Get<reg::PA_SU_SC_MODE_CNTL>().multi_prim_ib_ena;
// Swap the reset index because we will be comparing unswapped values to it.
@@ -207,22 +207,22 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
uint32_t reset_index_host = index_32bit ? 0xFFFFFFFFu : 0xFFFFu;
// Degenerate line loops are just lines.
if (source_type == PrimitiveType::kLineLoop && index_count <= 2) {
source_type = PrimitiveType::kLineStrip;
if (source_type == xenos::PrimitiveType::kLineLoop && index_count <= 2) {
source_type = xenos::PrimitiveType::kLineStrip;
}
// Check if need to convert at all.
if (source_type == PrimitiveType::kTriangleStrip ||
source_type == PrimitiveType::kLineStrip) {
if (source_type == xenos::PrimitiveType::kTriangleStrip ||
source_type == xenos::PrimitiveType::kLineStrip) {
if (!reset || reset_index == reset_index_host) {
return ConversionResult::kConversionNotNeeded;
}
} else if (source_type == PrimitiveType::kQuadList) {
} else if (source_type == xenos::PrimitiveType::kQuadList) {
if (!cvars::d3d12_convert_quads_to_triangles) {
return ConversionResult::kConversionNotNeeded;
}
} else if (source_type != PrimitiveType::kTriangleFan &&
source_type != PrimitiveType::kLineLoop) {
} else if (source_type != xenos::PrimitiveType::kTriangleFan &&
source_type != xenos::PrimitiveType::kLineLoop) {
return ConversionResult::kConversionNotNeeded;
}
@@ -232,10 +232,10 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
// Exit early for clearly empty draws, without even reading the memory.
uint32_t index_count_min;
if (source_type == PrimitiveType::kLineStrip ||
source_type == PrimitiveType::kLineLoop) {
if (source_type == xenos::PrimitiveType::kLineStrip ||
source_type == xenos::PrimitiveType::kLineLoop) {
index_count_min = 2;
} else if (source_type == PrimitiveType::kQuadList) {
} else if (source_type == xenos::PrimitiveType::kQuadList) {
index_count_min = 4;
} else {
index_count_min = 3;
@@ -308,15 +308,16 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
// Optimization specific to primitive types - if reset index not found in the
// source index buffer, can set this to false and use a faster way of copying.
bool reset_actually_used = reset;
if (source_type == PrimitiveType::kTriangleFan) {
if (source_type == xenos::PrimitiveType::kTriangleFan) {
// Triangle fans are not supported by Direct3D 12 at all.
conversion_needed = true;
trace_writer_->WriteMemoryRead(address, index_buffer_size);
if (reset) {
uint32_t current_fan_index_count = 0;
for (uint32_t i = 0; i < index_count; ++i) {
uint32_t index =
index_format == IndexFormat::kInt32 ? source_32[i] : source_16[i];
uint32_t index = index_format == xenos::IndexFormat::kInt32
? source_32[i]
: source_16[i];
if (index == reset_index) {
current_fan_index_count = 0;
continue;
@@ -328,8 +329,8 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
} else {
converted_index_count = 3 * (index_count - 2);
}
} else if (source_type == PrimitiveType::kTriangleStrip ||
source_type == PrimitiveType::kLineStrip) {
} else if (source_type == xenos::PrimitiveType::kTriangleStrip ||
source_type == xenos::PrimitiveType::kLineStrip) {
converted_index_count = index_count;
// Check if the restart index is used at all in this buffer because reading
// vertices from a default heap is faster than from an upload heap.
@@ -348,7 +349,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
check_source = source;
uint32_t check_indices_remaining = index_count;
alignas(16) uint64_t check_result[2];
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
while (check_indices_remaining != 0 && (check_source_uintptr & 15)) {
--check_indices_remaining;
if (*(check_source_32++) == reset_index) {
@@ -402,7 +403,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
}
#else
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
for (uint32_t i = 0; i < index_count; ++i) {
if (source_32[i] == reset_index) {
conversion_needed = true;
@@ -418,15 +419,16 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
}
#endif // XE_ARCH_AMD64
} else if (source_type == PrimitiveType::kLineLoop) {
} else if (source_type == xenos::PrimitiveType::kLineLoop) {
conversion_needed = true;
trace_writer_->WriteMemoryRead(address, index_buffer_size);
if (reset) {
reset_actually_used = false;
uint32_t current_strip_index_count = 0;
for (uint32_t i = 0; i < index_count; ++i) {
uint32_t index =
index_format == IndexFormat::kInt32 ? source_32[i] : source_16[i];
uint32_t index = index_format == xenos::IndexFormat::kInt32
? source_32[i]
: source_16[i];
if (index == reset_index) {
reset_actually_used = true;
// Loop strips with more than 2 vertices.
@@ -444,7 +446,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
} else {
converted_index_count = index_count + 1;
}
} else if (source_type == PrimitiveType::kQuadList) {
} else if (source_type == xenos::PrimitiveType::kQuadList) {
conversion_needed = true;
trace_writer_->WriteMemoryRead(address, index_buffer_size);
converted_index_count = (index_count >> 2) * 6;
@@ -471,13 +473,13 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
return ConversionResult::kFailed;
}
if (source_type == PrimitiveType::kTriangleFan) {
if (source_type == xenos::PrimitiveType::kTriangleFan) {
// https://docs.microsoft.com/en-us/windows/desktop/direct3d9/triangle-fans
// Ordered as (v1, v2, v0), (v2, v3, v0).
if (reset) {
uint32_t current_fan_index_count = 0;
uint32_t current_fan_first_index = 0;
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
uint32_t* target_32 = reinterpret_cast<uint32_t*>(target);
for (uint32_t i = 0; i < index_count; ++i) {
uint32_t index = source_32[i];
@@ -513,7 +515,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
}
} else {
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
uint32_t* target_32 = reinterpret_cast<uint32_t*>(target);
for (uint32_t i = 2; i < index_count; ++i) {
*(target_32++) = source_32[i - 1];
@@ -529,8 +531,8 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
}
}
} else if (source_type == PrimitiveType::kTriangleStrip ||
source_type == PrimitiveType::kLineStrip) {
} else if (source_type == xenos::PrimitiveType::kTriangleStrip ||
source_type == xenos::PrimitiveType::kLineStrip) {
#if XE_ARCH_AMD64
// Replace the reset index with the maximum representable value - vector OR
// gives 0 or 0xFFFF/0xFFFFFFFF, which is exactly what is needed.
@@ -549,7 +551,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
target_aligned_uintptr =
reinterpret_cast<uintptr_t>(target) & ~(uintptr_t(15));
uint32_t vector_count = (address_last >> 4) - (address >> 4) + 1;
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
__m128i reset_index_vector = _mm_set1_epi32(reset_index);
for (uint32_t i = 0; i < vector_count; ++i) {
__m128i indices_vector = _mm_load_si128(source_aligned_128++);
@@ -569,7 +571,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
}
#else
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
for (uint32_t i = 0; i < index_count; ++i) {
uint32_t index = source_32[i];
reinterpret_cast<uint32_t*>(target)[i] =
@@ -583,11 +585,11 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
}
#endif // XE_ARCH_AMD64
} else if (source_type == PrimitiveType::kLineLoop) {
} else if (source_type == xenos::PrimitiveType::kLineLoop) {
if (reset_actually_used) {
uint32_t current_strip_index_count = 0;
uint32_t current_strip_first_index = 0;
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
uint32_t* target_32 = reinterpret_cast<uint32_t*>(target);
for (uint32_t i = 0; i < index_count; ++i) {
uint32_t index = source_32[i];
@@ -635,16 +637,16 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
} else {
std::memcpy(target, source, index_count * index_size);
if (converted_index_count > index_count) {
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
reinterpret_cast<uint32_t*>(target)[index_count] = source_32[0];
} else {
reinterpret_cast<uint16_t*>(target)[index_count] = source_16[0];
}
}
}
} else if (source_type == PrimitiveType::kQuadList) {
} else if (source_type == xenos::PrimitiveType::kQuadList) {
uint32_t quad_count = index_count >> 4;
if (index_format == IndexFormat::kInt32) {
if (index_format == xenos::IndexFormat::kInt32) {
uint32_t* target_32 = reinterpret_cast<uint32_t*>(target);
for (uint32_t i = 0; i < quad_count; ++i) {
uint32_t quad_index = i << 2;
@@ -680,13 +682,14 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
}
void* PrimitiveConverter::AllocateIndices(
IndexFormat format, uint32_t count, uint32_t simd_offset,
xenos::IndexFormat format, uint32_t count, uint32_t simd_offset,
D3D12_GPU_VIRTUAL_ADDRESS& gpu_address_out) {
if (count == 0) {
return nullptr;
}
uint32_t size = count * (format == IndexFormat::kInt32 ? sizeof(uint32_t)
: sizeof(uint16_t));
uint32_t size =
count * (format == xenos::IndexFormat::kInt32 ? sizeof(uint32_t)
: sizeof(uint16_t));
// 16-align all index data because SIMD is used to replace the reset index
// (without that, 4-alignment would be required anyway to mix 16-bit and
// 32-bit indices in one buffer page).
@@ -703,7 +706,7 @@ void* PrimitiveConverter::AllocateIndices(
nullptr, nullptr, &gpu_address);
if (mapping == nullptr) {
XELOGE("Failed to allocate space for {} converted {}-bit vertex indices",
count, format == IndexFormat::kInt32 ? 32 : 16);
count, format == xenos::IndexFormat::kInt32 ? 32 : 16);
return nullptr;
}
gpu_address_out = gpu_address + simd_offset;
@@ -732,18 +735,18 @@ PrimitiveConverter::MemoryInvalidationCallbackThunk(
}
D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer(
PrimitiveType source_type, uint32_t index_count,
xenos::PrimitiveType source_type, uint32_t index_count,
uint32_t& index_count_out) const {
if (index_count > kMaxNonIndexedVertices) {
assert_always();
return D3D12_GPU_VIRTUAL_ADDRESS(0);
}
if (source_type == PrimitiveType::kTriangleFan) {
if (source_type == xenos::PrimitiveType::kTriangleFan) {
index_count_out = (std::max(index_count, uint32_t(2)) - 2) * 3;
return static_ib_gpu_address_ +
kStaticIBTriangleFanOffset * sizeof(uint16_t);
}
if (source_type == PrimitiveType::kQuadList &&
if (source_type == xenos::PrimitiveType::kQuadList &&
cvars::d3d12_convert_quads_to_triangles) {
index_count_out = (index_count >> 2) * 6;
return static_ib_gpu_address_ + kStaticIBQuadOffset * sizeof(uint16_t);

View File

@@ -51,7 +51,8 @@ class PrimitiveConverter {
void BeginFrame();
// Returns the primitive type that the original type will be converted to.
static PrimitiveType GetReplacementPrimitiveType(PrimitiveType type);
static xenos::PrimitiveType GetReplacementPrimitiveType(
xenos::PrimitiveType type);
enum class ConversionResult {
// Converted to a transient buffer.
@@ -69,10 +70,10 @@ class PrimitiveConverter {
// buffer will be in the GENERIC_READ state (it's in an upload heap). Only
// writing to the outputs if returning kConverted. The restart index will be
// handled internally from the register values.
ConversionResult ConvertPrimitives(PrimitiveType source_type,
ConversionResult ConvertPrimitives(xenos::PrimitiveType source_type,
uint32_t address, uint32_t index_count,
IndexFormat index_format,
Endian index_endianness,
xenos::IndexFormat index_format,
xenos::Endian index_endianness,
D3D12_GPU_VIRTUAL_ADDRESS& gpu_address_out,
uint32_t& index_count_out);
@@ -80,7 +81,7 @@ class PrimitiveConverter {
// primitives in INDEX_BUFFER state, for non-indexed drawing. Returns 0 if
// conversion is not available (can draw natively).
D3D12_GPU_VIRTUAL_ADDRESS GetStaticIndexBuffer(
PrimitiveType source_type, uint32_t index_count,
xenos::PrimitiveType source_type, uint32_t index_count,
uint32_t& index_count_out) const;
// Callback for invalidating buffers mid-frame.
@@ -93,7 +94,7 @@ class PrimitiveConverter {
// simd_offset is source address & 15 - if SIMD is used, the source and the
// target must have the same alignment within one register. 0 is optimal when
// not using SIMD.
void* AllocateIndices(IndexFormat format, uint32_t count,
void* AllocateIndices(xenos::IndexFormat format, uint32_t count,
uint32_t simd_offset,
D3D12_GPU_VIRTUAL_ADDRESS& gpu_address_out);
@@ -135,8 +136,8 @@ class PrimitiveConverter {
uint64_t value;
struct {
uint32_t address; // 32
PrimitiveType source_type : 6; // 38
IndexFormat format : 1; // 39
xenos::PrimitiveType source_type : 6; // 38
xenos::IndexFormat format : 1; // 39
uint32_t count : 16; // 55
uint32_t reset : 1; // 56
};

View File

@@ -579,9 +579,9 @@ bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
return false;
}
uint32_t msaa_samples_x =
rb_surface_info.msaa_samples >= MsaaSamples::k4X ? 2 : 1;
rb_surface_info.msaa_samples >= xenos::MsaaSamples::k4X ? 2 : 1;
uint32_t msaa_samples_y =
rb_surface_info.msaa_samples >= MsaaSamples::k2X ? 2 : 1;
rb_surface_info.msaa_samples >= xenos::MsaaSamples::k2X ? 2 : 1;
// Extract color/depth info in an unified way.
bool enabled[5];
@@ -596,7 +596,7 @@ bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
edram_bases[i] = std::min(color_info.color_base, 2048u);
formats[i] = uint32_t(GetBaseColorFormat(color_info.color_format));
formats_are_64bpp[i] =
IsColorFormat64bpp(ColorRenderTargetFormat(formats[i]));
IsColorFormat64bpp(xenos::ColorRenderTargetFormat(formats[i]));
}
auto rb_depthcontrol = regs.Get<reg::RB_DEPTHCONTROL>();
auto rb_depth_info = regs.Get<reg::RB_DEPTH_INFO>();
@@ -968,7 +968,7 @@ bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
render_target->state = D3D12_RESOURCE_STATE_RENDER_TARGET;
current_pipeline_render_targets_[rtv_count].guest_render_target = i;
current_pipeline_render_targets_[rtv_count].format =
GetColorDXGIFormat(ColorRenderTargetFormat(formats[i]));
GetColorDXGIFormat(xenos::ColorRenderTargetFormat(formats[i]));
++rtv_count;
}
for (uint32_t i = rtv_count; i < 4; ++i) {
@@ -985,7 +985,7 @@ bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
D3D12_RESOURCE_STATE_DEPTH_WRITE);
depth_render_target->state = D3D12_RESOURCE_STATE_DEPTH_WRITE;
current_pipeline_render_targets_[4].format =
GetDepthDXGIFormat(DepthRenderTargetFormat(formats[4]));
GetDepthDXGIFormat(xenos::DepthRenderTargetFormat(formats[4]));
} else {
current_pipeline_render_targets_[4].format = DXGI_FORMAT_UNKNOWN;
}
@@ -1094,7 +1094,7 @@ bool RenderTargetCache::Resolve(SharedMemory* shared_memory,
const auto& fetch = regs.Get<xenos::xe_gpu_vertex_fetch_t>(
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0);
assert_true(fetch.type == xenos::FetchConstantType::kVertex);
assert_true(fetch.endian == Endian::k8in32);
assert_true(fetch.endian == xenos::Endian::k8in32);
assert_true(fetch.size == 6);
trace_writer_->WriteMemoryRead(fetch.address << 2, fetch.size << 2);
const uint8_t* src_vertex_address =
@@ -1106,7 +1106,7 @@ bool RenderTargetCache::Resolve(SharedMemory* shared_memory,
for (uint32_t i = 0; i < 6; ++i) {
vertices[i] =
xenos::GpuSwap(xe::load<float>(src_vertex_address + i * sizeof(float)),
Endian(fetch.endian)) +
xenos::Endian(fetch.endian)) +
vertex_offset;
}
// Xenos only supports rectangle copies (luckily).
@@ -1175,7 +1175,7 @@ bool RenderTargetCache::Resolve(SharedMemory* shared_memory,
"at {}",
rect.left, rect.top, rect.right, rect.bottom, surface_index,
surface_pitch, 1 << uint32_t(rb_surface_info.msaa_samples),
rb_surface_info.msaa_samples != MsaaSamples::k1X ? "s" : "",
rb_surface_info.msaa_samples != xenos::MsaaSamples::k1X ? "s" : "",
surface_format, surface_edram_base);
if (rect.left >= rect.right || rect.top >= rect.bottom) {
@@ -1211,8 +1211,9 @@ bool RenderTargetCache::Resolve(SharedMemory* shared_memory,
bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
TextureCache* texture_cache,
uint32_t edram_base, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth,
uint32_t src_format, const D3D12_RECT& rect,
xenos::MsaaSamples msaa_samples,
bool is_depth, uint32_t src_format,
const D3D12_RECT& rect,
uint32_t& written_address_out,
uint32_t& written_length_out) {
written_address_out = written_length_out = 0;
@@ -1231,35 +1232,35 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
// Get format info.
auto rb_copy_dest_info = regs.Get<reg::RB_COPY_DEST_INFO>();
TextureFormat src_texture_format;
xenos::TextureFormat src_texture_format;
bool src_64bpp;
if (is_depth) {
src_texture_format =
DepthRenderTargetToTextureFormat(DepthRenderTargetFormat(src_format));
src_texture_format = DepthRenderTargetToTextureFormat(
xenos::DepthRenderTargetFormat(src_format));
src_64bpp = false;
} else {
// Force k_16_16 and k_16_16_16_16 RTs to be always resolved via drawing,
// because resolving to a k_16_16 or a k_16_16_16_16 texture should result
// in unsigned texture data, unlike the render target which is signed.
if (ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16) {
src_texture_format = TextureFormat::k_16_16_EDRAM;
} else if (ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16_16_16) {
src_texture_format = TextureFormat::k_16_16_16_16_EDRAM;
if (xenos::ColorRenderTargetFormat(src_format) ==
xenos::ColorRenderTargetFormat::k_16_16) {
src_texture_format = xenos::TextureFormat::k_16_16_EDRAM;
} else if (xenos::ColorRenderTargetFormat(src_format) ==
xenos::ColorRenderTargetFormat::k_16_16_16_16) {
src_texture_format = xenos::TextureFormat::k_16_16_16_16_EDRAM;
} else {
src_texture_format = GetBaseFormat(ColorRenderTargetToTextureFormat(
ColorRenderTargetFormat(src_format)));
xenos::ColorRenderTargetFormat(src_format)));
}
src_64bpp = IsColorFormat64bpp(ColorRenderTargetFormat(src_format));
src_64bpp = IsColorFormat64bpp(xenos::ColorRenderTargetFormat(src_format));
}
assert_true(src_texture_format != TextureFormat::kUnknown);
assert_true(src_texture_format != xenos::TextureFormat::kUnknown);
// The destination format is specified as k_8_8_8_8 when resolving depth, but
// no format conversion is done for depth, so ignore it.
TextureFormat dest_format =
is_depth
? src_texture_format
: GetBaseFormat(TextureFormat(rb_copy_dest_info.copy_dest_format));
xenos::TextureFormat dest_format =
is_depth ? src_texture_format
: GetBaseFormat(
xenos::TextureFormat(rb_copy_dest_info.copy_dest_format));
const FormatInfo* dest_format_info = FormatInfo::Get(dest_format);
// Get the destination region and clamp the source region to it.
@@ -1328,10 +1329,10 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
dest_exp_bias = 0;
} else {
dest_exp_bias = rb_copy_dest_info.copy_dest_exp_bias;
if (ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16 ||
ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16_16_16) {
if (xenos::ColorRenderTargetFormat(src_format) ==
xenos::ColorRenderTargetFormat::k_16_16 ||
xenos::ColorRenderTargetFormat(src_format) ==
xenos::ColorRenderTargetFormat::k_16_16_16_16) {
// On the Xbox 360, k_16_16_EDRAM and k_16_16_16_16_EDRAM internally have
// -32...32 range, but they're emulated using normalized RG16/RGBA16, so
// sampling the host render target gives 1/32 of what is actually stored
@@ -1505,9 +1506,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
edram_base | (resolution_scale_log2 << 13) |
(resolution_scale_edge_clamp ? (1 << 14) : 0) |
(is_depth ? (1 << 15) : 0) | (surface_pitch_tiles << 16);
if (msaa_samples >= MsaaSamples::k2X) {
if (msaa_samples >= xenos::MsaaSamples::k2X) {
root_constants.base_samples_2x_depth_pitch |= 1 << 11;
if (msaa_samples >= MsaaSamples::k4X) {
if (msaa_samples >= xenos::MsaaSamples::k4X) {
root_constants.base_samples_2x_depth_pitch |= 1 << 12;
}
}
@@ -1520,9 +1521,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
command_processor_->SubmitBarriers();
// 1 group per destination 80x16 region.
uint32_t group_count_x = row_width_ss_div_80, group_count_y = rows;
if (msaa_samples >= MsaaSamples::k2X) {
if (msaa_samples >= xenos::MsaaSamples::k2X) {
group_count_y = (group_count_y + 1) >> 1;
if (msaa_samples >= MsaaSamples::k4X) {
if (msaa_samples >= xenos::MsaaSamples::k4X) {
group_count_x = (group_count_x + 1) >> 1;
}
}
@@ -1648,9 +1649,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
load_root_constants.base_samples_2x_depth_pitch =
edram_base | (resolution_scale_log2 << 13) |
(surface_pitch_tiles << 16);
if (msaa_samples >= MsaaSamples::k2X) {
if (msaa_samples >= xenos::MsaaSamples::k2X) {
load_root_constants.base_samples_2x_depth_pitch |= 1 << 11;
if (msaa_samples >= MsaaSamples::k4X) {
if (msaa_samples >= xenos::MsaaSamples::k4X) {
load_root_constants.base_samples_2x_depth_pitch |= 1 << 12;
}
}
@@ -1713,8 +1714,8 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
command_list->D3DSetGraphicsRootSignature(resolve_root_signature_);
ResolveRootConstants resolve_root_constants;
uint32_t samples_x_log2 = msaa_samples >= MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= MsaaSamples::k2X ? 1 : 0;
uint32_t samples_x_log2 = msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= xenos::MsaaSamples::k2X ? 1 : 0;
resolve_root_constants.rect_samples_lw =
(copy_rect.left << (samples_x_log2 + resolution_scale_log2)) |
(copy_width << (16 + samples_x_log2 + resolution_scale_log2));
@@ -1728,10 +1729,10 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
samples_y_log2 | (samples_x_log2 << 1) |
(resolution_scale_edge_clamp ? (1 << 6) : 0) |
((uint32_t(dest_exp_bias) & 0x3F) << 7);
if (msaa_samples == MsaaSamples::k1X) {
if (msaa_samples == xenos::MsaaSamples::k1X) {
// No offset.
resolve_root_constants.resolve_info |= (1 << 2) | (1 << 4);
} else if (msaa_samples == MsaaSamples::k2X) {
} else if (msaa_samples == xenos::MsaaSamples::k2X) {
// -0.5 or +0.5 samples vertical offset if getting only one sample.
if (sample_select == xenos::CopySampleSelect::k0) {
resolve_root_constants.resolve_info |= (0 << 2) | (1 << 4);
@@ -1772,26 +1773,26 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
D3D12_SHADER_RESOURCE_VIEW_DESC rt_srv_desc;
rt_srv_desc.Format =
GetColorDXGIFormat(ColorRenderTargetFormat(src_format));
GetColorDXGIFormat(xenos::ColorRenderTargetFormat(src_format));
rt_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
UINT swizzle = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if (dest_swap) {
switch (ColorRenderTargetFormat(src_format)) {
case ColorRenderTargetFormat::k_8_8_8_8:
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
case ColorRenderTargetFormat::k_2_10_10_10:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_16_16_16_16:
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
case ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
switch (xenos::ColorRenderTargetFormat(src_format)) {
case xenos::ColorRenderTargetFormat::k_8_8_8_8:
case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
case xenos::ColorRenderTargetFormat::k_2_10_10_10:
case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case xenos::ColorRenderTargetFormat::k_16_16_16_16:
case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
swizzle = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(2, 1, 0, 3);
break;
default:
break;
}
}
if (dest_format == TextureFormat::k_6_5_5) {
if (dest_format == xenos::TextureFormat::k_6_5_5) {
// Green bits of the resolve target used for blue, and blue bits used for
// green.
swizzle = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
@@ -1810,7 +1811,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
command_list->D3DSetGraphicsRootDescriptorTable(1, descriptor_rt.second);
command_processor_->SubmitBarriers();
command_processor_->SetSamplePositions(MsaaSamples::k1X);
command_processor_->SetSamplePositions(xenos::MsaaSamples::k1X);
command_processor_->SetExternalGraphicsPipeline(resolve_pipeline);
command_list->D3DOMSetRenderTargets(1, &resolve_target->rtv_handle, TRUE,
nullptr);
@@ -1881,8 +1882,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
bool RenderTargetCache::ResolveClear(uint32_t edram_base,
uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth,
uint32_t format, const D3D12_RECT& rect) {
xenos::MsaaSamples msaa_samples,
bool is_depth, uint32_t format,
const D3D12_RECT& rect) {
auto& regs = *register_file_;
// Check if clearing is enabled.
@@ -1902,7 +1904,7 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
// Calculate the layout.
bool is_64bpp =
!is_depth && IsColorFormat64bpp(ColorRenderTargetFormat(format));
!is_depth && IsColorFormat64bpp(xenos::ColorRenderTargetFormat(format));
D3D12_RECT clear_rect = rect;
uint32_t surface_pitch_tiles, row_width_ss_div_80, rows;
if (!GetEDRAMLayout(surface_pitch, msaa_samples, is_64bpp, edram_base,
@@ -1911,8 +1913,8 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
// Nothing to clear.
return true;
}
uint32_t samples_x_log2 = msaa_samples >= MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= MsaaSamples::k2X ? 1 : 0;
uint32_t samples_x_log2 = msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= xenos::MsaaSamples::k2X ? 1 : 0;
// Get transient data needed for clearing.
ui::d3d12::util::DescriptorCPUGPUHandlePair descriptor_edram;
@@ -1941,7 +1943,8 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
(surface_pitch_tiles << 16);
// When ROV is used, there's no 32-bit depth buffer.
if (!edram_rov_used_ && is_depth &&
DepthRenderTargetFormat(format) == DepthRenderTargetFormat::kD24FS8) {
xenos::DepthRenderTargetFormat(format) ==
xenos::DepthRenderTargetFormat::kD24FS8) {
root_constants.clear_depth24 = regs[XE_GPU_REG_RB_DEPTH_CLEAR].u32;
// 20e4 [0,2), based on CFloat24 from d3dref9.dll and on 6e4 in DirectXTex.
uint32_t depth24 = root_constants.clear_depth24 >> 8;
@@ -2222,42 +2225,42 @@ void RenderTargetCache::WriteEDRAMRawUAVDescriptor(
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
}
ColorRenderTargetFormat RenderTargetCache::GetBaseColorFormat(
ColorRenderTargetFormat format) {
xenos::ColorRenderTargetFormat RenderTargetCache::GetBaseColorFormat(
xenos::ColorRenderTargetFormat format) {
switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return ColorRenderTargetFormat::k_8_8_8_8;
case ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
return ColorRenderTargetFormat::k_2_10_10_10;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return ColorRenderTargetFormat::k_2_10_10_10_FLOAT;
case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return xenos::ColorRenderTargetFormat::k_8_8_8_8;
case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
return xenos::ColorRenderTargetFormat::k_2_10_10_10;
case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT;
default:
return format;
}
}
DXGI_FORMAT RenderTargetCache::GetColorDXGIFormat(
ColorRenderTargetFormat format) {
xenos::ColorRenderTargetFormat format) {
switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8:
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
case xenos::ColorRenderTargetFormat::k_8_8_8_8:
case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case ColorRenderTargetFormat::k_2_10_10_10:
case ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
case xenos::ColorRenderTargetFormat::k_2_10_10_10:
case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
return DXGI_FORMAT_R10G10B10A2_UNORM;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
case ColorRenderTargetFormat::k_16_16:
case xenos::ColorRenderTargetFormat::k_16_16:
return DXGI_FORMAT_R16G16_SNORM;
case ColorRenderTargetFormat::k_16_16_16_16:
case xenos::ColorRenderTargetFormat::k_16_16_16_16:
return DXGI_FORMAT_R16G16B16A16_SNORM;
case ColorRenderTargetFormat::k_16_16_FLOAT:
case xenos::ColorRenderTargetFormat::k_16_16_FLOAT:
return DXGI_FORMAT_R16G16_FLOAT;
case ColorRenderTargetFormat::k_32_FLOAT:
case xenos::ColorRenderTargetFormat::k_32_FLOAT:
return DXGI_FORMAT_R32_FLOAT;
case ColorRenderTargetFormat::k_32_32_FLOAT:
case xenos::ColorRenderTargetFormat::k_32_32_FLOAT:
return DXGI_FORMAT_R32G32_FLOAT;
default:
break;
@@ -2412,7 +2415,7 @@ void RenderTargetCache::CommitEDRAMBufferUAVWrites(bool force) {
void RenderTargetCache::ClearBindings() {
current_surface_pitch_ = 0;
current_msaa_samples_ = MsaaSamples::k1X;
current_msaa_samples_ = xenos::MsaaSamples::k1X;
current_edram_max_rows_ = 0;
std::memset(current_bindings_, 0, sizeof(current_bindings_));
apply_to_command_list_ = true;
@@ -2481,8 +2484,9 @@ bool RenderTargetCache::GetResourceDesc(RenderTargetKey key,
return false;
}
DXGI_FORMAT dxgi_format =
key.is_depth ? GetDepthDXGIFormat(DepthRenderTargetFormat(key.format))
: GetColorDXGIFormat(ColorRenderTargetFormat(key.format));
key.is_depth
? GetDepthDXGIFormat(xenos::DepthRenderTargetFormat(key.format))
: GetColorDXGIFormat(xenos::ColorRenderTargetFormat(key.format));
if (dxgi_format == DXGI_FORMAT_UNKNOWN) {
return false;
}
@@ -2651,7 +2655,7 @@ RenderTargetCache::RenderTarget* RenderTargetCache::FindOrCreateRenderTarget(
}
bool RenderTargetCache::GetEDRAMLayout(
uint32_t pitch_pixels, MsaaSamples msaa_samples, bool is_64bpp,
uint32_t pitch_pixels, xenos::MsaaSamples msaa_samples, bool is_64bpp,
uint32_t& base_in_out, D3D12_RECT& rect_in_out, uint32_t& pitch_tiles_out,
uint32_t& row_width_ss_div_80_out, uint32_t& rows_out) {
if (pitch_pixels == 0 || rect_in_out.right <= 0 || rect_in_out.bottom <= 0 ||
@@ -2667,8 +2671,8 @@ bool RenderTargetCache::GetEDRAMLayout(
return false;
}
uint32_t samples_x_log2 = msaa_samples >= MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= MsaaSamples::k2X ? 1 : 0;
uint32_t samples_x_log2 = msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= xenos::MsaaSamples::k2X ? 1 : 0;
uint32_t sample_size_log2 = is_64bpp ? 1 : 0;
uint32_t pitch_tiles = (((pitch_pixels << samples_x_log2) + 79) / 80)
@@ -2711,14 +2715,16 @@ bool RenderTargetCache::GetEDRAMLayout(
RenderTargetCache::EDRAMLoadStoreMode RenderTargetCache::GetLoadStoreMode(
bool is_depth, uint32_t format) {
if (is_depth) {
return DepthRenderTargetFormat(format) == DepthRenderTargetFormat::kD24FS8
return xenos::DepthRenderTargetFormat(format) ==
xenos::DepthRenderTargetFormat::kD24FS8
? EDRAMLoadStoreMode::kDepthFloat
: EDRAMLoadStoreMode::kDepthUnorm;
}
ColorRenderTargetFormat color_format = ColorRenderTargetFormat(format);
if (color_format == ColorRenderTargetFormat::k_2_10_10_10_FLOAT ||
xenos::ColorRenderTargetFormat color_format =
xenos::ColorRenderTargetFormat(format);
if (color_format == xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT ||
color_format ==
ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16) {
xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16) {
return EDRAMLoadStoreMode::kColor7e3;
}
return IsColorFormat64bpp(color_format) ? EDRAMLoadStoreMode::kColor64bpp
@@ -2824,7 +2830,7 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
// Calculate the dispatch width.
uint32_t surface_pitch_ss =
current_surface_pitch_ *
(current_msaa_samples_ >= MsaaSamples::k4X ? 2 : 1);
(current_msaa_samples_ >= xenos::MsaaSamples::k4X ? 2 : 1);
uint32_t surface_pitch_tiles = (surface_pitch_ss + 79) / 80;
assert_true(surface_pitch_tiles != 0);
@@ -2854,7 +2860,7 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
uint32_t rt_pitch_tiles = surface_pitch_tiles;
if (!render_target->key.is_depth &&
IsColorFormat64bpp(
ColorRenderTargetFormat(render_target->key.format))) {
xenos::ColorRenderTargetFormat(render_target->key.format))) {
rt_pitch_tiles *= 2;
}
// TODO(Triang3l): log2(sample count, resolution scale).
@@ -2975,7 +2981,7 @@ void RenderTargetCache::LoadRenderTargetsFromEDRAM(
uint32_t edram_pitch_tiles = render_target->key.width_ss_div_80;
if (!render_target->key.is_depth &&
IsColorFormat64bpp(
ColorRenderTargetFormat(render_target->key.format))) {
xenos::ColorRenderTargetFormat(render_target->key.format))) {
edram_pitch_tiles *= 2;
}
// Clamp the height if somehow requested a render target that is too large.

View File

@@ -290,20 +290,21 @@ class RenderTargetCache {
// Totally necessary to rely on the base format - Too Human switches between
// 2_10_10_10_FLOAT and 2_10_10_10_FLOAT_AS_16_16_16_16 every draw.
static ColorRenderTargetFormat GetBaseColorFormat(
ColorRenderTargetFormat format);
static inline bool IsColorFormat64bpp(ColorRenderTargetFormat format) {
return format == ColorRenderTargetFormat::k_16_16_16_16 ||
format == ColorRenderTargetFormat::k_16_16_16_16_FLOAT ||
format == ColorRenderTargetFormat::k_32_32_FLOAT;
static xenos::ColorRenderTargetFormat GetBaseColorFormat(
xenos::ColorRenderTargetFormat format);
static inline bool IsColorFormat64bpp(xenos::ColorRenderTargetFormat format) {
return format == xenos::ColorRenderTargetFormat::k_16_16_16_16 ||
format == xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT ||
format == xenos::ColorRenderTargetFormat::k_32_32_FLOAT;
}
static DXGI_FORMAT GetColorDXGIFormat(ColorRenderTargetFormat format);
static DXGI_FORMAT GetColorDXGIFormat(xenos::ColorRenderTargetFormat format);
// Nvidia may have higher performance with 24-bit depth, AMD should have no
// performance difference, but with EDRAM loads/stores less conversion should
// be performed by the shaders if D24S8 is emulated as D24_UNORM_S8_UINT, and
// it's probably more accurate.
static inline DXGI_FORMAT GetDepthDXGIFormat(DepthRenderTargetFormat format) {
return format == DepthRenderTargetFormat::kD24FS8
static inline DXGI_FORMAT GetDepthDXGIFormat(
xenos::DepthRenderTargetFormat format) {
return format == xenos::DepthRenderTargetFormat::kD24FS8
? DXGI_FORMAT_D32_FLOAT_S8X24_UINT
: DXGI_FORMAT_D24_UNORM_S8_UINT;
}
@@ -396,8 +397,8 @@ class RenderTargetCache {
uint32_t edram_dirty_rows;
union {
uint32_t format;
ColorRenderTargetFormat color_format;
DepthRenderTargetFormat depth_format;
xenos::ColorRenderTargetFormat color_format;
xenos::DepthRenderTargetFormat depth_format;
};
RenderTarget* render_target;
};
@@ -472,9 +473,10 @@ class RenderTargetCache {
// rectangle is within the bounds of EDRAM and is not empty, but if it returns
// false, the output values may not be written, so the return value must be
// checked.
static bool GetEDRAMLayout(uint32_t pitch_pixels, MsaaSamples msaa_samples,
bool is_64bpp, uint32_t& base_in_out,
D3D12_RECT& rect_in_out, uint32_t& pitch_tiles_out,
static bool GetEDRAMLayout(uint32_t pitch_pixels,
xenos::MsaaSamples msaa_samples, bool is_64bpp,
uint32_t& base_in_out, D3D12_RECT& rect_in_out,
uint32_t& pitch_tiles_out,
uint32_t& row_width_ss_div_80_out,
uint32_t& rows_out);
@@ -493,13 +495,13 @@ class RenderTargetCache {
// Performs the copying part of a resolve.
bool ResolveCopy(SharedMemory* shared_memory, TextureCache* texture_cache,
uint32_t edram_base, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth, uint32_t src_format,
const D3D12_RECT& rect, uint32_t& written_address_out,
uint32_t& written_length_out);
xenos::MsaaSamples msaa_samples, bool is_depth,
uint32_t src_format, const D3D12_RECT& rect,
uint32_t& written_address_out, uint32_t& written_length_out);
// Performs the clearing part of a resolve.
bool ResolveClear(uint32_t edram_base, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth, uint32_t format,
const D3D12_RECT& rect);
xenos::MsaaSamples msaa_samples, bool is_depth,
uint32_t format, const D3D12_RECT& rect);
ID3D12PipelineState* GetResolvePipeline(DXGI_FORMAT dest_format);
// Returns any available resolve target placed at least at
@@ -646,7 +648,7 @@ class RenderTargetCache {
std::unordered_multimap<uint32_t, RenderTarget*> render_targets_;
uint32_t current_surface_pitch_ = 0;
MsaaSamples current_msaa_samples_ = MsaaSamples::k1X;
xenos::MsaaSamples current_msaa_samples_ = xenos::MsaaSamples::k1X;
// current_edram_max_rows_ is for RTV/DSV only (render target texture size).
uint32_t current_edram_max_rows_ = 0;
RenderTargetBinding current_bindings_[5] = {};

View File

@@ -1362,7 +1362,7 @@ void TextureCache::EndFrame() {
XELOGE("Unsupported texture formats used in the frame:");
unsupported_header_written = true;
}
XELOGE("* {}{}{}{}", FormatInfo::Get(TextureFormat(i))->name,
XELOGE("* {}{}{}{}", FormatInfo::Get(xenos::TextureFormat(i))->name,
unsupported_features & kUnsupportedResourceBit ? " resource" : "",
unsupported_features & kUnsupportedUnormBit ? " unorm" : "",
unsupported_features & kUnsupportedSnormBit ? " snorm" : "");
@@ -1595,15 +1595,16 @@ void TextureCache::WriteActiveTextureBindfulSRV(
} else {
NullSRVDescriptorIndex null_descriptor_index;
switch (host_shader_binding.dimension) {
case TextureDimension::k3D:
case xenos::FetchOpDimension::k3DOrStacked:
null_descriptor_index = NullSRVDescriptorIndex::k3D;
break;
case TextureDimension::kCube:
case xenos::FetchOpDimension::kCube:
null_descriptor_index = NullSRVDescriptorIndex::kCube;
break;
default:
assert_true(host_shader_binding.dimension == TextureDimension::k1D ||
host_shader_binding.dimension == TextureDimension::k2D);
assert_true(
host_shader_binding.dimension == xenos::FetchOpDimension::k1D ||
host_shader_binding.dimension == xenos::FetchOpDimension::k2D);
null_descriptor_index = NullSRVDescriptorIndex::k2DArray;
}
source_handle = provider->OffsetViewDescriptor(
@@ -1637,17 +1638,18 @@ uint32_t TextureCache::GetActiveTextureBindlessSRVIndex(
}
if (descriptor_index == UINT32_MAX) {
switch (host_shader_binding.dimension) {
case TextureDimension::k3D:
case xenos::FetchOpDimension::k3DOrStacked:
descriptor_index =
uint32_t(D3D12CommandProcessor::SystemBindlessView::kNullTexture3D);
break;
case TextureDimension::kCube:
case xenos::FetchOpDimension::kCube:
descriptor_index = uint32_t(
D3D12CommandProcessor::SystemBindlessView::kNullTextureCube);
break;
default:
assert_true(host_shader_binding.dimension == TextureDimension::k1D ||
host_shader_binding.dimension == TextureDimension::k2D);
assert_true(
host_shader_binding.dimension == xenos::FetchOpDimension::k1D ||
host_shader_binding.dimension == xenos::FetchOpDimension::k2D);
descriptor_index = uint32_t(
D3D12CommandProcessor::SystemBindlessView::kNullTexture2DArray);
}
@@ -1674,31 +1676,32 @@ TextureCache::SamplerParameters TextureCache::GetSamplerParameters(
nullptr, binding.mip_filter);
parameters.mip_min_level = mip_min_level;
AnisoFilter aniso_filter = binding.aniso_filter == AnisoFilter::kUseFetchConst
? fetch.aniso_filter
: binding.aniso_filter;
aniso_filter = std::min(aniso_filter, AnisoFilter::kMax_16_1);
xenos::AnisoFilter aniso_filter =
binding.aniso_filter == xenos::AnisoFilter::kUseFetchConst
? fetch.aniso_filter
: binding.aniso_filter;
aniso_filter = std::min(aniso_filter, xenos::AnisoFilter::kMax_16_1);
parameters.aniso_filter = aniso_filter;
if (aniso_filter != AnisoFilter::kDisabled) {
if (aniso_filter != xenos::AnisoFilter::kDisabled) {
parameters.mag_linear = 1;
parameters.min_linear = 1;
parameters.mip_linear = 1;
} else {
TextureFilter mag_filter =
binding.mag_filter == TextureFilter::kUseFetchConst
xenos::TextureFilter mag_filter =
binding.mag_filter == xenos::TextureFilter::kUseFetchConst
? fetch.mag_filter
: binding.mag_filter;
parameters.mag_linear = mag_filter == TextureFilter::kLinear;
TextureFilter min_filter =
binding.min_filter == TextureFilter::kUseFetchConst
parameters.mag_linear = mag_filter == xenos::TextureFilter::kLinear;
xenos::TextureFilter min_filter =
binding.min_filter == xenos::TextureFilter::kUseFetchConst
? fetch.min_filter
: binding.min_filter;
parameters.min_linear = min_filter == TextureFilter::kLinear;
TextureFilter mip_filter =
binding.mip_filter == TextureFilter::kUseFetchConst
parameters.min_linear = min_filter == xenos::TextureFilter::kLinear;
xenos::TextureFilter mip_filter =
binding.mip_filter == xenos::TextureFilter::kUseFetchConst
? fetch.mip_filter
: binding.mip_filter;
parameters.mip_linear = mip_filter == TextureFilter::kLinear;
parameters.mip_linear = mip_filter == xenos::TextureFilter::kLinear;
}
return parameters;
@@ -1707,7 +1710,7 @@ TextureCache::SamplerParameters TextureCache::GetSamplerParameters(
void TextureCache::WriteSampler(SamplerParameters parameters,
D3D12_CPU_DESCRIPTOR_HANDLE handle) const {
D3D12_SAMPLER_DESC desc;
if (parameters.aniso_filter != AnisoFilter::kDisabled) {
if (parameters.aniso_filter != xenos::AnisoFilter::kDisabled) {
desc.Filter = D3D12_FILTER_ANISOTROPIC;
desc.MaxAnisotropy = 1u << (uint32_t(parameters.aniso_filter) - 1);
} else {
@@ -1747,7 +1750,7 @@ void TextureCache::WriteSampler(SamplerParameters parameters,
desc.MipLODBias = 0.0f;
desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
// TODO(Triang3l): Border colors k_ACBYCR_BLACK and k_ACBCRY_BLACK.
if (parameters.border_color == BorderColor::k_AGBR_White) {
if (parameters.border_color == xenos::BorderColor::k_AGBR_White) {
desc.BorderColor[0] = 1.0f;
desc.BorderColor[1] = 1.0f;
desc.BorderColor[2] = 1.0f;
@@ -1799,10 +1802,10 @@ void TextureCache::MarkRangeAsResolved(uint32_t start_unscaled,
}
bool TextureCache::TileResolvedTexture(
TextureFormat format, uint32_t texture_base, uint32_t texture_pitch,
xenos::TextureFormat format, uint32_t texture_base, uint32_t texture_pitch,
uint32_t texture_height, bool is_3d, uint32_t offset_x, uint32_t offset_y,
uint32_t offset_z, uint32_t resolve_width, uint32_t resolve_height,
Endian128 endian, ID3D12Resource* buffer, uint32_t buffer_size,
xenos::Endian128 endian, ID3D12Resource* buffer, uint32_t buffer_size,
const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint,
uint32_t* written_address_out, uint32_t* written_length_out) {
if (written_address_out) {
@@ -2085,14 +2088,16 @@ void TextureCache::CreateScaledResolveBufferRawUAV(
}
ID3D12Resource* TextureCache::RequestSwapTexture(
D3D12_SHADER_RESOURCE_VIEW_DESC& srv_desc_out, TextureFormat& format_out) {
D3D12_SHADER_RESOURCE_VIEW_DESC& srv_desc_out,
xenos::TextureFormat& format_out) {
auto& regs = *register_file_;
const auto& fetch = regs.Get<xenos::xe_gpu_texture_fetch_t>(
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0);
TextureKey key;
uint32_t swizzle;
BindingInfoFromFetchConstant(fetch, key, &swizzle, nullptr);
if (key.base_page == 0 || key.dimension != Dimension::k2D) {
if (key.base_page == 0 ||
key.dimension != xenos::DataDimension::k2DOrStacked) {
return nullptr;
}
Texture* texture = FindOrCreateTexture(key);
@@ -2120,8 +2125,8 @@ ID3D12Resource* TextureCache::RequestSwapTexture(
return texture->resource;
}
bool TextureCache::IsDecompressionNeeded(TextureFormat format, uint32_t width,
uint32_t height) {
bool TextureCache::IsDecompressionNeeded(xenos::TextureFormat format,
uint32_t width, uint32_t height) {
DXGI_FORMAT dxgi_format_uncompressed =
host_formats_[uint32_t(format)].dxgi_format_uncompressed;
if (dxgi_format_uncompressed == DXGI_FORMAT_UNKNOWN) {
@@ -2154,7 +2159,8 @@ void TextureCache::BindingInfoFromFetchConstant(
(xenos::XE_GPU_SWIZZLE_0 << 6) | (xenos::XE_GPU_SWIZZLE_0 << 9);
}
if (swizzled_signs_out != nullptr) {
*swizzled_signs_out = uint8_t(TextureSign::kUnsigned) * uint8_t(0b01010101);
*swizzled_signs_out =
uint8_t(xenos::TextureSign::kUnsigned) * uint8_t(0b01010101);
}
switch (fetch.type) {
@@ -2190,7 +2196,7 @@ void TextureCache::BindingInfoFromFetchConstant(
// No texture data at all.
return;
}
if (fetch.dimension == Dimension::k1D && width > 8192) {
if (fetch.dimension == xenos::DataDimension::k1D && width > 8192) {
XELOGE(
"1D texture is too wide ({}) - ignoring! "
"Report the game to Xenia developers",
@@ -2198,7 +2204,7 @@ void TextureCache::BindingInfoFromFetchConstant(
return;
}
TextureFormat format = GetBaseFormat(fetch.format);
xenos::TextureFormat format = GetBaseFormat(fetch.format);
key_out.base_page = base_page;
key_out.mip_page = mip_page;
@@ -2305,7 +2311,7 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
kUnsupportedResourceBit;
return nullptr;
}
if (key.dimension == Dimension::k3D) {
if (key.dimension == xenos::DataDimension::k3D) {
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
} else {
// 1D textures are treated as 2D for simplicity.
@@ -2357,7 +2363,8 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) {
texture_used_last_ = texture;
texture->mip_offsets[0] = 0;
uint32_t width_blocks, height_blocks, depth_blocks;
uint32_t array_size = key.dimension != Dimension::k3D ? key.depth : 1;
uint32_t array_size =
key.dimension != xenos::DataDimension::k3D ? key.depth : 1;
if (key.base_page != 0) {
texture_util::GetGuestMipBlocks(key.dimension, key.width, key.height,
key.depth, key.format, 0, width_blocks,
@@ -2491,13 +2498,13 @@ bool TextureCache::LoadTextureData(Texture* texture) {
}
// Get the guest layout.
Dimension dimension = texture->key.dimension;
bool is_3d = dimension == Dimension::k3D;
xenos::DataDimension dimension = texture->key.dimension;
bool is_3d = dimension == xenos::DataDimension::k3D;
uint32_t width = texture->key.width;
uint32_t height = texture->key.height;
uint32_t depth = is_3d ? texture->key.depth : 1;
uint32_t slice_count = is_3d ? 1 : texture->key.depth;
TextureFormat guest_format = texture->key.format;
xenos::TextureFormat guest_format = texture->key.format;
const FormatInfo* guest_format_info = FormatInfo::Get(guest_format);
uint32_t block_width = guest_format_info->block_width;
uint32_t block_height = guest_format_info->block_height;
@@ -2871,7 +2878,7 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
// Create a new bindless or cached descriptor if supported.
D3D12_SHADER_RESOURCE_VIEW_DESC desc;
TextureFormat format = texture.key.format;
xenos::TextureFormat format = texture.key.format;
if (IsSignedVersionSeparate(format) &&
texture.key.signed_separate != uint32_t(is_signed)) {
// Not the version with the needed signedness.
@@ -2892,8 +2899,8 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
uint32_t mip_levels = texture.key.mip_max_level + 1;
switch (texture.key.dimension) {
case Dimension::k1D:
case Dimension::k2D:
case xenos::DataDimension::k1D:
case xenos::DataDimension::k2DOrStacked:
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MostDetailedMip = 0;
desc.Texture2DArray.MipLevels = mip_levels;
@@ -2902,13 +2909,13 @@ uint32_t TextureCache::FindOrCreateTextureDescriptor(Texture& texture,
desc.Texture2DArray.PlaneSlice = 0;
desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
break;
case Dimension::k3D:
case xenos::DataDimension::k3D:
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
desc.Texture3D.MostDetailedMip = 0;
desc.Texture3D.MipLevels = mip_levels;
desc.Texture3D.ResourceMinLODClamp = 0.0f;
break;
case Dimension::kCube:
case xenos::DataDimension::kCube:
desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
desc.TextureCube.MostDetailedMip = 0;
desc.TextureCube.MipLevels = mip_levels;

View File

@@ -61,9 +61,9 @@ class TextureCache {
struct {
// Physical 4 KB page with the base mip level, disregarding A/C/E address
// range prefix.
uint32_t base_page : 17; // 17 total
Dimension dimension : 2; // 19
uint32_t width : 13; // 32
uint32_t base_page : 17; // 17 total
xenos::DataDimension dimension : 2; // 19
uint32_t width : 13; // 32
uint32_t height : 13; // 45
uint32_t tiled : 1; // 46
@@ -72,10 +72,10 @@ class TextureCache {
uint32_t mip_page : 17; // 64
// Layers for stacked and 3D, 6 for cube, 1 for other dimensions.
uint32_t depth : 10; // 74
uint32_t mip_max_level : 4; // 78
TextureFormat format : 6; // 84
Endian endianness : 2; // 86
uint32_t depth : 10; // 74
uint32_t mip_max_level : 4; // 78
xenos::TextureFormat format : 6; // 84
xenos::Endian endianness : 2; // 86
// Whether this texture is signed and has a different host representation
// than an unsigned view of the same guest texture.
uint32_t signed_separate : 1; // 87
@@ -137,15 +137,15 @@ class TextureCache {
// for binding checking validity whether samplers are up to date.
union SamplerParameters {
struct {
ClampMode clamp_x : 3; // 3
ClampMode clamp_y : 3; // 6
ClampMode clamp_z : 3; // 9
BorderColor border_color : 2; // 11
xenos::ClampMode clamp_x : 3; // 3
xenos::ClampMode clamp_y : 3; // 6
xenos::ClampMode clamp_z : 3; // 9
xenos::BorderColor border_color : 2; // 11
// For anisotropic, these are true.
uint32_t mag_linear : 1; // 12
uint32_t min_linear : 1; // 13
uint32_t mip_linear : 1; // 14
AnisoFilter aniso_filter : 3; // 17
xenos::AnisoFilter aniso_filter : 3; // 17
uint32_t mip_min_level : 4; // 21
// Maximum mip level is in the texture resource itself.
};
@@ -221,15 +221,15 @@ class TextureCache {
D3D12_CPU_DESCRIPTOR_HANDLE handle) const;
void MarkRangeAsResolved(uint32_t start_unscaled, uint32_t length_unscaled);
static inline DXGI_FORMAT GetResolveDXGIFormat(TextureFormat format) {
static inline DXGI_FORMAT GetResolveDXGIFormat(xenos::TextureFormat format) {
return host_formats_[uint32_t(format)].dxgi_format_resolve_tile;
}
// The source buffer must be in the non-pixel-shader SRV state.
bool TileResolvedTexture(TextureFormat format, uint32_t texture_base,
bool TileResolvedTexture(xenos::TextureFormat format, uint32_t texture_base,
uint32_t texture_pitch, uint32_t texture_height,
bool is_3d, uint32_t offset_x, uint32_t offset_y,
uint32_t offset_z, uint32_t resolve_width,
uint32_t resolve_height, Endian128 endian,
uint32_t resolve_height, xenos::Endian128 endian,
ID3D12Resource* buffer, uint32_t buffer_size,
const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint,
uint32_t* written_address_out,
@@ -256,7 +256,8 @@ class TextureCache {
// description of its SRV. May call LoadTextureData, so the same restrictions
// (such as about descriptor heap change possibility) apply.
ID3D12Resource* RequestSwapTexture(
D3D12_SHADER_RESOURCE_VIEW_DESC& srv_desc_out, TextureFormat& format_out);
D3D12_SHADER_RESOURCE_VIEW_DESC& srv_desc_out,
xenos::TextureFormat& format_out);
private:
enum class LoadMode {
@@ -498,16 +499,16 @@ class TextureCache {
// Whether the signed version of the texture has a different representation on
// the host than its unsigned version (for example, if it's a fixed-point
// texture emulated with a larger host pixel format).
static inline bool IsSignedVersionSeparate(TextureFormat format) {
static inline bool IsSignedVersionSeparate(xenos::TextureFormat format) {
const HostFormat& host_format = host_formats_[uint32_t(format)];
return host_format.load_mode_snorm != LoadMode::kUnknown &&
host_format.load_mode_snorm != host_format.load_mode;
}
// Whether decompression is needed on the host (Direct3D only allows creation
// of block-compressed textures with 4x4-aligned dimensions on PC).
static bool IsDecompressionNeeded(TextureFormat format, uint32_t width,
static bool IsDecompressionNeeded(xenos::TextureFormat format, uint32_t width,
uint32_t height);
static inline DXGI_FORMAT GetDXGIResourceFormat(TextureFormat format,
static inline DXGI_FORMAT GetDXGIResourceFormat(xenos::TextureFormat format,
uint32_t width,
uint32_t height) {
const HostFormat& host_format = host_formats_[uint32_t(format)];
@@ -518,7 +519,7 @@ class TextureCache {
static inline DXGI_FORMAT GetDXGIResourceFormat(TextureKey key) {
return GetDXGIResourceFormat(key.format, key.width, key.height);
}
static inline DXGI_FORMAT GetDXGIUnormFormat(TextureFormat format,
static inline DXGI_FORMAT GetDXGIUnormFormat(xenos::TextureFormat format,
uint32_t width,
uint32_t height) {
const HostFormat& host_format = host_formats_[uint32_t(format)];
@@ -540,16 +541,17 @@ class TextureCache {
uint32_t* host_swizzle_out, uint8_t* swizzled_signs_out);
static constexpr bool AreDimensionsCompatible(
TextureDimension binding_dimension, Dimension resource_dimension) {
xenos::FetchOpDimension binding_dimension,
xenos::DataDimension resource_dimension) {
switch (binding_dimension) {
case TextureDimension::k1D:
case TextureDimension::k2D:
return resource_dimension == Dimension::k1D ||
resource_dimension == Dimension::k2D;
case TextureDimension::k3D:
return resource_dimension == Dimension::k3D;
case TextureDimension::kCube:
return resource_dimension == Dimension::kCube;
case xenos::FetchOpDimension::k1D:
case xenos::FetchOpDimension::k2D:
return resource_dimension == xenos::DataDimension::k1D ||
resource_dimension == xenos::DataDimension::k2DOrStacked;
case xenos::FetchOpDimension::k3DOrStacked:
return resource_dimension == xenos::DataDimension::k3D;
case xenos::FetchOpDimension::kCube:
return resource_dimension == xenos::DataDimension::kCube;
default:
return false;
}