diff options
Diffstat (limited to 'src/video_core/command_processor.cpp')
-rw-r--r-- | src/video_core/command_processor.cpp | 98 |
1 files changed, 71 insertions, 27 deletions
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index e031871e8..c4cdf672b 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -27,6 +27,10 @@ static int float_regs_counter = 0; static u32 uniform_write_buffer[4]; +static int default_attr_counter = 0; + +static u32 default_attr_write_buffer[3]; + Common::Profiling::TimingCategory category_drawing("Drawing"); static inline void WritePicaReg(u32 id, u32 value, u32 mask) { @@ -71,12 +75,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { u32 vertex_attribute_sources[16]; boost::fill(vertex_attribute_sources, 0xdeadbeef); u32 vertex_attribute_strides[16]; - u32 vertex_attribute_formats[16]; + Regs::VertexAttributeFormat vertex_attribute_formats[16]; - // HACK: Initialize vertex_attribute_elements to zero to prevent infinite loops below. - // This is one of the hacks required to deal with uninitalized vertex attributes. - // TODO: Fix this properly. - u32 vertex_attribute_elements[16] = {}; + u32 vertex_attribute_elements[16]; u32 vertex_attribute_element_size[16]; // Setup attribute data from loaders @@ -90,7 +91,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { u32 attribute_index = loader_config.GetComponent(component); vertex_attribute_sources[attribute_index] = load_address; vertex_attribute_strides[attribute_index] = static_cast<u32>(loader_config.byte_count); - vertex_attribute_formats[attribute_index] = static_cast<u32>(attribute_config.GetFormat(attribute_index)); + vertex_attribute_formats[attribute_index] = attribute_config.GetFormat(attribute_index); vertex_attribute_elements[attribute_index] = attribute_config.GetNumElements(attribute_index); vertex_attribute_element_size[attribute_index] = attribute_config.GetElementSizeInBytes(attribute_index); load_address += attribute_config.GetStride(attribute_index); @@ -126,26 +127,29 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { input.attr[0].w = debug_token; for (int i = 0; i < attribute_config.GetNumTotalAttributes(); ++i) { - for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { - const u8* srcdata = Memory::GetPointer(PAddrToVAddr(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i])); - - // TODO(neobrain): Ocarina of Time 3D has GetNumTotalAttributes return 8, - // yet only provides 2 valid source data addresses. Need to figure out - // what's wrong there, until then we just continue when address lookup fails - if (srcdata == nullptr) - continue; - - const float srcval = (vertex_attribute_formats[i] == 0) ? *(s8*)srcdata : - (vertex_attribute_formats[i] == 1) ? *(u8*)srcdata : - (vertex_attribute_formats[i] == 2) ? *(s16*)srcdata : - *(float*)srcdata; - input.attr[i][comp] = float24::FromFloat32(srcval); - LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f", - comp, i, vertex, index, - attribute_config.GetPhysicalBaseAddress(), - vertex_attribute_sources[i] - base_address, - vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i], - input.attr[i][comp].ToFloat32()); + if (attribute_config.IsDefaultAttribute(i)) { + input.attr[i] = VertexShader::GetDefaultAttribute(i); + LOG_TRACE(HW_GPU, "Loaded default attribute %x for vertex %x (index %x): (%f, %f, %f, %f)", + i, vertex, index, + input.attr[i][0].ToFloat32(), input.attr[i][1].ToFloat32(), + input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32()); + } else { + for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { + const u8* srcdata = Memory::GetPointer(PAddrToVAddr(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i])); + + const float srcval = (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::BYTE) ? *(s8*)srcdata : + (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::UBYTE) ? *(u8*)srcdata : + (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) ? *(s16*)srcdata : + *(float*)srcdata; + + input.attr[i][comp] = float24::FromFloat32(srcval); + LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f", + comp, i, vertex, index, + attribute_config.GetPhysicalBaseAddress(), + vertex_attribute_sources[i] - base_address, + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i], + input.attr[i][comp].ToFloat32()); + } } } @@ -224,7 +228,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { // it directly write the values? uniform_write_buffer[float_regs_counter++] = value; - // Uniforms are written in a packed format such that 4 float24 values are encoded in + // Uniforms are written in a packed format such that four float24 values are encoded in // three 32-bit numbers. We write to internal memory once a full such vector is // written. if ((float_regs_counter >= 4 && uniform_setup.IsFloat32()) || @@ -259,6 +263,46 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { } break; } + + // Load default vertex input attributes + case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[0], 0x233): + case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[1], 0x234): + case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.set_value[2], 0x235): + { + // TODO: Does actual hardware indeed keep an intermediate buffer or does + // it directly write the values? + default_attr_write_buffer[default_attr_counter++] = value; + + // Default attributes are written in a packed format such that four float24 values are encoded in + // three 32-bit numbers. We write to internal memory once a full such vector is + // written. + if (default_attr_counter >= 3) { + default_attr_counter = 0; + + auto& setup = registers.vs_default_attributes_setup; + + if (setup.index >= 16) { + LOG_ERROR(HW_GPU, "Invalid VS default attribute index %d", (int)setup.index); + break; + } + + Math::Vec4<float24>& attribute = VertexShader::GetDefaultAttribute(setup.index); + + // NOTE: The destination component order indeed is "backwards" + attribute.w = float24::FromRawFloat24(default_attr_write_buffer[0] >> 8); + attribute.z = float24::FromRawFloat24(((default_attr_write_buffer[0] & 0xFF) << 16) | ((default_attr_write_buffer[1] >> 16) & 0xFFFF)); + attribute.y = float24::FromRawFloat24(((default_attr_write_buffer[1] & 0xFFFF) << 8) | ((default_attr_write_buffer[2] >> 24) & 0xFF)); + attribute.x = float24::FromRawFloat24(default_attr_write_buffer[2] & 0xFFFFFF); + + LOG_TRACE(HW_GPU, "Set default VS attribute %x to (%f %f %f %f)", (int)setup.index, + attribute.x.ToFloat32(), attribute.y.ToFloat32(), attribute.z.ToFloat32(), + attribute.w.ToFloat32()); + + // TODO: Verify that this actually modifies the register! + setup.index = setup.index + 1; + } + break; + } // Load shader program code case PICA_REG_INDEX_WORKAROUND(vs_program.set_word[0], 0x2cc): |