diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index cfc9ba2e0..d4c1e24b2 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -1739,7 +1739,10 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( float ndc_offset_x = (pa_cl_vte_cntl & (1 << 1)) ? 0.0f : -1.0f; float ndc_offset_y = (pa_cl_vte_cntl & (1 << 3)) ? 0.0f : 1.0f; float ndc_offset_z = gl_clip_space_def ? 0.5f : 0.0f; - float pixel_half_pixel_offset = 0.0f; + // Like in OpenGL - VPOS giving pixel centers. + // TODO(Triang3l): Check if ps_param_gen should give center positions in + // OpenGL mode on the Xbox 360. + float pixel_half_pixel_offset = 0.5f; if (FLAGS_d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) { // Signs are hopefully correct here, tested in GTA IV on both clearing // (without a viewport) and drawing things near the edges of the screen. @@ -1757,7 +1760,8 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( } else { ndc_offset_y -= 1.0f / 2560.0f; } - pixel_half_pixel_offset = -0.5f; + // Like in Direct3D 9 - VPOS giving the top-left corner. + pixel_half_pixel_offset = 0.0f; } dirty |= system_constants_.ndc_scale[0] != ndc_scale_x; dirty |= system_constants_.ndc_scale[1] != ndc_scale_y; diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index cba883287..6d1fffb37 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -961,10 +961,9 @@ void DxbcShaderTranslator::StartPixelShader() { ++stat_.dynamic_flow_control_count; // Write VPOS (without supersampling because SSAA is used to fake MSAA, and // at integer coordinates rather than half-pixel if needed) to XY. - system_constants_used_ |= (1ull << kSysConst_SSAAInvScale_Index) | - (1ull << kSysConst_PixelHalfPixelOffset_Index); - shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MAD) | - ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(13)); + system_constants_used_ |= 1ull << kSysConst_SSAAInvScale_Index; + shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MUL) | + ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(9)); shader_code_.push_back( EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0011, 1)); shader_code_.push_back(param_gen_value_temp); @@ -978,6 +977,30 @@ void DxbcShaderTranslator::StartPixelShader() { shader_code_.push_back(cbuffer_index_system_constants_); shader_code_.push_back(uint32_t(CbufferRegister::kSystemConstants)); shader_code_.push_back(kSysConst_SSAAInvScale_Vec); + ++stat_.instruction_count; + ++stat_.float_instruction_count; + // Floor VPOS so with AA, the resulting pixel corner/center is written, not + // the sample position (games likely don't expect it to be fractional). + shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ROUND_NI) | + ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); + shader_code_.push_back( + EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0011, 1)); + shader_code_.push_back(param_gen_value_temp); + shader_code_.push_back( + EncodeVectorSwizzledOperand(D3D10_SB_OPERAND_TYPE_TEMP, kSwizzleXYZW, 1)); + shader_code_.push_back(param_gen_value_temp); + ++stat_.instruction_count; + ++stat_.float_instruction_count; + // If in OpenGL half-pixel offset mode, write the center of the pixel. + system_constants_used_ |= 1ull << kSysConst_PixelHalfPixelOffset_Index; + shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ADD) | + ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(9)); + shader_code_.push_back( + EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0011, 1)); + shader_code_.push_back(param_gen_value_temp); + shader_code_.push_back( + EncodeVectorSwizzledOperand(D3D10_SB_OPERAND_TYPE_TEMP, kSwizzleXYZW, 1)); + shader_code_.push_back(param_gen_value_temp); shader_code_.push_back( EncodeVectorReplicatedOperand(D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER, kSysConst_PixelHalfPixelOffset_Comp, 3));