[GPU] Move all xenos.h to gpu::xenos, disambiguate Dimension/TextureDimension
This commit is contained in:
parent
39490f3c3a
commit
4bb0ca0e09
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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] = {};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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]));
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¶ms, 0, sizeof(params));
|
std::memset(¶ms, 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)});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue