[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

@ -864,7 +864,7 @@ bool CommandProcessor::ExecutePacketType3_WAIT_REG_MEM(RingBuffer* reader,
uint32_t value; uint32_t value;
if (wait_info & 0x10) { if (wait_info & 0x10) {
// Memory. // Memory.
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3); auto endianness = static_cast<xenos::Endian>(poll_reg_addr & 0x3);
poll_reg_addr &= ~0x3; poll_reg_addr &= ~0x3;
value = xe::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr)); value = xe::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr));
value = GpuSwap(value, endianness); value = GpuSwap(value, endianness);
@ -971,7 +971,7 @@ bool CommandProcessor::ExecutePacketType3_REG_TO_MEM(RingBuffer* reader,
assert_true(reg_addr < RegisterFile::kRegisterCount); assert_true(reg_addr < RegisterFile::kRegisterCount);
reg_val = register_file_->values[reg_addr].u32; reg_val = register_file_->values[reg_addr].u32;
auto endianness = static_cast<Endian>(mem_addr & 0x3); auto endianness = static_cast<xenos::Endian>(mem_addr & 0x3);
mem_addr &= ~0x3; mem_addr &= ~0x3;
reg_val = GpuSwap(reg_val, endianness); reg_val = GpuSwap(reg_val, endianness);
xe::store(memory_->TranslatePhysical(mem_addr), reg_val); xe::store(memory_->TranslatePhysical(mem_addr), reg_val);
@ -987,7 +987,7 @@ bool CommandProcessor::ExecutePacketType3_MEM_WRITE(RingBuffer* reader,
for (uint32_t i = 0; i < count - 1; i++) { for (uint32_t i = 0; i < count - 1; i++) {
uint32_t write_data = reader->ReadAndSwap<uint32_t>(); uint32_t write_data = reader->ReadAndSwap<uint32_t>();
auto endianness = static_cast<Endian>(write_addr & 0x3); auto endianness = static_cast<xenos::Endian>(write_addr & 0x3);
auto addr = write_addr & ~0x3; auto addr = write_addr & ~0x3;
write_data = GpuSwap(write_data, endianness); write_data = GpuSwap(write_data, endianness);
xe::store(memory_->TranslatePhysical(addr), write_data); xe::store(memory_->TranslatePhysical(addr), write_data);
@ -1011,7 +1011,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingBuffer* reader,
uint32_t value; uint32_t value;
if (wait_info & 0x10) { if (wait_info & 0x10) {
// Memory. // Memory.
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3); auto endianness = static_cast<xenos::Endian>(poll_reg_addr & 0x3);
poll_reg_addr &= ~0x3; poll_reg_addr &= ~0x3;
trace_writer_.WriteMemoryRead(CpuToGpu(poll_reg_addr), 4); trace_writer_.WriteMemoryRead(CpuToGpu(poll_reg_addr), 4);
value = xe::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr)); value = xe::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr));
@ -1052,7 +1052,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingBuffer* reader,
// Write. // Write.
if (wait_info & 0x100) { if (wait_info & 0x100) {
// Memory. // Memory.
auto endianness = static_cast<Endian>(write_reg_addr & 0x3); auto endianness = static_cast<xenos::Endian>(write_reg_addr & 0x3);
write_reg_addr &= ~0x3; write_reg_addr &= ~0x3;
write_data = GpuSwap(write_data, endianness); write_data = GpuSwap(write_data, endianness);
xe::store(memory_->TranslatePhysical(write_reg_addr), write_data); xe::store(memory_->TranslatePhysical(write_reg_addr), write_data);
@ -1099,7 +1099,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_SHD(RingBuffer* reader,
// Write value. // Write value.
data_value = value; data_value = value;
} }
auto endianness = static_cast<Endian>(address & 0x3); auto endianness = static_cast<xenos::Endian>(address & 0x3);
address &= ~0x3; address &= ~0x3;
data_value = GpuSwap(data_value, endianness); data_value = GpuSwap(data_value, endianness);
xe::store(memory_->TranslatePhysical(address), data_value); xe::store(memory_->TranslatePhysical(address), data_value);
@ -1115,7 +1115,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_EXT(RingBuffer* reader,
uint32_t address = reader->ReadAndSwap<uint32_t>(); uint32_t address = reader->ReadAndSwap<uint32_t>();
// Writeback initiator. // Writeback initiator.
WriteRegister(XE_GPU_REG_VGT_EVENT_INITIATOR, initiator & 0x3F); WriteRegister(XE_GPU_REG_VGT_EVENT_INITIATOR, initiator & 0x3F);
auto endianness = static_cast<Endian>(address & 0x3); auto endianness = static_cast<xenos::Endian>(address & 0x3);
address &= ~0x3; address &= ~0x3;
// Let us hope we can fake this. // Let us hope we can fake this.
@ -1130,7 +1130,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_EXT(RingBuffer* reader,
0, // min z 0, // min z
1, // max z 1, // max z
}; };
assert_true(endianness == Endian::k8in16); assert_true(endianness == xenos::Endian::k8in16);
xe::copy_and_swap_16_unaligned(memory_->TranslatePhysical(address), extents, xe::copy_and_swap_16_unaligned(memory_->TranslatePhysical(address), extents,
xe::countof(extents)); xe::countof(extents));
trace_writer_.WriteMemoryWrite(CpuToGpu(address), sizeof(extents)); trace_writer_.WriteMemoryWrite(CpuToGpu(address), sizeof(extents));
@ -1188,11 +1188,12 @@ bool CommandProcessor::ExecutePacketType3_DRAW_INDX(RingBuffer* reader,
is_indexed = true; is_indexed = true;
index_buffer_info.guest_base = reader->ReadAndSwap<uint32_t>(); index_buffer_info.guest_base = reader->ReadAndSwap<uint32_t>();
uint32_t index_size = reader->ReadAndSwap<uint32_t>(); uint32_t index_size = reader->ReadAndSwap<uint32_t>();
index_buffer_info.endianness = static_cast<Endian>(index_size >> 30); index_buffer_info.endianness =
static_cast<xenos::Endian>(index_size >> 30);
index_size &= 0x00FFFFFF; index_size &= 0x00FFFFFF;
index_buffer_info.format = vgt_draw_initiator.index_size; index_buffer_info.format = vgt_draw_initiator.index_size;
index_size *= index_size *=
(vgt_draw_initiator.index_size == IndexFormat::kInt32) ? 4 : 2; (vgt_draw_initiator.index_size == xenos::IndexFormat::kInt32) ? 4 : 2;
index_buffer_info.length = index_size; index_buffer_info.length = index_size;
index_buffer_info.count = vgt_draw_initiator.num_indices; index_buffer_info.count = vgt_draw_initiator.num_indices;
} break; } break;
@ -1238,7 +1239,8 @@ bool CommandProcessor::ExecutePacketType3_DRAW_INDX_2(RingBuffer* reader,
// Index buffer unused as automatic. // Index buffer unused as automatic.
// uint32_t indices_size = // uint32_t indices_size =
// vgt_draw_initiator.num_indices * // vgt_draw_initiator.num_indices *
// (vgt_draw_initiator.index_size == IndexFormat::kInt32 ? 4 : 2); // (vgt_draw_initiator.index_size == xenos::IndexFormat::kInt32 ? 4
// : 2);
// uint32_t index_ptr = reader->ptr(); // uint32_t index_ptr = reader->ptr();
// TODO(Triang3l): VGT_IMMED_DATA. // TODO(Triang3l): VGT_IMMED_DATA.
reader->AdvanceRead((count - 1) * sizeof(uint32_t)); reader->AdvanceRead((count - 1) * sizeof(uint32_t));
@ -1363,7 +1365,7 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD(RingBuffer* reader,
// load sequencer instruction memory (pointer-based) // load sequencer instruction memory (pointer-based)
uint32_t addr_type = reader->ReadAndSwap<uint32_t>(); uint32_t addr_type = reader->ReadAndSwap<uint32_t>();
auto shader_type = static_cast<ShaderType>(addr_type & 0x3); auto shader_type = static_cast<xenos::ShaderType>(addr_type & 0x3);
uint32_t addr = addr_type & ~0x3; uint32_t addr = addr_type & ~0x3;
uint32_t start_size = reader->ReadAndSwap<uint32_t>(); uint32_t start_size = reader->ReadAndSwap<uint32_t>();
uint32_t start = start_size >> 16; uint32_t start = start_size >> 16;
@ -1374,10 +1376,10 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD(RingBuffer* reader,
LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(addr), LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(addr),
size_dwords); size_dwords);
switch (shader_type) { switch (shader_type) {
case ShaderType::kVertex: case xenos::ShaderType::kVertex:
active_vertex_shader_ = shader; active_vertex_shader_ = shader;
break; break;
case ShaderType::kPixel: case xenos::ShaderType::kPixel:
active_pixel_shader_ = shader; active_pixel_shader_ = shader;
break; break;
default: default:
@ -1395,7 +1397,7 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD_IMMEDIATE(RingBuffer* reader,
// load sequencer instruction memory (code embedded in packet) // load sequencer instruction memory (code embedded in packet)
uint32_t dword0 = reader->ReadAndSwap<uint32_t>(); uint32_t dword0 = reader->ReadAndSwap<uint32_t>();
uint32_t dword1 = reader->ReadAndSwap<uint32_t>(); uint32_t dword1 = reader->ReadAndSwap<uint32_t>();
auto shader_type = static_cast<ShaderType>(dword0); auto shader_type = static_cast<xenos::ShaderType>(dword0);
uint32_t start_size = dword1; uint32_t start_size = dword1;
uint32_t start = start_size >> 16; uint32_t start = start_size >> 16;
uint32_t size_dwords = start_size & 0xFFFF; // dwords uint32_t size_dwords = start_size & 0xFFFF; // dwords
@ -1406,10 +1408,10 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD_IMMEDIATE(RingBuffer* reader,
LoadShader(shader_type, uint32_t(reader->read_ptr()), LoadShader(shader_type, uint32_t(reader->read_ptr()),
reinterpret_cast<uint32_t*>(reader->read_ptr()), size_dwords); reinterpret_cast<uint32_t*>(reader->read_ptr()), size_dwords);
switch (shader_type) { switch (shader_type) {
case ShaderType::kVertex: case xenos::ShaderType::kVertex:
active_vertex_shader_ = shader; active_vertex_shader_ = shader;
break; break;
case ShaderType::kPixel: case xenos::ShaderType::kPixel:
active_pixel_shader_ = shader; active_pixel_shader_ = shader;
break; break;
default: default:

View File

@ -161,8 +161,8 @@ class CommandProcessor {
protected: protected:
struct IndexBufferInfo { struct IndexBufferInfo {
IndexFormat format = IndexFormat::kInt16; xenos::IndexFormat format = xenos::IndexFormat::kInt16;
Endian endianness = Endian::kNone; xenos::Endian endianness = xenos::Endian::kNone;
uint32_t count = 0; uint32_t count = 0;
uint32_t guest_base = 0; uint32_t guest_base = 0;
size_t length = 0; size_t length = 0;
@ -241,11 +241,12 @@ class CommandProcessor {
bool ExecutePacketType3_VIZ_QUERY(RingBuffer* reader, uint32_t packet, bool ExecutePacketType3_VIZ_QUERY(RingBuffer* reader, uint32_t packet,
uint32_t count); uint32_t count);
virtual Shader* LoadShader(ShaderType shader_type, uint32_t guest_address, virtual Shader* LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address,
const uint32_t* host_address, const uint32_t* host_address,
uint32_t dword_count) = 0; uint32_t dword_count) = 0;
virtual bool IssueDraw(PrimitiveType prim_type, uint32_t index_count, virtual bool IssueDraw(xenos::PrimitiveType prim_type, uint32_t index_count,
IndexBufferInfo* index_buffer_info, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) = 0; bool major_mode_explicit) = 0;
virtual bool IssueCopy() = 0; virtual bool IssueCopy() = 0;

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

View File

@ -158,7 +158,7 @@ class D3D12CommandProcessor : public CommandProcessor {
// Sets the current SSAA sample positions, needs to be done before setting // Sets the current SSAA sample positions, needs to be done before setting
// render targets or copying to depth render targets. // 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 // Returns a pipeline state object with deferred creation by its handle. May
// return nullptr if failed to create the pipeline state object. // return nullptr if failed to create the pipeline state object.
@ -206,11 +206,11 @@ class D3D12CommandProcessor : public CommandProcessor {
void OnPrimaryBufferEnd() override; 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, const uint32_t* host_address,
uint32_t dword_count) override; 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, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) override; bool major_mode_explicit) override;
bool IssueCopy() override; bool IssueCopy() override;
@ -336,7 +336,7 @@ class D3D12CommandProcessor : public CommandProcessor {
void UpdateFixedFunctionState(bool primitive_two_faced); void UpdateFixedFunctionState(bool primitive_two_faced);
void UpdateSystemConstantValues( void UpdateSystemConstantValues(
bool shared_memory_is_uav, bool primitive_two_faced, 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, uint32_t used_texture_mask, bool early_z, uint32_t color_mask,
const RenderTargetCache::PipelineRenderTarget render_targets[4]); const RenderTargetCache::PipelineRenderTarget render_targets[4]);
bool UpdateBindings(const D3D12Shader* vertex_shader, bool UpdateBindings(const D3D12Shader* vertex_shader,
@ -348,7 +348,7 @@ class D3D12CommandProcessor : public CommandProcessor {
// for instance). // for instance).
// TODO(Triang3l): Check if any game uses memexport with formats smaller than // TODO(Triang3l): Check if any game uses memexport with formats smaller than
// 32 bits per element. // 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 // Returns a buffer for reading GPU data back to the CPU. Assuming
// synchronizing immediately after use. Always in COPY_DEST state. // synchronizing immediately after use. Always in COPY_DEST state.
@ -524,7 +524,7 @@ class D3D12CommandProcessor : public CommandProcessor {
bool ff_stencil_ref_update_needed_; bool ff_stencil_ref_update_needed_;
// Current SSAA sample positions (to be updated by the render target cache). // 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 // Currently bound pipeline, either a graphics pipeline from the pipeline
// cache (with potentially deferred creation - current_external_pipeline_ is // 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::kMaxSamplerBindingIndexBits;
constexpr uint32_t D3D12Shader::kMaxSamplerBindings; 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) const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, 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/dxbc_shader_translator.h"
#include "xenia/gpu/shader.h" #include "xenia/gpu/shader.h"
#include "xenia/gpu/xenos.h"
#include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/d3d12/d3d12_provider.h"
namespace xe { namespace xe {
@ -22,7 +23,7 @@ namespace d3d12 {
class D3D12Shader : public Shader { class D3D12Shader : public Shader {
public: 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); const uint32_t* dword_ptr, uint32_t dword_count);
void SetTexturesAndSamplers( void SetTexturesAndSamplers(
@ -53,7 +54,7 @@ class D3D12Shader : public Shader {
uint32_t fetch_constant; uint32_t fetch_constant;
// Stacked and 3D are separate TextureBindings, even for bindless for null // Stacked and 3D are separate TextureBindings, even for bindless for null
// descriptor handling simplicity. // descriptor handling simplicity.
TextureDimension dimension; xenos::FetchOpDimension dimension;
bool is_signed; bool is_signed;
}; };
// Safe to hash and compare with memcmp for layout hashing. // Safe to hash and compare with memcmp for layout hashing.
@ -70,10 +71,10 @@ class D3D12Shader : public Shader {
struct SamplerBinding { struct SamplerBinding {
uint32_t bindless_descriptor_index; uint32_t bindless_descriptor_index;
uint32_t fetch_constant; uint32_t fetch_constant;
TextureFilter mag_filter; xenos::TextureFilter mag_filter;
TextureFilter min_filter; xenos::TextureFilter min_filter;
TextureFilter mip_filter; xenos::TextureFilter mip_filter;
AnisoFilter aniso_filter; xenos::AnisoFilter aniso_filter;
}; };
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const { const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
count_out = uint32_t(sampler_bindings_.size()); 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()); return std::unique_ptr<gpu::GraphicsSystem>(new D3D12GraphicsSystem());
} }
uintptr_t GetColorRenderTarget(uint32_t pitch, MsaaSamples samples, uintptr_t GetColorRenderTarget(
uint32_t base, uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
ColorRenderTargetFormat format) override { xenos::ColorRenderTargetFormat format) override {
// TODO(Triang3l): EDRAM viewer. // TODO(Triang3l): EDRAM viewer.
return 0; return 0;
} }
uintptr_t GetDepthRenderTarget(uint32_t pitch, MsaaSamples samples, uintptr_t GetDepthRenderTarget(
uint32_t base, uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
DepthRenderTargetFormat format) override { xenos::DepthRenderTargetFormat format) override {
// TODO(Triang3l): EDRAM viewer. // TODO(Triang3l): EDRAM viewer.
return 0; return 0;
} }

View File

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

View File

@ -56,7 +56,7 @@ class PipelineCache {
void EndSubmission(); void EndSubmission();
bool IsCreatingPipelineStates(); 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); const uint32_t* host_address, uint32_t dword_count);
// Returns the host vertex shader type for the current draw if it's valid and // Returns the host vertex shader type for the current draw if it's valid and
@ -70,7 +70,8 @@ class PipelineCache {
bool ConfigurePipeline( bool ConfigurePipeline(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader, 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], const RenderTargetCache::PipelineRenderTarget render_targets[5],
void** pipeline_state_handle_out, void** pipeline_state_handle_out,
ID3D12RootSignature** root_signature_out); ID3D12RootSignature** root_signature_out);
@ -87,7 +88,7 @@ class PipelineCache {
uint64_t ucode_data_hash; uint64_t ucode_data_hash;
uint32_t ucode_dword_count : 16; uint32_t ucode_dword_count : 16;
ShaderType type : 1; xenos::ShaderType type : 1;
Shader::HostVertexShaderType host_vertex_shader_type : 3; Shader::HostVertexShaderType host_vertex_shader_type : 3;
reg::SQ_PROGRAM_CNTL sq_program_cntl; reg::SQ_PROGRAM_CNTL sq_program_cntl;
@ -156,13 +157,13 @@ class PipelineCache {
// Update PipelineDescription::kVersion if anything is changed! // Update PipelineDescription::kVersion if anything is changed!
XEPACKEDSTRUCT(PipelineRenderTarget, { XEPACKEDSTRUCT(PipelineRenderTarget, {
uint32_t used : 1; // 1 uint32_t used : 1; // 1
ColorRenderTargetFormat format : 4; // 5 xenos::ColorRenderTargetFormat format : 4; // 5
PipelineBlendFactor src_blend : 4; // 9 PipelineBlendFactor src_blend : 4; // 9
PipelineBlendFactor dest_blend : 4; // 13 PipelineBlendFactor dest_blend : 4; // 13
BlendOp blend_op : 3; // 16 xenos::BlendOp blend_op : 3; // 16
PipelineBlendFactor src_blend_alpha : 4; // 20 PipelineBlendFactor src_blend_alpha : 4; // 20
PipelineBlendFactor dest_blend_alpha : 4; // 24 PipelineBlendFactor dest_blend_alpha : 4; // 24
BlendOp blend_op_alpha : 3; // 27 xenos::BlendOp blend_op_alpha : 3; // 27
uint32_t write_mask : 4; // 31 uint32_t write_mask : 4; // 31
}); });
@ -186,22 +187,22 @@ class PipelineCache {
uint32_t front_counter_clockwise : 1; // 13 uint32_t front_counter_clockwise : 1; // 13
uint32_t depth_clip : 1; // 14 uint32_t depth_clip : 1; // 14
uint32_t rov_msaa : 1; // 15 uint32_t rov_msaa : 1; // 15
DepthRenderTargetFormat depth_format : 1; // 16 xenos::DepthRenderTargetFormat depth_format : 1; // 16
CompareFunction depth_func : 3; // 19 xenos::CompareFunction depth_func : 3; // 19
uint32_t depth_write : 1; // 20 uint32_t depth_write : 1; // 20
uint32_t stencil_enable : 1; // 21 uint32_t stencil_enable : 1; // 21
uint32_t stencil_read_mask : 8; // 29 uint32_t stencil_read_mask : 8; // 29
uint32_t force_early_z : 1; // 30 uint32_t force_early_z : 1; // 30
uint32_t stencil_write_mask : 8; // 8 uint32_t stencil_write_mask : 8; // 8
StencilOp stencil_front_fail_op : 3; // 11 xenos::StencilOp stencil_front_fail_op : 3; // 11
StencilOp stencil_front_depth_fail_op : 3; // 14 xenos::StencilOp stencil_front_depth_fail_op : 3; // 14
StencilOp stencil_front_pass_op : 3; // 17 xenos::StencilOp stencil_front_pass_op : 3; // 17
CompareFunction stencil_front_func : 3; // 20 xenos::CompareFunction stencil_front_func : 3; // 20
StencilOp stencil_back_fail_op : 3; // 23 xenos::StencilOp stencil_back_fail_op : 3; // 23
StencilOp stencil_back_depth_fail_op : 3; // 26 xenos::StencilOp stencil_back_depth_fail_op : 3; // 26
StencilOp stencil_back_pass_op : 3; // 29 xenos::StencilOp stencil_back_pass_op : 3; // 29
CompareFunction stencil_back_func : 3; // 32 xenos::CompareFunction stencil_back_func : 3; // 32
PipelineRenderTarget render_targets[4]; PipelineRenderTarget render_targets[4];
@ -228,7 +229,8 @@ class PipelineCache {
bool GetCurrentStateDescription( bool GetCurrentStateDescription(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader, 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], const RenderTargetCache::PipelineRenderTarget render_targets[5],
PipelineRuntimeDescription& runtime_description_out); PipelineRuntimeDescription& runtime_description_out);

View File

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

View File

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

View File

@ -579,9 +579,9 @@ bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
return false; return false;
} }
uint32_t msaa_samples_x = 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 = 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. // Extract color/depth info in an unified way.
bool enabled[5]; bool enabled[5];
@ -596,7 +596,7 @@ bool RenderTargetCache::UpdateRenderTargets(const D3D12Shader* pixel_shader) {
edram_bases[i] = std::min(color_info.color_base, 2048u); edram_bases[i] = std::min(color_info.color_base, 2048u);
formats[i] = uint32_t(GetBaseColorFormat(color_info.color_format)); formats[i] = uint32_t(GetBaseColorFormat(color_info.color_format));
formats_are_64bpp[i] = formats_are_64bpp[i] =
IsColorFormat64bpp(ColorRenderTargetFormat(formats[i])); IsColorFormat64bpp(xenos::ColorRenderTargetFormat(formats[i]));
} }
auto rb_depthcontrol = regs.Get<reg::RB_DEPTHCONTROL>(); auto rb_depthcontrol = regs.Get<reg::RB_DEPTHCONTROL>();
auto rb_depth_info = regs.Get<reg::RB_DEPTH_INFO>(); 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; render_target->state = D3D12_RESOURCE_STATE_RENDER_TARGET;
current_pipeline_render_targets_[rtv_count].guest_render_target = i; current_pipeline_render_targets_[rtv_count].guest_render_target = i;
current_pipeline_render_targets_[rtv_count].format = current_pipeline_render_targets_[rtv_count].format =
GetColorDXGIFormat(ColorRenderTargetFormat(formats[i])); GetColorDXGIFormat(xenos::ColorRenderTargetFormat(formats[i]));
++rtv_count; ++rtv_count;
} }
for (uint32_t i = rtv_count; i < 4; ++i) { 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); D3D12_RESOURCE_STATE_DEPTH_WRITE);
depth_render_target->state = D3D12_RESOURCE_STATE_DEPTH_WRITE; depth_render_target->state = D3D12_RESOURCE_STATE_DEPTH_WRITE;
current_pipeline_render_targets_[4].format = current_pipeline_render_targets_[4].format =
GetDepthDXGIFormat(DepthRenderTargetFormat(formats[4])); GetDepthDXGIFormat(xenos::DepthRenderTargetFormat(formats[4]));
} else { } else {
current_pipeline_render_targets_[4].format = DXGI_FORMAT_UNKNOWN; 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>( const auto& fetch = regs.Get<xenos::xe_gpu_vertex_fetch_t>(
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0); XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0);
assert_true(fetch.type == xenos::FetchConstantType::kVertex); 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); assert_true(fetch.size == 6);
trace_writer_->WriteMemoryRead(fetch.address << 2, fetch.size << 2); trace_writer_->WriteMemoryRead(fetch.address << 2, fetch.size << 2);
const uint8_t* src_vertex_address = const uint8_t* src_vertex_address =
@ -1106,7 +1106,7 @@ bool RenderTargetCache::Resolve(SharedMemory* shared_memory,
for (uint32_t i = 0; i < 6; ++i) { for (uint32_t i = 0; i < 6; ++i) {
vertices[i] = vertices[i] =
xenos::GpuSwap(xe::load<float>(src_vertex_address + i * sizeof(float)), xenos::GpuSwap(xe::load<float>(src_vertex_address + i * sizeof(float)),
Endian(fetch.endian)) + xenos::Endian(fetch.endian)) +
vertex_offset; vertex_offset;
} }
// Xenos only supports rectangle copies (luckily). // Xenos only supports rectangle copies (luckily).
@ -1175,7 +1175,7 @@ bool RenderTargetCache::Resolve(SharedMemory* shared_memory,
"at {}", "at {}",
rect.left, rect.top, rect.right, rect.bottom, surface_index, rect.left, rect.top, rect.right, rect.bottom, surface_index,
surface_pitch, 1 << uint32_t(rb_surface_info.msaa_samples), 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); surface_format, surface_edram_base);
if (rect.left >= rect.right || rect.top >= rect.bottom) { 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, bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
TextureCache* texture_cache, TextureCache* texture_cache,
uint32_t edram_base, uint32_t surface_pitch, uint32_t edram_base, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth, xenos::MsaaSamples msaa_samples,
uint32_t src_format, const D3D12_RECT& rect, bool is_depth, uint32_t src_format,
const D3D12_RECT& rect,
uint32_t& written_address_out, uint32_t& written_address_out,
uint32_t& written_length_out) { uint32_t& written_length_out) {
written_address_out = written_length_out = 0; written_address_out = written_length_out = 0;
@ -1231,35 +1232,35 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
// Get format info. // Get format info.
auto rb_copy_dest_info = regs.Get<reg::RB_COPY_DEST_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; bool src_64bpp;
if (is_depth) { if (is_depth) {
src_texture_format = src_texture_format = DepthRenderTargetToTextureFormat(
DepthRenderTargetToTextureFormat(DepthRenderTargetFormat(src_format)); xenos::DepthRenderTargetFormat(src_format));
src_64bpp = false; src_64bpp = false;
} else { } else {
// Force k_16_16 and k_16_16_16_16 RTs to be always resolved via drawing, // 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 // 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. // in unsigned texture data, unlike the render target which is signed.
if (ColorRenderTargetFormat(src_format) == if (xenos::ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16) { xenos::ColorRenderTargetFormat::k_16_16) {
src_texture_format = TextureFormat::k_16_16_EDRAM; src_texture_format = xenos::TextureFormat::k_16_16_EDRAM;
} else if (ColorRenderTargetFormat(src_format) == } else if (xenos::ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16_16_16) { xenos::ColorRenderTargetFormat::k_16_16_16_16) {
src_texture_format = TextureFormat::k_16_16_16_16_EDRAM; src_texture_format = xenos::TextureFormat::k_16_16_16_16_EDRAM;
} else { } else {
src_texture_format = GetBaseFormat(ColorRenderTargetToTextureFormat( 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 // 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. // no format conversion is done for depth, so ignore it.
TextureFormat dest_format = xenos::TextureFormat dest_format =
is_depth is_depth ? src_texture_format
? src_texture_format : GetBaseFormat(
: GetBaseFormat(TextureFormat(rb_copy_dest_info.copy_dest_format)); xenos::TextureFormat(rb_copy_dest_info.copy_dest_format));
const FormatInfo* dest_format_info = FormatInfo::Get(dest_format); const FormatInfo* dest_format_info = FormatInfo::Get(dest_format);
// Get the destination region and clamp the source region to it. // 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; dest_exp_bias = 0;
} else { } else {
dest_exp_bias = rb_copy_dest_info.copy_dest_exp_bias; dest_exp_bias = rb_copy_dest_info.copy_dest_exp_bias;
if (ColorRenderTargetFormat(src_format) == if (xenos::ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16 || xenos::ColorRenderTargetFormat::k_16_16 ||
ColorRenderTargetFormat(src_format) == xenos::ColorRenderTargetFormat(src_format) ==
ColorRenderTargetFormat::k_16_16_16_16) { xenos::ColorRenderTargetFormat::k_16_16_16_16) {
// On the Xbox 360, k_16_16_EDRAM and k_16_16_16_16_EDRAM internally have // 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 // -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 // 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) | edram_base | (resolution_scale_log2 << 13) |
(resolution_scale_edge_clamp ? (1 << 14) : 0) | (resolution_scale_edge_clamp ? (1 << 14) : 0) |
(is_depth ? (1 << 15) : 0) | (surface_pitch_tiles << 16); (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; 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; root_constants.base_samples_2x_depth_pitch |= 1 << 12;
} }
} }
@ -1520,9 +1521,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
command_processor_->SubmitBarriers(); command_processor_->SubmitBarriers();
// 1 group per destination 80x16 region. // 1 group per destination 80x16 region.
uint32_t group_count_x = row_width_ss_div_80, group_count_y = rows; 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; 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; 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 = load_root_constants.base_samples_2x_depth_pitch =
edram_base | (resolution_scale_log2 << 13) | edram_base | (resolution_scale_log2 << 13) |
(surface_pitch_tiles << 16); (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; 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; 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_); command_list->D3DSetGraphicsRootSignature(resolve_root_signature_);
ResolveRootConstants resolve_root_constants; ResolveRootConstants resolve_root_constants;
uint32_t samples_x_log2 = msaa_samples >= MsaaSamples::k4X ? 1 : 0; uint32_t samples_x_log2 = msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= MsaaSamples::k2X ? 1 : 0; uint32_t samples_y_log2 = msaa_samples >= xenos::MsaaSamples::k2X ? 1 : 0;
resolve_root_constants.rect_samples_lw = resolve_root_constants.rect_samples_lw =
(copy_rect.left << (samples_x_log2 + resolution_scale_log2)) | (copy_rect.left << (samples_x_log2 + resolution_scale_log2)) |
(copy_width << (16 + 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) | samples_y_log2 | (samples_x_log2 << 1) |
(resolution_scale_edge_clamp ? (1 << 6) : 0) | (resolution_scale_edge_clamp ? (1 << 6) : 0) |
((uint32_t(dest_exp_bias) & 0x3F) << 7); ((uint32_t(dest_exp_bias) & 0x3F) << 7);
if (msaa_samples == MsaaSamples::k1X) { if (msaa_samples == xenos::MsaaSamples::k1X) {
// No offset. // No offset.
resolve_root_constants.resolve_info |= (1 << 2) | (1 << 4); 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. // -0.5 or +0.5 samples vertical offset if getting only one sample.
if (sample_select == xenos::CopySampleSelect::k0) { if (sample_select == xenos::CopySampleSelect::k0) {
resolve_root_constants.resolve_info |= (0 << 2) | (1 << 4); 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; D3D12_SHADER_RESOURCE_VIEW_DESC rt_srv_desc;
rt_srv_desc.Format = rt_srv_desc.Format =
GetColorDXGIFormat(ColorRenderTargetFormat(src_format)); GetColorDXGIFormat(xenos::ColorRenderTargetFormat(src_format));
rt_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; rt_srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
UINT swizzle = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; UINT swizzle = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if (dest_swap) { if (dest_swap) {
switch (ColorRenderTargetFormat(src_format)) { switch (xenos::ColorRenderTargetFormat(src_format)) {
case ColorRenderTargetFormat::k_8_8_8_8: case xenos::ColorRenderTargetFormat::k_8_8_8_8:
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
case ColorRenderTargetFormat::k_2_10_10_10: case xenos::ColorRenderTargetFormat::k_2_10_10_10:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_16_16_16_16: case xenos::ColorRenderTargetFormat::k_16_16_16_16:
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
case ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10: case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: 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); swizzle = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(2, 1, 0, 3);
break; break;
default: default:
break; 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 bits of the resolve target used for blue, and blue bits used for
// green. // green.
swizzle = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( 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_list->D3DSetGraphicsRootDescriptorTable(1, descriptor_rt.second);
command_processor_->SubmitBarriers(); command_processor_->SubmitBarriers();
command_processor_->SetSamplePositions(MsaaSamples::k1X); command_processor_->SetSamplePositions(xenos::MsaaSamples::k1X);
command_processor_->SetExternalGraphicsPipeline(resolve_pipeline); command_processor_->SetExternalGraphicsPipeline(resolve_pipeline);
command_list->D3DOMSetRenderTargets(1, &resolve_target->rtv_handle, TRUE, command_list->D3DOMSetRenderTargets(1, &resolve_target->rtv_handle, TRUE,
nullptr); nullptr);
@ -1881,8 +1882,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
bool RenderTargetCache::ResolveClear(uint32_t edram_base, bool RenderTargetCache::ResolveClear(uint32_t edram_base,
uint32_t surface_pitch, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth, xenos::MsaaSamples msaa_samples,
uint32_t format, const D3D12_RECT& rect) { bool is_depth, uint32_t format,
const D3D12_RECT& rect) {
auto& regs = *register_file_; auto& regs = *register_file_;
// Check if clearing is enabled. // Check if clearing is enabled.
@ -1902,7 +1904,7 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
// Calculate the layout. // Calculate the layout.
bool is_64bpp = bool is_64bpp =
!is_depth && IsColorFormat64bpp(ColorRenderTargetFormat(format)); !is_depth && IsColorFormat64bpp(xenos::ColorRenderTargetFormat(format));
D3D12_RECT clear_rect = rect; D3D12_RECT clear_rect = rect;
uint32_t surface_pitch_tiles, row_width_ss_div_80, rows; uint32_t surface_pitch_tiles, row_width_ss_div_80, rows;
if (!GetEDRAMLayout(surface_pitch, msaa_samples, is_64bpp, edram_base, if (!GetEDRAMLayout(surface_pitch, msaa_samples, is_64bpp, edram_base,
@ -1911,8 +1913,8 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
// Nothing to clear. // Nothing to clear.
return true; return true;
} }
uint32_t samples_x_log2 = msaa_samples >= MsaaSamples::k4X ? 1 : 0; uint32_t samples_x_log2 = msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= MsaaSamples::k2X ? 1 : 0; uint32_t samples_y_log2 = msaa_samples >= xenos::MsaaSamples::k2X ? 1 : 0;
// Get transient data needed for clearing. // Get transient data needed for clearing.
ui::d3d12::util::DescriptorCPUGPUHandlePair descriptor_edram; ui::d3d12::util::DescriptorCPUGPUHandlePair descriptor_edram;
@ -1941,7 +1943,8 @@ bool RenderTargetCache::ResolveClear(uint32_t edram_base,
(surface_pitch_tiles << 16); (surface_pitch_tiles << 16);
// When ROV is used, there's no 32-bit depth buffer. // When ROV is used, there's no 32-bit depth buffer.
if (!edram_rov_used_ && is_depth && 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; 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. // 20e4 [0,2), based on CFloat24 from d3dref9.dll and on 6e4 in DirectXTex.
uint32_t depth24 = root_constants.clear_depth24 >> 8; uint32_t depth24 = root_constants.clear_depth24 >> 8;
@ -2222,42 +2225,42 @@ void RenderTargetCache::WriteEDRAMRawUAVDescriptor(
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
} }
ColorRenderTargetFormat RenderTargetCache::GetBaseColorFormat( xenos::ColorRenderTargetFormat RenderTargetCache::GetBaseColorFormat(
ColorRenderTargetFormat format) { xenos::ColorRenderTargetFormat format) {
switch (format) { switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return ColorRenderTargetFormat::k_8_8_8_8; return xenos::ColorRenderTargetFormat::k_8_8_8_8;
case ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10: case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
return ColorRenderTargetFormat::k_2_10_10_10; return xenos::ColorRenderTargetFormat::k_2_10_10_10;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return ColorRenderTargetFormat::k_2_10_10_10_FLOAT; return xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT;
default: default:
return format; return format;
} }
} }
DXGI_FORMAT RenderTargetCache::GetColorDXGIFormat( DXGI_FORMAT RenderTargetCache::GetColorDXGIFormat(
ColorRenderTargetFormat format) { xenos::ColorRenderTargetFormat format) {
switch (format) { switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8: case xenos::ColorRenderTargetFormat::k_8_8_8_8:
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return DXGI_FORMAT_R8G8B8A8_UNORM; return DXGI_FORMAT_R8G8B8A8_UNORM;
case ColorRenderTargetFormat::k_2_10_10_10: case xenos::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_AS_10_10_10_10:
return DXGI_FORMAT_R10G10B10A2_UNORM; return DXGI_FORMAT_R10G10B10A2_UNORM;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case xenos::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_AS_16_16_16_16:
return DXGI_FORMAT_R16G16B16A16_FLOAT; return DXGI_FORMAT_R16G16B16A16_FLOAT;
case ColorRenderTargetFormat::k_16_16: case xenos::ColorRenderTargetFormat::k_16_16:
return DXGI_FORMAT_R16G16_SNORM; 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; return DXGI_FORMAT_R16G16B16A16_SNORM;
case ColorRenderTargetFormat::k_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_FLOAT:
return DXGI_FORMAT_R16G16_FLOAT; return DXGI_FORMAT_R16G16_FLOAT;
case ColorRenderTargetFormat::k_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_FLOAT:
return DXGI_FORMAT_R32_FLOAT; return DXGI_FORMAT_R32_FLOAT;
case ColorRenderTargetFormat::k_32_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_32_FLOAT:
return DXGI_FORMAT_R32G32_FLOAT; return DXGI_FORMAT_R32G32_FLOAT;
default: default:
break; break;
@ -2412,7 +2415,7 @@ void RenderTargetCache::CommitEDRAMBufferUAVWrites(bool force) {
void RenderTargetCache::ClearBindings() { void RenderTargetCache::ClearBindings() {
current_surface_pitch_ = 0; current_surface_pitch_ = 0;
current_msaa_samples_ = MsaaSamples::k1X; current_msaa_samples_ = xenos::MsaaSamples::k1X;
current_edram_max_rows_ = 0; current_edram_max_rows_ = 0;
std::memset(current_bindings_, 0, sizeof(current_bindings_)); std::memset(current_bindings_, 0, sizeof(current_bindings_));
apply_to_command_list_ = true; apply_to_command_list_ = true;
@ -2481,8 +2484,9 @@ bool RenderTargetCache::GetResourceDesc(RenderTargetKey key,
return false; return false;
} }
DXGI_FORMAT dxgi_format = DXGI_FORMAT dxgi_format =
key.is_depth ? GetDepthDXGIFormat(DepthRenderTargetFormat(key.format)) key.is_depth
: GetColorDXGIFormat(ColorRenderTargetFormat(key.format)); ? GetDepthDXGIFormat(xenos::DepthRenderTargetFormat(key.format))
: GetColorDXGIFormat(xenos::ColorRenderTargetFormat(key.format));
if (dxgi_format == DXGI_FORMAT_UNKNOWN) { if (dxgi_format == DXGI_FORMAT_UNKNOWN) {
return false; return false;
} }
@ -2651,7 +2655,7 @@ RenderTargetCache::RenderTarget* RenderTargetCache::FindOrCreateRenderTarget(
} }
bool RenderTargetCache::GetEDRAMLayout( 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& 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) { 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 || if (pitch_pixels == 0 || rect_in_out.right <= 0 || rect_in_out.bottom <= 0 ||
@ -2667,8 +2671,8 @@ bool RenderTargetCache::GetEDRAMLayout(
return false; return false;
} }
uint32_t samples_x_log2 = msaa_samples >= MsaaSamples::k4X ? 1 : 0; uint32_t samples_x_log2 = msaa_samples >= xenos::MsaaSamples::k4X ? 1 : 0;
uint32_t samples_y_log2 = msaa_samples >= MsaaSamples::k2X ? 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 sample_size_log2 = is_64bpp ? 1 : 0;
uint32_t pitch_tiles = (((pitch_pixels << samples_x_log2) + 79) / 80) uint32_t pitch_tiles = (((pitch_pixels << samples_x_log2) + 79) / 80)
@ -2711,14 +2715,16 @@ bool RenderTargetCache::GetEDRAMLayout(
RenderTargetCache::EDRAMLoadStoreMode RenderTargetCache::GetLoadStoreMode( RenderTargetCache::EDRAMLoadStoreMode RenderTargetCache::GetLoadStoreMode(
bool is_depth, uint32_t format) { bool is_depth, uint32_t format) {
if (is_depth) { if (is_depth) {
return DepthRenderTargetFormat(format) == DepthRenderTargetFormat::kD24FS8 return xenos::DepthRenderTargetFormat(format) ==
xenos::DepthRenderTargetFormat::kD24FS8
? EDRAMLoadStoreMode::kDepthFloat ? EDRAMLoadStoreMode::kDepthFloat
: EDRAMLoadStoreMode::kDepthUnorm; : EDRAMLoadStoreMode::kDepthUnorm;
} }
ColorRenderTargetFormat color_format = ColorRenderTargetFormat(format); xenos::ColorRenderTargetFormat color_format =
if (color_format == ColorRenderTargetFormat::k_2_10_10_10_FLOAT || xenos::ColorRenderTargetFormat(format);
if (color_format == xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT ||
color_format == 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 EDRAMLoadStoreMode::kColor7e3;
} }
return IsColorFormat64bpp(color_format) ? EDRAMLoadStoreMode::kColor64bpp return IsColorFormat64bpp(color_format) ? EDRAMLoadStoreMode::kColor64bpp
@ -2824,7 +2830,7 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
// Calculate the dispatch width. // Calculate the dispatch width.
uint32_t surface_pitch_ss = uint32_t surface_pitch_ss =
current_surface_pitch_ * 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; uint32_t surface_pitch_tiles = (surface_pitch_ss + 79) / 80;
assert_true(surface_pitch_tiles != 0); assert_true(surface_pitch_tiles != 0);
@ -2854,7 +2860,7 @@ void RenderTargetCache::StoreRenderTargetsToEDRAM() {
uint32_t rt_pitch_tiles = surface_pitch_tiles; uint32_t rt_pitch_tiles = surface_pitch_tiles;
if (!render_target->key.is_depth && if (!render_target->key.is_depth &&
IsColorFormat64bpp( IsColorFormat64bpp(
ColorRenderTargetFormat(render_target->key.format))) { xenos::ColorRenderTargetFormat(render_target->key.format))) {
rt_pitch_tiles *= 2; rt_pitch_tiles *= 2;
} }
// TODO(Triang3l): log2(sample count, resolution scale). // 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; uint32_t edram_pitch_tiles = render_target->key.width_ss_div_80;
if (!render_target->key.is_depth && if (!render_target->key.is_depth &&
IsColorFormat64bpp( IsColorFormat64bpp(
ColorRenderTargetFormat(render_target->key.format))) { xenos::ColorRenderTargetFormat(render_target->key.format))) {
edram_pitch_tiles *= 2; edram_pitch_tiles *= 2;
} }
// Clamp the height if somehow requested a render target that is too large. // 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 // 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. // 2_10_10_10_FLOAT and 2_10_10_10_FLOAT_AS_16_16_16_16 every draw.
static ColorRenderTargetFormat GetBaseColorFormat( static xenos::ColorRenderTargetFormat GetBaseColorFormat(
ColorRenderTargetFormat format); xenos::ColorRenderTargetFormat format);
static inline bool IsColorFormat64bpp(ColorRenderTargetFormat format) { static inline bool IsColorFormat64bpp(xenos::ColorRenderTargetFormat format) {
return format == ColorRenderTargetFormat::k_16_16_16_16 || return format == xenos::ColorRenderTargetFormat::k_16_16_16_16 ||
format == ColorRenderTargetFormat::k_16_16_16_16_FLOAT || format == xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT ||
format == ColorRenderTargetFormat::k_32_32_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 // Nvidia may have higher performance with 24-bit depth, AMD should have no
// performance difference, but with EDRAM loads/stores less conversion should // 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 // be performed by the shaders if D24S8 is emulated as D24_UNORM_S8_UINT, and
// it's probably more accurate. // it's probably more accurate.
static inline DXGI_FORMAT GetDepthDXGIFormat(DepthRenderTargetFormat format) { static inline DXGI_FORMAT GetDepthDXGIFormat(
return format == DepthRenderTargetFormat::kD24FS8 xenos::DepthRenderTargetFormat format) {
return format == xenos::DepthRenderTargetFormat::kD24FS8
? DXGI_FORMAT_D32_FLOAT_S8X24_UINT ? DXGI_FORMAT_D32_FLOAT_S8X24_UINT
: DXGI_FORMAT_D24_UNORM_S8_UINT; : DXGI_FORMAT_D24_UNORM_S8_UINT;
} }
@ -396,8 +397,8 @@ class RenderTargetCache {
uint32_t edram_dirty_rows; uint32_t edram_dirty_rows;
union { union {
uint32_t format; uint32_t format;
ColorRenderTargetFormat color_format; xenos::ColorRenderTargetFormat color_format;
DepthRenderTargetFormat depth_format; xenos::DepthRenderTargetFormat depth_format;
}; };
RenderTarget* render_target; RenderTarget* render_target;
}; };
@ -472,9 +473,10 @@ class RenderTargetCache {
// rectangle is within the bounds of EDRAM and is not empty, but if it returns // 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 // false, the output values may not be written, so the return value must be
// checked. // checked.
static bool GetEDRAMLayout(uint32_t pitch_pixels, MsaaSamples msaa_samples, static bool GetEDRAMLayout(uint32_t pitch_pixels,
bool is_64bpp, uint32_t& base_in_out, xenos::MsaaSamples msaa_samples, bool is_64bpp,
D3D12_RECT& rect_in_out, uint32_t& pitch_tiles_out, 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& row_width_ss_div_80_out,
uint32_t& rows_out); uint32_t& rows_out);
@ -493,13 +495,13 @@ class RenderTargetCache {
// Performs the copying part of a resolve. // Performs the copying part of a resolve.
bool ResolveCopy(SharedMemory* shared_memory, TextureCache* texture_cache, bool ResolveCopy(SharedMemory* shared_memory, TextureCache* texture_cache,
uint32_t edram_base, uint32_t surface_pitch, uint32_t edram_base, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth, uint32_t src_format, xenos::MsaaSamples msaa_samples, bool is_depth,
const D3D12_RECT& rect, uint32_t& written_address_out, uint32_t src_format, const D3D12_RECT& rect,
uint32_t& written_length_out); uint32_t& written_address_out, uint32_t& written_length_out);
// Performs the clearing part of a resolve. // Performs the clearing part of a resolve.
bool ResolveClear(uint32_t edram_base, uint32_t surface_pitch, bool ResolveClear(uint32_t edram_base, uint32_t surface_pitch,
MsaaSamples msaa_samples, bool is_depth, uint32_t format, xenos::MsaaSamples msaa_samples, bool is_depth,
const D3D12_RECT& rect); uint32_t format, const D3D12_RECT& rect);
ID3D12PipelineState* GetResolvePipeline(DXGI_FORMAT dest_format); ID3D12PipelineState* GetResolvePipeline(DXGI_FORMAT dest_format);
// Returns any available resolve target placed at least at // Returns any available resolve target placed at least at
@ -646,7 +648,7 @@ class RenderTargetCache {
std::unordered_multimap<uint32_t, RenderTarget*> render_targets_; std::unordered_multimap<uint32_t, RenderTarget*> render_targets_;
uint32_t current_surface_pitch_ = 0; 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). // current_edram_max_rows_ is for RTV/DSV only (render target texture size).
uint32_t current_edram_max_rows_ = 0; uint32_t current_edram_max_rows_ = 0;
RenderTargetBinding current_bindings_[5] = {}; RenderTargetBinding current_bindings_[5] = {};

View File

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

View File

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

View File

@ -414,8 +414,8 @@ void DxbcShaderTranslator::StartVertexShader_LoadVertexIndex() {
// 8-in-16 or one half of 8-in-32. // 8-in-16 or one half of 8-in-32.
DxbcOpSwitch(endian_src); DxbcOpSwitch(endian_src);
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian::k8in16))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian::k8in16)));
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian::k8in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian::k8in32)));
// Temp = X0Z0. // Temp = X0Z0.
DxbcOpAnd(swap_temp_dest, index_src, DxbcSrc::LU(0x00FF00FF)); DxbcOpAnd(swap_temp_dest, index_src, DxbcSrc::LU(0x00FF00FF));
// Index = YZW0. // Index = YZW0.
@ -429,8 +429,8 @@ void DxbcShaderTranslator::StartVertexShader_LoadVertexIndex() {
// 16-in-32 or another half of 8-in-32. // 16-in-32 or another half of 8-in-32.
DxbcOpSwitch(endian_src); DxbcOpSwitch(endian_src);
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian::k8in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian::k8in32)));
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian::k16in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian::k16in32)));
// Temp = ZW00. // Temp = ZW00.
DxbcOpUShR(swap_temp_dest, index_src, DxbcSrc::LU(16)); DxbcOpUShR(swap_temp_dest, index_src, DxbcSrc::LU(16));
// Index = ZWXY. // Index = ZWXY.
@ -684,7 +684,7 @@ void DxbcShaderTranslator::StartPixelShader() {
// set). // set).
DxbcOpAnd(DxbcDest::R(centroid_register, 0b0001), sampling_pattern_src, DxbcOpAnd(DxbcDest::R(centroid_register, 0b0001), sampling_pattern_src,
DxbcSrc::LU(uint32_t(1) << i)); DxbcSrc::LU(uint32_t(1) << i));
DxbcOpIf(bool(SampleLocation::kCenter), DxbcOpIf(bool(xenos::SampleLocation::kCenter),
DxbcSrc::R(centroid_register, DxbcSrc::kXXXX)); DxbcSrc::R(centroid_register, DxbcSrc::kXXXX));
// At center. // At center.
DxbcOpMov(uses_register_dynamic_addressing() ? DxbcDest::X(0, i) DxbcOpMov(uses_register_dynamic_addressing() ? DxbcDest::X(0, i)
@ -811,7 +811,7 @@ void DxbcShaderTranslator::StartPixelShader() {
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
kSysConst_InterpolatorSamplingPattern_Vec) kSysConst_InterpolatorSamplingPattern_Vec)
.Select(kSysConst_InterpolatorSamplingPattern_Comp)); .Select(kSysConst_InterpolatorSamplingPattern_Comp));
DxbcOpIf(bool(SampleLocation::kCenter), DxbcOpIf(bool(xenos::SampleLocation::kCenter),
DxbcSrc::R(param_gen_temp, DxbcSrc::kZZZZ)); DxbcSrc::R(param_gen_temp, DxbcSrc::kZZZZ));
// At center. // At center.
DxbcOpMov(point_coord_r_zw_dest, point_coord_v_xxxy_src); DxbcOpMov(point_coord_r_zw_dest, point_coord_v_xxxy_src);
@ -2641,14 +2641,15 @@ void DxbcShaderTranslator::WriteResourceDefinitions() {
texture_bindings_[texture_binding_index]; texture_bindings_[texture_binding_index];
texture_name_offset = texture_binding.bindful_srv_rdef_name_offset; texture_name_offset = texture_binding.bindful_srv_rdef_name_offset;
switch (texture_binding.dimension) { switch (texture_binding.dimension) {
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
texture_dimension = DxbcRdefDimension::kSRVTexture3D; texture_dimension = DxbcRdefDimension::kSRVTexture3D;
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
texture_dimension = DxbcRdefDimension::kSRVTextureCube; texture_dimension = DxbcRdefDimension::kSRVTextureCube;
break; break;
default: default:
assert_true(texture_binding.dimension == TextureDimension::k2D); assert_true(texture_binding.dimension ==
xenos::FetchOpDimension::k2D);
texture_dimension = DxbcRdefDimension::kSRVTexture2DArray; texture_dimension = DxbcRdefDimension::kSRVTexture2DArray;
} }
texture_register = uint32_t(SRVMainRegister::kBindfulTexturesStart) + texture_register = uint32_t(SRVMainRegister::kBindfulTexturesStart) +
@ -3540,14 +3541,15 @@ void DxbcShaderTranslator::WriteShaderCode() {
const TextureBinding& texture_binding = const TextureBinding& texture_binding =
texture_bindings_[texture_binding_index]; texture_bindings_[texture_binding_index];
switch (texture_binding.dimension) { switch (texture_binding.dimension) {
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURE3D; texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURE3D;
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURECUBE; texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURECUBE;
break; break;
default: default:
assert_true(texture_binding.dimension == TextureDimension::k2D); assert_true(texture_binding.dimension ==
xenos::FetchOpDimension::k2D);
texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURE2DARRAY; texture_srv_dimension = D3D10_SB_RESOURCE_DIMENSION_TEXTURE2DARRAY;
} }
texture_register_first = texture_register_last = texture_register_first = texture_register_last =

View File

@ -218,7 +218,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
}; };
uint32_t line_loop_closing_index; uint32_t line_loop_closing_index;
Endian vertex_index_endian; xenos::Endian vertex_index_endian;
int32_t vertex_base_index; int32_t vertex_base_index;
float point_size[2]; float point_size[2];
@ -360,7 +360,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
uint32_t fetch_constant; uint32_t fetch_constant;
// Stacked and 3D are separate TextureBindings, even for bindless for null // Stacked and 3D are separate TextureBindings, even for bindless for null
// descriptor handling simplicity. // descriptor handling simplicity.
TextureDimension dimension; xenos::FetchOpDimension dimension;
bool is_signed; bool is_signed;
std::string name; std::string name;
}; };
@ -385,10 +385,10 @@ class DxbcShaderTranslator : public ShaderTranslator {
struct SamplerBinding { struct SamplerBinding {
uint32_t bindless_descriptor_index; uint32_t bindless_descriptor_index;
uint32_t fetch_constant; uint32_t fetch_constant;
TextureFilter mag_filter; xenos::TextureFilter mag_filter;
TextureFilter min_filter; xenos::TextureFilter min_filter;
TextureFilter mip_filter; xenos::TextureFilter mip_filter;
AnisoFilter aniso_filter; xenos::AnisoFilter aniso_filter;
std::string name; std::string name;
}; };
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const { const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
@ -415,24 +415,24 @@ class DxbcShaderTranslator : public ShaderTranslator {
// Returns the format with internal flags for passing via the // Returns the format with internal flags for passing via the
// edram_rt_format_flags system constant. // edram_rt_format_flags system constant.
static constexpr uint32_t ROV_AddColorFormatFlags( static constexpr uint32_t ROV_AddColorFormatFlags(
ColorRenderTargetFormat format) { xenos::ColorRenderTargetFormat format) {
uint32_t format_flags = uint32_t(format); uint32_t format_flags = uint32_t(format);
if (format == ColorRenderTargetFormat::k_16_16_16_16 || if (format == xenos::ColorRenderTargetFormat::k_16_16_16_16 ||
format == ColorRenderTargetFormat::k_16_16_16_16_FLOAT || format == xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT ||
format == ColorRenderTargetFormat::k_32_32_FLOAT) { format == xenos::ColorRenderTargetFormat::k_32_32_FLOAT) {
format_flags |= kRTFormatFlag_64bpp; format_flags |= kRTFormatFlag_64bpp;
} }
if (format == ColorRenderTargetFormat::k_8_8_8_8 || if (format == xenos::ColorRenderTargetFormat::k_8_8_8_8 ||
format == ColorRenderTargetFormat::k_8_8_8_8_GAMMA || format == xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA ||
format == ColorRenderTargetFormat::k_2_10_10_10 || format == xenos::ColorRenderTargetFormat::k_2_10_10_10 ||
format == ColorRenderTargetFormat::k_16_16 || format == xenos::ColorRenderTargetFormat::k_16_16 ||
format == ColorRenderTargetFormat::k_16_16_16_16 || format == xenos::ColorRenderTargetFormat::k_16_16_16_16 ||
format == ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10) { format == xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10) {
format_flags |= format_flags |=
kRTFormatFlag_FixedPointColor | kRTFormatFlag_FixedPointAlpha; kRTFormatFlag_FixedPointColor | kRTFormatFlag_FixedPointAlpha;
} else if (format == ColorRenderTargetFormat::k_2_10_10_10_FLOAT || } else if (format == xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT ||
format == format == xenos::ColorRenderTargetFormat::
ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16) { k_2_10_10_10_FLOAT_AS_16_16_16_16) {
format_flags |= kRTFormatFlag_FixedPointAlpha; format_flags |= kRTFormatFlag_FixedPointAlpha;
} }
return format_flags; return format_flags;
@ -441,9 +441,10 @@ class DxbcShaderTranslator : public ShaderTranslator {
// be done externally, not in SetColorFormatConstants, because the flags // be done externally, not in SetColorFormatConstants, because the flags
// contain other state. // contain other state.
static void ROV_GetColorFormatSystemConstants( static void ROV_GetColorFormatSystemConstants(
ColorRenderTargetFormat format, uint32_t write_mask, float& clamp_rgb_low, xenos::ColorRenderTargetFormat format, uint32_t write_mask,
float& clamp_alpha_low, float& clamp_rgb_high, float& clamp_alpha_high, float& clamp_rgb_low, float& clamp_alpha_low, float& clamp_rgb_high,
uint32_t& keep_mask_low, uint32_t& keep_mask_high); float& clamp_alpha_high, uint32_t& keep_mask_low,
uint32_t& keep_mask_high);
// Creates a special pixel shader without color outputs - this resets the // Creates a special pixel shader without color outputs - this resets the
// state of the translator. // state of the translator.
@ -2361,12 +2362,13 @@ class DxbcShaderTranslator : public ShaderTranslator {
void JumpToLabel(uint32_t address); void JumpToLabel(uint32_t address);
uint32_t FindOrAddTextureBinding(uint32_t fetch_constant, uint32_t FindOrAddTextureBinding(uint32_t fetch_constant,
TextureDimension dimension, bool is_signed); xenos::FetchOpDimension dimension,
bool is_signed);
uint32_t FindOrAddSamplerBinding(uint32_t fetch_constant, uint32_t FindOrAddSamplerBinding(uint32_t fetch_constant,
TextureFilter mag_filter, xenos::TextureFilter mag_filter,
TextureFilter min_filter, xenos::TextureFilter min_filter,
TextureFilter mip_filter, xenos::TextureFilter mip_filter,
AnisoFilter aniso_filter); xenos::AnisoFilter aniso_filter);
// Marks fetch constants as used by the DXBC shader and returns DxbcSrc // Marks fetch constants as used by the DXBC shader and returns DxbcSrc
// for the words 01 (pair 0), 23 (pair 1) or 45 (pair 2) of the texture fetch // for the words 01 (pair 0), 23 (pair 1) or 45 (pair 2) of the texture fetch
// constant. // constant.

View File

@ -32,7 +32,7 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
instr.predicate_condition); instr.predicate_condition);
uint32_t used_result_components = instr.result.GetUsedResultComponents(); uint32_t used_result_components = instr.result.GetUsedResultComponents();
uint32_t needed_words = GetVertexFormatNeededWords( uint32_t needed_words = xenos::GetVertexFormatNeededWords(
instr.attributes.data_format, used_result_components); instr.attributes.data_format, used_result_components);
if (!needed_words) { if (!needed_words) {
// Nothing to load - just constant 0/1 writes, or the swizzle includes only // Nothing to load - just constant 0/1 writes, or the swizzle includes only
@ -217,8 +217,8 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
// 8-in-16 or one half of 8-in-32. // 8-in-16 or one half of 8-in-32.
DxbcOpSwitch(endian_src); DxbcOpSwitch(endian_src);
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k8in16))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k8in16)));
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k8in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k8in32)));
// Temp = X0Z0. // Temp = X0Z0.
DxbcOpAnd(swap_temp_dest, result_src, DxbcSrc::LU(0x00FF00FF)); DxbcOpAnd(swap_temp_dest, result_src, DxbcSrc::LU(0x00FF00FF));
// Result = YZW0. // Result = YZW0.
@ -232,8 +232,8 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
// 16-in-32 or another half of 8-in-32. // 16-in-32 or another half of 8-in-32.
DxbcOpSwitch(endian_src); DxbcOpSwitch(endian_src);
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k8in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k8in32)));
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k16in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k16in32)));
// Temp = ZW00. // Temp = ZW00.
DxbcOpUShR(swap_temp_dest, result_src, DxbcSrc::LU(16)); DxbcOpUShR(swap_temp_dest, result_src, DxbcSrc::LU(16));
// Result = ZWXY. // Result = ZWXY.
@ -249,8 +249,9 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
// - Unpack the format. // - Unpack the format.
uint32_t used_format_components = uint32_t used_format_components =
used_result_components & used_result_components & ((1 << xenos::GetVertexFormatComponentCount(
((1 << GetVertexFormatComponentCount(instr.attributes.data_format)) - 1); instr.attributes.data_format)) -
1);
DxbcDest result_unpacked_dest( DxbcDest result_unpacked_dest(
DxbcDest::R(system_temp_result_, used_format_components)); DxbcDest::R(system_temp_result_, used_format_components));
// If needed_words is not zero (checked in the beginning), this must not be // If needed_words is not zero (checked in the beginning), this must not be
@ -260,37 +261,37 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
uint32_t packed_widths[4] = {}, packed_offsets[4] = {}; uint32_t packed_widths[4] = {}, packed_offsets[4] = {};
uint32_t packed_swizzle = DxbcSrc::kXXXX; uint32_t packed_swizzle = DxbcSrc::kXXXX;
switch (instr.attributes.data_format) { switch (instr.attributes.data_format) {
case VertexFormat::k_8_8_8_8: case xenos::VertexFormat::k_8_8_8_8:
packed_widths[0] = packed_widths[1] = packed_widths[2] = packed_widths[0] = packed_widths[1] = packed_widths[2] =
packed_widths[3] = 8; packed_widths[3] = 8;
packed_offsets[1] = 8; packed_offsets[1] = 8;
packed_offsets[2] = 16; packed_offsets[2] = 16;
packed_offsets[3] = 24; packed_offsets[3] = 24;
break; break;
case VertexFormat::k_2_10_10_10: case xenos::VertexFormat::k_2_10_10_10:
packed_widths[0] = packed_widths[1] = packed_widths[2] = 10; packed_widths[0] = packed_widths[1] = packed_widths[2] = 10;
packed_widths[3] = 2; packed_widths[3] = 2;
packed_offsets[1] = 10; packed_offsets[1] = 10;
packed_offsets[2] = 20; packed_offsets[2] = 20;
packed_offsets[3] = 30; packed_offsets[3] = 30;
break; break;
case VertexFormat::k_10_11_11: case xenos::VertexFormat::k_10_11_11:
packed_widths[0] = packed_widths[1] = 11; packed_widths[0] = packed_widths[1] = 11;
packed_widths[2] = 10; packed_widths[2] = 10;
packed_offsets[1] = 11; packed_offsets[1] = 11;
packed_offsets[2] = 22; packed_offsets[2] = 22;
break; break;
case VertexFormat::k_11_11_10: case xenos::VertexFormat::k_11_11_10:
packed_widths[0] = 10; packed_widths[0] = 10;
packed_widths[1] = packed_widths[2] = 11; packed_widths[1] = packed_widths[2] = 11;
packed_offsets[1] = 10; packed_offsets[1] = 10;
packed_offsets[2] = 21; packed_offsets[2] = 21;
break; break;
case VertexFormat::k_16_16: case xenos::VertexFormat::k_16_16:
packed_widths[0] = packed_widths[1] = 16; packed_widths[0] = packed_widths[1] = 16;
packed_offsets[1] = 16; packed_offsets[1] = 16;
break; break;
case VertexFormat::k_16_16_16_16: case xenos::VertexFormat::k_16_16_16_16:
packed_widths[0] = packed_widths[1] = packed_widths[2] = packed_widths[0] = packed_widths[1] = packed_widths[2] =
packed_widths[3] = 16; packed_widths[3] = 16;
packed_offsets[1] = packed_offsets[3] = 16; packed_offsets[1] = packed_offsets[3] = 16;
@ -373,8 +374,8 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
} }
} else { } else {
switch (instr.attributes.data_format) { switch (instr.attributes.data_format) {
case VertexFormat::k_16_16_FLOAT: case xenos::VertexFormat::k_16_16_FLOAT:
case VertexFormat::k_16_16_16_16_FLOAT: case xenos::VertexFormat::k_16_16_16_16_FLOAT:
// FIXME(Triang3l): This converts from D3D10+ float16 with NaNs instead // FIXME(Triang3l): This converts from D3D10+ float16 with NaNs instead
// of Xbox 360 float16 with extended range. However, haven't encountered // of Xbox 360 float16 with extended range. However, haven't encountered
// games relying on that yet. // games relying on that yet.
@ -383,9 +384,9 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
DxbcSrc::R(system_temp_result_, 0b01010000)); DxbcSrc::R(system_temp_result_, 0b01010000));
DxbcOpF16ToF32(result_unpacked_dest, result_src); DxbcOpF16ToF32(result_unpacked_dest, result_src);
break; break;
case VertexFormat::k_32: case xenos::VertexFormat::k_32:
case VertexFormat::k_32_32: case xenos::VertexFormat::k_32_32:
case VertexFormat::k_32_32_32_32: case xenos::VertexFormat::k_32_32_32_32:
if (instr.attributes.is_signed) { if (instr.attributes.is_signed) {
DxbcOpIToF(result_unpacked_dest, result_src); DxbcOpIToF(result_unpacked_dest, result_src);
} else { } else {
@ -414,10 +415,10 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
} }
} }
break; break;
case VertexFormat::k_32_FLOAT: case xenos::VertexFormat::k_32_FLOAT:
case VertexFormat::k_32_32_FLOAT: case xenos::VertexFormat::k_32_32_FLOAT:
case VertexFormat::k_32_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_32_FLOAT:
case VertexFormat::k_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_FLOAT:
// Already in the needed result components. // Already in the needed result components.
break; break;
default: default:
@ -447,11 +448,12 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
} }
uint32_t DxbcShaderTranslator::FindOrAddTextureBinding( uint32_t DxbcShaderTranslator::FindOrAddTextureBinding(
uint32_t fetch_constant, TextureDimension dimension, bool is_signed) { uint32_t fetch_constant, xenos::FetchOpDimension dimension,
bool is_signed) {
// 1D and 2D textures (including stacked ones) are treated as 2D arrays for // 1D and 2D textures (including stacked ones) are treated as 2D arrays for
// binding and coordinate simplicity. // binding and coordinate simplicity.
if (dimension == TextureDimension::k1D) { if (dimension == xenos::FetchOpDimension::k1D) {
dimension = TextureDimension::k2D; dimension = xenos::FetchOpDimension::k2D;
} }
uint32_t srv_index = UINT32_MAX; uint32_t srv_index = UINT32_MAX;
for (uint32_t i = 0; i < uint32_t(texture_bindings_.size()); ++i) { for (uint32_t i = 0; i < uint32_t(texture_bindings_.size()); ++i) {
@ -484,10 +486,10 @@ uint32_t DxbcShaderTranslator::FindOrAddTextureBinding(
new_texture_binding.is_signed = is_signed; new_texture_binding.is_signed = is_signed;
const char* dimension_name; const char* dimension_name;
switch (dimension) { switch (dimension) {
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
dimension_name = "3d"; dimension_name = "3d";
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
dimension_name = "cube"; dimension_name = "cube";
break; break;
default: default:
@ -500,15 +502,16 @@ uint32_t DxbcShaderTranslator::FindOrAddTextureBinding(
} }
uint32_t DxbcShaderTranslator::FindOrAddSamplerBinding( uint32_t DxbcShaderTranslator::FindOrAddSamplerBinding(
uint32_t fetch_constant, TextureFilter mag_filter, TextureFilter min_filter, uint32_t fetch_constant, xenos::TextureFilter mag_filter,
TextureFilter mip_filter, AnisoFilter aniso_filter) { xenos::TextureFilter min_filter, xenos::TextureFilter mip_filter,
xenos::AnisoFilter aniso_filter) {
// In Direct3D 12, anisotropic filtering implies linear filtering. // In Direct3D 12, anisotropic filtering implies linear filtering.
if (aniso_filter != AnisoFilter::kDisabled && if (aniso_filter != xenos::AnisoFilter::kDisabled &&
aniso_filter != AnisoFilter::kUseFetchConst) { aniso_filter != xenos::AnisoFilter::kUseFetchConst) {
mag_filter = TextureFilter::kLinear; mag_filter = xenos::TextureFilter::kLinear;
min_filter = TextureFilter::kLinear; min_filter = xenos::TextureFilter::kLinear;
mip_filter = TextureFilter::kLinear; mip_filter = xenos::TextureFilter::kLinear;
aniso_filter = std::min(aniso_filter, AnisoFilter::kMax_16_1); aniso_filter = std::min(aniso_filter, xenos::AnisoFilter::kMax_16_1);
} }
uint32_t sampler_index = UINT32_MAX; uint32_t sampler_index = UINT32_MAX;
for (uint32_t i = 0; i < uint32_t(sampler_bindings_.size()); ++i) { for (uint32_t i = 0; i < uint32_t(sampler_bindings_.size()); ++i) {
@ -527,15 +530,15 @@ uint32_t DxbcShaderTranslator::FindOrAddSamplerBinding(
} }
std::ostringstream name; std::ostringstream name;
name << "xe_sampler" << fetch_constant; name << "xe_sampler" << fetch_constant;
if (aniso_filter != AnisoFilter::kUseFetchConst) { if (aniso_filter != xenos::AnisoFilter::kUseFetchConst) {
if (aniso_filter == AnisoFilter::kDisabled) { if (aniso_filter == xenos::AnisoFilter::kDisabled) {
name << "_a0"; name << "_a0";
} else { } else {
name << "_a" << (1u << (uint32_t(aniso_filter) - 1)); name << "_a" << (1u << (uint32_t(aniso_filter) - 1));
} }
} }
if (aniso_filter == AnisoFilter::kDisabled || if (aniso_filter == xenos::AnisoFilter::kDisabled ||
aniso_filter == AnisoFilter::kUseFetchConst) { aniso_filter == xenos::AnisoFilter::kUseFetchConst) {
static const char* kFilterSuffixes[] = {"p", "l", "b", "f"}; static const char* kFilterSuffixes[] = {"p", "l", "b", "f"};
name << "_" << kFilterSuffixes[uint32_t(mag_filter)] name << "_" << kFilterSuffixes[uint32_t(mag_filter)]
<< kFilterSuffixes[uint32_t(min_filter)] << kFilterSuffixes[uint32_t(min_filter)]
@ -710,7 +713,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// but the left/upper pixel is still sampled instead. // but the left/upper pixel is still sampled instead.
const float rounding_offset = 1.0f / 1024.0f; const float rounding_offset = 1.0f / 1024.0f;
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
offsets[0] = instr.attributes.offset_x + rounding_offset; offsets[0] = instr.attributes.offset_x + rounding_offset;
if (instr.opcode == FetchOpcode::kGetTextureWeights) { if (instr.opcode == FetchOpcode::kGetTextureWeights) {
// For coordinate lerp factors. This needs to be done separately for // For coordinate lerp factors. This needs to be done separately for
@ -719,7 +722,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
offsets[0] -= 0.5f; offsets[0] -= 0.5f;
} }
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
offsets[0] = instr.attributes.offset_x + rounding_offset; offsets[0] = instr.attributes.offset_x + rounding_offset;
offsets[1] = instr.attributes.offset_y + rounding_offset; offsets[1] = instr.attributes.offset_y + rounding_offset;
if (instr.opcode == FetchOpcode::kGetTextureWeights) { if (instr.opcode == FetchOpcode::kGetTextureWeights) {
@ -727,7 +730,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
offsets[1] -= 0.5f; offsets[1] -= 0.5f;
} }
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
offsets[0] = instr.attributes.offset_x + rounding_offset; offsets[0] = instr.attributes.offset_x + rounding_offset;
offsets[1] = instr.attributes.offset_y + rounding_offset; offsets[1] = instr.attributes.offset_y + rounding_offset;
offsets[2] = instr.attributes.offset_z + rounding_offset; offsets[2] = instr.attributes.offset_z + rounding_offset;
@ -737,7 +740,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
offsets[2] -= 0.5f; offsets[2] -= 0.5f;
} }
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
// Applying the rounding epsilon to cube maps too for potential game // Applying the rounding epsilon to cube maps too for potential game
// passes processing cube map faces themselves. // passes processing cube map faces themselves.
offsets[0] = instr.attributes.offset_x + rounding_offset; offsets[0] = instr.attributes.offset_x + rounding_offset;
@ -777,14 +780,14 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// indices is used, coordinates will need to be normalized as normally). // indices is used, coordinates will need to be normalized as normally).
if (!instr.attributes.unnormalized_coordinates) { if (!instr.attributes.unnormalized_coordinates) {
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
size_needed_components |= used_result_nonzero_components & 0b0001; size_needed_components |= used_result_nonzero_components & 0b0001;
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
size_needed_components |= used_result_nonzero_components & 0b0011; size_needed_components |= used_result_nonzero_components & 0b0011;
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
size_needed_components |= used_result_nonzero_components & 0b0111; size_needed_components |= used_result_nonzero_components & 0b0111;
break; break;
} }
@ -794,17 +797,17 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// denormalization) and for offsets. // denormalization) and for offsets.
size_needed_components |= offsets_not_zero; size_needed_components |= offsets_not_zero;
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
size_needed_components |= 0b0001; size_needed_components |= 0b0001;
} }
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
size_needed_components |= 0b0011; size_needed_components |= 0b0011;
} }
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
// Stacked and 3D textures are fetched from different SRVs - the check // Stacked and 3D textures are fetched from different SRVs - the check
// is always needed. // is always needed.
size_needed_components |= 0b1000; size_needed_components |= 0b1000;
@ -816,7 +819,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
size_needed_components |= 0b0100; size_needed_components |= 0b0100;
} }
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
if (instr.attributes.unnormalized_coordinates) { if (instr.attributes.unnormalized_coordinates) {
size_needed_components |= 0b0011; size_needed_components |= 0b0011;
} }
@ -825,7 +828,8 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
break; break;
} }
} }
if (instr.dimension == TextureDimension::k3D && size_needed_components) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked &&
size_needed_components) {
// Stacked and 3D textures have different size packing - need to get whether // Stacked and 3D textures have different size packing - need to get whether
// the texture is 3D unconditionally. // the texture is 3D unconditionally.
size_needed_components |= 0b1000; size_needed_components |= 0b1000;
@ -834,25 +838,25 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
size_needed_components ? PushSystemTemp() : UINT32_MAX; size_needed_components ? PushSystemTemp() : UINT32_MAX;
if (size_needed_components) { if (size_needed_components) {
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
DxbcOpUBFE(DxbcDest::R(size_and_is_3d_temp, 0b0001), DxbcSrc::LU(24), DxbcOpUBFE(DxbcDest::R(size_and_is_3d_temp, 0b0001), DxbcSrc::LU(24),
DxbcSrc::LU(0), DxbcSrc::LU(0),
RequestTextureFetchConstantWord(tfetch_index, 2)); RequestTextureFetchConstantWord(tfetch_index, 2));
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
DxbcOpUBFE(DxbcDest::R(size_and_is_3d_temp, size_needed_components), DxbcOpUBFE(DxbcDest::R(size_and_is_3d_temp, size_needed_components),
DxbcSrc::LU(13, 13, 0, 0), DxbcSrc::LU(0, 13, 0, 0), DxbcSrc::LU(13, 13, 0, 0), DxbcSrc::LU(0, 13, 0, 0),
RequestTextureFetchConstantWord(tfetch_index, 2)); RequestTextureFetchConstantWord(tfetch_index, 2));
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
// tfetch3D is used for both stacked and 3D - first, check if 3D. // tfetch3D is used for both stacked and 3D - first, check if 3D.
DxbcOpUBFE(DxbcDest::R(size_and_is_3d_temp, 0b1000), DxbcSrc::LU(2), DxbcOpUBFE(DxbcDest::R(size_and_is_3d_temp, 0b1000), DxbcSrc::LU(2),
DxbcSrc::LU(9), DxbcSrc::LU(9),
RequestTextureFetchConstantWord(tfetch_index, 5)); RequestTextureFetchConstantWord(tfetch_index, 5));
DxbcOpIEq(DxbcDest::R(size_and_is_3d_temp, 0b1000), DxbcOpIEq(DxbcDest::R(size_and_is_3d_temp, 0b1000),
DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW), DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW),
DxbcSrc::LU(uint32_t(Dimension::k3D))); DxbcSrc::LU(uint32_t(xenos::DataDimension::k3D)));
if (size_needed_components & 0b0111) { if (size_needed_components & 0b0111) {
// Even if depth isn't needed specifically for stacked or specifically // Even if depth isn't needed specifically for stacked or specifically
// for 3D later, load both cases anyway to make sure the register is // for 3D later, load both cases anyway to make sure the register is
@ -969,18 +973,18 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
bool coord_operand_temp_pushed = false; bool coord_operand_temp_pushed = false;
DxbcSrc coord_operand = LoadOperand( DxbcSrc coord_operand = LoadOperand(
instr.operands[0], instr.operands[0],
(1 << GetTextureDimensionComponentCount(instr.dimension)) - 1, (1 << xenos::GetFetchOpDimensionComponentCount(instr.dimension)) - 1,
coord_operand_temp_pushed); coord_operand_temp_pushed);
uint32_t normalized_components = 0b0000; uint32_t normalized_components = 0b0000;
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
normalized_components = 0b0001; normalized_components = 0b0001;
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
normalized_components = 0b0011; normalized_components = 0b0011;
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
normalized_components = 0b0111; normalized_components = 0b0111;
break; break;
} }
@ -998,7 +1002,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
DxbcDest::R(coord_and_sampler_temp, normalized_components & 0b011), DxbcDest::R(coord_and_sampler_temp, normalized_components & 0b011),
DxbcSrc::R(coord_and_sampler_temp), DxbcSrc::R(coord_and_sampler_temp),
DxbcSrc::R(size_and_is_3d_temp)); DxbcSrc::R(size_and_is_3d_temp));
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Normalize if 3D. // Normalize if 3D.
assert_true((size_needed_components & 0b1100) == 0b1100); assert_true((size_needed_components & 0b1100) == 0b1100);
DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW)); DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW));
@ -1010,7 +1014,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
} else { } else {
DxbcOpDiv(DxbcDest::R(coord_and_sampler_temp, normalized_components), DxbcOpDiv(DxbcDest::R(coord_and_sampler_temp, normalized_components),
coord_operand, DxbcSrc::R(size_and_is_3d_temp)); coord_operand, DxbcSrc::R(size_and_is_3d_temp));
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Don't normalize if stacked. // Don't normalize if stacked.
assert_true((size_needed_components & 0b1000) == 0b1000); assert_true((size_needed_components & 0b1000) == 0b1000);
DxbcOpMovC(DxbcDest::R(coord_and_sampler_temp, 0b0100), DxbcOpMovC(DxbcDest::R(coord_and_sampler_temp, 0b0100),
@ -1040,7 +1044,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
DxbcDest::R(coord_and_sampler_temp, coords_without_offset & 0b011), DxbcDest::R(coord_and_sampler_temp, coords_without_offset & 0b011),
coord_operand); coord_operand);
} }
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
assert_true((size_needed_components & 0b1100) == 0b1100); assert_true((size_needed_components & 0b1100) == 0b1100);
if (coords_with_offset & 0b100) { if (coords_with_offset & 0b100) {
// Denormalize and offset Z (re-apply the offset not to lose precision // Denormalize and offset Z (re-apply the offset not to lose precision
@ -1064,17 +1068,17 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
} }
} }
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
// Pad to 2D array coordinates. // Pad to 2D array coordinates.
DxbcOpMov(DxbcDest::R(coord_and_sampler_temp, 0b0110), DxbcOpMov(DxbcDest::R(coord_and_sampler_temp, 0b0110),
DxbcSrc::LF(0.0f)); DxbcSrc::LF(0.0f));
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
// Pad to 2D array coordinates. // Pad to 2D array coordinates.
DxbcOpMov(DxbcDest::R(coord_and_sampler_temp, 0b0100), DxbcOpMov(DxbcDest::R(coord_and_sampler_temp, 0b0100),
DxbcSrc::LF(0.0f)); DxbcSrc::LF(0.0f));
break; break;
case TextureDimension::kCube: { case xenos::FetchOpDimension::kCube: {
// Transform from the major axis SC/TC plus 1 into cube coordinates. // Transform from the major axis SC/TC plus 1 into cube coordinates.
// Move SC/TC from 1...2 to -1...1. // Move SC/TC from 1...2 to -1...1.
DxbcOpMAd(DxbcDest::R(coord_and_sampler_temp, 0b0011), DxbcOpMAd(DxbcDest::R(coord_and_sampler_temp, 0b0011),
@ -1169,7 +1173,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// for getCompTexLOD). // for getCompTexLOD).
uint32_t sampler_binding_index = FindOrAddSamplerBinding( uint32_t sampler_binding_index = FindOrAddSamplerBinding(
tfetch_index, instr.attributes.mag_filter, tfetch_index, instr.attributes.mag_filter,
instr.attributes.min_filter, TextureFilter::kLinear, instr.attributes.min_filter, xenos::TextureFilter::kLinear,
instr.attributes.aniso_filter); instr.attributes.aniso_filter);
DxbcSrc sampler(DxbcSrc::S(sampler_binding_index, sampler_binding_index)); DxbcSrc sampler(DxbcSrc::S(sampler_binding_index, sampler_binding_index));
if (bindless_resources_used_) { if (bindless_resources_used_) {
@ -1193,23 +1197,26 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
system_constants_used_ |= 1ull << kSysConst_TextureSwizzledSigns_Index; system_constants_used_ |= 1ull << kSysConst_TextureSwizzledSigns_Index;
DxbcOpUBFE(DxbcDest::R(is_unsigned_temp, 0b0001), DxbcSrc::LU(8), DxbcOpUBFE(DxbcDest::R(is_unsigned_temp, 0b0001), DxbcSrc::LU(8),
DxbcSrc::LU(signs_shift), signs_uint_src); DxbcSrc::LU(signs_shift), signs_uint_src);
DxbcOpINE(DxbcDest::R(is_unsigned_temp, 0b0001), DxbcOpINE(
DxbcDest::R(is_unsigned_temp, 0b0001),
DxbcSrc::R(is_unsigned_temp, DxbcSrc::kXXXX), DxbcSrc::R(is_unsigned_temp, DxbcSrc::kXXXX),
DxbcSrc::LU(uint32_t(TextureSign::kSigned) * 0b01010101)); DxbcSrc::LU(uint32_t(xenos::TextureSign::kSigned) * 0b01010101));
if (bindless_resources_used_) { if (bindless_resources_used_) {
// Bindless path - select the SRV index between unsigned and signed to // Bindless path - select the SRV index between unsigned and signed to
// query. // query.
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Check if 3D. // Check if 3D.
assert_true((size_needed_components & 0b1000) == 0b1000); assert_true((size_needed_components & 0b1000) == 0b1000);
DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW)); DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW));
} }
for (uint32_t is_stacked = 0; for (uint32_t is_stacked = 0;
is_stacked < (instr.dimension == TextureDimension::k3D ? 2u : 1u); is_stacked <
(instr.dimension == xenos::FetchOpDimension::k3DOrStacked ? 2u
: 1u);
++is_stacked) { ++is_stacked) {
TextureDimension srv_dimension = instr.dimension; xenos::FetchOpDimension srv_dimension = instr.dimension;
if (is_stacked) { if (is_stacked) {
srv_dimension = TextureDimension::k2D; srv_dimension = xenos::FetchOpDimension::k2D;
DxbcOpElse(); DxbcOpElse();
} }
uint32_t texture_binding_index_unsigned = uint32_t texture_binding_index_unsigned =
@ -1251,14 +1258,14 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
assert_true(used_result_nonzero_components == 0b0001); assert_true(used_result_nonzero_components == 0b0001);
uint32_t* bindless_srv_index = nullptr; uint32_t* bindless_srv_index = nullptr;
switch (srv_dimension) { switch (srv_dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
bindless_srv_index = &srv_index_bindless_textures_2d_; bindless_srv_index = &srv_index_bindless_textures_2d_;
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
bindless_srv_index = &srv_index_bindless_textures_3d_; bindless_srv_index = &srv_index_bindless_textures_3d_;
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
bindless_srv_index = &srv_index_bindless_textures_cube_; bindless_srv_index = &srv_index_bindless_textures_cube_;
break; break;
} }
@ -1272,7 +1279,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
DxbcIndex(is_unsigned_temp, 0), DxbcSrc::kYYYY), DxbcIndex(is_unsigned_temp, 0), DxbcSrc::kYYYY),
sampler); sampler);
} }
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Close the 3D/stacked check. // Close the 3D/stacked check.
DxbcOpEndIf(); DxbcOpEndIf();
} }
@ -1283,14 +1290,15 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
if (is_signed) { if (is_signed) {
DxbcOpElse(); DxbcOpElse();
} }
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Check if 3D. // Check if 3D.
assert_true((size_needed_components & 0b1000) == 0b1000); assert_true((size_needed_components & 0b1000) == 0b1000);
DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW)); DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW));
} }
for (uint32_t is_stacked = 0; for (uint32_t is_stacked = 0;
is_stacked < is_stacked <
(instr.dimension == TextureDimension::k3D ? 2u : 1u); (instr.dimension == xenos::FetchOpDimension::k3DOrStacked ? 2u
: 1u);
++is_stacked) { ++is_stacked) {
if (is_stacked) { if (is_stacked) {
DxbcOpElse(); DxbcOpElse();
@ -1298,7 +1306,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
assert_true(used_result_nonzero_components == 0b0001); assert_true(used_result_nonzero_components == 0b0001);
uint32_t texture_binding_index = FindOrAddTextureBinding( uint32_t texture_binding_index = FindOrAddTextureBinding(
tfetch_index, tfetch_index,
is_stacked ? TextureDimension::k2D : instr.dimension, is_stacked ? xenos::FetchOpDimension::k2D : instr.dimension,
is_signed != 0); is_signed != 0);
DxbcOpLOD( DxbcOpLOD(
DxbcDest::R(system_temp_result_, 0b0001), DxbcDest::R(system_temp_result_, 0b0001),
@ -1310,7 +1318,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
DxbcSrc::kYYYY), DxbcSrc::kYYYY),
sampler); sampler);
} }
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Close the 3D/stacked check. // Close the 3D/stacked check.
DxbcOpEndIf(); DxbcOpEndIf();
} }
@ -1330,7 +1338,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// Will be allocated for computed LOD only, and if not using basemap mip // Will be allocated for computed LOD only, and if not using basemap mip
// filter. // filter.
uint32_t grad_v_temp = UINT32_MAX; uint32_t grad_v_temp = UINT32_MAX;
if (instr.attributes.mip_filter != TextureFilter::kBaseMap) { if (instr.attributes.mip_filter != xenos::TextureFilter::kBaseMap) {
grad_h_lod_temp = PushSystemTemp(); grad_h_lod_temp = PushSystemTemp();
lod_src = DxbcSrc::R(grad_h_lod_temp, DxbcSrc::kWWWW); lod_src = DxbcSrc::R(grad_h_lod_temp, DxbcSrc::kWWWW);
// Accumulate the explicit LOD sources (in D3D11.3 specification order: // Accumulate the explicit LOD sources (in D3D11.3 specification order:
@ -1362,14 +1370,14 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
if (use_computed_lod) { if (use_computed_lod) {
grad_v_temp = PushSystemTemp(); grad_v_temp = PushSystemTemp();
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
grad_component_count = 1; grad_component_count = 1;
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
grad_component_count = 2; grad_component_count = 2;
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
grad_component_count = 3; grad_component_count = 3;
break; break;
} }
@ -1411,9 +1419,9 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// TODO(Triang3l): Are cube map register gradients unnormalized if // TODO(Triang3l): Are cube map register gradients unnormalized if
// the coordinates themselves are unnormalized? // the coordinates themselves are unnormalized?
if (instr.attributes.unnormalized_coordinates && if (instr.attributes.unnormalized_coordinates &&
instr.dimension != TextureDimension::kCube) { instr.dimension != xenos::FetchOpDimension::kCube) {
uint32_t grad_norm_mask = grad_mask; uint32_t grad_norm_mask = grad_mask;
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
grad_norm_mask &= 0b0011; grad_norm_mask &= 0b0011;
} }
assert_true((size_needed_components & grad_norm_mask) == assert_true((size_needed_components & grad_norm_mask) ==
@ -1454,7 +1462,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
DxbcSrc::R(grad_v_temp), lod_src); DxbcSrc::R(grad_v_temp), lod_src);
#endif #endif
} }
if (instr.dimension == TextureDimension::k1D) { if (instr.dimension == xenos::FetchOpDimension::k1D) {
// Pad the gradients to 2D because 1D textures are fetched as 2D // Pad the gradients to 2D because 1D textures are fetched as 2D
// arrays. // arrays.
DxbcOpMov(DxbcDest::R(grad_h_lod_temp, 0b0010), DxbcSrc::LF(0.0f)); DxbcOpMov(DxbcDest::R(grad_h_lod_temp, 0b0010), DxbcSrc::LF(0.0f));
@ -1477,7 +1485,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
tfetch_index, instr.attributes.mag_filter, tfetch_index, instr.attributes.mag_filter,
instr.attributes.min_filter, instr.attributes.mip_filter, instr.attributes.min_filter, instr.attributes.mip_filter,
use_computed_lod ? instr.attributes.aniso_filter use_computed_lod ? instr.attributes.aniso_filter
: AnisoFilter::kDisabled); : xenos::AnisoFilter::kDisabled);
DxbcSrc sampler(DxbcSrc::S(sampler_binding_index, sampler_binding_index)); DxbcSrc sampler(DxbcSrc::S(sampler_binding_index, sampler_binding_index));
if (bindless_resources_used_) { if (bindless_resources_used_) {
// Load the sampler index to coord_and_sampler_temp.w and use relative // Load the sampler index to coord_and_sampler_temp.w and use relative
@ -1505,7 +1513,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
uint32_t is_signed_temp = PushSystemTemp(); uint32_t is_signed_temp = PushSystemTemp();
DxbcOpIEq(DxbcDest::R(is_signed_temp, used_result_nonzero_components), DxbcOpIEq(DxbcDest::R(is_signed_temp, used_result_nonzero_components),
DxbcSrc::R(signs_temp), DxbcSrc::R(signs_temp),
DxbcSrc::LU(uint32_t(TextureSign::kSigned))); DxbcSrc::LU(uint32_t(xenos::TextureSign::kSigned)));
// Calculate the lerp factor between stacked texture layers if needed (or // Calculate the lerp factor between stacked texture layers if needed (or
// 0 if point-sampled), and check which signedness SRVs need to be // 0 if point-sampled), and check which signedness SRVs need to be
@ -1527,15 +1535,17 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// W is always needed for bindless. // W is always needed for bindless.
uint32_t srv_selection_temp = uint32_t srv_selection_temp =
bindless_resources_used_ ? PushSystemTemp() : UINT32_MAX; bindless_resources_used_ ? PushSystemTemp() : UINT32_MAX;
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
bool vol_mag_filter_is_fetch_const = bool vol_mag_filter_is_fetch_const =
instr.attributes.vol_mag_filter == TextureFilter::kUseFetchConst; instr.attributes.vol_mag_filter ==
xenos::TextureFilter::kUseFetchConst;
bool vol_min_filter_is_fetch_const = bool vol_min_filter_is_fetch_const =
instr.attributes.vol_min_filter == TextureFilter::kUseFetchConst; instr.attributes.vol_min_filter ==
xenos::TextureFilter::kUseFetchConst;
bool vol_mag_filter_is_linear = bool vol_mag_filter_is_linear =
instr.attributes.vol_mag_filter == TextureFilter::kLinear; instr.attributes.vol_mag_filter == xenos::TextureFilter::kLinear;
bool vol_min_filter_is_linear = bool vol_min_filter_is_linear =
instr.attributes.vol_min_filter == TextureFilter::kLinear; instr.attributes.vol_min_filter == xenos::TextureFilter::kLinear;
if (grad_v_temp != UINT32_MAX && if (grad_v_temp != UINT32_MAX &&
(vol_mag_filter_is_fetch_const || vol_min_filter_is_fetch_const || (vol_mag_filter_is_fetch_const || vol_min_filter_is_fetch_const ||
vol_mag_filter_is_linear != vol_min_filter_is_linear)) { vol_mag_filter_is_linear != vol_min_filter_is_linear)) {
@ -1691,21 +1701,22 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// Sample the texture - choose between 3D and stacked, and then sample // Sample the texture - choose between 3D and stacked, and then sample
// unsigned and signed SRVs and choose between them. // unsigned and signed SRVs and choose between them.
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
assert_true((size_needed_components & 0b1000) == 0b1000); assert_true((size_needed_components & 0b1000) == 0b1000);
// The first fetch attempt will be for the 3D SRV. // The first fetch attempt will be for the 3D SRV.
DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW)); DxbcOpIf(true, DxbcSrc::R(size_and_is_3d_temp, DxbcSrc::kWWWW));
} }
for (uint32_t is_stacked = 0; for (uint32_t is_stacked = 0;
is_stacked < (instr.dimension == TextureDimension::k3D ? 2u : 1u); is_stacked <
(instr.dimension == xenos::FetchOpDimension::k3DOrStacked ? 2u : 1u);
++is_stacked) { ++is_stacked) {
// i == 0 - 1D/2D/3D/cube. // i == 0 - 1D/2D/3D/cube.
// i == 1 - 2D stacked. // i == 1 - 2D stacked.
TextureDimension srv_dimension = instr.dimension; xenos::FetchOpDimension srv_dimension = instr.dimension;
uint32_t srv_grad_component_count = grad_component_count; uint32_t srv_grad_component_count = grad_component_count;
bool layer_lerp_needed = false; bool layer_lerp_needed = false;
if (is_stacked) { if (is_stacked) {
srv_dimension = TextureDimension::k2D; srv_dimension = xenos::FetchOpDimension::k2D;
srv_grad_component_count = 2; srv_grad_component_count = 2;
layer_lerp_needed = layer_lerp_needed =
layer_lerp_factor_src.type_ != DxbcOperandType::kImmediate32; layer_lerp_factor_src.type_ != DxbcOperandType::kImmediate32;
@ -1729,14 +1740,14 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
if (bindless_resources_used_) { if (bindless_resources_used_) {
uint32_t* bindless_srv_index = nullptr; uint32_t* bindless_srv_index = nullptr;
switch (srv_dimension) { switch (srv_dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
bindless_srv_index = &srv_index_bindless_textures_2d_; bindless_srv_index = &srv_index_bindless_textures_2d_;
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
bindless_srv_index = &srv_index_bindless_textures_3d_; bindless_srv_index = &srv_index_bindless_textures_3d_;
break; break;
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
bindless_srv_index = &srv_index_bindless_textures_cube_; bindless_srv_index = &srv_index_bindless_textures_cube_;
break; break;
} }
@ -1867,7 +1878,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
} }
} }
} }
if (instr.dimension == TextureDimension::k3D) { if (instr.dimension == xenos::FetchOpDimension::k3DOrStacked) {
// Close the stacked/3D check. // Close the stacked/3D check.
DxbcOpEndIf(); DxbcOpEndIf();
} }
@ -1902,11 +1913,11 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
DxbcDest component_dest(DxbcDest::R(system_temp_result_, 1 << i)); DxbcDest component_dest(DxbcDest::R(system_temp_result_, 1 << i));
DxbcSrc component_src(DxbcSrc::R(system_temp_result_).Select(i)); DxbcSrc component_src(DxbcSrc::R(system_temp_result_).Select(i));
DxbcOpSwitch(DxbcSrc::R(signs_temp).Select(i)); DxbcOpSwitch(DxbcSrc::R(signs_temp).Select(i));
DxbcOpCase(DxbcSrc::LU(uint32_t(TextureSign::kUnsignedBiased))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::TextureSign::kUnsignedBiased)));
DxbcOpMAd(component_dest, component_src, DxbcSrc::LF(2.0f), DxbcOpMAd(component_dest, component_src, DxbcSrc::LF(2.0f),
DxbcSrc::LF(-1.0f)); DxbcSrc::LF(-1.0f));
DxbcOpBreak(); DxbcOpBreak();
DxbcOpCase(DxbcSrc::LU(uint32_t(TextureSign::kGamma))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::TextureSign::kGamma)));
uint32_t gamma_temp = PushSystemTemp(); uint32_t gamma_temp = PushSystemTemp();
ConvertPWLGamma(false, system_temp_result_, i, system_temp_result_, i, ConvertPWLGamma(false, system_temp_result_, i, system_temp_result_, i,
gamma_temp, 0, gamma_temp, 1); gamma_temp, 0, gamma_temp, 1);

View File

@ -190,8 +190,9 @@ void DxbcShaderTranslator::ExportToMemory() {
{ {
// k_8_8_8_8 // k_8_8_8_8
// k_8_8_8_8_AS_16_16_16_16 // k_8_8_8_8_AS_16_16_16_16
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_8_8_8_8))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_8_8_8_8)));
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_8_8_8_8_AS_16_16_16_16))); DxbcOpCase(
DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_8_8_8_8_AS_16_16_16_16)));
{ {
uint32_t bits[4] = {8, 8, 8, 8}; uint32_t bits[4] = {8, 8, 8, 8};
ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer, ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer,
@ -201,9 +202,9 @@ void DxbcShaderTranslator::ExportToMemory() {
// k_2_10_10_10 // k_2_10_10_10
// k_2_10_10_10_AS_16_16_16_16 // k_2_10_10_10_AS_16_16_16_16
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_2_10_10_10))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_2_10_10_10)));
DxbcOpCase( DxbcOpCase(DxbcSrc::LU(
DxbcSrc::LU(uint32_t(ColorFormat::k_2_10_10_10_AS_16_16_16_16))); uint32_t(xenos::ColorFormat::k_2_10_10_10_AS_16_16_16_16)));
{ {
uint32_t bits[4] = {10, 10, 10, 2}; uint32_t bits[4] = {10, 10, 10, 2};
ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer, ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer,
@ -213,8 +214,9 @@ void DxbcShaderTranslator::ExportToMemory() {
// k_10_11_11 // k_10_11_11
// k_10_11_11_AS_16_16_16_16 // k_10_11_11_AS_16_16_16_16
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_10_11_11))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_10_11_11)));
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_10_11_11_AS_16_16_16_16))); DxbcOpCase(
DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_10_11_11_AS_16_16_16_16)));
{ {
uint32_t bits[4] = {11, 11, 10}; uint32_t bits[4] = {11, 11, 10};
ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer, ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer,
@ -224,8 +226,9 @@ void DxbcShaderTranslator::ExportToMemory() {
// k_11_11_10 // k_11_11_10
// k_11_11_10_AS_16_16_16_16 // k_11_11_10_AS_16_16_16_16
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_11_11_10))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_11_11_10)));
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_11_11_10_AS_16_16_16_16))); DxbcOpCase(
DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_11_11_10_AS_16_16_16_16)));
{ {
uint32_t bits[4] = {10, 11, 11}; uint32_t bits[4] = {10, 11, 11};
ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer, ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer,
@ -234,7 +237,7 @@ void DxbcShaderTranslator::ExportToMemory() {
DxbcOpBreak(); DxbcOpBreak();
// k_16_16 // k_16_16
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_16_16))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_16_16)));
{ {
uint32_t bits[4] = {16, 16}; uint32_t bits[4] = {16, 16};
ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer, ExportToMemory_PackFixed32(eM_temps, eM_count, bits, is_integer,
@ -243,7 +246,7 @@ void DxbcShaderTranslator::ExportToMemory() {
DxbcOpBreak(); DxbcOpBreak();
// k_16_16_16_16 // k_16_16_16_16
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_16_16_16_16))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_16_16_16_16)));
DxbcOpMov(element_size_dest, DxbcSrc::LU(8)); DxbcOpMov(element_size_dest, DxbcSrc::LU(8));
DxbcOpIf(true, is_signed); DxbcOpIf(true, is_signed);
{ {
@ -291,7 +294,7 @@ void DxbcShaderTranslator::ExportToMemory() {
DxbcOpBreak(); DxbcOpBreak();
// k_16_16_FLOAT // k_16_16_FLOAT
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_16_16_FLOAT))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_16_16_FLOAT)));
for (uint32_t j = 0; j < eM_count; ++j) { for (uint32_t j = 0; j < eM_count; ++j) {
uint32_t eM_temp = eM_temps[j]; uint32_t eM_temp = eM_temps[j];
DxbcOpF32ToF16(DxbcDest::R(eM_temp, 0b0011), DxbcSrc::R(eM_temp)); DxbcOpF32ToF16(DxbcDest::R(eM_temp, 0b0011), DxbcSrc::R(eM_temp));
@ -302,7 +305,8 @@ void DxbcShaderTranslator::ExportToMemory() {
DxbcOpBreak(); DxbcOpBreak();
// k_16_16_16_16_FLOAT // k_16_16_16_16_FLOAT
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_16_16_16_16_FLOAT))); DxbcOpCase(
DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_16_16_16_16_FLOAT)));
DxbcOpMov(element_size_dest, DxbcSrc::LU(8)); DxbcOpMov(element_size_dest, DxbcSrc::LU(8));
for (uint32_t j = 0; j < eM_count; ++j) { for (uint32_t j = 0; j < eM_count; ++j) {
uint32_t eM_temp = eM_temps[j]; uint32_t eM_temp = eM_temps[j];
@ -318,13 +322,14 @@ void DxbcShaderTranslator::ExportToMemory() {
// selected. // selected.
// k_32_32_FLOAT // k_32_32_FLOAT
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_32_32_FLOAT))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_32_32_FLOAT)));
DxbcOpMov(element_size_dest, DxbcSrc::LU(8)); DxbcOpMov(element_size_dest, DxbcSrc::LU(8));
// Already in the destination format. // Already in the destination format.
DxbcOpBreak(); DxbcOpBreak();
// k_32_32_32_32_FLOAT // k_32_32_32_32_FLOAT
DxbcOpCase(DxbcSrc::LU(uint32_t(ColorFormat::k_32_32_32_32_FLOAT))); DxbcOpCase(
DxbcSrc::LU(uint32_t(xenos::ColorFormat::k_32_32_32_32_FLOAT)));
DxbcOpMov(element_size_dest, DxbcSrc::LU(16)); DxbcOpMov(element_size_dest, DxbcSrc::LU(16));
// Already in the destination format. // Already in the destination format.
DxbcOpBreak(); DxbcOpBreak();
@ -342,9 +347,9 @@ void DxbcShaderTranslator::ExportToMemory() {
// Change 8-in-64 and 8-in-128 to 8-in-32. // Change 8-in-64 and 8-in-128 to 8-in-32.
for (uint32_t j = 0; j < 2; ++j) { for (uint32_t j = 0; j < 2; ++j) {
DxbcOpIEq( DxbcOpIEq(DxbcDest::R(control_temp, 0b0100), endian_src,
DxbcDest::R(control_temp, 0b0100), endian_src, DxbcSrc::LU(uint32_t(j ? xenos::Endian128::k8in128
DxbcSrc::LU(uint32_t(j ? Endian128::k8in128 : Endian128::k8in64))); : xenos::Endian128::k8in64)));
for (uint32_t k = 0; k < eM_count; ++k) { for (uint32_t k = 0; k < eM_count; ++k) {
uint32_t eM_temp = eM_temps[k]; uint32_t eM_temp = eM_temps[k];
DxbcOpMovC(DxbcDest::R(eM_temp), DxbcOpMovC(DxbcDest::R(eM_temp),
@ -353,7 +358,7 @@ void DxbcShaderTranslator::ExportToMemory() {
DxbcSrc::R(eM_temp)); DxbcSrc::R(eM_temp));
} }
DxbcOpMovC(endian_dest, DxbcSrc::R(control_temp, DxbcSrc::kZZZZ), DxbcOpMovC(endian_dest, DxbcSrc::R(control_temp, DxbcSrc::kZZZZ),
DxbcSrc::LU(uint32_t(Endian128::k8in32)), endian_src); DxbcSrc::LU(uint32_t(xenos::Endian128::k8in32)), endian_src);
} }
uint32_t swap_temp = PushSystemTemp(); uint32_t swap_temp = PushSystemTemp();
@ -362,8 +367,8 @@ void DxbcShaderTranslator::ExportToMemory() {
// 8-in-16 or one half of 8-in-32. // 8-in-16 or one half of 8-in-32.
DxbcOpSwitch(endian_src); DxbcOpSwitch(endian_src);
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k8in16))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k8in16)));
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k8in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k8in32)));
for (uint32_t j = 0; j < eM_count; ++j) { for (uint32_t j = 0; j < eM_count; ++j) {
DxbcDest eM_dest(DxbcDest::R(eM_temps[j])); DxbcDest eM_dest(DxbcDest::R(eM_temps[j]));
DxbcSrc eM_src(DxbcSrc::R(eM_temps[j])); DxbcSrc eM_src(DxbcSrc::R(eM_temps[j]));
@ -381,8 +386,8 @@ void DxbcShaderTranslator::ExportToMemory() {
// 16-in-32 or another half of 8-in-32. // 16-in-32 or another half of 8-in-32.
DxbcOpSwitch(endian_src); DxbcOpSwitch(endian_src);
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k8in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k8in32)));
DxbcOpCase(DxbcSrc::LU(uint32_t(Endian128::k16in32))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::Endian128::k16in32)));
for (uint32_t j = 0; j < eM_count; ++j) { for (uint32_t j = 0; j < eM_count; ++j) {
DxbcDest eM_dest(DxbcDest::R(eM_temps[j])); DxbcDest eM_dest(DxbcDest::R(eM_temps[j]));
DxbcSrc eM_src(DxbcSrc::R(eM_temps[j])); DxbcSrc eM_src(DxbcSrc::R(eM_temps[j]));

View File

@ -17,13 +17,14 @@ namespace gpu {
using namespace ucode; using namespace ucode;
void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants( void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
ColorRenderTargetFormat format, uint32_t write_mask, float& clamp_rgb_low, xenos::ColorRenderTargetFormat format, uint32_t write_mask,
float& clamp_alpha_low, float& clamp_rgb_high, float& clamp_alpha_high, float& clamp_rgb_low, float& clamp_alpha_low, float& clamp_rgb_high,
uint32_t& keep_mask_low, uint32_t& keep_mask_high) { float& clamp_alpha_high, uint32_t& keep_mask_low,
uint32_t& keep_mask_high) {
keep_mask_low = keep_mask_high = 0; keep_mask_low = keep_mask_high = 0;
switch (format) { switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8: case xenos::ColorRenderTargetFormat::k_8_8_8_8:
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: { case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA: {
clamp_rgb_low = clamp_alpha_low = 0.0f; clamp_rgb_low = clamp_alpha_low = 0.0f;
clamp_rgb_high = clamp_alpha_high = 1.0f; clamp_rgb_high = clamp_alpha_high = 1.0f;
for (uint32_t i = 0; i < 4; ++i) { for (uint32_t i = 0; i < 4; ++i) {
@ -32,8 +33,8 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
} }
} }
} break; } break;
case ColorRenderTargetFormat::k_2_10_10_10: case xenos::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_AS_10_10_10_10: {
clamp_rgb_low = clamp_alpha_low = 0.0f; clamp_rgb_low = clamp_alpha_low = 0.0f;
clamp_rgb_high = clamp_alpha_high = 1.0f; clamp_rgb_high = clamp_alpha_high = 1.0f;
for (uint32_t i = 0; i < 3; ++i) { for (uint32_t i = 0; i < 3; ++i) {
@ -45,8 +46,8 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
keep_mask_low |= uint32_t(3) << 30; keep_mask_low |= uint32_t(3) << 30;
} }
} break; } break;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: { case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: {
clamp_rgb_low = clamp_alpha_low = 0.0f; clamp_rgb_low = clamp_alpha_low = 0.0f;
clamp_rgb_high = 31.875f; clamp_rgb_high = 31.875f;
clamp_alpha_high = 1.0f; clamp_alpha_high = 1.0f;
@ -59,8 +60,8 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
keep_mask_low |= uint32_t(3) << 30; keep_mask_low |= uint32_t(3) << 30;
} }
} break; } break;
case ColorRenderTargetFormat::k_16_16: case xenos::ColorRenderTargetFormat::k_16_16:
case ColorRenderTargetFormat::k_16_16_16_16: case xenos::ColorRenderTargetFormat::k_16_16_16_16:
// Alpha clamping affects blending source, so it's non-zero for alpha for // Alpha clamping affects blending source, so it's non-zero for alpha for
// k_16_16 (the render target is fixed-point). // k_16_16 (the render target is fixed-point).
clamp_rgb_low = clamp_alpha_low = -32.0f; clamp_rgb_low = clamp_alpha_low = -32.0f;
@ -71,7 +72,7 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
if (!(write_mask & 0b0010)) { if (!(write_mask & 0b0010)) {
keep_mask_low |= 0xFFFF0000u; keep_mask_low |= 0xFFFF0000u;
} }
if (format == ColorRenderTargetFormat::k_16_16_16_16) { if (format == xenos::ColorRenderTargetFormat::k_16_16_16_16) {
if (!(write_mask & 0b0100)) { if (!(write_mask & 0b0100)) {
keep_mask_high |= 0xFFFFu; keep_mask_high |= 0xFFFFu;
} }
@ -82,8 +83,8 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
write_mask &= 0b0011; write_mask &= 0b0011;
} }
break; break;
case ColorRenderTargetFormat::k_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_FLOAT:
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
// No NaNs on the Xbox 360 GPU, though can't use the extended range with // No NaNs on the Xbox 360 GPU, though can't use the extended range with
// f32tof16. // f32tof16.
clamp_rgb_low = clamp_alpha_low = -65504.0f; clamp_rgb_low = clamp_alpha_low = -65504.0f;
@ -94,7 +95,7 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
if (!(write_mask & 0b0010)) { if (!(write_mask & 0b0010)) {
keep_mask_low |= 0xFFFF0000u; keep_mask_low |= 0xFFFF0000u;
} }
if (format == ColorRenderTargetFormat::k_16_16_16_16_FLOAT) { if (format == xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT) {
if (!(write_mask & 0b0100)) { if (!(write_mask & 0b0100)) {
keep_mask_high |= 0xFFFFu; keep_mask_high |= 0xFFFFu;
} }
@ -105,7 +106,7 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
write_mask &= 0b0011; write_mask &= 0b0011;
} }
break; break;
case ColorRenderTargetFormat::k_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_FLOAT:
// No clamping - let min/max always pick the original value. // No clamping - let min/max always pick the original value.
clamp_rgb_low = clamp_alpha_low = clamp_rgb_high = clamp_alpha_high = clamp_rgb_low = clamp_alpha_low = clamp_rgb_high = clamp_alpha_high =
std::nanf(""); std::nanf("");
@ -114,7 +115,7 @@ void DxbcShaderTranslator::ROV_GetColorFormatSystemConstants(
keep_mask_low = ~uint32_t(0); keep_mask_low = ~uint32_t(0);
} }
break; break;
case ColorRenderTargetFormat::k_32_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_32_FLOAT:
// No clamping - let min/max always pick the original value. // No clamping - let min/max always pick the original value.
clamp_rgb_low = clamp_alpha_low = clamp_rgb_high = clamp_alpha_high = clamp_rgb_low = clamp_alpha_low = clamp_rgb_high = clamp_alpha_high =
std::nanf(""); std::nanf("");
@ -701,9 +702,9 @@ void DxbcShaderTranslator::ROV_UnpackColor(
// k_8_8_8_8_GAMMA // k_8_8_8_8_GAMMA
// *************************************************************************** // ***************************************************************************
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ROV_AddColorFormatFlags(i ? ColorRenderTargetFormat::k_8_8_8_8_GAMMA i ? xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA
: ColorRenderTargetFormat::k_8_8_8_8))); : xenos::ColorRenderTargetFormat::k_8_8_8_8)));
// Unpack the components. // Unpack the components.
DxbcOpUBFE(DxbcDest::R(color_temp), DxbcSrc::LU(8), DxbcOpUBFE(DxbcDest::R(color_temp), DxbcSrc::LU(8),
DxbcSrc::LU(0, 8, 16, 24), packed_temp_low); DxbcSrc::LU(0, 8, 16, 24), packed_temp_low);
@ -726,9 +727,9 @@ void DxbcShaderTranslator::ROV_UnpackColor(
// k_2_10_10_10_AS_10_10_10_10 // k_2_10_10_10_AS_10_10_10_10
// *************************************************************************** // ***************************************************************************
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(
ROV_AddColorFormatFlags(ColorRenderTargetFormat::k_2_10_10_10))); ROV_AddColorFormatFlags(xenos::ColorRenderTargetFormat::k_2_10_10_10)));
DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10))); xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10)));
{ {
// Unpack the components. // Unpack the components.
DxbcOpUBFE(DxbcDest::R(color_temp), DxbcSrc::LU(10, 10, 10, 2), DxbcOpUBFE(DxbcDest::R(color_temp), DxbcSrc::LU(10, 10, 10, 2),
@ -747,10 +748,10 @@ void DxbcShaderTranslator::ROV_UnpackColor(
// k_2_10_10_10_FLOAT_AS_16_16_16_16 // k_2_10_10_10_FLOAT_AS_16_16_16_16
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp // https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
// *************************************************************************** // ***************************************************************************
DxbcOpCase(DxbcSrc::LU(
ROV_AddColorFormatFlags(ColorRenderTargetFormat::k_2_10_10_10_FLOAT)));
DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16))); xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT)));
DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16)));
{ {
// Unpack the alpha. // Unpack the alpha.
DxbcOpUBFE(DxbcDest::R(color_temp, 0b1000), DxbcSrc::LU(2), DxbcSrc::LU(30), DxbcOpUBFE(DxbcDest::R(color_temp, 0b1000), DxbcSrc::LU(2), DxbcSrc::LU(30),
@ -824,9 +825,9 @@ void DxbcShaderTranslator::ROV_UnpackColor(
// k_16_16_16_16 (64bpp) // k_16_16_16_16 (64bpp)
// *************************************************************************** // ***************************************************************************
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ROV_AddColorFormatFlags(i ? ColorRenderTargetFormat::k_16_16_16_16 i ? xenos::ColorRenderTargetFormat::k_16_16_16_16
: ColorRenderTargetFormat::k_16_16))); : xenos::ColorRenderTargetFormat::k_16_16)));
DxbcDest color_components_dest( DxbcDest color_components_dest(
DxbcDest::R(color_temp, i ? 0b1111 : 0b0011)); DxbcDest::R(color_temp, i ? 0b1111 : 0b0011));
// Unpack the components. // Unpack the components.
@ -847,9 +848,9 @@ void DxbcShaderTranslator::ROV_UnpackColor(
// k_16_16_16_16_FLOAT (64bpp) // k_16_16_16_16_FLOAT (64bpp)
// *************************************************************************** // ***************************************************************************
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ROV_AddColorFormatFlags(i ? ColorRenderTargetFormat::k_16_16_16_16_FLOAT i ? xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT
: ColorRenderTargetFormat::k_16_16_FLOAT))); : xenos::ColorRenderTargetFormat::k_16_16_FLOAT)));
DxbcDest color_components_dest( DxbcDest color_components_dest(
DxbcDest::R(color_temp, i ? 0b1111 : 0b0011)); DxbcDest::R(color_temp, i ? 0b1111 : 0b0011));
// Unpack the components. // Unpack the components.
@ -905,9 +906,9 @@ void DxbcShaderTranslator::ROV_PackPreClampedColor(
// k_8_8_8_8_GAMMA // k_8_8_8_8_GAMMA
// *************************************************************************** // ***************************************************************************
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ROV_AddColorFormatFlags(i ? ColorRenderTargetFormat::k_8_8_8_8_GAMMA i ? xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA
: ColorRenderTargetFormat::k_8_8_8_8))); : xenos::ColorRenderTargetFormat::k_8_8_8_8)));
for (uint32_t j = 0; j < 4; ++j) { for (uint32_t j = 0; j < 4; ++j) {
if (i && j < 3) { if (i && j < 3) {
ConvertPWLGamma(true, color_temp, j, temp1, temp1_component, temp1, ConvertPWLGamma(true, color_temp, j, temp1, temp1_component, temp1,
@ -939,9 +940,9 @@ void DxbcShaderTranslator::ROV_PackPreClampedColor(
// k_2_10_10_10_AS_10_10_10_10 // k_2_10_10_10_AS_10_10_10_10
// *************************************************************************** // ***************************************************************************
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(
ROV_AddColorFormatFlags(ColorRenderTargetFormat::k_2_10_10_10))); ROV_AddColorFormatFlags(xenos::ColorRenderTargetFormat::k_2_10_10_10)));
DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10))); xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10)));
for (uint32_t i = 0; i < 4; ++i) { for (uint32_t i = 0; i < 4; ++i) {
// Denormalize. // Denormalize.
DxbcOpMul(temp1_dest, DxbcSrc::R(color_temp).Select(i), DxbcOpMul(temp1_dest, DxbcSrc::R(color_temp).Select(i),
@ -965,10 +966,10 @@ void DxbcShaderTranslator::ROV_PackPreClampedColor(
// k_2_10_10_10_FLOAT_AS_16_16_16_16 // k_2_10_10_10_FLOAT_AS_16_16_16_16
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp // https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
// *************************************************************************** // ***************************************************************************
DxbcOpCase(DxbcSrc::LU(
ROV_AddColorFormatFlags(ColorRenderTargetFormat::k_2_10_10_10_FLOAT)));
DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16))); xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT)));
DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16)));
{ {
for (uint32_t i = 0; i < 3; ++i) { for (uint32_t i = 0; i < 3; ++i) {
DxbcSrc color_component_src(DxbcSrc::R(color_temp).Select(i)); DxbcSrc color_component_src(DxbcSrc::R(color_temp).Select(i));
@ -1039,9 +1040,9 @@ void DxbcShaderTranslator::ROV_PackPreClampedColor(
// k_16_16_16_16 (64bpp) // k_16_16_16_16 (64bpp)
// *************************************************************************** // ***************************************************************************
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ROV_AddColorFormatFlags(i ? ColorRenderTargetFormat::k_16_16_16_16 i ? xenos::ColorRenderTargetFormat::k_16_16_16_16
: ColorRenderTargetFormat::k_16_16))); : xenos::ColorRenderTargetFormat::k_16_16)));
for (uint32_t j = 0; j < (uint32_t(2) << i); ++j) { for (uint32_t j = 0; j < (uint32_t(2) << i); ++j) {
// Denormalize. // Denormalize.
DxbcOpMul(temp1_dest, DxbcSrc::R(color_temp).Select(j), DxbcOpMul(temp1_dest, DxbcSrc::R(color_temp).Select(j),
@ -1069,9 +1070,9 @@ void DxbcShaderTranslator::ROV_PackPreClampedColor(
// k_16_16_16_16_FLOAT (64bpp) // k_16_16_16_16_FLOAT (64bpp)
// *************************************************************************** // ***************************************************************************
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU( DxbcOpCase(DxbcSrc::LU(ROV_AddColorFormatFlags(
ROV_AddColorFormatFlags(i ? ColorRenderTargetFormat::k_16_16_16_16_FLOAT i ? xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT
: ColorRenderTargetFormat::k_16_16_FLOAT))); : xenos::ColorRenderTargetFormat::k_16_16_FLOAT)));
for (uint32_t j = 0; j < (uint32_t(2) << i); ++j) { for (uint32_t j = 0; j < (uint32_t(2) << i); ++j) {
DxbcDest packed_dest_half( DxbcDest packed_dest_half(
DxbcDest::R(packed_temp, 1 << (packed_temp_components + (j >> 1)))); DxbcDest::R(packed_temp, 1 << (packed_temp_components + (j >> 1))));
@ -1105,51 +1106,51 @@ void DxbcShaderTranslator::ROV_HandleColorBlendFactorCases(
DxbcSrc one_src(DxbcSrc::LF(1.0f)); DxbcSrc one_src(DxbcSrc::LF(1.0f));
// kOne. // kOne.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOne))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOne)));
DxbcOpMov(factor_dest, one_src); DxbcOpMov(factor_dest, one_src);
DxbcOpBreak(); DxbcOpBreak();
// kSrcColor // kSrcColor
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kSrcColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kSrcColor)));
if (factor_temp != src_temp) { if (factor_temp != src_temp) {
DxbcOpMov(factor_dest, DxbcSrc::R(src_temp)); DxbcOpMov(factor_dest, DxbcSrc::R(src_temp));
} }
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusSrcColor // kOneMinusSrcColor
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusSrcColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusSrcColor)));
DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(src_temp)); DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(src_temp));
DxbcOpBreak(); DxbcOpBreak();
// kSrcAlpha // kSrcAlpha
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kSrcAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kSrcAlpha)));
DxbcOpMov(factor_dest, DxbcSrc::R(src_temp, DxbcSrc::kWWWW)); DxbcOpMov(factor_dest, DxbcSrc::R(src_temp, DxbcSrc::kWWWW));
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusSrcAlpha // kOneMinusSrcAlpha
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusSrcAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusSrcAlpha)));
DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(src_temp, DxbcSrc::kWWWW)); DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(src_temp, DxbcSrc::kWWWW));
DxbcOpBreak(); DxbcOpBreak();
// kDstColor // kDstColor
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kDstColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kDstColor)));
if (factor_temp != dst_temp) { if (factor_temp != dst_temp) {
DxbcOpMov(factor_dest, DxbcSrc::R(dst_temp)); DxbcOpMov(factor_dest, DxbcSrc::R(dst_temp));
} }
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusDstColor // kOneMinusDstColor
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusDstColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusDstColor)));
DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(dst_temp)); DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(dst_temp));
DxbcOpBreak(); DxbcOpBreak();
// kDstAlpha // kDstAlpha
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kDstAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kDstAlpha)));
DxbcOpMov(factor_dest, DxbcSrc::R(dst_temp, DxbcSrc::kWWWW)); DxbcOpMov(factor_dest, DxbcSrc::R(dst_temp, DxbcSrc::kWWWW));
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusDstAlpha // kOneMinusDstAlpha
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusDstAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusDstAlpha)));
DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(dst_temp, DxbcSrc::kWWWW)); DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(dst_temp, DxbcSrc::kWWWW));
DxbcOpBreak(); DxbcOpBreak();
@ -1157,7 +1158,7 @@ void DxbcShaderTranslator::ROV_HandleColorBlendFactorCases(
system_constants_used_ |= 1ull << kSysConst_EDRAMBlendConstant_Index; system_constants_used_ |= 1ull << kSysConst_EDRAMBlendConstant_Index;
// kConstantColor // kConstantColor
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kConstantColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kConstantColor)));
DxbcOpMov(factor_dest, DxbcOpMov(factor_dest,
DxbcSrc::CB(cbuffer_index_system_constants_, DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
@ -1165,7 +1166,7 @@ void DxbcShaderTranslator::ROV_HandleColorBlendFactorCases(
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusConstantColor // kOneMinusConstantColor
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusConstantColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusConstantColor)));
DxbcOpAdd(factor_dest, one_src, DxbcOpAdd(factor_dest, one_src,
-DxbcSrc::CB(cbuffer_index_system_constants_, -DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
@ -1173,7 +1174,7 @@ void DxbcShaderTranslator::ROV_HandleColorBlendFactorCases(
DxbcOpBreak(); DxbcOpBreak();
// kConstantAlpha // kConstantAlpha
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kConstantAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kConstantAlpha)));
DxbcOpMov(factor_dest, DxbcOpMov(factor_dest,
DxbcSrc::CB(cbuffer_index_system_constants_, DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
@ -1181,7 +1182,7 @@ void DxbcShaderTranslator::ROV_HandleColorBlendFactorCases(
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusConstantAlpha // kOneMinusConstantAlpha
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusConstantAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusConstantAlpha)));
DxbcOpAdd(factor_dest, one_src, DxbcOpAdd(factor_dest, one_src,
-DxbcSrc::CB(cbuffer_index_system_constants_, -DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
@ -1189,7 +1190,7 @@ void DxbcShaderTranslator::ROV_HandleColorBlendFactorCases(
DxbcOpBreak(); DxbcOpBreak();
// kSrcAlphaSaturate // kSrcAlphaSaturate
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kSrcAlphaSaturate))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kSrcAlphaSaturate)));
DxbcOpAdd(DxbcDest::R(factor_temp, 0b0001), one_src, DxbcOpAdd(DxbcDest::R(factor_temp, 0b0001), one_src,
-DxbcSrc::R(dst_temp, DxbcSrc::kWWWW)); -DxbcSrc::R(dst_temp, DxbcSrc::kWWWW));
DxbcOpMin(factor_dest, DxbcSrc::R(src_temp, DxbcSrc::kWWWW), DxbcOpMin(factor_dest, DxbcSrc::R(src_temp, DxbcSrc::kWWWW),
@ -1209,36 +1210,36 @@ void DxbcShaderTranslator::ROV_HandleAlphaBlendFactorCases(
DxbcSrc one_src(DxbcSrc::LF(1.0f)); DxbcSrc one_src(DxbcSrc::LF(1.0f));
// kOne, kSrcAlphaSaturate. // kOne, kSrcAlphaSaturate.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOne))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOne)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kSrcAlphaSaturate))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kSrcAlphaSaturate)));
DxbcOpMov(factor_dest, one_src); DxbcOpMov(factor_dest, one_src);
DxbcOpBreak(); DxbcOpBreak();
// kSrcColor, kSrcAlpha. // kSrcColor, kSrcAlpha.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kSrcColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kSrcColor)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kSrcAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kSrcAlpha)));
if (factor_temp != src_temp || factor_component != 3) { if (factor_temp != src_temp || factor_component != 3) {
DxbcOpMov(factor_dest, DxbcSrc::R(src_temp, DxbcSrc::kWWWW)); DxbcOpMov(factor_dest, DxbcSrc::R(src_temp, DxbcSrc::kWWWW));
} }
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusSrcColor, kOneMinusSrcAlpha. // kOneMinusSrcColor, kOneMinusSrcAlpha.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusSrcColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusSrcColor)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusSrcAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusSrcAlpha)));
DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(src_temp, DxbcSrc::kWWWW)); DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(src_temp, DxbcSrc::kWWWW));
DxbcOpBreak(); DxbcOpBreak();
// kDstColor, kDstAlpha. // kDstColor, kDstAlpha.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kDstColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kDstColor)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kDstAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kDstAlpha)));
if (factor_temp != dst_temp || factor_component != 3) { if (factor_temp != dst_temp || factor_component != 3) {
DxbcOpMov(factor_dest, DxbcSrc::R(dst_temp, DxbcSrc::kWWWW)); DxbcOpMov(factor_dest, DxbcSrc::R(dst_temp, DxbcSrc::kWWWW));
} }
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusDstColor, kOneMinusDstAlpha. // kOneMinusDstColor, kOneMinusDstAlpha.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusDstColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusDstColor)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusDstAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusDstAlpha)));
DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(dst_temp, DxbcSrc::kWWWW)); DxbcOpAdd(factor_dest, one_src, -DxbcSrc::R(dst_temp, DxbcSrc::kWWWW));
DxbcOpBreak(); DxbcOpBreak();
@ -1246,8 +1247,8 @@ void DxbcShaderTranslator::ROV_HandleAlphaBlendFactorCases(
system_constants_used_ |= 1ull << kSysConst_EDRAMBlendConstant_Index; system_constants_used_ |= 1ull << kSysConst_EDRAMBlendConstant_Index;
// kConstantColor, kConstantAlpha. // kConstantColor, kConstantAlpha.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kConstantColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kConstantColor)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kConstantAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kConstantAlpha)));
DxbcOpMov(factor_dest, DxbcOpMov(factor_dest,
DxbcSrc::CB(cbuffer_index_system_constants_, DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
@ -1255,8 +1256,8 @@ void DxbcShaderTranslator::ROV_HandleAlphaBlendFactorCases(
DxbcOpBreak(); DxbcOpBreak();
// kOneMinusConstantColor, kOneMinusConstantAlpha. // kOneMinusConstantColor, kOneMinusConstantAlpha.
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusConstantColor))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusConstantColor)));
DxbcOpCase(DxbcSrc::LU(uint32_t(BlendFactor::kOneMinusConstantAlpha))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::BlendFactor::kOneMinusConstantAlpha)));
DxbcOpAdd(factor_dest, one_src, DxbcOpAdd(factor_dest, one_src,
-DxbcSrc::CB(cbuffer_index_system_constants_, -DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
@ -2287,14 +2288,14 @@ void DxbcShaderTranslator::
DxbcOpSwitch(DxbcSrc::R(system_temps_subroutine_, DxbcSrc::kWWWW)); DxbcOpSwitch(DxbcSrc::R(system_temps_subroutine_, DxbcSrc::kWWWW));
{ {
// Zero. // Zero.
DxbcOpCase(DxbcSrc::LU(uint32_t(StencilOp::kZero))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::StencilOp::kZero)));
{ {
DxbcOpMov(DxbcDest::R(system_temps_subroutine_, 0b1000), DxbcOpMov(DxbcDest::R(system_temps_subroutine_, 0b1000),
DxbcSrc::LU(0)); DxbcSrc::LU(0));
} }
DxbcOpBreak(); DxbcOpBreak();
// Replace. // Replace.
DxbcOpCase(DxbcSrc::LU(uint32_t(StencilOp::kReplace))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::StencilOp::kReplace)));
{ {
in_front_face_used_ = true; in_front_face_used_ = true;
system_constants_used_ |= 1ull << kSysConst_EDRAMStencil_Index; system_constants_used_ |= 1ull << kSysConst_EDRAMStencil_Index;
@ -2306,7 +2307,7 @@ void DxbcShaderTranslator::
} }
DxbcOpBreak(); DxbcOpBreak();
// Increment and clamp. // Increment and clamp.
DxbcOpCase(DxbcSrc::LU(uint32_t(StencilOp::kIncrementClamp))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::StencilOp::kIncrementClamp)));
{ {
// Clear the upper bits for saturation. // Clear the upper bits for saturation.
DxbcOpAnd(DxbcDest::R(system_temps_subroutine_, 0b1000), DxbcOpAnd(DxbcDest::R(system_temps_subroutine_, 0b1000),
@ -2323,7 +2324,7 @@ void DxbcShaderTranslator::
} }
DxbcOpBreak(); DxbcOpBreak();
// Decrement and clamp. // Decrement and clamp.
DxbcOpCase(DxbcSrc::LU(uint32_t(StencilOp::kDecrementClamp))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::StencilOp::kDecrementClamp)));
{ {
// Clear the upper bits for saturation. // Clear the upper bits for saturation.
DxbcOpAnd(DxbcDest::R(system_temps_subroutine_, 0b1000), DxbcOpAnd(DxbcDest::R(system_temps_subroutine_, 0b1000),
@ -2340,7 +2341,7 @@ void DxbcShaderTranslator::
} }
DxbcOpBreak(); DxbcOpBreak();
// Invert. // Invert.
DxbcOpCase(DxbcSrc::LU(uint32_t(StencilOp::kInvert))); DxbcOpCase(DxbcSrc::LU(uint32_t(xenos::StencilOp::kInvert)));
{ {
DxbcOpNot(DxbcDest::R(system_temps_subroutine_, 0b1000), DxbcOpNot(DxbcDest::R(system_temps_subroutine_, 0b1000),
DxbcSrc::R(system_temps_subroutine_, DxbcSrc::kZZZZ)); DxbcSrc::R(system_temps_subroutine_, DxbcSrc::kZZZZ));
@ -2348,8 +2349,8 @@ void DxbcShaderTranslator::
DxbcOpBreak(); DxbcOpBreak();
// Increment/decrement and wrap. // Increment/decrement and wrap.
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
DxbcOpCase(DxbcSrc::LU(uint32_t(i ? StencilOp::kDecrementWrap DxbcOpCase(DxbcSrc::LU(uint32_t(i ? xenos::StencilOp::kDecrementWrap
: StencilOp::kIncrementWrap))); : xenos::StencilOp::kIncrementWrap)));
{ {
DxbcOpIAdd(DxbcDest::R(system_temps_subroutine_, 0b1000), DxbcOpIAdd(DxbcDest::R(system_temps_subroutine_, 0b1000),
DxbcSrc::R(system_temps_subroutine_, DxbcSrc::kZZZZ), DxbcSrc::R(system_temps_subroutine_, DxbcSrc::kZZZZ),

View File

@ -35,14 +35,14 @@ void NullCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
uint32_t frontbuffer_width, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) {} uint32_t frontbuffer_height) {}
Shader* NullCommandProcessor::LoadShader(ShaderType shader_type, Shader* NullCommandProcessor::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address, uint32_t guest_address,
const uint32_t* host_address, const uint32_t* host_address,
uint32_t dword_count) { uint32_t dword_count) {
return nullptr; return nullptr;
} }
bool NullCommandProcessor::IssueDraw(PrimitiveType prim_type, bool NullCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type,
uint32_t index_count, uint32_t index_count,
IndexBufferInfo* index_buffer_info, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) { bool major_mode_explicit) {

View File

@ -36,11 +36,11 @@ class NullCommandProcessor : public CommandProcessor {
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override; uint32_t frontbuffer_height) 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, const uint32_t* host_address,
uint32_t dword_count) override; uint32_t dword_count) override;
bool IssueDraw(PrimitiveType prim_type, uint32_t index_count, bool IssueDraw(xenos::PrimitiveType prim_type, uint32_t index_count,
IndexBufferInfo* index_buffer_info, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) override; bool major_mode_explicit) override;
bool IssueCopy() override; bool IssueCopy() override;

View File

@ -241,13 +241,13 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0); uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t dword1 = xe::load_and_swap<uint32_t>(ptr + 4); uint32_t dword1 = xe::load_and_swap<uint32_t>(ptr + 4);
uint32_t index_count = dword1 >> 16; uint32_t index_count = dword1 >> 16;
auto prim_type = static_cast<PrimitiveType>(dword1 & 0x3F); auto prim_type = static_cast<xenos::PrimitiveType>(dword1 & 0x3F);
uint32_t src_sel = (dword1 >> 6) & 0x3; uint32_t src_sel = (dword1 >> 6) & 0x3;
if (src_sel == 0x0) { if (src_sel == 0x0) {
// Indexed draw. // Indexed draw.
uint32_t guest_base = xe::load_and_swap<uint32_t>(ptr + 8); uint32_t guest_base = xe::load_and_swap<uint32_t>(ptr + 8);
uint32_t index_size = xe::load_and_swap<uint32_t>(ptr + 12); uint32_t index_size = xe::load_and_swap<uint32_t>(ptr + 12);
auto endianness = static_cast<Endian>(index_size >> 30); auto endianness = static_cast<xenos::Endian>(index_size >> 30);
index_size &= 0x00FFFFFF; index_size &= 0x00FFFFFF;
bool index_32bit = (dword1 >> 11) & 0x1; bool index_32bit = (dword1 >> 11) & 0x1;
index_size *= index_32bit ? 4 : 2; index_size *= index_32bit ? 4 : 2;
@ -266,7 +266,7 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
out_info->type_info = &op_info; out_info->type_info = &op_info;
uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0); uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t index_count = dword0 >> 16; uint32_t index_count = dword0 >> 16;
auto prim_type = static_cast<PrimitiveType>(dword0 & 0x3F); auto prim_type = static_cast<xenos::PrimitiveType>(dword0 & 0x3F);
uint32_t src_sel = (dword0 >> 6) & 0x3; uint32_t src_sel = (dword0 >> 6) & 0x3;
assert_true(src_sel == 0x2); // 'SrcSel=AutoIndex' assert_true(src_sel == 0x2); // 'SrcSel=AutoIndex'
bool index_32bit = (dword0 >> 11) & 0x1; bool index_32bit = (dword0 >> 11) & 0x1;
@ -386,7 +386,7 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
"PM4_IM_LOAD"}; "PM4_IM_LOAD"};
out_info->type_info = &op_info; out_info->type_info = &op_info;
uint32_t addr_type = xe::load_and_swap<uint32_t>(ptr + 0); uint32_t addr_type = xe::load_and_swap<uint32_t>(ptr + 0);
auto shader_type = static_cast<ShaderType>(addr_type & 0x3); auto shader_type = static_cast<xenos::ShaderType>(addr_type & 0x3);
uint32_t addr = addr_type & ~0x3; uint32_t addr = addr_type & ~0x3;
uint32_t start_size = xe::load_and_swap<uint32_t>(ptr + 4); uint32_t start_size = xe::load_and_swap<uint32_t>(ptr + 4);
uint32_t start = start_size >> 16; uint32_t start = start_size >> 16;
@ -401,7 +401,7 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr,
out_info->type_info = &op_info; out_info->type_info = &op_info;
uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0); uint32_t dword0 = xe::load_and_swap<uint32_t>(ptr + 0);
uint32_t dword1 = xe::load_and_swap<uint32_t>(ptr + 4); uint32_t dword1 = xe::load_and_swap<uint32_t>(ptr + 4);
auto shader_type = static_cast<ShaderType>(dword0); auto shader_type = static_cast<xenos::ShaderType>(dword0);
uint32_t start_size = dword1; uint32_t start_size = dword1;
uint32_t start = start_size >> 16; uint32_t start = start_size >> 16;
uint32_t size_dwords = start_size & 0xFFFF; // dwords uint32_t size_dwords = start_size & 0xFFFF; // dwords

View File

@ -175,11 +175,11 @@ union SQ_INTERPOLATOR_CNTL {
union VGT_DRAW_INITIATOR { union VGT_DRAW_INITIATOR {
// Different than on A2xx and R6xx/R7xx. // Different than on A2xx and R6xx/R7xx.
struct { struct {
PrimitiveType prim_type : 6; // +0 xenos::PrimitiveType prim_type : 6; // +0
xenos::SourceSelect source_select : 2; // +6 xenos::SourceSelect source_select : 2; // +6
xenos::MajorMode major_mode : 2; // +8 xenos::MajorMode major_mode : 2; // +8
uint32_t : 1; // +10 uint32_t : 1; // +10
IndexFormat index_size : 1; // +11 xenos::IndexFormat index_size : 1; // +11
uint32_t not_eop : 1; // +12 uint32_t not_eop : 1; // +12
uint32_t : 3; // +13 uint32_t : 3; // +13
uint32_t num_indices : 16; // +16 uint32_t num_indices : 16; // +16
@ -396,7 +396,7 @@ union RB_SURFACE_INFO {
struct { struct {
uint32_t surface_pitch : 14; // +0 uint32_t surface_pitch : 14; // +0
uint32_t : 2; // +14 uint32_t : 2; // +14
MsaaSamples msaa_samples : 2; // +16 xenos::MsaaSamples msaa_samples : 2; // +16
uint32_t hiz_pitch : 14; // +18 uint32_t hiz_pitch : 14; // +18
}; };
uint32_t value; uint32_t value;
@ -405,7 +405,7 @@ union RB_SURFACE_INFO {
union RB_COLORCONTROL { union RB_COLORCONTROL {
struct { struct {
CompareFunction alpha_func : 3; // +0 xenos::CompareFunction alpha_func : 3; // +0
uint32_t alpha_test_enable : 1; // +3 uint32_t alpha_test_enable : 1; // +3
uint32_t alpha_to_mask_enable : 1; // +4 uint32_t alpha_to_mask_enable : 1; // +4
// Everything in between was added on Adreno. // Everything in between was added on Adreno.
@ -456,7 +456,7 @@ union RB_COLOR_INFO {
struct { struct {
uint32_t color_base : 12; // +0 uint32_t color_base : 12; // +0
uint32_t : 4; // +12 uint32_t : 4; // +12
ColorRenderTargetFormat color_format : 4; // +16 xenos::ColorRenderTargetFormat color_format : 4; // +16
int32_t color_exp_bias : 6; // +20 int32_t color_exp_bias : 6; // +20
}; };
uint32_t value; uint32_t value;
@ -490,13 +490,13 @@ union RB_COLOR_MASK {
union RB_BLENDCONTROL { union RB_BLENDCONTROL {
struct { struct {
BlendFactor color_srcblend : 5; // +0 xenos::BlendFactor color_srcblend : 5; // +0
BlendOp color_comb_fcn : 3; // +5 xenos::BlendOp color_comb_fcn : 3; // +5
BlendFactor color_destblend : 5; // +8 xenos::BlendFactor color_destblend : 5; // +8
uint32_t : 3; // +13 uint32_t : 3; // +13
BlendFactor alpha_srcblend : 5; // +16 xenos::BlendFactor alpha_srcblend : 5; // +16
BlendOp alpha_comb_fcn : 3; // +21 xenos::BlendOp alpha_comb_fcn : 3; // +21
BlendFactor alpha_destblend : 5; // +24 xenos::BlendFactor alpha_destblend : 5; // +24
// BLEND_FORCE_ENABLE and BLEND_FORCE were added on Adreno. // BLEND_FORCE_ENABLE and BLEND_FORCE were added on Adreno.
}; };
uint32_t value; uint32_t value;
@ -512,16 +512,16 @@ union RB_DEPTHCONTROL {
uint32_t z_write_enable : 1; // +2 uint32_t z_write_enable : 1; // +2
// EARLY_Z_ENABLE was added on Adreno. // EARLY_Z_ENABLE was added on Adreno.
uint32_t : 1; // +3 uint32_t : 1; // +3
CompareFunction zfunc : 3; // +4 xenos::CompareFunction zfunc : 3; // +4
uint32_t backface_enable : 1; // +7 uint32_t backface_enable : 1; // +7
CompareFunction stencilfunc : 3; // +8 xenos::CompareFunction stencilfunc : 3; // +8
StencilOp stencilfail : 3; // +11 xenos::StencilOp stencilfail : 3; // +11
StencilOp stencilzpass : 3; // +14 xenos::StencilOp stencilzpass : 3; // +14
StencilOp stencilzfail : 3; // +17 xenos::StencilOp stencilzfail : 3; // +17
CompareFunction stencilfunc_bf : 3; // +20 xenos::CompareFunction stencilfunc_bf : 3; // +20
StencilOp stencilfail_bf : 3; // +23 xenos::StencilOp stencilfail_bf : 3; // +23
StencilOp stencilzpass_bf : 3; // +26 xenos::StencilOp stencilzpass_bf : 3; // +26
StencilOp stencilzfail_bf : 3; // +29 xenos::StencilOp stencilzfail_bf : 3; // +29
}; };
uint32_t value; uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_DEPTHCONTROL; static constexpr Register register_index = XE_GPU_REG_RB_DEPTHCONTROL;
@ -542,7 +542,7 @@ union RB_DEPTH_INFO {
struct { struct {
uint32_t depth_base : 12; // +0 uint32_t depth_base : 12; // +0
uint32_t : 4; // +12 uint32_t : 4; // +12
DepthRenderTargetFormat depth_format : 1; // +16 xenos::DepthRenderTargetFormat depth_format : 1; // +16
}; };
uint32_t value; uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_DEPTH_INFO; static constexpr Register register_index = XE_GPU_REG_RB_DEPTH_INFO;
@ -565,10 +565,10 @@ union RB_COPY_CONTROL {
union RB_COPY_DEST_INFO { union RB_COPY_DEST_INFO {
struct { struct {
Endian128 copy_dest_endian : 3; // +0 xenos::Endian128 copy_dest_endian : 3; // +0
uint32_t copy_dest_array : 1; // +3 uint32_t copy_dest_array : 1; // +3
uint32_t copy_dest_slice : 3; // +4 uint32_t copy_dest_slice : 3; // +4
ColorFormat copy_dest_format : 6; // +7 xenos::ColorFormat copy_dest_format : 6; // +7
uint32_t copy_dest_number : 3; // +13 uint32_t copy_dest_number : 3; // +13
int32_t copy_dest_exp_bias : 6; // +16 int32_t copy_dest_exp_bias : 6; // +16
uint32_t : 2; // +22 uint32_t : 2; // +22

View File

@ -23,22 +23,22 @@ bool SamplerInfo::Prepare(const xenos::xe_gpu_texture_fetch_t& fetch,
std::memset(out_info, 0, sizeof(SamplerInfo)); std::memset(out_info, 0, sizeof(SamplerInfo));
out_info->min_filter = out_info->min_filter =
fetch_instr.attributes.min_filter == TextureFilter::kUseFetchConst fetch_instr.attributes.min_filter == xenos::TextureFilter::kUseFetchConst
? fetch.min_filter ? fetch.min_filter
: fetch_instr.attributes.min_filter; : fetch_instr.attributes.min_filter;
out_info->mag_filter = out_info->mag_filter =
fetch_instr.attributes.mag_filter == TextureFilter::kUseFetchConst fetch_instr.attributes.mag_filter == xenos::TextureFilter::kUseFetchConst
? fetch.mag_filter ? fetch.mag_filter
: fetch_instr.attributes.mag_filter; : fetch_instr.attributes.mag_filter;
out_info->mip_filter = out_info->mip_filter =
fetch_instr.attributes.mip_filter == TextureFilter::kUseFetchConst fetch_instr.attributes.mip_filter == xenos::TextureFilter::kUseFetchConst
? fetch.mip_filter ? fetch.mip_filter
: fetch_instr.attributes.mip_filter; : fetch_instr.attributes.mip_filter;
out_info->clamp_u = fetch.clamp_x; out_info->clamp_u = fetch.clamp_x;
out_info->clamp_v = fetch.clamp_y; out_info->clamp_v = fetch.clamp_y;
out_info->clamp_w = fetch.clamp_z; out_info->clamp_w = fetch.clamp_z;
out_info->aniso_filter = out_info->aniso_filter =
fetch_instr.attributes.aniso_filter == AnisoFilter::kUseFetchConst fetch_instr.attributes.aniso_filter == xenos::AnisoFilter::kUseFetchConst
? fetch.aniso_filter ? fetch.aniso_filter
: fetch_instr.attributes.aniso_filter; : fetch_instr.attributes.aniso_filter;

View File

@ -17,14 +17,14 @@ namespace xe {
namespace gpu { namespace gpu {
struct SamplerInfo { struct SamplerInfo {
TextureFilter min_filter; xenos::TextureFilter min_filter;
TextureFilter mag_filter; xenos::TextureFilter mag_filter;
TextureFilter mip_filter; xenos::TextureFilter mip_filter;
ClampMode clamp_u; xenos::ClampMode clamp_u;
ClampMode clamp_v; xenos::ClampMode clamp_v;
ClampMode clamp_w; xenos::ClampMode clamp_w;
AnisoFilter aniso_filter; xenos::AnisoFilter aniso_filter;
BorderColor border_color; xenos::BorderColor border_color;
float lod_bias; float lod_bias;
uint32_t mip_min_level; uint32_t mip_min_level;
uint32_t mip_max_level; uint32_t mip_max_level;

View File

@ -23,7 +23,7 @@ namespace xe {
namespace gpu { namespace gpu {
using namespace ucode; using namespace ucode;
Shader::Shader(ShaderType shader_type, uint64_t ucode_data_hash, Shader::Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count) const uint32_t* ucode_dwords, size_t ucode_dword_count)
: shader_type_(shader_type), ucode_data_hash_(ucode_data_hash) { : shader_type_(shader_type), ucode_data_hash_(ucode_data_hash) {
// We keep ucode data in host native format so it's easier to work with. // We keep ucode data in host native format so it's easier to work with.
@ -54,7 +54,7 @@ std::pair<std::filesystem::path, std::filesystem::path> Shader::Dump(
fmt::format("shader_{}_{:016X}", path_prefix, ucode_data_hash_); fmt::format("shader_{}_{:016X}", path_prefix, ucode_data_hash_);
std::string txt_name, bin_name; std::string txt_name, bin_name;
if (shader_type_ == ShaderType::kVertex) { if (shader_type_ == xenos::ShaderType::kVertex) {
txt_name = base_name + ".vert"; txt_name = base_name + ".vert";
bin_name = base_name + ".bin.vert"; bin_name = base_name + ".bin.vert";
} else { } else {

View File

@ -422,7 +422,7 @@ struct ParsedVertexFetchInstruction {
InstructionOperand operands[2]; InstructionOperand operands[2];
struct Attributes { struct Attributes {
VertexFormat data_format = VertexFormat::kUndefined; xenos::VertexFormat data_format = xenos::VertexFormat::kUndefined;
int32_t offset = 0; int32_t offset = 0;
uint32_t stride = 0; // In dwords. uint32_t stride = 0; // In dwords.
int32_t exp_adjust = 0; int32_t exp_adjust = 0;
@ -447,7 +447,7 @@ struct ParsedTextureFetchInstruction {
// Friendly name of the instruction. // Friendly name of the instruction.
const char* opcode_name = nullptr; const char* opcode_name = nullptr;
// Texture dimension for opcodes that have multiple dimension forms. // Texture dimension for opcodes that have multiple dimension forms.
TextureDimension dimension = TextureDimension::k1D; xenos::FetchOpDimension dimension = xenos::FetchOpDimension::k1D;
// True if the instruction is predicated on the specified // True if the instruction is predicated on the specified
// predicate_condition. // predicate_condition.
@ -470,12 +470,12 @@ struct ParsedTextureFetchInstruction {
struct Attributes { struct Attributes {
bool fetch_valid_only = true; bool fetch_valid_only = true;
bool unnormalized_coordinates = false; bool unnormalized_coordinates = false;
TextureFilter mag_filter = TextureFilter::kUseFetchConst; xenos::TextureFilter mag_filter = xenos::TextureFilter::kUseFetchConst;
TextureFilter min_filter = TextureFilter::kUseFetchConst; xenos::TextureFilter min_filter = xenos::TextureFilter::kUseFetchConst;
TextureFilter mip_filter = TextureFilter::kUseFetchConst; xenos::TextureFilter mip_filter = xenos::TextureFilter::kUseFetchConst;
AnisoFilter aniso_filter = AnisoFilter::kUseFetchConst; xenos::AnisoFilter aniso_filter = xenos::AnisoFilter::kUseFetchConst;
TextureFilter vol_mag_filter = TextureFilter::kUseFetchConst; xenos::TextureFilter vol_mag_filter = xenos::TextureFilter::kUseFetchConst;
TextureFilter vol_min_filter = TextureFilter::kUseFetchConst; xenos::TextureFilter vol_min_filter = xenos::TextureFilter::kUseFetchConst;
bool use_computed_lod = true; bool use_computed_lod = true;
bool use_register_lod = false; bool use_register_lod = false;
bool use_register_gradients = false; bool use_register_gradients = false;
@ -666,12 +666,12 @@ class Shader {
} }
}; };
Shader(ShaderType shader_type, uint64_t ucode_data_hash, Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count); const uint32_t* ucode_dwords, size_t ucode_dword_count);
virtual ~Shader(); virtual ~Shader();
// Whether the shader is identified as a vertex or pixel shader. // Whether the shader is identified as a vertex or pixel shader.
ShaderType type() const { return shader_type_; } xenos::ShaderType type() const { return shader_type_; }
// If this is a vertex shader, and it has been translated, type of the shader // If this is a vertex shader, and it has been translated, type of the shader
// in a D3D11-like rendering pipeline - shader interface depends on in, so it // in a D3D11-like rendering pipeline - shader interface depends on in, so it
@ -761,7 +761,7 @@ class Shader {
protected: protected:
friend class ShaderTranslator; friend class ShaderTranslator;
ShaderType shader_type_; xenos::ShaderType shader_type_;
HostVertexShaderType host_vertex_shader_type_ = HostVertexShaderType::kVertex; HostVertexShaderType host_vertex_shader_type_ = HostVertexShaderType::kVertex;
std::vector<uint32_t> ucode_data_; std::vector<uint32_t> ucode_data_;
uint64_t ucode_data_hash_; uint64_t ucode_data_hash_;

View File

@ -51,12 +51,12 @@ namespace xe {
namespace gpu { namespace gpu {
int shader_compiler_main(const std::vector<std::string>& args) { int shader_compiler_main(const std::vector<std::string>& args) {
ShaderType shader_type; xenos::ShaderType shader_type;
if (!cvars::shader_input_type.empty()) { if (!cvars::shader_input_type.empty()) {
if (cvars::shader_input_type == "vs") { if (cvars::shader_input_type == "vs") {
shader_type = ShaderType::kVertex; shader_type = xenos::ShaderType::kVertex;
} else if (cvars::shader_input_type == "ps") { } else if (cvars::shader_input_type == "ps") {
shader_type = ShaderType::kPixel; shader_type = xenos::ShaderType::kPixel;
} else { } else {
XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'."); XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'.");
return 1; return 1;
@ -66,10 +66,10 @@ int shader_compiler_main(const std::vector<std::string>& args) {
if (cvars::shader_input.has_extension()) { if (cvars::shader_input.has_extension()) {
auto extension = cvars::shader_input.extension(); auto extension = cvars::shader_input.extension();
if (extension == ".vs") { if (extension == ".vs") {
shader_type = ShaderType::kVertex; shader_type = xenos::ShaderType::kVertex;
valid_type = true; valid_type = true;
} else if (extension == ".ps") { } else if (extension == ".ps") {
shader_type = ShaderType::kPixel; shader_type = xenos::ShaderType::kPixel;
valid_type = true; valid_type = true;
} }
} }
@ -96,7 +96,7 @@ int shader_compiler_main(const std::vector<std::string>& args) {
XELOGI("Opened {} as a {} shader, {} words ({} bytes).", XELOGI("Opened {} as a {} shader, {} words ({} bytes).",
xe::path_to_utf8(cvars::shader_input), xe::path_to_utf8(cvars::shader_input),
shader_type == ShaderType::kVertex ? "vertex" : "pixel", shader_type == xenos::ShaderType::kVertex ? "vertex" : "pixel",
ucode_dwords.size(), ucode_dwords.size() * 4); ucode_dwords.size(), ucode_dwords.size() * 4);
// TODO(benvanik): hash? need to return the data to big-endian format first. // TODO(benvanik): hash? need to return the data to big-endian format first.
@ -119,7 +119,7 @@ int shader_compiler_main(const std::vector<std::string>& args) {
Shader::HostVertexShaderType host_vertex_shader_type = Shader::HostVertexShaderType host_vertex_shader_type =
Shader::HostVertexShaderType::kVertex; Shader::HostVertexShaderType::kVertex;
if (shader_type == ShaderType::kVertex) { if (shader_type == xenos::ShaderType::kVertex) {
if (cvars::vertex_shader_output_type == "linedomaincp") { if (cvars::vertex_shader_output_type == "linedomaincp") {
host_vertex_shader_type = host_vertex_shader_type =
Shader::HostVertexShaderType::kLineDomainCPIndexed; Shader::HostVertexShaderType::kLineDomainCPIndexed;

View File

@ -111,8 +111,9 @@ bool ShaderTranslator::Translate(
Shader* shader, reg::SQ_PROGRAM_CNTL cntl, Shader* shader, reg::SQ_PROGRAM_CNTL cntl,
Shader::HostVertexShaderType host_vertex_shader_type) { Shader::HostVertexShaderType host_vertex_shader_type) {
Reset(); Reset();
uint32_t cntl_num_reg = uint32_t cntl_num_reg = shader->type() == xenos::ShaderType::kVertex
shader->type() == ShaderType::kVertex ? cntl.vs_num_reg : cntl.ps_num_reg; ? cntl.vs_num_reg
: cntl.ps_num_reg;
register_count_ = (cntl_num_reg & 0x80) ? 0 : (cntl_num_reg + 1); register_count_ = (cntl_num_reg & 0x80) ? 0 : (cntl_num_reg + 1);
return TranslateInternal(shader, host_vertex_shader_type); return TranslateInternal(shader, host_vertex_shader_type);
@ -494,8 +495,8 @@ void ShaderTranslator::GatherVertexFetchInformation(
// Populate attribute. // Populate attribute.
attrib->attrib_index = total_attrib_count_++; attrib->attrib_index = total_attrib_count_++;
attrib->fetch_instr = fetch_instr; attrib->fetch_instr = fetch_instr;
attrib->size_words = attrib->size_words = xenos::GetVertexFormatSizeInWords(
GetVertexFormatSizeInWords(attrib->fetch_instr.attributes.data_format); attrib->fetch_instr.attributes.data_format);
} }
void ShaderTranslator::GatherTextureFetchInformation( void ShaderTranslator::GatherTextureFetchInformation(
@ -1080,7 +1081,7 @@ void ShaderTranslator::ParseTextureFetchInstruction(
src_op.component_count = src_op.component_count =
opcode_info.override_component_count opcode_info.override_component_count
? opcode_info.override_component_count ? opcode_info.override_component_count
: GetTextureDimensionComponentCount(op.dimension()); : xenos::GetFetchOpDimensionComponentCount(op.dimension());
uint32_t swizzle = op.src_swizzle(); uint32_t swizzle = op.src_swizzle();
for (uint32_t j = 0; j < src_op.component_count; ++j, swizzle >>= 2) { for (uint32_t j = 0; j < src_op.component_count; ++j, swizzle >>= 2) {
src_op.components[j] = GetSwizzleFromComponentIndex(swizzle & 0x3); src_op.components[j] = GetSwizzleFromComponentIndex(swizzle & 0x3);
@ -1131,20 +1132,20 @@ uint32_t ParsedTextureFetchInstruction::GetNonZeroResultComponents() const {
// simplicity. It's very unlikely that this instruction is ever seriously // simplicity. It's very unlikely that this instruction is ever seriously
// used to retrieve weights of zero though. // used to retrieve weights of zero though.
switch (dimension) { switch (dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
components = 0b1001; components = 0b1001;
break; break;
case TextureDimension::k2D: case xenos::FetchOpDimension::k2D:
case TextureDimension::kCube: case xenos::FetchOpDimension::kCube:
// TODO(Triang3l): Is the depth lerp factor always 0 for cube maps? // TODO(Triang3l): Is the depth lerp factor always 0 for cube maps?
components = 0b1011; components = 0b1011;
break; break;
case TextureDimension::k3D: case xenos::FetchOpDimension::k3DOrStacked:
components = 0b1111; components = 0b1111;
break; break;
} }
if (attributes.mip_filter == TextureFilter::kBaseMap || if (attributes.mip_filter == xenos::TextureFilter::kBaseMap ||
attributes.mip_filter == TextureFilter::kPoint) { attributes.mip_filter == xenos::TextureFilter::kPoint) {
components &= ~uint32_t(0b1000); components &= ~uint32_t(0b1000);
} }
break; break;

View File

@ -49,14 +49,18 @@ class ShaderTranslator {
// Register count. // Register count.
uint32_t register_count() const { return register_count_; } uint32_t register_count() const { return register_count_; }
// True if the current shader is a vertex shader. // True if the current shader is a vertex shader.
bool is_vertex_shader() const { return shader_type_ == ShaderType::kVertex; } bool is_vertex_shader() const {
return shader_type_ == xenos::ShaderType::kVertex;
}
// If translating a vertex shader, type of the shader in a D3D11-like // If translating a vertex shader, type of the shader in a D3D11-like
// rendering pipeline. // rendering pipeline.
Shader::HostVertexShaderType host_vertex_shader_type() const { Shader::HostVertexShaderType host_vertex_shader_type() const {
return host_vertex_shader_type_; return host_vertex_shader_type_;
} }
// True if the current shader is a pixel shader. // True if the current shader is a pixel shader.
bool is_pixel_shader() const { return shader_type_ == ShaderType::kPixel; } bool is_pixel_shader() const {
return shader_type_ == xenos::ShaderType::kPixel;
}
// Used constant register info, populated before translation. // Used constant register info, populated before translation.
const Shader::ConstantRegisterMap& constant_register_map() const { const Shader::ConstantRegisterMap& constant_register_map() const {
return constant_register_map_; return constant_register_map_;
@ -243,7 +247,7 @@ class ShaderTranslator {
InstructionOperand& out_op); InstructionOperand& out_op);
// Input shader metadata and microcode. // Input shader metadata and microcode.
ShaderType shader_type_; xenos::ShaderType shader_type_;
Shader::HostVertexShaderType host_vertex_shader_type_; Shader::HostVertexShaderType host_vertex_shader_type_;
const uint32_t* ucode_dwords_; const uint32_t* ucode_dwords_;
size_t ucode_dword_count_; size_t ucode_dword_count_;

View File

@ -341,7 +341,7 @@ void ParsedVertexFetchInstruction::Disassemble(StringBuffer* out) const {
if (attributes.offset) { if (attributes.offset) {
out->AppendFormat(", Offset={}", attributes.offset); out->AppendFormat(", Offset={}", attributes.offset);
} }
if (attributes.data_format != VertexFormat::kUndefined) { if (attributes.data_format != xenos::VertexFormat::kUndefined) {
out->AppendFormat( out->AppendFormat(
", DataFormat={}", ", DataFormat={}",
kVertexFetchDataFormats[static_cast<int>(attributes.data_format)].name); kVertexFetchDataFormats[static_cast<int>(attributes.data_format)].name);
@ -404,32 +404,32 @@ void ParsedTextureFetchInstruction::Disassemble(StringBuffer* out) const {
if (attributes.unnormalized_coordinates) { if (attributes.unnormalized_coordinates) {
out->Append(", UnnormalizedTextureCoords=true"); out->Append(", UnnormalizedTextureCoords=true");
} }
if (attributes.mag_filter != TextureFilter::kUseFetchConst) { if (attributes.mag_filter != xenos::TextureFilter::kUseFetchConst) {
out->AppendFormat( out->AppendFormat(
", MagFilter={}", ", MagFilter={}",
kTextureFilterNames[static_cast<int>(attributes.mag_filter)]); kTextureFilterNames[static_cast<int>(attributes.mag_filter)]);
} }
if (attributes.min_filter != TextureFilter::kUseFetchConst) { if (attributes.min_filter != xenos::TextureFilter::kUseFetchConst) {
out->AppendFormat( out->AppendFormat(
", MinFilter={}", ", MinFilter={}",
kTextureFilterNames[static_cast<int>(attributes.min_filter)]); kTextureFilterNames[static_cast<int>(attributes.min_filter)]);
} }
if (attributes.mip_filter != TextureFilter::kUseFetchConst) { if (attributes.mip_filter != xenos::TextureFilter::kUseFetchConst) {
out->AppendFormat( out->AppendFormat(
", MipFilter={}", ", MipFilter={}",
kTextureFilterNames[static_cast<int>(attributes.mip_filter)]); kTextureFilterNames[static_cast<int>(attributes.mip_filter)]);
} }
if (attributes.aniso_filter != AnisoFilter::kUseFetchConst) { if (attributes.aniso_filter != xenos::AnisoFilter::kUseFetchConst) {
out->AppendFormat( out->AppendFormat(
", AnisoFilter={}", ", AnisoFilter={}",
kAnisoFilterNames[static_cast<int>(attributes.aniso_filter)]); kAnisoFilterNames[static_cast<int>(attributes.aniso_filter)]);
} }
if (attributes.vol_mag_filter != TextureFilter::kUseFetchConst) { if (attributes.vol_mag_filter != xenos::TextureFilter::kUseFetchConst) {
out->AppendFormat( out->AppendFormat(
", VolMagFilter={}", ", VolMagFilter={}",
kTextureFilterNames[static_cast<int>(attributes.vol_mag_filter)]); kTextureFilterNames[static_cast<int>(attributes.vol_mag_filter)]);
} }
if (attributes.vol_min_filter != TextureFilter::kUseFetchConst) { if (attributes.vol_min_filter != xenos::TextureFilter::kUseFetchConst) {
out->AppendFormat( out->AppendFormat(
", VolMinFilter={}", ", VolMinFilter={}",
kTextureFilterNames[static_cast<int>(attributes.vol_min_filter)]); kTextureFilterNames[static_cast<int>(attributes.vol_min_filter)]);
@ -446,7 +446,7 @@ void ParsedTextureFetchInstruction::Disassemble(StringBuffer* out) const {
if (attributes.lod_bias != 0.0f) { if (attributes.lod_bias != 0.0f) {
out->AppendFormat(", LODBias={:g}", attributes.lod_bias); out->AppendFormat(", LODBias={:g}", attributes.lod_bias);
} }
int component_count = GetTextureDimensionComponentCount(dimension); int component_count = xenos::GetFetchOpDimensionComponentCount(dimension);
if (attributes.offset_x != 0.0f) { if (attributes.offset_x != 0.0f) {
out->AppendFormat(", OffsetX={:g}", attributes.offset_x); out->AppendFormat(", OffsetX={:g}", attributes.offset_x);
} }

View File

@ -1279,7 +1279,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
spv::Id vertex = 0; spv::Id vertex = 0;
switch (instr.attributes.data_format) { switch (instr.attributes.data_format) {
case VertexFormat::k_8_8_8_8: { case xenos::VertexFormat::k_8_8_8_8: {
auto vertex_ptr = b.createAccessChain( auto vertex_ptr = b.createAccessChain(
spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx});
auto vertex_data = b.createLoad(vertex_ptr); auto vertex_data = b.createLoad(vertex_ptr);
@ -1312,7 +1312,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
} }
} break; } break;
case VertexFormat::k_16_16: { case xenos::VertexFormat::k_16_16: {
spv::Id components[1] = {}; spv::Id components[1] = {};
for (uint32_t i = 0; i < 1; i++) { for (uint32_t i = 0; i < 1; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1359,7 +1359,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
vertex = components[0]; vertex = components[0];
} break; } break;
case VertexFormat::k_16_16_16_16: { case xenos::VertexFormat::k_16_16_16_16: {
spv::Id components[2] = {}; spv::Id components[2] = {};
for (uint32_t i = 0; i < 2; i++) { for (uint32_t i = 0; i < 2; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1407,7 +1407,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
spv::NoPrecision, {components[0], components[1]}, vec4_float_type_); spv::NoPrecision, {components[0], components[1]}, vec4_float_type_);
} break; } break;
case VertexFormat::k_16_16_FLOAT: { case xenos::VertexFormat::k_16_16_FLOAT: {
spv::Id components[1] = {}; spv::Id components[1] = {};
for (uint32_t i = 0; i < 1; i++) { for (uint32_t i = 0; i < 1; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1426,7 +1426,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
vertex = components[0]; vertex = components[0];
} break; } break;
case VertexFormat::k_16_16_16_16_FLOAT: { case xenos::VertexFormat::k_16_16_16_16_FLOAT: {
spv::Id components[2] = {}; spv::Id components[2] = {};
for (uint32_t i = 0; i < 2; i++) { for (uint32_t i = 0; i < 2; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1446,7 +1446,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
spv::NoPrecision, {components[0], components[1]}, vec4_float_type_); spv::NoPrecision, {components[0], components[1]}, vec4_float_type_);
} break; } break;
case VertexFormat::k_32: { case xenos::VertexFormat::k_32: {
spv::Id components[1] = {}; spv::Id components[1] = {};
for (uint32_t i = 0; i < 1; i++) { for (uint32_t i = 0; i < 1; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1481,7 +1481,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
vertex = components[0]; vertex = components[0];
} break; } break;
case VertexFormat::k_32_32: { case xenos::VertexFormat::k_32_32: {
spv::Id components[2] = {}; spv::Id components[2] = {};
for (uint32_t i = 0; i < 2; i++) { for (uint32_t i = 0; i < 2; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1516,7 +1516,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
{components[0], components[1]}); {components[0], components[1]});
} break; } break;
case VertexFormat::k_32_32_32_32: { case xenos::VertexFormat::k_32_32_32_32: {
spv::Id components[4] = {}; spv::Id components[4] = {};
for (uint32_t i = 0; i < 4; i++) { for (uint32_t i = 0; i < 4; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1552,7 +1552,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
{components[0], components[1], components[2], components[3]}); {components[0], components[1], components[2], components[3]});
} break; } break;
case VertexFormat::k_32_FLOAT: { case xenos::VertexFormat::k_32_FLOAT: {
auto vertex_ptr = b.createAccessChain( auto vertex_ptr = b.createAccessChain(
spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx});
auto vertex_data = b.createLoad(vertex_ptr); auto vertex_data = b.createLoad(vertex_ptr);
@ -1560,7 +1560,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
vertex = b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data); vertex = b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data);
} break; } break;
case VertexFormat::k_32_32_FLOAT: { case xenos::VertexFormat::k_32_32_FLOAT: {
spv::Id components[2] = {}; spv::Id components[2] = {};
for (uint32_t i = 0; i < 2; i++) { for (uint32_t i = 0; i < 2; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1577,7 +1577,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
{components[0], components[1]}); {components[0], components[1]});
} break; } break;
case VertexFormat::k_32_32_32_FLOAT: { case xenos::VertexFormat::k_32_32_32_FLOAT: {
spv::Id components[3] = {}; spv::Id components[3] = {};
for (uint32_t i = 0; i < 3; i++) { for (uint32_t i = 0; i < 3; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1594,7 +1594,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
vec3_float_type_, {components[0], components[1], components[2]}); vec3_float_type_, {components[0], components[1], components[2]});
} break; } break;
case VertexFormat::k_32_32_32_32_FLOAT: { case xenos::VertexFormat::k_32_32_32_32_FLOAT: {
spv::Id components[4] = {}; spv::Id components[4] = {};
for (uint32_t i = 0; i < 4; i++) { for (uint32_t i = 0; i < 4; i++) {
auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx,
@ -1612,7 +1612,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
{components[0], components[1], components[2], components[3]}); {components[0], components[1], components[2], components[3]});
} break; } break;
case VertexFormat::k_2_10_10_10: { case xenos::VertexFormat::k_2_10_10_10: {
auto vertex_ptr = b.createAccessChain( auto vertex_ptr = b.createAccessChain(
spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx});
auto vertex_data = b.createLoad(vertex_ptr); auto vertex_data = b.createLoad(vertex_ptr);
@ -1659,7 +1659,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
components[2], components[3]})); components[2], components[3]}));
} break; } break;
case VertexFormat::k_10_11_11: { case xenos::VertexFormat::k_10_11_11: {
auto vertex_ptr = b.createAccessChain( auto vertex_ptr = b.createAccessChain(
spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx});
auto vertex_data = b.createLoad(vertex_ptr); auto vertex_data = b.createLoad(vertex_ptr);
@ -1717,7 +1717,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
std::vector<Id>({components[0], components[1], components[2]})); std::vector<Id>({components[0], components[1], components[2]}));
} break; } break;
case VertexFormat::k_11_11_10: { case xenos::VertexFormat::k_11_11_10: {
auto vertex_ptr = b.createAccessChain( auto vertex_ptr = b.createAccessChain(
spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx});
auto vertex_data = b.createLoad(vertex_ptr); auto vertex_data = b.createLoad(vertex_ptr);
@ -1768,7 +1768,7 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
std::vector<Id>({components[0], components[1], components[2]})); std::vector<Id>({components[0], components[1], components[2]}));
} break; } break;
case VertexFormat::kUndefined: case xenos::VertexFormat::kUndefined:
break; break;
} }
@ -1815,14 +1815,14 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
uint32_t dim_idx = 0; uint32_t dim_idx = 0;
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
case TextureDimension::k2D: { case xenos::FetchOpDimension::k2D: {
dim_idx = 0; dim_idx = 0;
} break; } break;
case TextureDimension::k3D: { case xenos::FetchOpDimension::k3DOrStacked: {
dim_idx = 1; dim_idx = 1;
} break; } break;
case TextureDimension::kCube: { case xenos::FetchOpDimension::kCube: {
dim_idx = 2; dim_idx = 2;
} break; } break;
default: default:
@ -1838,7 +1838,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
tex_[dim_idx], std::vector<Id>({texture_index})); tex_[dim_idx], std::vector<Id>({texture_index}));
auto texture = b.createLoad(texture_ptr); auto texture = b.createLoad(texture_ptr);
if (instr.dimension == TextureDimension::k1D) { if (instr.dimension == xenos::FetchOpDimension::k1D) {
// Upgrade 1D src coordinate into 2D // Upgrade 1D src coordinate into 2D
src = b.createCompositeConstruct(vec2_float_type_, src = b.createCompositeConstruct(vec2_float_type_,
{src, b.makeFloatConstant(0.f)}); {src, b.makeFloatConstant(0.f)});
@ -1863,7 +1863,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
Id offset = 0; Id offset = 0;
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: { case xenos::FetchOpDimension::k1D: {
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb944006.aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/bb944006.aspx
// "Because the runtime does not support 1D textures, the compiler // "Because the runtime does not support 1D textures, the compiler
// will use a 2D texture with the knowledge that the y-coordinate is // will use a 2D texture with the knowledge that the y-coordinate is
@ -1872,18 +1872,18 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
vec2_int_type_, vec2_int_type_,
{b.makeIntConstant(int(offset_x)), b.makeIntConstant(0)}); {b.makeIntConstant(int(offset_x)), b.makeIntConstant(0)});
} break; } break;
case TextureDimension::k2D: { case xenos::FetchOpDimension::k2D: {
offset = b.makeCompositeConstant( offset = b.makeCompositeConstant(
vec2_int_type_, {b.makeIntConstant(int(offset_x)), vec2_int_type_, {b.makeIntConstant(int(offset_x)),
b.makeIntConstant(int(offset_y))}); b.makeIntConstant(int(offset_y))});
} break; } break;
case TextureDimension::k3D: { case xenos::FetchOpDimension::k3DOrStacked: {
offset = b.makeCompositeConstant( offset = b.makeCompositeConstant(
vec3_int_type_, {b.makeIntConstant(int(offset_x)), vec3_int_type_, {b.makeIntConstant(int(offset_x)),
b.makeIntConstant(int(offset_y)), b.makeIntConstant(int(offset_y)),
b.makeIntConstant(int(offset_z))}); b.makeIntConstant(int(offset_z))});
} break; } break;
case TextureDimension::kCube: { case xenos::FetchOpDimension::kCube: {
// FIXME(DrChat): Is this the correct dimension? I forget // FIXME(DrChat): Is this the correct dimension? I forget
offset = b.makeCompositeConstant( offset = b.makeCompositeConstant(
vec3_int_type_, {b.makeIntConstant(int(offset_x)), vec3_int_type_, {b.makeIntConstant(int(offset_x)),
@ -1926,8 +1926,8 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
b.createUnaryOp(spv::OpImage, b.getImageType(texture), texture); b.createUnaryOp(spv::OpImage, b.getImageType(texture), texture);
switch (instr.dimension) { switch (instr.dimension) {
case TextureDimension::k1D: case xenos::FetchOpDimension::k1D:
case TextureDimension::k2D: { case xenos::FetchOpDimension::k2D: {
spv::Builder::TextureParameters params; spv::Builder::TextureParameters params;
std::memset(&params, 0, sizeof(params)); std::memset(&params, 0, sizeof(params));
params.sampler = image; params.sampler = image;
@ -1966,7 +1966,7 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
tex_[dim_idx], std::vector<Id>({texture_index})); tex_[dim_idx], std::vector<Id>({texture_index}));
auto texture = b.createLoad(texture_ptr); auto texture = b.createLoad(texture_ptr);
if (instr.dimension == TextureDimension::k1D) { if (instr.dimension == xenos::FetchOpDimension::k1D) {
// Upgrade 1D src coordinate into 2D // Upgrade 1D src coordinate into 2D
src = b.createCompositeConstruct(vec2_float_type_, src = b.createCompositeConstruct(vec2_float_type_,
{src, b.makeFloatConstant(0.f)}); {src, b.makeFloatConstant(0.f)});

View File

@ -27,27 +27,28 @@ namespace texture_conversion {
using namespace xe::gpu::xenos; using namespace xe::gpu::xenos;
void CopySwapBlock(Endian endian, void* output, const void* input, void CopySwapBlock(xenos::Endian endian, void* output, const void* input,
size_t length) { size_t length) {
switch (endian) { switch (endian) {
case Endian::k8in16: case xenos::Endian::k8in16:
xe::copy_and_swap_16_unaligned(output, input, length / 2); xe::copy_and_swap_16_unaligned(output, input, length / 2);
break; break;
case Endian::k8in32: case xenos::Endian::k8in32:
xe::copy_and_swap_32_unaligned(output, input, length / 4); xe::copy_and_swap_32_unaligned(output, input, length / 4);
break; break;
case Endian::k16in32: // Swap high and low 16 bits within a 32 bit word case xenos::Endian::k16in32: // Swap high and low 16 bits within a 32 bit
// word
xe::copy_and_swap_16_in_32_unaligned(output, input, length); xe::copy_and_swap_16_in_32_unaligned(output, input, length);
break; break;
default: default:
case Endian::kNone: case xenos::Endian::kNone:
std::memcpy(output, input, length); std::memcpy(output, input, length);
break; break;
} }
} }
void ConvertTexelCTX1ToR8G8(Endian endian, void* output, const void* input, void ConvertTexelCTX1ToR8G8(xenos::Endian endian, void* output,
size_t length) { const void* input, size_t length) {
// https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf // https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf
// (R is in the higher bits, according to how this format is used in Halo 3). // (R is in the higher bits, according to how this format is used in Halo 3).
union { union {
@ -81,8 +82,8 @@ void ConvertTexelCTX1ToR8G8(Endian endian, void* output, const void* input,
} }
} }
void ConvertTexelDXT3AToDXT3(Endian endian, void* output, const void* input, void ConvertTexelDXT3AToDXT3(xenos::Endian endian, void* output,
size_t length) { const void* input, size_t length) {
const uint32_t bytes_per_block = 16; const uint32_t bytes_per_block = 16;
auto output_bytes = static_cast<uint8_t*>(output); auto output_bytes = static_cast<uint8_t*>(output);
CopySwapBlock(endian, &output_bytes[0], input, 8); CopySwapBlock(endian, &output_bytes[0], input, 8);

View File

@ -22,15 +22,15 @@ namespace xe {
namespace gpu { namespace gpu {
namespace texture_conversion { namespace texture_conversion {
typedef std::function<void(Endian, void*, const void*, size_t)> typedef std::function<void(xenos::Endian, void*, const void*, size_t)>
CopyBlockCallback; CopyBlockCallback;
void CopySwapBlock(Endian endian, void* output, const void* input, void CopySwapBlock(xenos::Endian endian, void* output, const void* input,
size_t length);
void ConvertTexelCTX1ToR8G8(Endian endian, void* output, const void* input,
size_t length);
void ConvertTexelDXT3AToDXT3(Endian endian, void* output, const void* input,
size_t length); size_t length);
void ConvertTexelCTX1ToR8G8(xenos::Endian endian, void* output,
const void* input, size_t length);
void ConvertTexelDXT3AToDXT3(xenos::Endian endian, void* output,
const void* input, size_t length);
typedef std::function<void(void*, const void*, size_t)> UntileCopyBlockCallback; typedef std::function<void(void*, const void*, size_t)> UntileCopyBlockCallback;

View File

@ -57,22 +57,22 @@ void TextureDump(const TextureInfo& src, void* buffer, size_t length) {
dds_header.pixel_format.size = sizeof(dds_header.pixel_format); dds_header.pixel_format.size = sizeof(dds_header.pixel_format);
switch (src.format) { switch (src.format) {
case TextureFormat::k_DXT1: { case xenos::TextureFormat::k_DXT1: {
dds_header.pixel_format.flags = 0x4u; dds_header.pixel_format.flags = 0x4u;
dds_header.pixel_format.fourcc = '1TXD'; dds_header.pixel_format.fourcc = '1TXD';
break; break;
} }
case TextureFormat::k_DXT2_3: { case xenos::TextureFormat::k_DXT2_3: {
dds_header.pixel_format.flags = 0x4u; dds_header.pixel_format.flags = 0x4u;
dds_header.pixel_format.fourcc = '3TXD'; dds_header.pixel_format.fourcc = '3TXD';
break; break;
} }
case TextureFormat::k_DXT4_5: { case xenos::TextureFormat::k_DXT4_5: {
dds_header.pixel_format.flags = 0x4u; dds_header.pixel_format.flags = 0x4u;
dds_header.pixel_format.fourcc = '5TXD'; dds_header.pixel_format.fourcc = '5TXD';
break; break;
} }
case TextureFormat::k_8_8_8_8: { case xenos::TextureFormat::k_8_8_8_8: {
dds_header.pixel_format.flags = 0x1u | 0x40u; dds_header.pixel_format.flags = 0x1u | 0x40u;
dds_header.pixel_format.rgb_bit_count = 32; dds_header.pixel_format.rgb_bit_count = 32;
dds_header.pixel_format.r_bit_mask = 0x00FF0000u; dds_header.pixel_format.r_bit_mask = 0x00FF0000u;

View File

@ -40,12 +40,13 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
info.width = info.height = info.depth = 0; info.width = info.height = info.depth = 0;
info.is_stacked = false; info.is_stacked = false;
switch (info.dimension) { switch (info.dimension) {
case Dimension::k1D: case xenos::DataDimension::k1D:
info.dimension = Dimension::k2D; // we treat 1D textures as 2D // we treat 1D textures as 2D
info.dimension = DataDimension::k2DOrStacked;
info.width = fetch.size_1d.width; info.width = fetch.size_1d.width;
assert_true(!fetch.stacked); assert_true(!fetch.stacked);
break; break;
case Dimension::k2D: case xenos::DataDimension::k2DOrStacked:
info.width = fetch.size_2d.width; info.width = fetch.size_2d.width;
info.height = fetch.size_2d.height; info.height = fetch.size_2d.height;
if (fetch.stacked) { if (fetch.stacked) {
@ -53,13 +54,13 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
info.is_stacked = true; info.is_stacked = true;
} }
break; break;
case Dimension::k3D: case xenos::DataDimension::k3D:
info.width = fetch.size_3d.width; info.width = fetch.size_3d.width;
info.height = fetch.size_3d.height; info.height = fetch.size_3d.height;
info.depth = fetch.size_3d.depth; info.depth = fetch.size_3d.depth;
assert_true(!fetch.stacked); assert_true(!fetch.stacked);
break; break;
case Dimension::kCube: case xenos::DataDimension::kCube:
info.width = fetch.size_2d.width; info.width = fetch.size_2d.width;
info.height = fetch.size_2d.height; info.height = fetch.size_2d.height;
assert_true(fetch.size_2d.stack_depth == 5); assert_true(fetch.size_2d.stack_depth == 5);
@ -78,7 +79,7 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
info.is_tiled = fetch.tiled; info.is_tiled = fetch.tiled;
info.has_packed_mips = fetch.packed_mips; info.has_packed_mips = fetch.packed_mips;
if (info.format_info()->format == TextureFormat::kUnknown) { if (info.format_info()->format == xenos::TextureFormat::kUnknown) {
XELOGE("Attempting to fetch from unsupported texture format {}", XELOGE("Attempting to fetch from unsupported texture format {}",
info.format); info.format);
info.memory.base_address = fetch.base_address << 12; info.memory.base_address = fetch.base_address << 12;
@ -100,10 +101,10 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
} }
bool TextureInfo::PrepareResolve(uint32_t physical_address, bool TextureInfo::PrepareResolve(uint32_t physical_address,
TextureFormat format, Endian endian, xenos::TextureFormat format,
uint32_t pitch, uint32_t width, xenos::Endian endian, uint32_t pitch,
uint32_t height, uint32_t depth, uint32_t width, uint32_t height,
TextureInfo* out_info) { uint32_t depth, TextureInfo* out_info) {
assert_true(width > 0); assert_true(width > 0);
assert_true(height > 0); assert_true(height > 0);
@ -113,7 +114,7 @@ bool TextureInfo::PrepareResolve(uint32_t physical_address,
info.format = format; info.format = format;
info.endianness = endian; info.endianness = endian;
info.dimension = Dimension::k2D; info.dimension = xenos::DataDimension::k2DOrStacked;
info.width = width - 1; info.width = width - 1;
info.height = height - 1; info.height = height - 1;
info.depth = depth - 1; info.depth = depth - 1;
@ -125,7 +126,7 @@ bool TextureInfo::PrepareResolve(uint32_t physical_address,
info.is_tiled = true; info.is_tiled = true;
info.has_packed_mips = false; info.has_packed_mips = false;
if (info.format_info()->format == TextureFormat::kUnknown) { if (info.format_info()->format == xenos::TextureFormat::kUnknown) {
assert_true("Unsupported texture format"); assert_true("Unsupported texture format");
info.memory.base_address = physical_address; info.memory.base_address = physical_address;
return false; return false;

View File

@ -19,31 +19,31 @@
namespace xe { namespace xe {
namespace gpu { namespace gpu {
inline TextureFormat GetBaseFormat(TextureFormat texture_format) { inline xenos::TextureFormat GetBaseFormat(xenos::TextureFormat texture_format) {
// These formats are used for resampling textures / gamma control. // These formats are used for resampling textures / gamma control.
switch (texture_format) { switch (texture_format) {
case TextureFormat::k_16_EXPAND: case xenos::TextureFormat::k_16_EXPAND:
return TextureFormat::k_16_FLOAT; return xenos::TextureFormat::k_16_FLOAT;
case TextureFormat::k_16_16_EXPAND: case xenos::TextureFormat::k_16_16_EXPAND:
return TextureFormat::k_16_16_FLOAT; return xenos::TextureFormat::k_16_16_FLOAT;
case TextureFormat::k_16_16_16_16_EXPAND: case xenos::TextureFormat::k_16_16_16_16_EXPAND:
return TextureFormat::k_16_16_16_16_FLOAT; return xenos::TextureFormat::k_16_16_16_16_FLOAT;
case TextureFormat::k_8_8_8_8_AS_16_16_16_16: case xenos::TextureFormat::k_8_8_8_8_AS_16_16_16_16:
return TextureFormat::k_8_8_8_8; return xenos::TextureFormat::k_8_8_8_8;
case TextureFormat::k_DXT1_AS_16_16_16_16: case xenos::TextureFormat::k_DXT1_AS_16_16_16_16:
return TextureFormat::k_DXT1; return xenos::TextureFormat::k_DXT1;
case TextureFormat::k_DXT2_3_AS_16_16_16_16: case xenos::TextureFormat::k_DXT2_3_AS_16_16_16_16:
return TextureFormat::k_DXT2_3; return xenos::TextureFormat::k_DXT2_3;
case TextureFormat::k_DXT4_5_AS_16_16_16_16: case xenos::TextureFormat::k_DXT4_5_AS_16_16_16_16:
return TextureFormat::k_DXT4_5; return xenos::TextureFormat::k_DXT4_5;
case TextureFormat::k_2_10_10_10_AS_16_16_16_16: case xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16:
return TextureFormat::k_2_10_10_10; return xenos::TextureFormat::k_2_10_10_10;
case TextureFormat::k_10_11_11_AS_16_16_16_16: case xenos::TextureFormat::k_10_11_11_AS_16_16_16_16:
return TextureFormat::k_10_11_11; return xenos::TextureFormat::k_10_11_11;
case TextureFormat::k_11_11_10_AS_16_16_16_16: case xenos::TextureFormat::k_11_11_10_AS_16_16_16_16:
return TextureFormat::k_11_11_10; return xenos::TextureFormat::k_11_11_10;
case TextureFormat::k_8_8_8_8_GAMMA_EDRAM: case xenos::TextureFormat::k_8_8_8_8_GAMMA_EDRAM:
return TextureFormat::k_8_8_8_8; return xenos::TextureFormat::k_8_8_8_8;
default: default:
break; break;
} }
@ -51,42 +51,42 @@ inline TextureFormat GetBaseFormat(TextureFormat texture_format) {
return texture_format; return texture_format;
} }
inline size_t GetTexelSize(TextureFormat format) { inline size_t GetTexelSize(xenos::TextureFormat format) {
switch (format) { switch (format) {
case TextureFormat::k_1_5_5_5: case xenos::TextureFormat::k_1_5_5_5:
return 2; return 2;
case TextureFormat::k_2_10_10_10: case xenos::TextureFormat::k_2_10_10_10:
return 4; return 4;
case TextureFormat::k_4_4_4_4: case xenos::TextureFormat::k_4_4_4_4:
return 2; return 2;
case TextureFormat::k_5_6_5: case xenos::TextureFormat::k_5_6_5:
return 2; return 2;
case TextureFormat::k_8: case xenos::TextureFormat::k_8:
return 1; return 1;
case TextureFormat::k_8_8: case xenos::TextureFormat::k_8_8:
return 2; return 2;
case TextureFormat::k_8_8_8_8: case xenos::TextureFormat::k_8_8_8_8:
return 4; return 4;
case TextureFormat::k_16: case xenos::TextureFormat::k_16:
return 4; return 4;
case TextureFormat::k_16_FLOAT: case xenos::TextureFormat::k_16_FLOAT:
return 4; return 4;
case TextureFormat::k_16_16: case xenos::TextureFormat::k_16_16:
return 4; return 4;
case TextureFormat::k_16_16_FLOAT: case xenos::TextureFormat::k_16_16_FLOAT:
return 4; return 4;
case TextureFormat::k_16_16_16_16: case xenos::TextureFormat::k_16_16_16_16:
return 8; return 8;
case TextureFormat::k_16_16_16_16_FLOAT: case xenos::TextureFormat::k_16_16_16_16_FLOAT:
return 8; return 8;
case TextureFormat::k_32_FLOAT: case xenos::TextureFormat::k_32_FLOAT:
return 4; return 4;
case TextureFormat::k_32_32_FLOAT: case xenos::TextureFormat::k_32_32_FLOAT:
return 8; return 8;
case TextureFormat::k_32_32_32_32_FLOAT: case xenos::TextureFormat::k_32_32_32_32_FLOAT:
return 16; return 16;
case TextureFormat::k_10_11_11: case xenos::TextureFormat::k_10_11_11:
case TextureFormat::k_11_11_10: case xenos::TextureFormat::k_11_11_10:
return 4; return 4;
default: default:
assert_unhandled_case(format); assert_unhandled_case(format);
@ -94,104 +94,52 @@ inline size_t GetTexelSize(TextureFormat format) {
} }
} }
inline bool IsSRGBCapable(TextureFormat format) { inline xenos::TextureFormat ColorFormatToTextureFormat(
switch (format) { xenos::ColorFormat color_format) {
case TextureFormat::k_1_REVERSE: return static_cast<xenos::TextureFormat>(color_format);
case TextureFormat::k_1:
case TextureFormat::k_8:
case TextureFormat::k_1_5_5_5:
case TextureFormat::k_5_6_5:
case TextureFormat::k_6_5_5:
case TextureFormat::k_8_8_8_8:
case TextureFormat::k_8_8:
case TextureFormat::k_Cr_Y1_Cb_Y0_REP:
case TextureFormat::k_Y1_Cr_Y0_Cb_REP:
case TextureFormat::k_4_4_4_4:
case TextureFormat::k_DXT1:
case TextureFormat::k_DXT2_3:
case TextureFormat::k_DXT4_5:
case TextureFormat::k_24_8:
case TextureFormat::k_16:
case TextureFormat::k_16_16:
case TextureFormat::k_16_16_16_16:
case TextureFormat::k_16_EXPAND:
case TextureFormat::k_16_16_EXPAND:
case TextureFormat::k_16_16_16_16_EXPAND:
case TextureFormat::k_32:
case TextureFormat::k_32_32:
case TextureFormat::k_32_32_32_32:
case TextureFormat::k_32_FLOAT:
case TextureFormat::k_32_32_FLOAT:
case TextureFormat::k_32_32_32_32_FLOAT:
case TextureFormat::k_32_AS_8:
case TextureFormat::k_32_AS_8_8:
case TextureFormat::k_16_MPEG:
case TextureFormat::k_16_16_MPEG:
case TextureFormat::k_8_INTERLACED:
case TextureFormat::k_32_AS_8_INTERLACED:
case TextureFormat::k_32_AS_8_8_INTERLACED:
case TextureFormat::k_16_INTERLACED:
case TextureFormat::k_16_MPEG_INTERLACED:
case TextureFormat::k_16_16_MPEG_INTERLACED:
case TextureFormat::k_DXN:
case TextureFormat::k_8_8_8_8_AS_16_16_16_16:
case TextureFormat::k_DXT1_AS_16_16_16_16:
case TextureFormat::k_DXT2_3_AS_16_16_16_16:
case TextureFormat::k_DXT4_5_AS_16_16_16_16:
case TextureFormat::k_2_10_10_10_AS_16_16_16_16:
case TextureFormat::k_10_11_11_AS_16_16_16_16:
case TextureFormat::k_11_11_10_AS_16_16_16_16:
return true;
default:
return false;
}
} }
inline TextureFormat ColorFormatToTextureFormat(ColorFormat color_format) { inline xenos::TextureFormat ColorRenderTargetToTextureFormat(
return static_cast<TextureFormat>(color_format); xenos::ColorRenderTargetFormat color_format) {
}
inline TextureFormat ColorRenderTargetToTextureFormat(
ColorRenderTargetFormat color_format) {
switch (color_format) { switch (color_format) {
case ColorRenderTargetFormat::k_8_8_8_8: case xenos::ColorRenderTargetFormat::k_8_8_8_8:
return TextureFormat::k_8_8_8_8; return xenos::TextureFormat::k_8_8_8_8;
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return TextureFormat::k_8_8_8_8_GAMMA_EDRAM; return xenos::TextureFormat::k_8_8_8_8_GAMMA_EDRAM;
case ColorRenderTargetFormat::k_2_10_10_10: case xenos::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_AS_10_10_10_10:
return TextureFormat::k_2_10_10_10; return xenos::TextureFormat::k_2_10_10_10;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return TextureFormat::k_2_10_10_10_FLOAT_EDRAM; return xenos::TextureFormat::k_2_10_10_10_FLOAT_EDRAM;
case ColorRenderTargetFormat::k_16_16: case xenos::ColorRenderTargetFormat::k_16_16:
return TextureFormat::k_16_16_EDRAM; return xenos::TextureFormat::k_16_16_EDRAM;
case ColorRenderTargetFormat::k_16_16_16_16: case xenos::ColorRenderTargetFormat::k_16_16_16_16:
return TextureFormat::k_16_16_16_16_EDRAM; return xenos::TextureFormat::k_16_16_16_16_EDRAM;
case ColorRenderTargetFormat::k_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_FLOAT:
return TextureFormat::k_16_16_FLOAT; return xenos::TextureFormat::k_16_16_FLOAT;
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
return TextureFormat::k_16_16_16_16_FLOAT; return xenos::TextureFormat::k_16_16_16_16_FLOAT;
case ColorRenderTargetFormat::k_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_FLOAT:
return TextureFormat::k_32_FLOAT; return xenos::TextureFormat::k_32_FLOAT;
case ColorRenderTargetFormat::k_32_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_32_FLOAT:
return TextureFormat::k_32_32_FLOAT; return xenos::TextureFormat::k_32_32_FLOAT;
default: default:
assert_unhandled_case(color_format); assert_unhandled_case(color_format);
return TextureFormat::kUnknown; return xenos::TextureFormat::kUnknown;
} }
} }
inline TextureFormat DepthRenderTargetToTextureFormat( inline xenos::TextureFormat DepthRenderTargetToTextureFormat(
DepthRenderTargetFormat depth_format) { xenos::DepthRenderTargetFormat depth_format) {
switch (depth_format) { switch (depth_format) {
case DepthRenderTargetFormat::kD24S8: case xenos::DepthRenderTargetFormat::kD24S8:
return TextureFormat::k_24_8; return xenos::TextureFormat::k_24_8;
case DepthRenderTargetFormat::kD24FS8: case xenos::DepthRenderTargetFormat::kD24FS8:
return TextureFormat::k_24_8_FLOAT; return xenos::TextureFormat::k_24_8_FLOAT;
default: default:
assert_unhandled_case(depth_format); assert_unhandled_case(depth_format);
return TextureFormat::kUnknown; return xenos::TextureFormat::kUnknown;
} }
} }
@ -201,7 +149,7 @@ enum class FormatType {
}; };
struct FormatInfo { struct FormatInfo {
TextureFormat format; xenos::TextureFormat format;
const char* name; const char* name;
FormatType type; FormatType type;
uint32_t block_width; uint32_t block_width;
@ -214,7 +162,7 @@ struct FormatInfo {
static const FormatInfo* Get(uint32_t gpu_format); static const FormatInfo* Get(uint32_t gpu_format);
static const FormatInfo* Get(TextureFormat format) { static const FormatInfo* Get(xenos::TextureFormat format) {
return Get(static_cast<uint32_t>(format)); return Get(static_cast<uint32_t>(format));
} }
}; };
@ -250,10 +198,10 @@ struct TextureMemoryInfo {
}; };
struct TextureInfo { struct TextureInfo {
TextureFormat format; xenos::TextureFormat format;
Endian endianness; xenos::Endian endianness;
Dimension dimension; xenos::DataDimension dimension;
uint32_t width; // width in pixels uint32_t width; // width in pixels
uint32_t height; // height in pixels uint32_t height; // height in pixels
uint32_t depth; // depth in layers uint32_t depth; // depth in layers
@ -281,9 +229,10 @@ struct TextureInfo {
TextureInfo* out_info); TextureInfo* out_info);
static bool PrepareResolve(uint32_t physical_address, static bool PrepareResolve(uint32_t physical_address,
TextureFormat texture_format, Endian endian, xenos::TextureFormat texture_format,
uint32_t pitch, uint32_t width, uint32_t height, xenos::Endian endian, uint32_t pitch,
uint32_t depth, TextureInfo* out_info); uint32_t width, uint32_t height, uint32_t depth,
TextureInfo* out_info);
uint32_t GetMaxMipLevels() const; uint32_t GetMaxMipLevels() const;

View File

@ -17,7 +17,7 @@ namespace gpu {
using namespace xe::gpu::xenos; using namespace xe::gpu::xenos;
#define FORMAT_INFO(texture_format, format, block_width, block_height, bits_per_pixel) \ #define FORMAT_INFO(texture_format, format, block_width, block_height, bits_per_pixel) \
{TextureFormat::texture_format, #texture_format, FormatType::format, block_width, block_height, bits_per_pixel} {xenos::TextureFormat::texture_format, #texture_format, FormatType::format, block_width, block_height, bits_per_pixel}
const FormatInfo* FormatInfo::Get(uint32_t gpu_format) { const FormatInfo* FormatInfo::Get(uint32_t gpu_format) {
static const FormatInfo format_infos[64] = { static const FormatInfo format_infos[64] = {
FORMAT_INFO(k_1_REVERSE , kUncompressed, 1, 1, 1), FORMAT_INFO(k_1_REVERSE , kUncompressed, 1, 1, 1),

View File

@ -22,27 +22,27 @@ void GetSubresourcesFromFetchConstant(
const xenos::xe_gpu_texture_fetch_t& fetch, uint32_t* width_out, const xenos::xe_gpu_texture_fetch_t& fetch, uint32_t* width_out,
uint32_t* height_out, uint32_t* depth_or_faces_out, uint32_t* base_page_out, uint32_t* height_out, uint32_t* depth_or_faces_out, uint32_t* base_page_out,
uint32_t* mip_page_out, uint32_t* mip_min_level_out, uint32_t* mip_page_out, uint32_t* mip_min_level_out,
uint32_t* mip_max_level_out, TextureFilter sampler_mip_filter) { uint32_t* mip_max_level_out, xenos::TextureFilter sampler_mip_filter) {
uint32_t width = 0, height = 0, depth_or_faces = 0; uint32_t width = 0, height = 0, depth_or_faces = 0;
switch (fetch.dimension) { switch (fetch.dimension) {
case Dimension::k1D: case xenos::DataDimension::k1D:
assert_false(fetch.stacked); assert_false(fetch.stacked);
assert_false(fetch.tiled); assert_false(fetch.tiled);
assert_false(fetch.packed_mips); assert_false(fetch.packed_mips);
width = fetch.size_1d.width; width = fetch.size_1d.width;
break; break;
case Dimension::k2D: case xenos::DataDimension::k2DOrStacked:
width = fetch.size_2d.width; width = fetch.size_2d.width;
height = fetch.size_2d.height; height = fetch.size_2d.height;
depth_or_faces = fetch.stacked ? fetch.size_2d.stack_depth : 0; depth_or_faces = fetch.stacked ? fetch.size_2d.stack_depth : 0;
break; break;
case Dimension::k3D: case xenos::DataDimension::k3D:
assert_false(fetch.stacked); assert_false(fetch.stacked);
width = fetch.size_3d.width; width = fetch.size_3d.width;
height = fetch.size_3d.height; height = fetch.size_3d.height;
depth_or_faces = fetch.size_3d.depth; depth_or_faces = fetch.size_3d.depth;
break; break;
case Dimension::kCube: case xenos::DataDimension::kCube:
assert_false(fetch.stacked); assert_false(fetch.stacked);
assert_true(fetch.size_2d.stack_depth == 5); assert_true(fetch.size_2d.stack_depth == 5);
width = fetch.size_2d.width; width = fetch.size_2d.width;
@ -64,11 +64,12 @@ void GetSubresourcesFromFetchConstant(
} }
uint32_t longest_axis = std::max(width, height); uint32_t longest_axis = std::max(width, height);
if (fetch.dimension == Dimension::k3D) { if (fetch.dimension == xenos::DataDimension::k3D) {
longest_axis = std::max(longest_axis, depth_or_faces); longest_axis = std::max(longest_axis, depth_or_faces);
} }
uint32_t size_mip_max_level = xe::log2_floor(longest_axis); uint32_t size_mip_max_level = xe::log2_floor(longest_axis);
TextureFilter mip_filter = sampler_mip_filter == TextureFilter::kUseFetchConst xenos::TextureFilter mip_filter =
sampler_mip_filter == xenos::TextureFilter::kUseFetchConst
? fetch.mip_filter ? fetch.mip_filter
: sampler_mip_filter; : sampler_mip_filter;
@ -76,7 +77,7 @@ void GetSubresourcesFromFetchConstant(
uint32_t mip_page = fetch.mip_address & 0x1FFFF; uint32_t mip_page = fetch.mip_address & 0x1FFFF;
uint32_t mip_min_level, mip_max_level; uint32_t mip_min_level, mip_max_level;
if (mip_filter == TextureFilter::kBaseMap || mip_page == 0) { if (mip_filter == xenos::TextureFilter::kBaseMap || mip_page == 0) {
mip_min_level = 0; mip_min_level = 0;
mip_max_level = 0; mip_max_level = 0;
} else { } else {
@ -117,16 +118,17 @@ void GetSubresourcesFromFetchConstant(
} }
} }
void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height, void GetGuestMipBlocks(xenos::DataDimension dimension, uint32_t width,
uint32_t depth, TextureFormat format, uint32_t mip, uint32_t height, uint32_t depth,
xenos::TextureFormat format, uint32_t mip,
uint32_t& width_blocks_out, uint32_t& height_blocks_out, uint32_t& width_blocks_out, uint32_t& height_blocks_out,
uint32_t& depth_blocks_out) { uint32_t& depth_blocks_out) {
// Get mipmap size. // Get mipmap size.
if (mip != 0) { if (mip != 0) {
width = std::max(xe::next_pow2(width) >> mip, uint32_t(1)); width = std::max(xe::next_pow2(width) >> mip, uint32_t(1));
if (dimension != Dimension::k1D) { if (dimension != xenos::DataDimension::k1D) {
height = std::max(xe::next_pow2(height) >> mip, uint32_t(1)); height = std::max(xe::next_pow2(height) >> mip, uint32_t(1));
if (dimension == Dimension::k3D) { if (dimension == xenos::DataDimension::k3D) {
depth = std::max(xe::next_pow2(depth) >> mip, uint32_t(1)); depth = std::max(xe::next_pow2(depth) >> mip, uint32_t(1));
} }
} }
@ -140,12 +142,12 @@ void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height,
// Align to tile size. // Align to tile size.
width_blocks_out = xe::align(width, uint32_t(32)); width_blocks_out = xe::align(width, uint32_t(32));
if (dimension != Dimension::k1D) { if (dimension != xenos::DataDimension::k1D) {
height_blocks_out = xe::align(height, uint32_t(32)); height_blocks_out = xe::align(height, uint32_t(32));
} else { } else {
height_blocks_out = 1; height_blocks_out = 1;
} }
if (dimension == Dimension::k3D) { if (dimension == xenos::DataDimension::k3D) {
depth_blocks_out = xe::align(depth, uint32_t(4)); depth_blocks_out = xe::align(depth, uint32_t(4));
} else { } else {
depth_blocks_out = 1; depth_blocks_out = 1;
@ -155,7 +157,7 @@ void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height,
uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks, uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks,
uint32_t height_blocks, uint32_t height_blocks,
uint32_t depth_blocks, bool is_tiled, uint32_t depth_blocks, bool is_tiled,
TextureFormat format, xenos::TextureFormat format,
uint32_t* row_pitch_out, bool align_4kb) { uint32_t* row_pitch_out, bool align_4kb) {
const FormatInfo* format_info = FormatInfo::Get(format); const FormatInfo* format_info = FormatInfo::Get(format);
uint32_t row_pitch = width_blocks * format_info->block_width * uint32_t row_pitch = width_blocks * format_info->block_width *
@ -175,8 +177,9 @@ uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks,
} }
bool GetPackedMipOffset(uint32_t width, uint32_t height, uint32_t depth, bool GetPackedMipOffset(uint32_t width, uint32_t height, uint32_t depth,
TextureFormat format, uint32_t mip, uint32_t& x_blocks, xenos::TextureFormat format, uint32_t mip,
uint32_t& y_blocks, uint32_t& z_blocks) { uint32_t& x_blocks, uint32_t& y_blocks,
uint32_t& z_blocks) {
// Tile size is 32x32, and once textures go <=16 they are packed into a // Tile size is 32x32, and once textures go <=16 they are packed into a
// single tile together. The math here is insane. Most sourced from // single tile together. The math here is insane. Most sourced from
// graph paper, looking at dds dumps and executable reverse engineering. // graph paper, looking at dds dumps and executable reverse engineering.
@ -266,11 +269,12 @@ bool GetPackedMipOffset(uint32_t width, uint32_t height, uint32_t depth,
return true; return true;
} }
void GetTextureTotalSize(Dimension dimension, uint32_t width, uint32_t height, void GetTextureTotalSize(xenos::DataDimension dimension, uint32_t width,
uint32_t depth, TextureFormat format, bool is_tiled, uint32_t height, uint32_t depth,
xenos::TextureFormat format, bool is_tiled,
bool packed_mips, uint32_t mip_max_level, bool packed_mips, uint32_t mip_max_level,
uint32_t* base_size_out, uint32_t* mip_size_out) { uint32_t* base_size_out, uint32_t* mip_size_out) {
bool is_3d = dimension == Dimension::k3D; bool is_3d = dimension == xenos::DataDimension::k3D;
uint32_t width_blocks, height_blocks, depth_blocks; uint32_t width_blocks, height_blocks, depth_blocks;
if (base_size_out) { if (base_size_out) {
GetGuestMipBlocks(dimension, width, height, depth, format, 0, width_blocks, GetGuestMipBlocks(dimension, width, height, depth, format, 0, width_blocks,
@ -362,30 +366,30 @@ uint8_t SwizzleSigns(const xenos::xe_gpu_texture_fetch_t& fetch) {
if (swizzle & 0b100) { if (swizzle & 0b100) {
constant_mask |= uint8_t(1) << (i * 2); constant_mask |= uint8_t(1) << (i * 2);
} else { } else {
TextureSign sign = xenos::TextureSign sign =
TextureSign((fetch.dword_0 >> (2 + swizzle * 2)) & 0b11); xenos::TextureSign((fetch.dword_0 >> (2 + swizzle * 2)) & 0b11);
signs |= uint8_t(sign) << (i * 2); signs |= uint8_t(sign) << (i * 2);
if (sign == TextureSign::kSigned) { if (sign == xenos::TextureSign::kSigned) {
any_signed = true; any_signed = true;
} else { } else {
any_not_signed = true; any_not_signed = true;
} }
} }
} }
TextureSign constants_sign = TextureSign::kUnsigned; xenos::TextureSign constants_sign = xenos::TextureSign::kUnsigned;
if (constant_mask == 0b01010101) { if (constant_mask == 0b01010101) {
// If only constant components, choose according to the original format // If only constant components, choose according to the original format
// (what would more likely be loaded if there were non-constant components). // (what would more likely be loaded if there were non-constant components).
// If all components would be signed, use signed. // If all components would be signed, use signed.
if (((fetch.dword_0 >> 2) & 0b11111111) == if (((fetch.dword_0 >> 2) & 0b11111111) ==
uint32_t(TextureSign::kSigned) * 0b01010101) { uint32_t(xenos::TextureSign::kSigned) * 0b01010101) {
constants_sign = TextureSign::kSigned; constants_sign = xenos::TextureSign::kSigned;
} }
} else { } else {
// If only signed and constant components, reading just from the signed host // If only signed and constant components, reading just from the signed host
// view is enough. // view is enough.
if (any_signed && !any_not_signed) { if (any_signed && !any_not_signed) {
constants_sign = TextureSign::kSigned; constants_sign = xenos::TextureSign::kSigned;
} }
} }
signs |= uint8_t(constants_sign) * constant_mask; signs |= uint8_t(constants_sign) * constant_mask;

View File

@ -30,12 +30,14 @@ void GetSubresourcesFromFetchConstant(
uint32_t* height_out, uint32_t* depth_or_faces_out, uint32_t* base_page_out, uint32_t* height_out, uint32_t* depth_or_faces_out, uint32_t* base_page_out,
uint32_t* mip_page_out, uint32_t* mip_min_level_out, uint32_t* mip_page_out, uint32_t* mip_min_level_out,
uint32_t* mip_max_level_out, uint32_t* mip_max_level_out,
TextureFilter sampler_mip_filter = TextureFilter::kUseFetchConst); xenos::TextureFilter sampler_mip_filter =
xenos::TextureFilter::kUseFetchConst);
// Calculates width, height and depth of the image backing the guest mipmap (or // Calculates width, height and depth of the image backing the guest mipmap (or
// the base level if mip is 0). // the base level if mip is 0).
void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height, void GetGuestMipBlocks(xenos::DataDimension dimension, uint32_t width,
uint32_t depth, TextureFormat format, uint32_t mip, uint32_t height, uint32_t depth,
xenos::TextureFormat format, uint32_t mip,
uint32_t& width_blocks_out, uint32_t& height_blocks_out, uint32_t& width_blocks_out, uint32_t& height_blocks_out,
uint32_t& depth_blocks_out); uint32_t& depth_blocks_out);
@ -46,7 +48,7 @@ void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height,
uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks, uint32_t GetGuestMipSliceStorageSize(uint32_t width_blocks,
uint32_t height_blocks, uint32_t height_blocks,
uint32_t depth_blocks, bool is_tiled, uint32_t depth_blocks, bool is_tiled,
TextureFormat format, xenos::TextureFormat format,
uint32_t* row_pitch_out, uint32_t* row_pitch_out,
bool align_4kb = true); bool align_4kb = true);
@ -60,13 +62,15 @@ inline uint32_t GetPackedMipLevel(uint32_t width, uint32_t height) {
// returns false) if the mip level is not packed. Width, height and depth are in // returns false) if the mip level is not packed. Width, height and depth are in
// texels. For non-3D textures, set depth to 1. // texels. For non-3D textures, set depth to 1.
bool GetPackedMipOffset(uint32_t width, uint32_t height, uint32_t depth, bool GetPackedMipOffset(uint32_t width, uint32_t height, uint32_t depth,
TextureFormat format, uint32_t mip, uint32_t& x_blocks, xenos::TextureFormat format, uint32_t mip,
uint32_t& y_blocks, uint32_t& z_blocks); uint32_t& x_blocks, uint32_t& y_blocks,
uint32_t& z_blocks);
// Returns the total size of memory the texture uses starting from its base and // Returns the total size of memory the texture uses starting from its base and
// mip addresses, in bytes (both are optional). // mip addresses, in bytes (both are optional).
void GetTextureTotalSize(Dimension dimension, uint32_t width, uint32_t height, void GetTextureTotalSize(xenos::DataDimension dimension, uint32_t width,
uint32_t depth, TextureFormat format, bool is_tiled, uint32_t height, uint32_t depth,
xenos::TextureFormat format, bool is_tiled,
bool packed_mips, uint32_t mip_max_level, bool packed_mips, uint32_t mip_max_level,
uint32_t* base_size_out, uint32_t* mip_size_out); uint32_t* base_size_out, uint32_t* mip_size_out);
@ -111,12 +115,12 @@ int32_t GetTiledOffset3D(int32_t x, int32_t y, int32_t z, uint32_t width,
// constant components). // constant components).
uint8_t SwizzleSigns(const xenos::xe_gpu_texture_fetch_t& fetch); uint8_t SwizzleSigns(const xenos::xe_gpu_texture_fetch_t& fetch);
constexpr bool IsAnySignNotSigned(uint8_t packed_signs) { constexpr bool IsAnySignNotSigned(uint8_t packed_signs) {
return packed_signs != uint32_t(TextureSign::kSigned) * 0b01010101; return packed_signs != uint32_t(xenos::TextureSign::kSigned) * 0b01010101;
} }
constexpr bool IsAnySignSigned(uint8_t packed_signs) { constexpr bool IsAnySignSigned(uint8_t packed_signs) {
// Make signed 00 - check if all are 01, 10 or 11. // Make signed 00 - check if all are 01, 10 or 11.
uint32_t xor_signed = uint32_t xor_signed =
packed_signs ^ (uint32_t(TextureSign::kSigned) * 0b01010101); packed_signs ^ (uint32_t(xenos::TextureSign::kSigned) * 0b01010101);
return ((xor_signed | (xor_signed >> 1)) & 0b01010101) != 0b01010101; return ((xor_signed | (xor_signed >> 1)) & 0b01010101) != 0b01010101;
} }

View File

@ -699,18 +699,18 @@ void TraceViewer::DrawTextureInfo(
ImGui::Text("Guest Address: %.8X", texture_info.memory.base_address); ImGui::Text("Guest Address: %.8X", texture_info.memory.base_address);
ImGui::Text("Format: %s", texture_info.format_info()->name); ImGui::Text("Format: %s", texture_info.format_info()->name);
switch (texture_info.dimension) { switch (texture_info.dimension) {
case Dimension::k1D: case xenos::DataDimension::k1D:
ImGui::Text("1D: %dpx", texture_info.width + 1); ImGui::Text("1D: %dpx", texture_info.width + 1);
break; break;
case Dimension::k2D: case xenos::DataDimension::k2DOrStacked:
ImGui::Text("2D: %dx%dpx", texture_info.width + 1, ImGui::Text("2D: %dx%dpx", texture_info.width + 1,
texture_info.height + 1); texture_info.height + 1);
break; break;
case Dimension::k3D: case xenos::DataDimension::k3D:
ImGui::Text("3D: %dx%dx%dpx", texture_info.width + 1, ImGui::Text("3D: %dx%dx%dpx", texture_info.width + 1,
texture_info.height + 1, texture_info.depth + 1); texture_info.height + 1, texture_info.depth + 1);
break; break;
case Dimension::kCube: case xenos::DataDimension::kCube:
ImGui::Text("Cube: ?"); ImGui::Text("Cube: ?");
break; break;
} }
@ -737,32 +737,32 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
int column_count = 0; int column_count = 0;
for (const auto& attrib : vertex_binding.attributes) { for (const auto& attrib : vertex_binding.attributes) {
switch (attrib.fetch_instr.attributes.data_format) { switch (attrib.fetch_instr.attributes.data_format) {
case VertexFormat::k_32: case xenos::VertexFormat::k_32:
case VertexFormat::k_32_FLOAT: case xenos::VertexFormat::k_32_FLOAT:
++column_count; ++column_count;
break; break;
case VertexFormat::k_16_16: case xenos::VertexFormat::k_16_16:
case VertexFormat::k_16_16_FLOAT: case xenos::VertexFormat::k_16_16_FLOAT:
case VertexFormat::k_32_32: case xenos::VertexFormat::k_32_32:
case VertexFormat::k_32_32_FLOAT: case xenos::VertexFormat::k_32_32_FLOAT:
column_count += 2; column_count += 2;
break; break;
case VertexFormat::k_10_11_11: case xenos::VertexFormat::k_10_11_11:
case VertexFormat::k_11_11_10: case xenos::VertexFormat::k_11_11_10:
case VertexFormat::k_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_FLOAT:
column_count += 3; column_count += 3;
break; break;
case VertexFormat::k_8_8_8_8: case xenos::VertexFormat::k_8_8_8_8:
++column_count; ++column_count;
break; break;
case VertexFormat::k_2_10_10_10: case xenos::VertexFormat::k_2_10_10_10:
case VertexFormat::k_16_16_16_16: case xenos::VertexFormat::k_16_16_16_16:
case VertexFormat::k_32_32_32_32: case xenos::VertexFormat::k_32_32_32_32:
case VertexFormat::k_16_16_16_16_FLOAT: case xenos::VertexFormat::k_16_16_16_16_FLOAT:
case VertexFormat::k_32_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_32_FLOAT:
column_count += 4; column_count += 4;
break; break;
case VertexFormat::kUndefined: case xenos::VertexFormat::kUndefined:
assert_unhandled_case(attrib.fetch_instr.attributes.data_format); assert_unhandled_case(attrib.fetch_instr.attributes.data_format);
break; break;
} }
@ -780,23 +780,23 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
++el_index) { ++el_index) {
const auto& attrib = vertex_binding.attributes[el_index]; const auto& attrib = vertex_binding.attributes[el_index];
switch (attrib.fetch_instr.attributes.data_format) { switch (attrib.fetch_instr.attributes.data_format) {
case VertexFormat::k_32: case xenos::VertexFormat::k_32:
case VertexFormat::k_32_FLOAT: case xenos::VertexFormat::k_32_FLOAT:
ImGui::Text("e%" PRId64 ".x", el_index); ImGui::Text("e%" PRId64 ".x", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_16_16: case xenos::VertexFormat::k_16_16:
case VertexFormat::k_16_16_FLOAT: case xenos::VertexFormat::k_16_16_FLOAT:
case VertexFormat::k_32_32: case xenos::VertexFormat::k_32_32:
case VertexFormat::k_32_32_FLOAT: case xenos::VertexFormat::k_32_32_FLOAT:
ImGui::Text("e%" PRId64 ".x", el_index); ImGui::Text("e%" PRId64 ".x", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("e%" PRId64 ".y", el_index); ImGui::Text("e%" PRId64 ".y", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_10_11_11: case xenos::VertexFormat::k_10_11_11:
case VertexFormat::k_11_11_10: case xenos::VertexFormat::k_11_11_10:
case VertexFormat::k_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_FLOAT:
ImGui::Text("e%" PRId64 ".x", el_index); ImGui::Text("e%" PRId64 ".x", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("e%" PRId64 ".y", el_index); ImGui::Text("e%" PRId64 ".y", el_index);
@ -804,15 +804,15 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("e%" PRId64 ".z", el_index); ImGui::Text("e%" PRId64 ".z", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_8_8_8_8: case xenos::VertexFormat::k_8_8_8_8:
ImGui::Text("e%" PRId64 ".xyzw", el_index); ImGui::Text("e%" PRId64 ".xyzw", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_2_10_10_10: case xenos::VertexFormat::k_2_10_10_10:
case VertexFormat::k_16_16_16_16: case xenos::VertexFormat::k_16_16_16_16:
case VertexFormat::k_32_32_32_32: case xenos::VertexFormat::k_32_32_32_32:
case VertexFormat::k_16_16_16_16_FLOAT: case xenos::VertexFormat::k_16_16_16_16_FLOAT:
case VertexFormat::k_32_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_32_FLOAT:
ImGui::Text("e%" PRId64 ".x", el_index); ImGui::Text("e%" PRId64 ".x", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("e%" PRId64 ".y", el_index); ImGui::Text("e%" PRId64 ".y", el_index);
@ -822,7 +822,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("e%" PRId64 ".w", el_index); ImGui::Text("e%" PRId64 ".w", el_index);
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::kUndefined: case xenos::VertexFormat::kUndefined:
assert_unhandled_case(attrib.fetch_instr.attributes.data_format); assert_unhandled_case(attrib.fetch_instr.attributes.data_format);
break; break;
} }
@ -837,22 +837,22 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
(attrib.fetch_instr.attributes.offset + wo) * 4), \ (attrib.fetch_instr.attributes.offset + wo) * 4), \
fetch->endian) fetch->endian)
switch (attrib.fetch_instr.attributes.data_format) { switch (attrib.fetch_instr.attributes.data_format) {
case VertexFormat::k_32: case xenos::VertexFormat::k_32:
ImGui::Text("%.8X", LOADEL(uint32_t, 0)); ImGui::Text("%.8X", LOADEL(uint32_t, 0));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_32_FLOAT: case xenos::VertexFormat::k_32_FLOAT:
ImGui::Text("%.3f", LOADEL(float, 0)); ImGui::Text("%.3f", LOADEL(float, 0));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_16_16: { case xenos::VertexFormat::k_16_16: {
auto e0 = LOADEL(uint32_t, 0); auto e0 = LOADEL(uint32_t, 0);
ImGui::Text("%.4X", (e0 >> 16) & 0xFFFF); ImGui::Text("%.4X", (e0 >> 16) & 0xFFFF);
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("%.4X", (e0 >> 0) & 0xFFFF); ImGui::Text("%.4X", (e0 >> 0) & 0xFFFF);
ImGui::NextColumn(); ImGui::NextColumn();
} break; } break;
case VertexFormat::k_16_16_FLOAT: { case xenos::VertexFormat::k_16_16_FLOAT: {
auto e0 = LOADEL(uint32_t, 0); auto e0 = LOADEL(uint32_t, 0);
ImGui::Text("%.2f", ImGui::Text("%.2f",
half_float::detail::half2float((e0 >> 16) & 0xFFFF)); half_float::detail::half2float((e0 >> 16) & 0xFFFF));
@ -861,20 +861,20 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
half_float::detail::half2float((e0 >> 0) & 0xFFFF)); half_float::detail::half2float((e0 >> 0) & 0xFFFF));
ImGui::NextColumn(); ImGui::NextColumn();
} break; } break;
case VertexFormat::k_32_32: case xenos::VertexFormat::k_32_32:
ImGui::Text("%.8X", LOADEL(uint32_t, 0)); ImGui::Text("%.8X", LOADEL(uint32_t, 0));
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("%.8X", LOADEL(uint32_t, 1)); ImGui::Text("%.8X", LOADEL(uint32_t, 1));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_32_32_FLOAT: case xenos::VertexFormat::k_32_32_FLOAT:
ImGui::Text("%.3f", LOADEL(float, 0)); ImGui::Text("%.3f", LOADEL(float, 0));
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("%.3f", LOADEL(float, 1)); ImGui::Text("%.3f", LOADEL(float, 1));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_10_11_11: case xenos::VertexFormat::k_10_11_11:
case VertexFormat::k_11_11_10: case xenos::VertexFormat::k_11_11_10:
ImGui::Text("??"); ImGui::Text("??");
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("??"); ImGui::Text("??");
@ -882,7 +882,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("??"); ImGui::Text("??");
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_FLOAT:
ImGui::Text("%.3f", LOADEL(float, 0)); ImGui::Text("%.3f", LOADEL(float, 0));
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("%.3f", LOADEL(float, 1)); ImGui::Text("%.3f", LOADEL(float, 1));
@ -890,11 +890,11 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("%.3f", LOADEL(float, 2)); ImGui::Text("%.3f", LOADEL(float, 2));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_8_8_8_8: case xenos::VertexFormat::k_8_8_8_8:
ImGui::Text("%.8X", LOADEL(uint32_t, 0)); ImGui::Text("%.8X", LOADEL(uint32_t, 0));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_2_10_10_10: { case xenos::VertexFormat::k_2_10_10_10: {
auto e0 = LOADEL(uint32_t, 0); auto e0 = LOADEL(uint32_t, 0);
ImGui::Text("??"); ImGui::Text("??");
ImGui::NextColumn(); ImGui::NextColumn();
@ -905,7 +905,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("??"); ImGui::Text("??");
ImGui::NextColumn(); ImGui::NextColumn();
} break; } break;
case VertexFormat::k_16_16_16_16: { case xenos::VertexFormat::k_16_16_16_16: {
auto e0 = LOADEL(uint32_t, 0); auto e0 = LOADEL(uint32_t, 0);
auto e1 = LOADEL(uint32_t, 1); auto e1 = LOADEL(uint32_t, 1);
ImGui::Text("%.4X", (e0 >> 16) & 0xFFFF); ImGui::Text("%.4X", (e0 >> 16) & 0xFFFF);
@ -917,7 +917,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("%.4X", (e1 >> 0) & 0xFFFF); ImGui::Text("%.4X", (e1 >> 0) & 0xFFFF);
ImGui::NextColumn(); ImGui::NextColumn();
} break; } break;
case VertexFormat::k_32_32_32_32: case xenos::VertexFormat::k_32_32_32_32:
ImGui::Text("%.8X", LOADEL(uint32_t, 0)); ImGui::Text("%.8X", LOADEL(uint32_t, 0));
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("%.8X", LOADEL(uint32_t, 1)); ImGui::Text("%.8X", LOADEL(uint32_t, 1));
@ -927,7 +927,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("%.8X", LOADEL(uint32_t, 3)); ImGui::Text("%.8X", LOADEL(uint32_t, 3));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::k_16_16_16_16_FLOAT: { case xenos::VertexFormat::k_16_16_16_16_FLOAT: {
auto e0 = LOADEL(uint32_t, 0); auto e0 = LOADEL(uint32_t, 0);
auto e1 = LOADEL(uint32_t, 1); auto e1 = LOADEL(uint32_t, 1);
ImGui::Text("%.2f", ImGui::Text("%.2f",
@ -943,7 +943,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
half_float::detail::half2float((e1 >> 0) & 0xFFFF)); half_float::detail::half2float((e1 >> 0) & 0xFFFF));
ImGui::NextColumn(); ImGui::NextColumn();
} break; } break;
case VertexFormat::k_32_32_32_32_FLOAT: case xenos::VertexFormat::k_32_32_32_32_FLOAT:
ImGui::Text("%.3f", LOADEL(float, 0)); ImGui::Text("%.3f", LOADEL(float, 0));
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("%.3f", LOADEL(float, 1)); ImGui::Text("%.3f", LOADEL(float, 1));
@ -953,7 +953,7 @@ void TraceViewer::DrawVertexFetcher(Shader* shader,
ImGui::Text("%.3f", LOADEL(float, 3)); ImGui::Text("%.3f", LOADEL(float, 3));
ImGui::NextColumn(); ImGui::NextColumn();
break; break;
case VertexFormat::kUndefined: case xenos::VertexFormat::kUndefined:
assert_unhandled_case(attrib.fetch_instr.attributes.data_format); assert_unhandled_case(attrib.fetch_instr.attributes.data_format);
break; break;
} }
@ -1078,13 +1078,13 @@ void TraceViewer::DrawStateUI() {
assert_true(packet_type == 0x03); assert_true(packet_type == 0x03);
uint32_t opcode = (packet >> 8) & 0x7F; uint32_t opcode = (packet >> 8) & 0x7F;
struct { struct {
PrimitiveType prim_type; xenos::PrimitiveType prim_type;
bool is_auto_index; bool is_auto_index;
uint32_t index_count; uint32_t index_count;
uint32_t index_buffer_ptr; uint32_t index_buffer_ptr;
uint32_t index_buffer_size; uint32_t index_buffer_size;
Endian index_endianness; xenos::Endian index_endianness;
IndexFormat index_format; xenos::IndexFormat index_format;
} draw_info; } draw_info;
std::memset(&draw_info, 0, sizeof(draw_info)); std::memset(&draw_info, 0, sizeof(draw_info));
switch (opcode) { switch (opcode) {
@ -1092,7 +1092,7 @@ void TraceViewer::DrawStateUI() {
uint32_t dword0 = xe::load_and_swap<uint32_t>(packet_head + 4); uint32_t dword0 = xe::load_and_swap<uint32_t>(packet_head + 4);
uint32_t dword1 = xe::load_and_swap<uint32_t>(packet_head + 8); uint32_t dword1 = xe::load_and_swap<uint32_t>(packet_head + 8);
draw_info.index_count = dword1 >> 16; draw_info.index_count = dword1 >> 16;
draw_info.prim_type = static_cast<PrimitiveType>(dword1 & 0x3F); draw_info.prim_type = static_cast<xenos::PrimitiveType>(dword1 & 0x3F);
uint32_t src_sel = (dword1 >> 6) & 0x3; uint32_t src_sel = (dword1 >> 6) & 0x3;
if (src_sel == 0x0) { if (src_sel == 0x0) {
// Indexed draw. // Indexed draw.
@ -1100,11 +1100,12 @@ void TraceViewer::DrawStateUI() {
draw_info.index_buffer_ptr = draw_info.index_buffer_ptr =
xe::load_and_swap<uint32_t>(packet_head + 12); xe::load_and_swap<uint32_t>(packet_head + 12);
uint32_t index_size = xe::load_and_swap<uint32_t>(packet_head + 16); uint32_t index_size = xe::load_and_swap<uint32_t>(packet_head + 16);
draw_info.index_endianness = static_cast<Endian>(index_size >> 30); draw_info.index_endianness =
static_cast<xenos::Endian>(index_size >> 30);
index_size &= 0x00FFFFFF; index_size &= 0x00FFFFFF;
bool index_32bit = (dword1 >> 11) & 0x1; bool index_32bit = (dword1 >> 11) & 0x1;
draw_info.index_format = draw_info.index_format = index_32bit ? xenos::IndexFormat::kInt32
index_32bit ? IndexFormat::kInt32 : IndexFormat::kInt16; : xenos::IndexFormat::kInt16;
draw_info.index_buffer_size = index_size * (index_32bit ? 4 : 2); draw_info.index_buffer_size = index_size * (index_32bit ? 4 : 2);
} else if (src_sel == 0x2) { } else if (src_sel == 0x2) {
// Auto draw. // Auto draw.
@ -1119,7 +1120,7 @@ void TraceViewer::DrawStateUI() {
uint32_t dword0 = xe::load_and_swap<uint32_t>(packet_head + 4); uint32_t dword0 = xe::load_and_swap<uint32_t>(packet_head + 4);
uint32_t src_sel = (dword0 >> 6) & 0x3; uint32_t src_sel = (dword0 >> 6) & 0x3;
assert_true(src_sel == 0x2); // 'SrcSel=AutoIndex' assert_true(src_sel == 0x2); // 'SrcSel=AutoIndex'
draw_info.prim_type = static_cast<PrimitiveType>(dword0 & 0x3F); draw_info.prim_type = static_cast<xenos::PrimitiveType>(dword0 & 0x3F);
draw_info.is_auto_index = true; draw_info.is_auto_index = true;
draw_info.index_count = dword0 >> 16; draw_info.index_count = dword0 >> 16;
break; break;
@ -1312,7 +1313,8 @@ void TraceViewer::DrawStateUI() {
auto rb_surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32; auto rb_surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32;
uint32_t surface_pitch = rb_surface_info & 0x3FFF; uint32_t surface_pitch = rb_surface_info & 0x3FFF;
auto surface_msaa = static_cast<MsaaSamples>((rb_surface_info >> 16) & 0x3); auto surface_msaa =
static_cast<xenos::MsaaSamples>((rb_surface_info >> 16) & 0x3);
if (ImGui::CollapsingHeader("Color Targets")) { if (ImGui::CollapsingHeader("Color Targets")) {
if (enable_mode != ModeControl::kDepth) { if (enable_mode != ModeControl::kDepth) {
@ -1413,8 +1415,8 @@ void TraceViewer::DrawStateUI() {
for (int i = 0; i < xe::countof(color_info); ++i) { for (int i = 0; i < xe::countof(color_info); ++i) {
uint32_t write_mask = (rb_color_mask >> (i * 4)) & 0xF; uint32_t write_mask = (rb_color_mask >> (i * 4)) & 0xF;
uint32_t color_base = color_info[i] & 0xFFF; uint32_t color_base = color_info[i] & 0xFFF;
auto color_format = auto color_format = static_cast<xenos::ColorRenderTargetFormat>(
static_cast<ColorRenderTargetFormat>((color_info[i] >> 16) & 0xF); (color_info[i] >> 16) & 0xF);
ImVec2 button_pos = ImGui::GetCursorScreenPos(); ImVec2 button_pos = ImGui::GetCursorScreenPos();
ImVec2 button_size(256, 256); ImVec2 button_size(256, 256);
ImTextureID tex = 0; ImTextureID tex = 0;
@ -1534,8 +1536,8 @@ void TraceViewer::DrawStateUI() {
if (uses_depth || uses_stencil) { if (uses_depth || uses_stencil) {
uint32_t depth_base = rb_depth_info & 0xFFF; uint32_t depth_base = rb_depth_info & 0xFFF;
auto depth_format = auto depth_format = static_cast<xenos::DepthRenderTargetFormat>(
static_cast<DepthRenderTargetFormat>((rb_depth_info >> 16) & 0x1); (rb_depth_info >> 16) & 0x1);
auto depth_target = GetDepthRenderTarget(surface_pitch, surface_msaa, auto depth_target = GetDepthRenderTarget(surface_pitch, surface_msaa,
depth_base, depth_format); depth_base, depth_format);
@ -1649,7 +1651,7 @@ void TraceViewer::DrawStateUI() {
if (pa_su_sc_mode_cntl & (1 << 21)) { if (pa_su_sc_mode_cntl & (1 << 21)) {
uint32_t reset_index = uint32_t reset_index =
regs[XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX].u32; regs[XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX].u32;
if (draw_info.index_format == IndexFormat::kInt16) { if (draw_info.index_format == xenos::IndexFormat::kInt16) {
ImGui::Text("Reset Index: %.4X", reset_index & 0xFFFF); ImGui::Text("Reset Index: %.4X", reset_index & 0xFFFF);
} else { } else {
ImGui::Text("Reset Index: %.8X", reset_index); ImGui::Text("Reset Index: %.8X", reset_index);
@ -1675,7 +1677,7 @@ void TraceViewer::DrawStateUI() {
ImGui::Separator(); ImGui::Separator();
} }
uint32_t element_size = uint32_t element_size =
draw_info.index_format == IndexFormat::kInt32 ? 4 : 2; draw_info.index_format == xenos::IndexFormat::kInt32 ? 4 : 2;
const uint8_t* data_ptr = memory_->TranslatePhysical( const uint8_t* data_ptr = memory_->TranslatePhysical(
draw_info.index_buffer_ptr + (display_start * element_size)); draw_info.index_buffer_ptr + (display_start * element_size));
for (int i = display_start; i < display_end; for (int i = display_start; i < display_end;
@ -1726,7 +1728,7 @@ void TraceViewer::DrawStateUI() {
fetch = &group->vertex_fetch_2; fetch = &group->vertex_fetch_2;
break; break;
} }
assert_true(fetch->endian == Endian::k8in32); assert_true(fetch->endian == xenos::Endian::k8in32);
char tree_root_id[32]; char tree_root_id[32];
sprintf(tree_root_id, "#vertices_root_%d", sprintf(tree_root_id, "#vertices_root_%d",
vertex_binding.fetch_constant); vertex_binding.fetch_constant);

View File

@ -45,12 +45,12 @@ class TraceViewer {
void DrawMultilineString(const std::string_view str); void DrawMultilineString(const std::string_view str);
virtual uintptr_t GetColorRenderTarget(uint32_t pitch, MsaaSamples samples, virtual uintptr_t GetColorRenderTarget(
uint32_t base, uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
ColorRenderTargetFormat format) = 0; xenos::ColorRenderTargetFormat format) = 0;
virtual uintptr_t GetDepthRenderTarget(uint32_t pitch, MsaaSamples samples, virtual uintptr_t GetDepthRenderTarget(
uint32_t base, uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
DepthRenderTargetFormat format) = 0; xenos::DepthRenderTargetFormat format) = 0;
virtual uintptr_t GetTextureEntry(const TextureInfo& texture_info, virtual uintptr_t GetTextureEntry(const TextureInfo& texture_info,
const SamplerInfo& sampler_info) = 0; const SamplerInfo& sampler_info) = 0;

View File

@ -627,7 +627,7 @@ struct VertexFetchInstruction {
uint32_t prefetch_count() const { return data_.prefetch_count; } uint32_t prefetch_count() const { return data_.prefetch_count; }
bool is_mini_fetch() const { return data_.is_mini_fetch == 1; } bool is_mini_fetch() const { return data_.is_mini_fetch == 1; }
VertexFormat data_format() const { return data_.format; } xenos::VertexFormat data_format() const { return data_.format; }
// [-32, 31] // [-32, 31]
int exp_adjust() const { return data_.exp_adjust; } int exp_adjust() const { return data_.exp_adjust; }
bool is_signed() const { return data_.fomat_comp_all == 1; } bool is_signed() const { return data_.fomat_comp_all == 1; }
@ -668,7 +668,7 @@ struct VertexFetchInstruction {
uint32_t num_format_all : 1; uint32_t num_format_all : 1;
xenos::SignedRepeatingFractionMode signed_rf_mode_all : 1; xenos::SignedRepeatingFractionMode signed_rf_mode_all : 1;
uint32_t is_index_rounded : 1; uint32_t is_index_rounded : 1;
VertexFormat format : 6; xenos::VertexFormat format : 6;
uint32_t reserved2 : 2; uint32_t reserved2 : 2;
int32_t exp_adjust : 6; int32_t exp_adjust : 6;
uint32_t is_mini_fetch : 1; uint32_t is_mini_fetch : 1;
@ -700,37 +700,39 @@ struct TextureFetchInstruction {
uint32_t src_swizzle() const { return data_.src_swiz; } uint32_t src_swizzle() const { return data_.src_swiz; }
bool is_src_relative() const { return data_.src_reg_am; } bool is_src_relative() const { return data_.src_reg_am; }
TextureDimension dimension() const { return data_.dimension; } xenos::FetchOpDimension dimension() const { return data_.dimension; }
bool fetch_valid_only() const { return data_.fetch_valid_only == 1; } bool fetch_valid_only() const { return data_.fetch_valid_only == 1; }
bool unnormalized_coordinates() const { return data_.tx_coord_denorm == 1; } bool unnormalized_coordinates() const { return data_.tx_coord_denorm == 1; }
bool has_mag_filter() const { bool has_mag_filter() const {
return data_.mag_filter != TextureFilter::kUseFetchConst; return data_.mag_filter != xenos::TextureFilter::kUseFetchConst;
} }
TextureFilter mag_filter() const { return data_.mag_filter; } xenos::TextureFilter mag_filter() const { return data_.mag_filter; }
bool has_min_filter() const { bool has_min_filter() const {
return data_.min_filter != TextureFilter::kUseFetchConst; return data_.min_filter != xenos::TextureFilter::kUseFetchConst;
} }
TextureFilter min_filter() const { return data_.min_filter; } xenos::TextureFilter min_filter() const { return data_.min_filter; }
bool has_mip_filter() const { bool has_mip_filter() const {
return data_.mip_filter != TextureFilter::kUseFetchConst; return data_.mip_filter != xenos::TextureFilter::kUseFetchConst;
} }
TextureFilter mip_filter() const { return data_.mip_filter; } xenos::TextureFilter mip_filter() const { return data_.mip_filter; }
bool has_aniso_filter() const { bool has_aniso_filter() const {
return data_.aniso_filter != AnisoFilter::kUseFetchConst; return data_.aniso_filter != xenos::AnisoFilter::kUseFetchConst;
} }
AnisoFilter aniso_filter() const { return data_.aniso_filter; } xenos::AnisoFilter aniso_filter() const { return data_.aniso_filter; }
bool has_vol_mag_filter() const { bool has_vol_mag_filter() const {
return data_.vol_mag_filter != TextureFilter::kUseFetchConst; return data_.vol_mag_filter != xenos::TextureFilter::kUseFetchConst;
} }
TextureFilter vol_mag_filter() const { return data_.vol_mag_filter; } xenos::TextureFilter vol_mag_filter() const { return data_.vol_mag_filter; }
bool has_vol_min_filter() const { bool has_vol_min_filter() const {
return data_.vol_min_filter != TextureFilter::kUseFetchConst; return data_.vol_min_filter != xenos::TextureFilter::kUseFetchConst;
} }
TextureFilter vol_min_filter() const { return data_.vol_min_filter; } xenos::TextureFilter vol_min_filter() const { return data_.vol_min_filter; }
bool use_computed_lod() const { return data_.use_comp_lod == 1; } bool use_computed_lod() const { return data_.use_comp_lod == 1; }
bool use_register_lod() const { return data_.use_reg_lod == 1; } bool use_register_lod() const { return data_.use_reg_lod == 1; }
bool use_register_gradients() const { return data_.use_reg_gradients == 1; } bool use_register_gradients() const { return data_.use_reg_gradients == 1; }
SampleLocation sample_location() const { return data_.sample_location; } xenos::SampleLocation sample_location() const {
return data_.sample_location;
}
float lod_bias() const { float lod_bias() const {
// http://web.archive.org/web/20090514012026/http://msdn.microsoft.com:80/en-us/library/bb313957.aspx // http://web.archive.org/web/20090514012026/http://msdn.microsoft.com:80/en-us/library/bb313957.aspx
return data_.lod_bias * (1.0f / 16.0f); return data_.lod_bias * (1.0f / 16.0f);
@ -754,13 +756,13 @@ struct TextureFetchInstruction {
}); });
XEPACKEDSTRUCTANONYMOUS({ XEPACKEDSTRUCTANONYMOUS({
uint32_t dst_swiz : 12; // xyzw uint32_t dst_swiz : 12; // xyzw
TextureFilter mag_filter : 2; xenos::TextureFilter mag_filter : 2;
TextureFilter min_filter : 2; xenos::TextureFilter min_filter : 2;
TextureFilter mip_filter : 2; xenos::TextureFilter mip_filter : 2;
AnisoFilter aniso_filter : 3; xenos::AnisoFilter aniso_filter : 3;
xenos::ArbitraryFilter arbitrary_filter : 3; xenos::ArbitraryFilter arbitrary_filter : 3;
TextureFilter vol_mag_filter : 2; xenos::TextureFilter vol_mag_filter : 2;
TextureFilter vol_min_filter : 2; xenos::TextureFilter vol_min_filter : 2;
uint32_t use_comp_lod : 1; uint32_t use_comp_lod : 1;
uint32_t use_reg_lod : 1; uint32_t use_reg_lod : 1;
uint32_t unk : 1; uint32_t unk : 1;
@ -768,10 +770,10 @@ struct TextureFetchInstruction {
}); });
XEPACKEDSTRUCTANONYMOUS({ XEPACKEDSTRUCTANONYMOUS({
uint32_t use_reg_gradients : 1; uint32_t use_reg_gradients : 1;
SampleLocation sample_location : 1; xenos::SampleLocation sample_location : 1;
int32_t lod_bias : 7; int32_t lod_bias : 7;
uint32_t unused : 5; uint32_t unused : 5;
TextureDimension dimension : 2; xenos::FetchOpDimension dimension : 2;
int32_t offset_x : 5; int32_t offset_x : 5;
int32_t offset_y : 5; int32_t offset_y : 5;
int32_t offset_z : 5; int32_t offset_z : 5;

View File

@ -31,14 +31,14 @@ void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
uint32_t frontbuffer_width, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) {} uint32_t frontbuffer_height) {}
Shader* VulkanCommandProcessor::LoadShader(ShaderType shader_type, Shader* VulkanCommandProcessor::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address, uint32_t guest_address,
const uint32_t* host_address, const uint32_t* host_address,
uint32_t dword_count) { uint32_t dword_count) {
return nullptr; return nullptr;
} }
bool VulkanCommandProcessor::IssueDraw(PrimitiveType primitive_type, bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
uint32_t index_count, uint32_t index_count,
IndexBufferInfo* index_buffer_info, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) { bool major_mode_explicit) {

View File

@ -35,11 +35,11 @@ class VulkanCommandProcessor : public CommandProcessor {
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override; uint32_t frontbuffer_height) 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, const uint32_t* host_address,
uint32_t dword_count) override; 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, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) override; bool major_mode_explicit) override;
bool IssueCopy() override; bool IssueCopy() override;

View File

@ -420,7 +420,7 @@ std::pair<VkDeviceSize, VkDeviceSize> BufferCache::UploadConstantRegisters(
std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadIndexBuffer( std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadIndexBuffer(
VkCommandBuffer command_buffer, uint32_t source_addr, VkCommandBuffer command_buffer, uint32_t source_addr,
uint32_t source_length, IndexFormat format, VkFence fence) { uint32_t source_length, xenos::IndexFormat format, VkFence fence) {
// Allocate space in the buffer for our data. // Allocate space in the buffer for our data.
auto offset = AllocateTransientData(source_length, fence); auto offset = AllocateTransientData(source_length, fence);
if (offset == VK_WHOLE_SIZE) { if (offset == VK_WHOLE_SIZE) {
@ -439,23 +439,23 @@ std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadIndexBuffer(
// primitive reset indices to something Vulkan understands. // primitive reset indices to something Vulkan understands.
// TODO(benvanik): memcpy then use compute shaders to swap? // TODO(benvanik): memcpy then use compute shaders to swap?
if (prim_reset_enabled) { if (prim_reset_enabled) {
if (format == IndexFormat::kInt16) { if (format == xenos::IndexFormat::kInt16) {
// Endian::k8in16, swap half-words. // Endian::k8in16, swap half-words.
copy_cmp_swap_16_unaligned( copy_cmp_swap_16_unaligned(
transient_buffer_->host_base() + offset, source_ptr, transient_buffer_->host_base() + offset, source_ptr,
static_cast<uint16_t>(prim_reset_index), source_length / 2); static_cast<uint16_t>(prim_reset_index), source_length / 2);
} else if (format == IndexFormat::kInt32) { } else if (format == xenos::IndexFormat::kInt32) {
// Endian::k8in32, swap words. // Endian::k8in32, swap words.
copy_cmp_swap_32_unaligned(transient_buffer_->host_base() + offset, copy_cmp_swap_32_unaligned(transient_buffer_->host_base() + offset,
source_ptr, prim_reset_index, source_ptr, prim_reset_index,
source_length / 4); source_length / 4);
} }
} else { } else {
if (format == IndexFormat::kInt16) { if (format == xenos::IndexFormat::kInt16) {
// Endian::k8in16, swap half-words. // Endian::k8in16, swap half-words.
xe::copy_and_swap_16_unaligned(transient_buffer_->host_base() + offset, xe::copy_and_swap_16_unaligned(transient_buffer_->host_base() + offset,
source_ptr, source_length / 2); source_ptr, source_length / 2);
} else if (format == IndexFormat::kInt32) { } else if (format == xenos::IndexFormat::kInt32) {
// Endian::k8in32, swap words. // Endian::k8in32, swap words.
xe::copy_and_swap_32_unaligned(transient_buffer_->host_base() + offset, xe::copy_and_swap_32_unaligned(transient_buffer_->host_base() + offset,
source_ptr, source_length / 4); source_ptr, source_length / 4);
@ -485,7 +485,7 @@ std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadIndexBuffer(
std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadVertexBuffer( std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadVertexBuffer(
VkCommandBuffer command_buffer, uint32_t source_addr, VkCommandBuffer command_buffer, uint32_t source_addr,
uint32_t source_length, Endian endian, VkFence fence) { uint32_t source_length, xenos::Endian endian, VkFence fence) {
auto offset = FindCachedTransientData(source_addr, source_length); auto offset = FindCachedTransientData(source_addr, source_length);
if (offset != VK_WHOLE_SIZE) { if (offset != VK_WHOLE_SIZE) {
return {transient_buffer_->gpu_buffer(), offset}; return {transient_buffer_->gpu_buffer(), offset};
@ -518,11 +518,11 @@ std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadVertexBuffer(
// Copy data into the buffer. // Copy data into the buffer.
// TODO(benvanik): memcpy then use compute shaders to swap? // TODO(benvanik): memcpy then use compute shaders to swap?
if (endian == Endian::k8in32) { if (endian == xenos::Endian::k8in32) {
// Endian::k8in32, swap words. // Endian::k8in32, swap words.
xe::copy_and_swap_32_unaligned(transient_buffer_->host_base() + offset, xe::copy_and_swap_32_unaligned(transient_buffer_->host_base() + offset,
upload_ptr, source_length / 4); upload_ptr, source_length / 4);
} else if (endian == Endian::k16in32) { } else if (endian == xenos::Endian::k16in32) {
xe::copy_and_swap_16_in_32_unaligned( xe::copy_and_swap_16_in_32_unaligned(
transient_buffer_->host_base() + offset, upload_ptr, source_length / 4); transient_buffer_->host_base() + offset, upload_ptr, source_length / 4);
} else { } else {

View File

@ -78,7 +78,7 @@ class BufferCache {
// Size will be VK_WHOLE_SIZE if the data could not be uploaded (OOM). // Size will be VK_WHOLE_SIZE if the data could not be uploaded (OOM).
std::pair<VkBuffer, VkDeviceSize> UploadIndexBuffer( std::pair<VkBuffer, VkDeviceSize> UploadIndexBuffer(
VkCommandBuffer command_buffer, uint32_t source_addr, VkCommandBuffer command_buffer, uint32_t source_addr,
uint32_t source_length, IndexFormat format, VkFence fence); uint32_t source_length, xenos::IndexFormat format, VkFence fence);
// Uploads vertex buffer data from guest memory, possibly eliding with // Uploads vertex buffer data from guest memory, possibly eliding with
// recently uploaded data or cached copies. // recently uploaded data or cached copies.
@ -86,7 +86,7 @@ class BufferCache {
// Size will be VK_WHOLE_SIZE if the data could not be uploaded (OOM). // Size will be VK_WHOLE_SIZE if the data could not be uploaded (OOM).
std::pair<VkBuffer, VkDeviceSize> UploadVertexBuffer( std::pair<VkBuffer, VkDeviceSize> UploadVertexBuffer(
VkCommandBuffer command_buffer, uint32_t source_addr, VkCommandBuffer command_buffer, uint32_t source_addr,
uint32_t source_length, Endian endian, VkFence fence); uint32_t source_length, xenos::Endian endian, VkFence fence);
// Prepares and returns a vertex descriptor set. // Prepares and returns a vertex descriptor set.
VkDescriptorSet PrepareVertexSet( VkDescriptorSet PrepareVertexSet(

View File

@ -203,7 +203,7 @@ void PipelineCache::Shutdown() {
} }
} }
VulkanShader* PipelineCache::LoadShader(ShaderType shader_type, VulkanShader* PipelineCache::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address, uint32_t guest_address,
const uint32_t* host_address, const uint32_t* host_address,
uint32_t dword_count) { uint32_t dword_count) {
@ -228,7 +228,7 @@ VulkanShader* PipelineCache::LoadShader(ShaderType shader_type,
PipelineCache::UpdateStatus PipelineCache::ConfigurePipeline( PipelineCache::UpdateStatus PipelineCache::ConfigurePipeline(
VkCommandBuffer command_buffer, const RenderState* render_state, VkCommandBuffer command_buffer, const RenderState* render_state,
VulkanShader* vertex_shader, VulkanShader* pixel_shader, VulkanShader* vertex_shader, VulkanShader* pixel_shader,
PrimitiveType primitive_type, VkPipeline* pipeline_out) { xenos::PrimitiveType primitive_type, VkPipeline* pipeline_out) {
#if FINE_GRAINED_DRAW_SCOPES #if FINE_GRAINED_DRAW_SCOPES
SCOPE_profile_cpu_f("gpu"); SCOPE_profile_cpu_f("gpu");
#endif // FINE_GRAINED_DRAW_SCOPES #endif // FINE_GRAINED_DRAW_SCOPES
@ -380,7 +380,7 @@ bool PipelineCache::TranslateShader(VulkanShader* shader,
if (shader->is_valid()) { if (shader->is_valid()) {
XELOGGPU("Generated {} shader ({}b) - hash {:016X}:\n{}\n", XELOGGPU("Generated {} shader ({}b) - hash {:016X}:\n{}\n",
shader->type() == ShaderType::kVertex ? "vertex" : "pixel", shader->type() == xenos::ShaderType::kVertex ? "vertex" : "pixel",
shader->ucode_dword_count() * 4, shader->ucode_data_hash(), shader->ucode_dword_count() * 4, shader->ucode_data_hash(),
shader->ucode_disassembly()); shader->ucode_disassembly());
} }
@ -529,33 +529,33 @@ void PipelineCache::DumpShaderDisasmNV(
vkDestroyPipelineCache(*device_, dummy_pipeline_cache, nullptr); vkDestroyPipelineCache(*device_, dummy_pipeline_cache, nullptr);
} }
VkShaderModule PipelineCache::GetGeometryShader(PrimitiveType primitive_type, VkShaderModule PipelineCache::GetGeometryShader(
bool is_line_mode) { xenos::PrimitiveType primitive_type, bool is_line_mode) {
switch (primitive_type) { switch (primitive_type) {
case PrimitiveType::kLineList: case xenos::PrimitiveType::kLineList:
case PrimitiveType::kLineLoop: case xenos::PrimitiveType::kLineLoop:
case PrimitiveType::kLineStrip: case xenos::PrimitiveType::kLineStrip:
case PrimitiveType::kTriangleList: case xenos::PrimitiveType::kTriangleList:
case PrimitiveType::kTriangleFan: case xenos::PrimitiveType::kTriangleFan:
case PrimitiveType::kTriangleStrip: case xenos::PrimitiveType::kTriangleStrip:
// Supported directly - no need to emulate. // Supported directly - no need to emulate.
return nullptr; return nullptr;
case PrimitiveType::kPointList: case xenos::PrimitiveType::kPointList:
return geometry_shaders_.point_list; return geometry_shaders_.point_list;
case PrimitiveType::kTriangleWithWFlags: case xenos::PrimitiveType::kTriangleWithWFlags:
assert_always("Unknown geometry type"); assert_always("Unknown geometry type");
return nullptr; return nullptr;
case PrimitiveType::kRectangleList: case xenos::PrimitiveType::kRectangleList:
return geometry_shaders_.rect_list; return geometry_shaders_.rect_list;
case PrimitiveType::kQuadList: case xenos::PrimitiveType::kQuadList:
return is_line_mode ? geometry_shaders_.line_quad_list return is_line_mode ? geometry_shaders_.line_quad_list
: geometry_shaders_.quad_list; : geometry_shaders_.quad_list;
case PrimitiveType::kQuadStrip: case xenos::PrimitiveType::kQuadStrip:
// TODO(benvanik): quad strip geometry shader. // TODO(benvanik): quad strip geometry shader.
assert_always("Quad strips not implemented"); assert_always("Quad strips not implemented");
return nullptr; return nullptr;
case PrimitiveType::kTrianglePatch: case xenos::PrimitiveType::kTrianglePatch:
case PrimitiveType::kQuadPatch: case xenos::PrimitiveType::kQuadPatch:
assert_always("Tessellation is not implemented"); assert_always("Tessellation is not implemented");
return nullptr; return nullptr;
default: default:
@ -640,18 +640,18 @@ bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer,
XE_GPU_REG_PA_CL_VPORT_ZSCALE); XE_GPU_REG_PA_CL_VPORT_ZSCALE);
// RB_SURFACE_INFO // RB_SURFACE_INFO
auto surface_msaa = auto surface_msaa =
static_cast<MsaaSamples>((regs.rb_surface_info >> 16) & 0x3); static_cast<xenos::MsaaSamples>((regs.rb_surface_info >> 16) & 0x3);
// Apply a multiplier to emulate MSAA. // Apply a multiplier to emulate MSAA.
float window_width_scalar = 1; float window_width_scalar = 1;
float window_height_scalar = 1; float window_height_scalar = 1;
switch (surface_msaa) { switch (surface_msaa) {
case MsaaSamples::k1X: case xenos::MsaaSamples::k1X:
break; break;
case MsaaSamples::k2X: case xenos::MsaaSamples::k2X:
window_height_scalar = 2; window_height_scalar = 2;
break; break;
case MsaaSamples::k4X: case xenos::MsaaSamples::k4X:
window_width_scalar = window_height_scalar = 2; window_width_scalar = window_height_scalar = 2;
break; break;
} }
@ -954,7 +954,7 @@ bool PipelineCache::SetShadowRegisterArray(uint32_t* dest, uint32_t num,
PipelineCache::UpdateStatus PipelineCache::UpdateState( PipelineCache::UpdateStatus PipelineCache::UpdateState(
VulkanShader* vertex_shader, VulkanShader* pixel_shader, VulkanShader* vertex_shader, VulkanShader* pixel_shader,
PrimitiveType primitive_type) { xenos::PrimitiveType primitive_type) {
bool mismatch = false; bool mismatch = false;
// Reset hash so we can build it up. // Reset hash so we can build it up.
@ -1035,7 +1035,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateRenderTargetState() {
PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages( PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
VulkanShader* vertex_shader, VulkanShader* pixel_shader, VulkanShader* vertex_shader, VulkanShader* pixel_shader,
PrimitiveType primitive_type) { xenos::PrimitiveType primitive_type) {
auto& regs = update_shader_stages_regs_; auto& regs = update_shader_stages_regs_;
// These are the constant base addresses/ranges for shaders. // These are the constant base addresses/ranges for shaders.
@ -1150,7 +1150,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState(
} }
PipelineCache::UpdateStatus PipelineCache::UpdateInputAssemblyState( PipelineCache::UpdateStatus PipelineCache::UpdateInputAssemblyState(
PrimitiveType primitive_type) { xenos::PrimitiveType primitive_type) {
auto& regs = update_input_assembly_state_regs_; auto& regs = update_input_assembly_state_regs_;
auto& state_info = update_input_assembly_state_info_; auto& state_info = update_input_assembly_state_info_;
@ -1172,35 +1172,35 @@ PipelineCache::UpdateStatus PipelineCache::UpdateInputAssemblyState(
state_info.flags = 0; state_info.flags = 0;
switch (primitive_type) { switch (primitive_type) {
case PrimitiveType::kPointList: case xenos::PrimitiveType::kPointList:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; state_info.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
break; break;
case PrimitiveType::kLineList: case xenos::PrimitiveType::kLineList:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
break; break;
case PrimitiveType::kLineStrip: case xenos::PrimitiveType::kLineStrip:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
break; break;
case PrimitiveType::kLineLoop: case xenos::PrimitiveType::kLineLoop:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
break; break;
case PrimitiveType::kTriangleList: case xenos::PrimitiveType::kTriangleList:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
break; break;
case PrimitiveType::kTriangleStrip: case xenos::PrimitiveType::kTriangleStrip:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
break; break;
case PrimitiveType::kTriangleFan: case xenos::PrimitiveType::kTriangleFan:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
break; break;
case PrimitiveType::kRectangleList: case xenos::PrimitiveType::kRectangleList:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
break; break;
case PrimitiveType::kQuadList: case xenos::PrimitiveType::kQuadList:
state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
break; break;
default: default:
case PrimitiveType::kTriangleWithWFlags: case xenos::PrimitiveType::kTriangleWithWFlags:
XELOGE("unsupported primitive type {}", primitive_type); XELOGE("unsupported primitive type {}", primitive_type);
assert_unhandled_case(primitive_type); assert_unhandled_case(primitive_type);
return UpdateStatus::kError; return UpdateStatus::kError;
@ -1243,7 +1243,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateViewportState() {
} }
PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState( PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState(
PrimitiveType primitive_type) { xenos::PrimitiveType primitive_type) {
auto& regs = update_rasterization_state_regs_; auto& regs = update_rasterization_state_regs_;
auto& state_info = update_rasterization_state_info_; auto& state_info = update_rasterization_state_info_;
@ -1341,10 +1341,10 @@ PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState(
} else { } else {
state_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; state_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
} }
if (primitive_type == PrimitiveType::kRectangleList) { if (primitive_type == xenos::PrimitiveType::kRectangleList) {
// Rectangle lists aren't culled. There may be other things they skip too. // Rectangle lists aren't culled. There may be other things they skip too.
state_info.cullMode = VK_CULL_MODE_NONE; state_info.cullMode = VK_CULL_MODE_NONE;
} else if (primitive_type == PrimitiveType::kPointList) { } else if (primitive_type == xenos::PrimitiveType::kPointList) {
// Face culling doesn't apply to point primitives. // Face culling doesn't apply to point primitives.
state_info.cullMode = VK_CULL_MODE_NONE; state_info.cullMode = VK_CULL_MODE_NONE;
} }
@ -1385,15 +1385,15 @@ PipelineCache::UpdateStatus PipelineCache::UpdateMultisampleState() {
// all sampled from the pixel center. // all sampled from the pixel center.
if (cvars::vulkan_native_msaa) { if (cvars::vulkan_native_msaa) {
auto msaa_num_samples = auto msaa_num_samples =
static_cast<MsaaSamples>((regs.rb_surface_info >> 16) & 0x3); static_cast<xenos::MsaaSamples>((regs.rb_surface_info >> 16) & 0x3);
switch (msaa_num_samples) { switch (msaa_num_samples) {
case MsaaSamples::k1X: case xenos::MsaaSamples::k1X:
state_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; state_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
break; break;
case MsaaSamples::k2X: case xenos::MsaaSamples::k2X:
state_info.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT; state_info.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
break; break;
case MsaaSamples::k4X: case xenos::MsaaSamples::k4X:
state_info.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; state_info.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
break; break;
default: default:

View File

@ -47,8 +47,9 @@ class PipelineCache {
void Shutdown(); void Shutdown();
// Loads a shader from the cache, possibly translating it. // Loads a shader from the cache, possibly translating it.
VulkanShader* LoadShader(ShaderType shader_type, uint32_t guest_address, VulkanShader* LoadShader(xenos::ShaderType shader_type,
const uint32_t* host_address, uint32_t dword_count); uint32_t guest_address, const uint32_t* host_address,
uint32_t dword_count);
// Configures a pipeline using the current render state and the given render // Configures a pipeline using the current render state and the given render
// pass. If a previously available pipeline is available it will be used, // pass. If a previously available pipeline is available it will be used,
@ -59,7 +60,7 @@ class PipelineCache {
const RenderState* render_state, const RenderState* render_state,
VulkanShader* vertex_shader, VulkanShader* vertex_shader,
VulkanShader* pixel_shader, VulkanShader* pixel_shader,
PrimitiveType primitive_type, xenos::PrimitiveType primitive_type,
VkPipeline* pipeline_out); VkPipeline* pipeline_out);
// Sets required dynamic state on the command buffer. // Sets required dynamic state on the command buffer.
@ -85,7 +86,7 @@ class PipelineCache {
// Gets a geometry shader used to emulate the given primitive type. // Gets a geometry shader used to emulate the given primitive type.
// Returns nullptr if the primitive doesn't need to be emulated. // Returns nullptr if the primitive doesn't need to be emulated.
VkShaderModule GetGeometryShader(PrimitiveType primitive_type, VkShaderModule GetGeometryShader(xenos::PrimitiveType primitive_type,
bool is_line_mode); bool is_line_mode);
RegisterFile* register_file_ = nullptr; RegisterFile* register_file_ = nullptr;
@ -131,16 +132,16 @@ class PipelineCache {
private: private:
UpdateStatus UpdateState(VulkanShader* vertex_shader, UpdateStatus UpdateState(VulkanShader* vertex_shader,
VulkanShader* pixel_shader, VulkanShader* pixel_shader,
PrimitiveType primitive_type); xenos::PrimitiveType primitive_type);
UpdateStatus UpdateRenderTargetState(); UpdateStatus UpdateRenderTargetState();
UpdateStatus UpdateShaderStages(VulkanShader* vertex_shader, UpdateStatus UpdateShaderStages(VulkanShader* vertex_shader,
VulkanShader* pixel_shader, VulkanShader* pixel_shader,
PrimitiveType primitive_type); xenos::PrimitiveType primitive_type);
UpdateStatus UpdateVertexInputState(VulkanShader* vertex_shader); UpdateStatus UpdateVertexInputState(VulkanShader* vertex_shader);
UpdateStatus UpdateInputAssemblyState(PrimitiveType primitive_type); UpdateStatus UpdateInputAssemblyState(xenos::PrimitiveType primitive_type);
UpdateStatus UpdateViewportState(); UpdateStatus UpdateViewportState();
UpdateStatus UpdateRasterizationState(PrimitiveType primitive_type); UpdateStatus UpdateRasterizationState(xenos::PrimitiveType primitive_type);
UpdateStatus UpdateMultisampleState(); UpdateStatus UpdateMultisampleState();
UpdateStatus UpdateDepthStencilState(); UpdateStatus UpdateDepthStencilState();
UpdateStatus UpdateColorBlendState(); UpdateStatus UpdateColorBlendState();
@ -167,7 +168,7 @@ class PipelineCache {
} update_render_targets_regs_; } update_render_targets_regs_;
struct UpdateShaderStagesRegisters { struct UpdateShaderStagesRegisters {
PrimitiveType primitive_type; xenos::PrimitiveType primitive_type;
uint32_t pa_su_sc_mode_cntl; uint32_t pa_su_sc_mode_cntl;
reg::SQ_PROGRAM_CNTL sq_program_cntl; reg::SQ_PROGRAM_CNTL sq_program_cntl;
VulkanShader* vertex_shader; VulkanShader* vertex_shader;
@ -191,7 +192,7 @@ class PipelineCache {
update_vertex_input_state_attrib_descrs_[96]; update_vertex_input_state_attrib_descrs_[96];
struct UpdateInputAssemblyStateRegisters { struct UpdateInputAssemblyStateRegisters {
PrimitiveType primitive_type; xenos::PrimitiveType primitive_type;
uint32_t pa_su_sc_mode_cntl; uint32_t pa_su_sc_mode_cntl;
uint32_t multi_prim_ib_reset_index; uint32_t multi_prim_ib_reset_index;
@ -221,7 +222,7 @@ class PipelineCache {
VkPipelineViewportStateCreateInfo update_viewport_state_info_; VkPipelineViewportStateCreateInfo update_viewport_state_info_;
struct UpdateRasterizationStateRegisters { struct UpdateRasterizationStateRegisters {
PrimitiveType primitive_type; xenos::PrimitiveType primitive_type;
uint32_t pa_cl_clip_cntl; uint32_t pa_cl_clip_cntl;
uint32_t pa_su_sc_mode_cntl; uint32_t pa_su_sc_mode_cntl;
uint32_t pa_sc_screen_scissor_tl; uint32_t pa_sc_screen_scissor_tl;

View File

@ -29,41 +29,43 @@ using xe::ui::vulkan::CheckResult;
constexpr uint32_t kEdramBufferCapacity = 10 * 1024 * 1024; constexpr uint32_t kEdramBufferCapacity = 10 * 1024 * 1024;
ColorRenderTargetFormat GetBaseRTFormat(ColorRenderTargetFormat format) { xenos::ColorRenderTargetFormat GetBaseRTFormat(
xenos::ColorRenderTargetFormat format) {
switch (format) { switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return ColorRenderTargetFormat::k_8_8_8_8; return xenos::ColorRenderTargetFormat::k_8_8_8_8;
case ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10: case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10:
return ColorRenderTargetFormat::k_2_10_10_10; return xenos::ColorRenderTargetFormat::k_2_10_10_10;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return ColorRenderTargetFormat::k_2_10_10_10_FLOAT; return xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT;
default: default:
return format; return format;
} }
} }
VkFormat ColorRenderTargetFormatToVkFormat(ColorRenderTargetFormat format) { VkFormat ColorRenderTargetFormatToVkFormat(
xenos::ColorRenderTargetFormat format) {
switch (format) { switch (format) {
case ColorRenderTargetFormat::k_8_8_8_8: case xenos::ColorRenderTargetFormat::k_8_8_8_8:
case ColorRenderTargetFormat::k_8_8_8_8_GAMMA: case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA:
return VK_FORMAT_R8G8B8A8_UNORM; return VK_FORMAT_R8G8B8A8_UNORM;
case ColorRenderTargetFormat::k_2_10_10_10: case xenos::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_AS_10_10_10_10:
return VK_FORMAT_A2R10G10B10_UNORM_PACK32; return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT:
case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16:
return VK_FORMAT_R16G16B16A16_SFLOAT; return VK_FORMAT_R16G16B16A16_SFLOAT;
case ColorRenderTargetFormat::k_16_16: case xenos::ColorRenderTargetFormat::k_16_16:
return VK_FORMAT_R16G16_UNORM; return VK_FORMAT_R16G16_UNORM;
case ColorRenderTargetFormat::k_16_16_16_16: case xenos::ColorRenderTargetFormat::k_16_16_16_16:
return VK_FORMAT_R16G16B16A16_UNORM; return VK_FORMAT_R16G16B16A16_UNORM;
case ColorRenderTargetFormat::k_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_FLOAT:
return VK_FORMAT_R16G16_SFLOAT; return VK_FORMAT_R16G16_SFLOAT;
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
return VK_FORMAT_R16G16B16A16_SFLOAT; return VK_FORMAT_R16G16B16A16_SFLOAT;
case ColorRenderTargetFormat::k_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_FLOAT:
return VK_FORMAT_R32_SFLOAT; return VK_FORMAT_R32_SFLOAT;
case ColorRenderTargetFormat::k_32_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_32_FLOAT:
return VK_FORMAT_R32G32_SFLOAT; return VK_FORMAT_R32G32_SFLOAT;
default: default:
assert_unhandled_case(key.edram_format); assert_unhandled_case(key.edram_format);
@ -71,11 +73,12 @@ VkFormat ColorRenderTargetFormatToVkFormat(ColorRenderTargetFormat format) {
} }
} }
VkFormat DepthRenderTargetFormatToVkFormat(DepthRenderTargetFormat format) { VkFormat DepthRenderTargetFormatToVkFormat(
xenos::DepthRenderTargetFormat format) {
switch (format) { switch (format) {
case DepthRenderTargetFormat::kD24S8: case xenos::DepthRenderTargetFormat::kD24S8:
return VK_FORMAT_D24_UNORM_S8_UINT; return VK_FORMAT_D24_UNORM_S8_UINT;
case DepthRenderTargetFormat::kD24FS8: case xenos::DepthRenderTargetFormat::kD24FS8:
// Vulkan doesn't support 24-bit floats, so just promote it to 32-bit // Vulkan doesn't support 24-bit floats, so just promote it to 32-bit
return VK_FORMAT_D32_SFLOAT_S8_UINT; return VK_FORMAT_D32_SFLOAT_S8_UINT;
default: default:
@ -161,12 +164,13 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) {
VkFormat vulkan_format = VK_FORMAT_UNDEFINED; VkFormat vulkan_format = VK_FORMAT_UNDEFINED;
uint32_t bpp = 4; uint32_t bpp = 4;
if (key.color_or_depth) { if (key.color_or_depth) {
auto edram_format = static_cast<ColorRenderTargetFormat>(key.edram_format); auto edram_format =
static_cast<xenos::ColorRenderTargetFormat>(key.edram_format);
vulkan_format = ColorRenderTargetFormatToVkFormat(edram_format); vulkan_format = ColorRenderTargetFormatToVkFormat(edram_format);
switch (edram_format) { switch (edram_format) {
case ColorRenderTargetFormat::k_16_16_16_16: case xenos::ColorRenderTargetFormat::k_16_16_16_16:
case ColorRenderTargetFormat::k_16_16_16_16_FLOAT: case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
case ColorRenderTargetFormat::k_32_32_FLOAT: case xenos::ColorRenderTargetFormat::k_32_32_FLOAT:
bpp = 8; bpp = 8;
break; break;
default: default:
@ -174,7 +178,8 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) {
break; break;
} }
} else { } else {
auto edram_format = static_cast<DepthRenderTargetFormat>(key.edram_format); auto edram_format =
static_cast<xenos::DepthRenderTargetFormat>(key.edram_format);
vulkan_format = DepthRenderTargetFormatToVkFormat(edram_format); vulkan_format = DepthRenderTargetFormatToVkFormat(edram_format);
} }
assert_true(vulkan_format != VK_FORMAT_UNDEFINED); assert_true(vulkan_format != VK_FORMAT_UNDEFINED);
@ -196,15 +201,15 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) {
image_info.mipLevels = 1; image_info.mipLevels = 1;
image_info.arrayLayers = 1; image_info.arrayLayers = 1;
if (cvars::vulkan_native_msaa) { if (cvars::vulkan_native_msaa) {
auto msaa_samples = static_cast<MsaaSamples>(key.msaa_samples); auto msaa_samples = static_cast<xenos::MsaaSamples>(key.msaa_samples);
switch (msaa_samples) { switch (msaa_samples) {
case MsaaSamples::k1X: case xenos::MsaaSamples::k1X:
image_info.samples = VK_SAMPLE_COUNT_1_BIT; image_info.samples = VK_SAMPLE_COUNT_1_BIT;
break; break;
case MsaaSamples::k2X: case xenos::MsaaSamples::k2X:
image_info.samples = VK_SAMPLE_COUNT_2_BIT; image_info.samples = VK_SAMPLE_COUNT_2_BIT;
break; break;
case MsaaSamples::k4X: case xenos::MsaaSamples::k4X:
image_info.samples = VK_SAMPLE_COUNT_4_BIT; image_info.samples = VK_SAMPLE_COUNT_4_BIT;
break; break;
default: default:
@ -371,10 +376,12 @@ bool CachedFramebuffer::IsCompatible(
const RenderConfiguration& desired_config) const { const RenderConfiguration& desired_config) const {
// We already know all render pass things line up, so let's verify dimensions, // We already know all render pass things line up, so let's verify dimensions,
// edram offsets, etc. We need an exact match. // edram offsets, etc. We need an exact match.
uint32_t surface_pitch_px = desired_config.surface_msaa != MsaaSamples::k4X uint32_t surface_pitch_px =
desired_config.surface_msaa != xenos::MsaaSamples::k4X
? desired_config.surface_pitch_px ? desired_config.surface_pitch_px
: desired_config.surface_pitch_px * 2; : desired_config.surface_pitch_px * 2;
uint32_t surface_height_px = desired_config.surface_msaa == MsaaSamples::k1X uint32_t surface_height_px =
desired_config.surface_msaa == xenos::MsaaSamples::k1X
? desired_config.surface_height_px ? desired_config.surface_height_px
: desired_config.surface_height_px * 2; : desired_config.surface_height_px * 2;
surface_pitch_px = std::min(surface_pitch_px, 2560u); surface_pitch_px = std::min(surface_pitch_px, 2560u);
@ -426,13 +433,13 @@ VkResult CachedRenderPass::Initialize() {
VkSampleCountFlagBits sample_count; VkSampleCountFlagBits sample_count;
if (cvars::vulkan_native_msaa) { if (cvars::vulkan_native_msaa) {
switch (config.surface_msaa) { switch (config.surface_msaa) {
case MsaaSamples::k1X: case xenos::MsaaSamples::k1X:
sample_count = VK_SAMPLE_COUNT_1_BIT; sample_count = VK_SAMPLE_COUNT_1_BIT;
break; break;
case MsaaSamples::k2X: case xenos::MsaaSamples::k2X:
sample_count = VK_SAMPLE_COUNT_2_BIT; sample_count = VK_SAMPLE_COUNT_2_BIT;
break; break;
case MsaaSamples::k4X: case xenos::MsaaSamples::k4X:
sample_count = VK_SAMPLE_COUNT_4_BIT; sample_count = VK_SAMPLE_COUNT_4_BIT;
break; break;
default: default:
@ -759,10 +766,10 @@ const RenderState* RenderCache::BeginRenderPass(VkCommandBuffer command_buffer,
render_pass_begin_info.renderArea.extent.width = config->surface_pitch_px; render_pass_begin_info.renderArea.extent.width = config->surface_pitch_px;
render_pass_begin_info.renderArea.extent.height = config->surface_height_px; render_pass_begin_info.renderArea.extent.height = config->surface_height_px;
if (config->surface_msaa == MsaaSamples::k2X) { if (config->surface_msaa == xenos::MsaaSamples::k2X) {
render_pass_begin_info.renderArea.extent.height = render_pass_begin_info.renderArea.extent.height =
std::min(config->surface_height_px * 2, 2560u); std::min(config->surface_height_px * 2, 2560u);
} else if (config->surface_msaa == MsaaSamples::k4X) { } else if (config->surface_msaa == xenos::MsaaSamples::k4X) {
render_pass_begin_info.renderArea.extent.width *= 2; render_pass_begin_info.renderArea.extent.width *= 2;
render_pass_begin_info.renderArea.extent.height = render_pass_begin_info.renderArea.extent.height =
std::min(config->surface_height_px * 2, 2560u); std::min(config->surface_height_px * 2, 2560u);
@ -822,7 +829,7 @@ bool RenderCache::ParseConfiguration(RenderConfiguration* config) {
} else { } else {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
config->color[i].edram_base = 0; config->color[i].edram_base = 0;
config->color[i].format = ColorRenderTargetFormat::k_8_8_8_8; config->color[i].format = xenos::ColorRenderTargetFormat::k_8_8_8_8;
config->color[i].used = false; config->color[i].used = false;
} }
} }
@ -834,7 +841,7 @@ bool RenderCache::ParseConfiguration(RenderConfiguration* config) {
config->depth_stencil.format = regs.rb_depth_info.depth_format; config->depth_stencil.format = regs.rb_depth_info.depth_format;
} else { } else {
config->depth_stencil.edram_base = 0; config->depth_stencil.edram_base = 0;
config->depth_stencil.format = DepthRenderTargetFormat::kD24S8; config->depth_stencil.format = xenos::DepthRenderTargetFormat::kD24S8;
config->depth_stencil.used = false; config->depth_stencil.used = false;
} }
@ -886,8 +893,10 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer,
// If no framebuffer was found in the cache create a new one. // If no framebuffer was found in the cache create a new one.
if (!framebuffer) { if (!framebuffer) {
uint32_t tile_width = config->surface_msaa == MsaaSamples::k4X ? 40 : 80; uint32_t tile_width =
uint32_t tile_height = config->surface_msaa != MsaaSamples::k1X ? 8 : 16; config->surface_msaa == xenos::MsaaSamples::k4X ? 40 : 80;
uint32_t tile_height =
config->surface_msaa != xenos::MsaaSamples::k1X ? 8 : 16;
CachedTileView* target_color_attachments[4] = {nullptr, nullptr, nullptr, CachedTileView* target_color_attachments[4] = {nullptr, nullptr, nullptr,
nullptr}; nullptr};
@ -930,10 +939,10 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer,
return false; return false;
} }
uint32_t surface_pitch_px = config->surface_msaa != MsaaSamples::k4X uint32_t surface_pitch_px = config->surface_msaa != xenos::MsaaSamples::k4X
? config->surface_pitch_px ? config->surface_pitch_px
: config->surface_pitch_px * 2; : config->surface_pitch_px * 2;
uint32_t surface_height_px = config->surface_msaa == MsaaSamples::k1X uint32_t surface_height_px = config->surface_msaa == xenos::MsaaSamples::k1X
? config->surface_height_px ? config->surface_height_px
: config->surface_height_px * 2; : config->surface_height_px * 2;
surface_pitch_px = std::min(surface_pitch_px, 2560u); surface_pitch_px = std::min(surface_pitch_px, 2560u);
@ -958,16 +967,16 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer,
} }
CachedTileView* RenderCache::FindTileView(uint32_t base, uint32_t pitch, CachedTileView* RenderCache::FindTileView(uint32_t base, uint32_t pitch,
MsaaSamples samples, xenos::MsaaSamples samples,
bool color_or_depth, bool color_or_depth,
uint32_t format) { uint32_t format) {
uint32_t tile_width = samples == MsaaSamples::k4X ? 40 : 80; uint32_t tile_width = samples == xenos::MsaaSamples::k4X ? 40 : 80;
uint32_t tile_height = samples != MsaaSamples::k1X ? 8 : 16; uint32_t tile_height = samples != xenos::MsaaSamples::k1X ? 8 : 16;
if (color_or_depth) { if (color_or_depth) {
// Adjust similar formats for easier matching. // Adjust similar formats for easier matching.
format = static_cast<uint32_t>( format = static_cast<uint32_t>(
GetBaseRTFormat(static_cast<ColorRenderTargetFormat>(format))); GetBaseRTFormat(static_cast<xenos::ColorRenderTargetFormat>(format)));
} }
TileViewKey key; TileViewKey key;
@ -1011,9 +1020,9 @@ void RenderCache::UpdateTileView(VkCommandBuffer command_buffer,
CachedTileView* view, bool load, CachedTileView* view, bool load,
bool insert_barrier) { bool insert_barrier) {
uint32_t tile_width = uint32_t tile_width =
view->key.msaa_samples == uint16_t(MsaaSamples::k4X) ? 40 : 80; view->key.msaa_samples == uint16_t(xenos::MsaaSamples::k4X) ? 40 : 80;
uint32_t tile_height = uint32_t tile_height =
view->key.msaa_samples != uint16_t(MsaaSamples::k1X) ? 8 : 16; view->key.msaa_samples != uint16_t(xenos::MsaaSamples::k1X) ? 8 : 16;
if (insert_barrier) { if (insert_barrier) {
VkBufferMemoryBarrier barrier; VkBufferMemoryBarrier barrier;
@ -1196,7 +1205,7 @@ void RenderCache::RawCopyToImage(VkCommandBuffer command_buffer,
void RenderCache::BlitToImage(VkCommandBuffer command_buffer, void RenderCache::BlitToImage(VkCommandBuffer command_buffer,
uint32_t edram_base, uint32_t pitch, uint32_t edram_base, uint32_t pitch,
uint32_t height, MsaaSamples num_samples, uint32_t height, xenos::MsaaSamples num_samples,
VkImage image, VkImageLayout image_layout, VkImage image, VkImageLayout image_layout,
bool color_or_depth, uint32_t format, bool color_or_depth, uint32_t format,
VkFilter filter, VkOffset3D offset, VkFilter filter, VkOffset3D offset,
@ -1204,11 +1213,11 @@ void RenderCache::BlitToImage(VkCommandBuffer command_buffer,
if (color_or_depth) { if (color_or_depth) {
// Adjust similar formats for easier matching. // Adjust similar formats for easier matching.
format = static_cast<uint32_t>( format = static_cast<uint32_t>(
GetBaseRTFormat(static_cast<ColorRenderTargetFormat>(format))); GetBaseRTFormat(static_cast<xenos::ColorRenderTargetFormat>(format)));
} }
uint32_t tile_width = num_samples == MsaaSamples::k4X ? 40 : 80; uint32_t tile_width = num_samples == xenos::MsaaSamples::k4X ? 40 : 80;
uint32_t tile_height = num_samples != MsaaSamples::k1X ? 8 : 16; uint32_t tile_height = num_samples != xenos::MsaaSamples::k1X ? 8 : 16;
// Grab a tile view that represents the source image. // Grab a tile view that represents the source image.
TileViewKey key; TileViewKey key;
@ -1300,17 +1309,18 @@ void RenderCache::BlitToImage(VkCommandBuffer command_buffer,
void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer, void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer,
uint32_t edram_base, uint32_t edram_base,
ColorRenderTargetFormat format, xenos::ColorRenderTargetFormat format,
uint32_t pitch, uint32_t height, uint32_t pitch, uint32_t height,
MsaaSamples num_samples, float* color) { xenos::MsaaSamples num_samples,
float* color) {
// TODO: For formats <= 4 bpp, we can directly fill the EDRAM buffer. Just // TODO: For formats <= 4 bpp, we can directly fill the EDRAM buffer. Just
// need to detect this and calculate a value. // need to detect this and calculate a value.
// Adjust similar formats for easier matching. // Adjust similar formats for easier matching.
format = GetBaseRTFormat(static_cast<ColorRenderTargetFormat>(format)); format = GetBaseRTFormat(static_cast<xenos::ColorRenderTargetFormat>(format));
uint32_t tile_width = num_samples == MsaaSamples::k4X ? 40 : 80; uint32_t tile_width = num_samples == xenos::MsaaSamples::k4X ? 40 : 80;
uint32_t tile_height = num_samples != MsaaSamples::k1X ? 8 : 16; uint32_t tile_height = num_samples != xenos::MsaaSamples::k1X ? 8 : 16;
// Grab a tile view (as we need to clear an image first) // Grab a tile view (as we need to clear an image first)
TileViewKey key; TileViewKey key;
@ -1338,15 +1348,15 @@ void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer,
void RenderCache::ClearEDRAMDepthStencil(VkCommandBuffer command_buffer, void RenderCache::ClearEDRAMDepthStencil(VkCommandBuffer command_buffer,
uint32_t edram_base, uint32_t edram_base,
DepthRenderTargetFormat format, xenos::DepthRenderTargetFormat format,
uint32_t pitch, uint32_t height, uint32_t pitch, uint32_t height,
MsaaSamples num_samples, float depth, xenos::MsaaSamples num_samples,
uint32_t stencil) { float depth, uint32_t stencil) {
// TODO: For formats <= 4 bpp, we can directly fill the EDRAM buffer. Just // TODO: For formats <= 4 bpp, we can directly fill the EDRAM buffer. Just
// need to detect this and calculate a value. // need to detect this and calculate a value.
uint32_t tile_width = num_samples == MsaaSamples::k4X ? 40 : 80; uint32_t tile_width = num_samples == xenos::MsaaSamples::k4X ? 40 : 80;
uint32_t tile_height = num_samples != MsaaSamples::k1X ? 8 : 16; uint32_t tile_height = num_samples != xenos::MsaaSamples::k1X ? 8 : 16;
// Grab a tile view (as we need to clear an image first) // Grab a tile view (as we need to clear an image first)
TileViewKey key; TileViewKey key;

View File

@ -101,18 +101,18 @@ struct RenderConfiguration {
// ESTIMATED target surface height multiplied by MSAA, in pixels. // ESTIMATED target surface height multiplied by MSAA, in pixels.
uint32_t surface_height_px; uint32_t surface_height_px;
// Surface MSAA setting. // Surface MSAA setting.
MsaaSamples surface_msaa; xenos::MsaaSamples surface_msaa;
// Color attachments for the 4 render targets. // Color attachments for the 4 render targets.
struct { struct {
bool used; bool used;
uint32_t edram_base; uint32_t edram_base;
ColorRenderTargetFormat format; xenos::ColorRenderTargetFormat format;
} color[4]; } color[4];
// Depth/stencil attachment. // Depth/stencil attachment.
struct { struct {
bool used; bool used;
uint32_t edram_base; uint32_t edram_base;
DepthRenderTargetFormat format; xenos::DepthRenderTargetFormat format;
} depth_stencil; } depth_stencil;
}; };
@ -285,7 +285,7 @@ class RenderCache {
bool dirty() const; bool dirty() const;
CachedTileView* FindTileView(uint32_t base, uint32_t pitch, CachedTileView* FindTileView(uint32_t base, uint32_t pitch,
MsaaSamples samples, bool color_or_depth, xenos::MsaaSamples samples, bool color_or_depth,
uint32_t format); uint32_t format);
// Begins a render pass targeting the state-specified framebuffer formats. // Begins a render pass targeting the state-specified framebuffer formats.
@ -311,23 +311,26 @@ class RenderCache {
// Queues commands to blit EDRAM contents into an image. // Queues commands to blit EDRAM contents into an image.
// The command buffer must not be inside of a render pass when calling this. // The command buffer must not be inside of a render pass when calling this.
void BlitToImage(VkCommandBuffer command_buffer, uint32_t edram_base, void BlitToImage(VkCommandBuffer command_buffer, uint32_t edram_base,
uint32_t pitch, uint32_t height, MsaaSamples num_samples, uint32_t pitch, uint32_t height,
VkImage image, VkImageLayout image_layout, xenos::MsaaSamples num_samples, VkImage image,
bool color_or_depth, uint32_t format, VkFilter filter, VkImageLayout image_layout, bool color_or_depth,
VkOffset3D offset, VkExtent3D extents); uint32_t format, VkFilter filter, VkOffset3D offset,
VkExtent3D extents);
// Queues commands to clear EDRAM contents with a solid color. // Queues commands to clear EDRAM contents with a solid color.
// The command buffer must not be inside of a render pass when calling this. // The command buffer must not be inside of a render pass when calling this.
void ClearEDRAMColor(VkCommandBuffer command_buffer, uint32_t edram_base, void ClearEDRAMColor(VkCommandBuffer command_buffer, uint32_t edram_base,
ColorRenderTargetFormat format, uint32_t pitch, xenos::ColorRenderTargetFormat format, uint32_t pitch,
uint32_t height, MsaaSamples num_samples, float* color); uint32_t height, xenos::MsaaSamples num_samples,
float* color);
// Queues commands to clear EDRAM contents with depth/stencil values. // Queues commands to clear EDRAM contents with depth/stencil values.
// The command buffer must not be inside of a render pass when calling this. // The command buffer must not be inside of a render pass when calling this.
void ClearEDRAMDepthStencil(VkCommandBuffer command_buffer, void ClearEDRAMDepthStencil(VkCommandBuffer command_buffer,
uint32_t edram_base, uint32_t edram_base,
DepthRenderTargetFormat format, uint32_t pitch, xenos::DepthRenderTargetFormat format,
uint32_t height, MsaaSamples num_samples, uint32_t pitch, uint32_t height,
float depth, uint32_t stencil); xenos::MsaaSamples num_samples, float depth,
uint32_t stencil);
// Queues commands to fill EDRAM contents with a constant value. // Queues commands to fill EDRAM contents with a constant value.
// The command buffer must not be inside of a render pass when calling this. // The command buffer must not be inside of a render pass when calling this.
void FillEDRAM(VkCommandBuffer command_buffer, uint32_t value); void FillEDRAM(VkCommandBuffer command_buffer, uint32_t value);

View File

@ -38,7 +38,7 @@ using xe::ui::vulkan::CheckResult;
constexpr uint32_t kMaxTextureSamplers = 32; constexpr uint32_t kMaxTextureSamplers = 32;
constexpr VkDeviceSize kStagingBufferSize = 64 * 1024 * 1024; constexpr VkDeviceSize kStagingBufferSize = 64 * 1024 * 1024;
const char* get_dimension_name(Dimension dimension) { const char* get_dimension_name(xenos::DataDimension dimension) {
static const char* names[] = { static const char* names[] = {
"1D", "1D",
"2D", "2D",
@ -203,8 +203,8 @@ TextureCache::Texture* TextureCache::AllocateTexture(
image_info.flags = 0; image_info.flags = 0;
switch (texture_info.dimension) { switch (texture_info.dimension) {
case Dimension::k1D: case xenos::DataDimension::k1D:
case Dimension::k2D: case xenos::DataDimension::k2DOrStacked:
if (!texture_info.is_stacked) { if (!texture_info.is_stacked) {
image_info.imageType = VK_IMAGE_TYPE_2D; image_info.imageType = VK_IMAGE_TYPE_2D;
} else { } else {
@ -212,10 +212,10 @@ TextureCache::Texture* TextureCache::AllocateTexture(
image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
} }
break; break;
case Dimension::k3D: case xenos::DataDimension::k3D:
image_info.imageType = VK_IMAGE_TYPE_3D; image_info.imageType = VK_IMAGE_TYPE_3D;
break; break;
case Dimension::kCube: case xenos::DataDimension::kCube:
image_info.imageType = VK_IMAGE_TYPE_2D; image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
is_cube = true; is_cube = true;
@ -242,7 +242,7 @@ TextureCache::Texture* TextureCache::AllocateTexture(
required_flags & ~props.optimalTilingFeatures))); required_flags & ~props.optimalTilingFeatures)));
} }
if (texture_info.dimension != Dimension::kCube && if (texture_info.dimension != xenos::DataDimension::kCube &&
props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) { props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
// Add color attachment usage if it's supported. // Add color attachment usage if it's supported.
image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
@ -502,8 +502,8 @@ TextureCache::Texture* TextureCache::DemandResolveTexture(
} }
VkFormatFeatureFlags required_flags = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; VkFormatFeatureFlags required_flags = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
if (texture_info.format == TextureFormat::k_24_8 || if (texture_info.format == xenos::TextureFormat::k_24_8 ||
texture_info.format == TextureFormat::k_24_8_FLOAT) { texture_info.format == xenos::TextureFormat::k_24_8_FLOAT) {
required_flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; required_flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
} else { } else {
required_flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; required_flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
@ -639,18 +639,18 @@ TextureCache::TextureView* TextureCache::DemandView(Texture* texture,
bool is_cube = false; bool is_cube = false;
switch (texture->texture_info.dimension) { switch (texture->texture_info.dimension) {
case Dimension::k1D: case xenos::DataDimension::k1D:
case Dimension::k2D: case xenos::DataDimension::k2DOrStacked:
if (!texture->texture_info.is_stacked) { if (!texture->texture_info.is_stacked) {
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
} else { } else {
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
} }
break; break;
case Dimension::k3D: case xenos::DataDimension::k3D:
view_info.viewType = VK_IMAGE_VIEW_TYPE_3D; view_info.viewType = VK_IMAGE_VIEW_TYPE_3D;
break; break;
case Dimension::kCube: case xenos::DataDimension::kCube:
view_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE; view_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
is_cube = true; is_cube = true;
break; break;
@ -739,14 +739,14 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) {
// Texture level filtering. // Texture level filtering.
VkSamplerMipmapMode mip_filter; VkSamplerMipmapMode mip_filter;
switch (sampler_info.mip_filter) { switch (sampler_info.mip_filter) {
case TextureFilter::kBaseMap: case xenos::TextureFilter::kBaseMap:
// TODO(DrChat): ? // TODO(DrChat): ?
mip_filter = VK_SAMPLER_MIPMAP_MODE_NEAREST; mip_filter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
break; break;
case TextureFilter::kPoint: case xenos::TextureFilter::kPoint:
mip_filter = VK_SAMPLER_MIPMAP_MODE_NEAREST; mip_filter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
break; break;
case TextureFilter::kLinear: case xenos::TextureFilter::kLinear:
mip_filter = VK_SAMPLER_MIPMAP_MODE_LINEAR; mip_filter = VK_SAMPLER_MIPMAP_MODE_LINEAR;
break; break;
default: default:
@ -756,10 +756,10 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) {
VkFilter min_filter; VkFilter min_filter;
switch (sampler_info.min_filter) { switch (sampler_info.min_filter) {
case TextureFilter::kPoint: case xenos::TextureFilter::kPoint:
min_filter = VK_FILTER_NEAREST; min_filter = VK_FILTER_NEAREST;
break; break;
case TextureFilter::kLinear: case xenos::TextureFilter::kLinear:
min_filter = VK_FILTER_LINEAR; min_filter = VK_FILTER_LINEAR;
break; break;
default: default:
@ -768,10 +768,10 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) {
} }
VkFilter mag_filter; VkFilter mag_filter;
switch (sampler_info.mag_filter) { switch (sampler_info.mag_filter) {
case TextureFilter::kPoint: case xenos::TextureFilter::kPoint:
mag_filter = VK_FILTER_NEAREST; mag_filter = VK_FILTER_NEAREST;
break; break;
case TextureFilter::kLinear: case xenos::TextureFilter::kLinear:
mag_filter = VK_FILTER_LINEAR; mag_filter = VK_FILTER_LINEAR;
break; break;
default: default:
@ -803,22 +803,22 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) {
float aniso = 0.f; float aniso = 0.f;
switch (sampler_info.aniso_filter) { switch (sampler_info.aniso_filter) {
case AnisoFilter::kDisabled: case xenos::AnisoFilter::kDisabled:
aniso = 1.0f; aniso = 1.0f;
break; break;
case AnisoFilter::kMax_1_1: case xenos::AnisoFilter::kMax_1_1:
aniso = 1.0f; aniso = 1.0f;
break; break;
case AnisoFilter::kMax_2_1: case xenos::AnisoFilter::kMax_2_1:
aniso = 2.0f; aniso = 2.0f;
break; break;
case AnisoFilter::kMax_4_1: case xenos::AnisoFilter::kMax_4_1:
aniso = 4.0f; aniso = 4.0f;
break; break;
case AnisoFilter::kMax_8_1: case xenos::AnisoFilter::kMax_8_1:
aniso = 8.0f; aniso = 8.0f;
break; break;
case AnisoFilter::kMax_16_1: case xenos::AnisoFilter::kMax_16_1:
aniso = 16.0f; aniso = 16.0f;
break; break;
default: default:
@ -827,7 +827,8 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) {
} }
sampler_create_info.anisotropyEnable = sampler_create_info.anisotropyEnable =
sampler_info.aniso_filter != AnisoFilter::kDisabled ? VK_TRUE : VK_FALSE; sampler_info.aniso_filter != xenos::AnisoFilter::kDisabled ? VK_TRUE
: VK_FALSE;
sampler_create_info.maxAnisotropy = aniso; sampler_create_info.maxAnisotropy = aniso;
sampler_create_info.compareEnable = VK_FALSE; sampler_create_info.compareEnable = VK_FALSE;
@ -853,10 +854,11 @@ TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) {
return sampler; return sampler;
} }
bool TextureFormatIsSimilar(TextureFormat left, TextureFormat right) { bool TextureFormatIsSimilar(xenos::TextureFormat left,
xenos::TextureFormat right) {
#define COMPARE_FORMAT(x, y) \ #define COMPARE_FORMAT(x, y) \
if ((left == TextureFormat::x && right == TextureFormat::y) || \ if ((left == xenos::TextureFormat::x && right == xenos::TextureFormat::y) || \
(left == TextureFormat::y && right == TextureFormat::x)) { \ (left == xenos::TextureFormat::y && right == xenos::TextureFormat::x)) { \
return true; \ return true; \
} }
@ -913,7 +915,7 @@ TextureCache::Texture* TextureCache::Lookup(const TextureInfo& texture_info) {
TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address, TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address,
uint32_t width, uint32_t width,
uint32_t height, uint32_t height,
TextureFormat format, xenos::TextureFormat format,
VkOffset2D* out_offset) { VkOffset2D* out_offset) {
for (auto it = textures_.begin(); it != textures_.end(); ++it) { for (auto it = textures_.begin(); it != textures_.end(); ++it) {
const auto& texture_info = it->second->texture_info; const auto& texture_info = it->second->texture_info;
@ -924,7 +926,7 @@ TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address,
out_offset) { out_offset) {
auto offset_bytes = guest_address - texture_info.memory.base_address; auto offset_bytes = guest_address - texture_info.memory.base_address;
if (texture_info.dimension == Dimension::k2D) { if (texture_info.dimension == xenos::DataDimension::k2DOrStacked) {
out_offset->x = 0; out_offset->x = 0;
out_offset->y = offset_bytes / texture_info.pitch; out_offset->y = offset_bytes / texture_info.pitch;
if (offset_bytes % texture_info.pitch != 0) { if (offset_bytes % texture_info.pitch != 0) {
@ -936,7 +938,7 @@ TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address,
} }
if (texture_info.memory.base_address == guest_address && if (texture_info.memory.base_address == guest_address &&
texture_info.dimension == Dimension::k2D && texture_info.dimension == xenos::DataDimension::k2DOrStacked &&
texture_info.pitch == width && texture_info.height == height) { texture_info.pitch == width && texture_info.height == height) {
if (out_offset) { if (out_offset) {
out_offset->x = 0; out_offset->x = 0;
@ -1000,7 +1002,7 @@ bool TextureCache::ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
void* host_address = memory_->TranslatePhysical(address); void* host_address = memory_->TranslatePhysical(address);
auto is_cube = src.dimension == Dimension::kCube; auto is_cube = src.dimension == xenos::DataDimension::kCube;
auto src_extent = src.GetMipExtent(mip, true); auto src_extent = src.GetMipExtent(mip, true);
auto dst_extent = GetMipExtent(src, mip); auto dst_extent = GetMipExtent(src, mip);
@ -1218,23 +1220,23 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
return true; return true;
} }
const FormatInfo* TextureCache::GetFormatInfo(TextureFormat format) { const FormatInfo* TextureCache::GetFormatInfo(xenos::TextureFormat format) {
switch (format) { switch (format) {
case TextureFormat::k_CTX1: case xenos::TextureFormat::k_CTX1:
return FormatInfo::Get(TextureFormat::k_8_8); return FormatInfo::Get(xenos::TextureFormat::k_8_8);
case TextureFormat::k_DXT3A: case xenos::TextureFormat::k_DXT3A:
return FormatInfo::Get(TextureFormat::k_DXT2_3); return FormatInfo::Get(xenos::TextureFormat::k_DXT2_3);
default: default:
return FormatInfo::Get(format); return FormatInfo::Get(format);
} }
} }
texture_conversion::CopyBlockCallback TextureCache::GetFormatCopyBlock( texture_conversion::CopyBlockCallback TextureCache::GetFormatCopyBlock(
TextureFormat format) { xenos::TextureFormat format) {
switch (format) { switch (format) {
case TextureFormat::k_CTX1: case xenos::TextureFormat::k_CTX1:
return texture_conversion::ConvertTexelCTX1ToR8G8; return texture_conversion::ConvertTexelCTX1ToR8G8;
case TextureFormat::k_DXT3A: case xenos::TextureFormat::k_DXT3A:
return texture_conversion::ConvertTexelDXT3AToDXT3; return texture_conversion::ConvertTexelDXT3AToDXT3;
default: default:
return texture_conversion::CopySwapBlock; return texture_conversion::CopySwapBlock;

View File

@ -110,7 +110,7 @@ class TextureCache {
// If offset_x and offset_y are not null, this may return a texture that // If offset_x and offset_y are not null, this may return a texture that
// contains this address at an offset. // contains this address at an offset.
Texture* LookupAddress(uint32_t guest_address, uint32_t width, Texture* LookupAddress(uint32_t guest_address, uint32_t width,
uint32_t height, TextureFormat format, uint32_t height, xenos::TextureFormat format,
VkOffset2D* out_offset = nullptr); VkOffset2D* out_offset = nullptr);
TextureView* DemandView(Texture* texture, uint16_t swizzle); TextureView* DemandView(Texture* texture, uint16_t swizzle);
@ -166,9 +166,9 @@ class TextureCache {
bool ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region, bool ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
uint32_t mip, const TextureInfo& src); uint32_t mip, const TextureInfo& src);
static const FormatInfo* GetFormatInfo(TextureFormat format); static const FormatInfo* GetFormatInfo(xenos::TextureFormat format);
static texture_conversion::CopyBlockCallback GetFormatCopyBlock( static texture_conversion::CopyBlockCallback GetFormatCopyBlock(
TextureFormat format); xenos::TextureFormat format);
static TextureExtent GetMipExtent(const TextureInfo& src, uint32_t mip); static TextureExtent GetMipExtent(const TextureInfo& src, uint32_t mip);
static uint32_t ComputeMipStorage(const FormatInfo* format_info, static uint32_t ComputeMipStorage(const FormatInfo* format_info,
uint32_t width, uint32_t height, uint32_t width, uint32_t height,

View File

@ -589,7 +589,7 @@ void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
current_batch_fence_ = nullptr; current_batch_fence_ = nullptr;
} }
Shader* VulkanCommandProcessor::LoadShader(ShaderType shader_type, Shader* VulkanCommandProcessor::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address, uint32_t guest_address,
const uint32_t* host_address, const uint32_t* host_address,
uint32_t dword_count) { uint32_t dword_count) {
@ -597,7 +597,7 @@ Shader* VulkanCommandProcessor::LoadShader(ShaderType shader_type,
dword_count); dword_count);
} }
bool VulkanCommandProcessor::IssueDraw(PrimitiveType primitive_type, bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
uint32_t index_count, uint32_t index_count,
IndexBufferInfo* index_buffer_info, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) { bool major_mode_explicit) {
@ -783,15 +783,16 @@ bool VulkanCommandProcessor::PopulateIndexBuffer(
assert_true(min_index == 0); assert_true(min_index == 0);
assert_true(max_index == 0xFFFF || max_index == 0xFFFFFF); assert_true(max_index == 0xFFFF || max_index == 0xFFFFFF);
assert_true(info.endianness == Endian::k8in16 || assert_true(info.endianness == xenos::Endian::k8in16 ||
info.endianness == Endian::k8in32); info.endianness == xenos::Endian::k8in32);
trace_writer_.WriteMemoryRead(info.guest_base, info.length); trace_writer_.WriteMemoryRead(info.guest_base, info.length);
// Upload (or get a cached copy of) the buffer. // Upload (or get a cached copy of) the buffer.
uint32_t source_addr = info.guest_base; uint32_t source_addr = info.guest_base;
uint32_t source_length = uint32_t source_length =
info.count * (info.format == IndexFormat::kInt32 ? sizeof(uint32_t) info.count * (info.format == xenos::IndexFormat::kInt32
? sizeof(uint32_t)
: sizeof(uint16_t)); : sizeof(uint16_t));
auto buffer_ref = buffer_cache_->UploadIndexBuffer( auto buffer_ref = buffer_cache_->UploadIndexBuffer(
current_setup_buffer_, source_addr, source_length, info.format, current_setup_buffer_, source_addr, source_length, info.format,
@ -802,7 +803,7 @@ bool VulkanCommandProcessor::PopulateIndexBuffer(
} }
// Bind the buffer. // Bind the buffer.
VkIndexType index_type = info.format == IndexFormat::kInt32 VkIndexType index_type = info.format == xenos::IndexFormat::kInt32
? VK_INDEX_TYPE_UINT32 ? VK_INDEX_TYPE_UINT32
: VK_INDEX_TYPE_UINT16; : VK_INDEX_TYPE_UINT16;
vkCmdBindIndexBuffer(command_buffer, buffer_ref.first, buffer_ref.second, vkCmdBindIndexBuffer(command_buffer, buffer_ref.first, buffer_ref.second,
@ -926,7 +927,8 @@ bool VulkanCommandProcessor::IssueCopy() {
// https://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html // https://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
uint32_t surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32; uint32_t surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32;
uint32_t surface_pitch = surface_info & 0x3FFF; uint32_t surface_pitch = surface_info & 0x3FFF;
auto surface_msaa = static_cast<MsaaSamples>((surface_info >> 16) & 0x3); auto surface_msaa =
static_cast<xenos::MsaaSamples>((surface_info >> 16) & 0x3);
// TODO(benvanik): any way to scissor this? a200 has: // TODO(benvanik): any way to scissor this? a200 has:
// REG_A2XX_RB_COPY_DEST_OFFSET = A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) | // REG_A2XX_RB_COPY_DEST_OFFSET = A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) |
@ -969,7 +971,7 @@ bool VulkanCommandProcessor::IssueCopy() {
break; break;
} }
assert_true(fetch->type == xenos::FetchConstantType::kVertex); 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); assert_true(fetch->size == 6);
const uint8_t* vertex_addr = memory_->TranslatePhysical(fetch->address << 2); const uint8_t* vertex_addr = memory_->TranslatePhysical(fetch->address << 2);
trace_writer_.WriteMemoryRead(fetch->address << 2, fetch->size * 4); trace_writer_.WriteMemoryRead(fetch->address << 2, fetch->size * 4);
@ -1002,8 +1004,8 @@ bool VulkanCommandProcessor::IssueCopy() {
uint32_t color_edram_base = 0; uint32_t color_edram_base = 0;
uint32_t depth_edram_base = 0; uint32_t depth_edram_base = 0;
ColorRenderTargetFormat color_format; xenos::ColorRenderTargetFormat color_format;
DepthRenderTargetFormat depth_format; xenos::DepthRenderTargetFormat depth_format;
if (is_color_source) { if (is_color_source) {
// Source from a color target. // Source from a color target.
reg::RB_COLOR_INFO color_info[4] = { reg::RB_COLOR_INFO color_info[4] = {
@ -1027,10 +1029,10 @@ bool VulkanCommandProcessor::IssueCopy() {
} }
} }
Endian resolve_endian = Endian::k8in32; xenos::Endian resolve_endian = xenos::Endian::k8in32;
if (copy_regs->copy_dest_info.copy_dest_endian <= Endian128::k16in32) { if (copy_regs->copy_dest_info.copy_dest_endian <= xenos::Endian128::k16in32) {
resolve_endian = resolve_endian =
static_cast<Endian>(copy_regs->copy_dest_info.copy_dest_endian); static_cast<xenos::Endian>(copy_regs->copy_dest_info.copy_dest_endian);
} }
// Demand a resolve texture from the texture cache. // Demand a resolve texture from the texture cache.

View File

@ -76,11 +76,11 @@ class VulkanCommandProcessor : public CommandProcessor {
void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width,
uint32_t frontbuffer_height) override; uint32_t frontbuffer_height) 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, const uint32_t* host_address,
uint32_t dword_count) override; 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, IndexBufferInfo* index_buffer_info,
bool major_mode_explicit) override; bool major_mode_explicit) override;
bool PopulateConstants(VkCommandBuffer command_buffer, bool PopulateConstants(VkCommandBuffer command_buffer,

View File

@ -23,7 +23,7 @@ namespace vulkan {
using xe::ui::vulkan::CheckResult; using xe::ui::vulkan::CheckResult;
VulkanShader::VulkanShader(ui::vulkan::VulkanDevice* device, VulkanShader::VulkanShader(ui::vulkan::VulkanDevice* device,
ShaderType shader_type, uint64_t data_hash, xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count) const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count), device_(device) {} : Shader(shader_type, data_hash, dword_ptr, dword_count), device_(device) {}
@ -50,9 +50,9 @@ bool VulkanShader::Prepare() {
vkCreateShaderModule(*device_, &shader_info, nullptr, &shader_module_); vkCreateShaderModule(*device_, &shader_info, nullptr, &shader_module_);
CheckResult(status, "vkCreateShaderModule"); CheckResult(status, "vkCreateShaderModule");
char typeChar = shader_type_ == ShaderType::kPixel char typeChar = shader_type_ == xenos::ShaderType::kPixel
? 'p' ? 'p'
: shader_type_ == ShaderType::kVertex ? 'v' : 'u'; : shader_type_ == xenos::ShaderType::kVertex ? 'v' : 'u';
device_->DbgSetObjectName( device_->DbgSetObjectName(
uint64_t(shader_module_), VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, uint64_t(shader_module_), VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT,
fmt::format("S({}): {:016X}", typeChar, ucode_data_hash())); fmt::format("S({}): {:016X}", typeChar, ucode_data_hash()));

View File

@ -21,7 +21,7 @@ namespace vulkan {
class VulkanShader : public Shader { class VulkanShader : public Shader {
public: public:
VulkanShader(ui::vulkan::VulkanDevice* device, ShaderType shader_type, VulkanShader(ui::vulkan::VulkanDevice* device, xenos::ShaderType shader_type,
uint64_t data_hash, const uint32_t* dword_ptr, uint64_t data_hash, const uint32_t* dword_ptr,
uint32_t dword_count); uint32_t dword_count);
~VulkanShader() override; ~VulkanShader() override;

View File

@ -25,9 +25,9 @@ class VulkanTraceViewer : public TraceViewer {
return std::unique_ptr<gpu::GraphicsSystem>(new VulkanGraphicsSystem()); return std::unique_ptr<gpu::GraphicsSystem>(new VulkanGraphicsSystem());
} }
uintptr_t GetColorRenderTarget(uint32_t pitch, MsaaSamples samples, uintptr_t GetColorRenderTarget(
uint32_t base, uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
ColorRenderTargetFormat format) override { xenos::ColorRenderTargetFormat format) override {
auto command_processor = static_cast<VulkanCommandProcessor*>( auto command_processor = static_cast<VulkanCommandProcessor*>(
graphics_system_->command_processor()); graphics_system_->command_processor());
// return command_processor->GetColorRenderTarget(pitch, samples, base, // return command_processor->GetColorRenderTarget(pitch, samples, base,
@ -35,9 +35,9 @@ class VulkanTraceViewer : public TraceViewer {
return 0; return 0;
} }
uintptr_t GetDepthRenderTarget(uint32_t pitch, MsaaSamples samples, uintptr_t GetDepthRenderTarget(
uint32_t base, uint32_t pitch, xenos::MsaaSamples samples, uint32_t base,
DepthRenderTargetFormat format) override { xenos::DepthRenderTargetFormat format) override {
auto command_processor = static_cast<VulkanCommandProcessor*>( auto command_processor = static_cast<VulkanCommandProcessor*>(
graphics_system_->command_processor()); graphics_system_->command_processor());
// return command_processor->GetDepthRenderTarget(pitch, samples, base, // return command_processor->GetDepthRenderTarget(pitch, samples, base,

View File

@ -16,6 +16,7 @@
namespace xe { namespace xe {
namespace gpu { namespace gpu {
namespace xenos {
enum class ShaderType : uint32_t { enum class ShaderType : uint32_t {
kVertex = 0, kVertex = 0,
@ -53,8 +54,8 @@ enum class PrimitiveType : uint32_t {
k2DTriStrip = 0x16, k2DTriStrip = 0x16,
// Tessellation patches when VGT_OUTPUT_PATH_CNTL::path_select is // Tessellation patches when VGT_OUTPUT_PATH_CNTL::path_select is
// xenos::VGTOutputPath::kTessellationEnable. The vertex shader receives patch // VGTOutputPath::kTessellationEnable. The vertex shader receives patch index
// index rather than control point indices. // rather than control point indices.
kLinePatch = 0x10, kLinePatch = 0x10,
kTrianglePatch = 0x11, kTrianglePatch = 0x11,
kQuadPatch = 0x12, kQuadPatch = 0x12,
@ -80,9 +81,11 @@ inline bool IsPrimitiveTwoFaced(bool tessellated, PrimitiveType type) {
return false; return false;
} }
enum class Dimension : uint32_t { // For the texture fetch constant (not the tfetch instruction), stacked stored
// as 2D.
enum class DataDimension : uint32_t {
k1D = 0, k1D = 0,
k2D = 1, k2DOrStacked = 1,
k3D = 2, k3D = 2,
kCube = 3, kCube = 3,
}; };
@ -133,23 +136,23 @@ enum class BorderColor : uint32_t {
k_ACBCRY_BLACK = 3, k_ACBCRY_BLACK = 3,
}; };
// For the tfetch instruction, not the fetch constant - slightly different // For the tfetch instruction (not the fetch constant) and related instructions,
// meaning, as stacked textures are stored as 2D, but fetched using tfetch3D. // stacked accessed using tfetch3D.
enum class TextureDimension : uint32_t { enum class FetchOpDimension : uint32_t {
k1D = 0, k1D = 0,
k2D = 1, k2D = 1,
k3D = 2, k3DOrStacked = 2,
kCube = 3, kCube = 3,
}; };
inline int GetTextureDimensionComponentCount(TextureDimension dimension) { inline int GetFetchOpDimensionComponentCount(FetchOpDimension dimension) {
switch (dimension) { switch (dimension) {
case TextureDimension::k1D: case FetchOpDimension::k1D:
return 1; return 1;
case TextureDimension::k2D: case FetchOpDimension::k2D:
return 2; return 2;
case TextureDimension::k3D: case FetchOpDimension::k3DOrStacked:
case TextureDimension::kCube: case FetchOpDimension::kCube:
return 3; return 3;
default: default:
assert_unhandled_case(dimension); assert_unhandled_case(dimension);
@ -488,8 +491,6 @@ enum class BlendOp : uint32_t {
kRevSubtract = 4, kRevSubtract = 4,
}; };
namespace xenos {
typedef enum { typedef enum {
XE_GPU_INVALIDATE_MASK_VERTEX_SHADER = 1 << 8, XE_GPU_INVALIDATE_MASK_VERTEX_SHADER = 1 << 8,
XE_GPU_INVALIDATE_MASK_PIXEL_SHADER = 1 << 9, XE_GPU_INVALIDATE_MASK_PIXEL_SHADER = 1 << 9,
@ -738,7 +739,7 @@ XEPACKEDUNION(xe_gpu_texture_fetch_t, {
ClampMode clamp_x : 3; // +10 ClampMode clamp_x : 3; // +10
ClampMode clamp_y : 3; // +13 ClampMode clamp_y : 3; // +13
ClampMode clamp_z : 3; // +16 ClampMode clamp_z : 3; // +16
xenos::SignedRepeatingFractionMode signed_rf_mode_all : 1; // +19 SignedRepeatingFractionMode signed_rf_mode_all : 1; // +19
// TODO(Triang3l): 1 or 2 dim_tbd bits? // TODO(Triang3l): 1 or 2 dim_tbd bits?
uint32_t unk_0 : 2; // +20 uint32_t unk_0 : 2; // +20
uint32_t pitch : 9; // +22 byte_pitch >> 5 uint32_t pitch : 9; // +22 byte_pitch >> 5
@ -778,7 +779,7 @@ XEPACKEDUNION(xe_gpu_texture_fetch_t, {
TextureFilter min_filter : 2; // +21 TextureFilter min_filter : 2; // +21
TextureFilter mip_filter : 2; // +23 TextureFilter mip_filter : 2; // +23
AnisoFilter aniso_filter : 3; // +25 AnisoFilter aniso_filter : 3; // +25
xenos::ArbitraryFilter arbitrary_filter : 3; // +28 ArbitraryFilter arbitrary_filter : 3; // +28
uint32_t border_size : 1; // +31 uint32_t border_size : 1; // +31
uint32_t vol_mag_filter : 1; // +0 dword_4 uint32_t vol_mag_filter : 1; // +0 dword_4
@ -798,7 +799,7 @@ XEPACKEDUNION(xe_gpu_texture_fetch_t, {
// Also known as TriJuice. // Also known as TriJuice.
uint32_t tri_clamp : 2; // +3 uint32_t tri_clamp : 2; // +3
int32_t aniso_bias : 4; // +5 int32_t aniso_bias : 4; // +5
Dimension dimension : 2; // +9 DataDimension dimension : 2; // +9
uint32_t packed_mips : 1; // +11 uint32_t packed_mips : 1; // +11
uint32_t mip_address : 20; // +12 mip address >> 12 uint32_t mip_address : 20; // +12 mip address >> 12
}); });

View File

@ -376,11 +376,11 @@ void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer
} }
fetch.base_address = frontbuffer_address >> 12; fetch.base_address = frontbuffer_address >> 12;
auto texture_format = gpu::TextureFormat(texture_format_ptr.value()); auto texture_format = gpu::xenos::TextureFormat(texture_format_ptr.value());
auto color_space = *color_space_ptr; auto color_space = *color_space_ptr;
assert_true(texture_format == gpu::TextureFormat::k_8_8_8_8 || assert_true(texture_format == gpu::xenos::TextureFormat::k_8_8_8_8 ||
texture_format == texture_format ==
gpu::TextureFormat::k_2_10_10_10_AS_16_16_16_16); gpu::xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16);
assert_true(color_space == 0); // RGB(0) assert_true(color_space == 0); // RGB(0)
assert_true(*width == 1 + fetch.size_2d.width); assert_true(*width == 1 + fetch.size_2d.width);
assert_true(*height == 1 + fetch.size_2d.height); assert_true(*height == 1 + fetch.size_2d.height);