diff --git a/hw/amdgpu/shader/src/Fragment.cpp b/hw/amdgpu/shader/src/Fragment.cpp index e55e7e7e0..03598f5f4 100644 --- a/hw/amdgpu/shader/src/Fragment.cpp +++ b/hw/amdgpu/shader/src/Fragment.cpp @@ -164,199 +164,208 @@ spirv::Type convertFromFormat(spirv::Value *result, int count, spv::StorageClass::StorageBuffer, loadType); auto &builder = fragment.builder; - std::size_t chanSize = 0; switch (surfaceFormat) { case kSurfaceFormat32: case kSurfaceFormat32_32: case kSurfaceFormat32_32_32: case kSurfaceFormat32_32_32_32: - chanSize += 16; - [[fallthrough]]; - case kSurfaceFormat16: case kSurfaceFormat16_16: case kSurfaceFormat16_16_16_16: - chanSize += 8; - [[fallthrough]]; - case kSurfaceFormat8: case kSurfaceFormat8_8: - case kSurfaceFormat8_8_8_8: - chanSize += 8; - { - // format not requires bit fetching - auto totalChannelsCount = getChannelsCount(surfaceFormat); - auto channelSize = sizeOfFormat(surfaceFormat) / 8 / totalChannelsCount; - auto channelsCount = std::min(count, totalChannelsCount); + case kSurfaceFormat8_8_8_8: { + // format not requires bit fetching + auto totalChannelsCount = getChannelsCount(surfaceFormat); + auto channelSize = sizeOfFormat(surfaceFormat) / 8 / totalChannelsCount; + auto channelsCount = std::min(count, totalChannelsCount); - if (channelSize != 1) { - offset = builder.createUDiv(fragment.context->getUInt32Type(), offset, - fragment.context->getUInt32(channelSize)); - } - - int channel = 0; - auto resultType = fragment.context->getType(loadType); - for (; channel < channelsCount; ++channel) { - auto channelOffset = offset; - - if (channel != 0) { - channelOffset = builder.createIAdd( - fragment.context->getUInt32Type(), channelOffset, - fragment.context->getUInt32(channel)); - } - - auto uniformPointerValue = fragment.builder.createAccessChain( - storageBufferPointerType, uniform->variable, - {{fragment.context->getUInt32(0), channelOffset}}); - - auto channelValue = fragment.builder.createLoad( - fragment.context->getType(loadType), uniformPointerValue); - - if (chanSize != 0) { - if (chanSize == 16) { - if (loadType != TypeId::Float16) { - channelValue = fragment.builder.createBitcast( - fragment.context->getFloat16Type(), channelValue); - } - - channelValue = fragment.builder.createFConvert( - fragment.context->getFloat32Type(), channelValue); - } - } - switch (channelType) { - case kTextureChannelTypeFloat: - case kTextureChannelTypeSInt: - case kTextureChannelTypeUInt: - result[channel] = channelValue; - break; - - case kTextureChannelTypeUNorm: { - auto maxValue = - (static_cast(1) << (channelSize * 8)) - 1; - - auto uintChannelValue = spirv::cast(channelValue); - - if (loadType != TypeId::UInt32) { - uintChannelValue = builder.createUConvert( - fragment.context->getUInt32Type(), uintChannelValue); - } - - auto floatChannelValue = builder.createConvertUToF( - fragment.context->getFloat32Type(), uintChannelValue); - floatChannelValue = builder.createFDiv( - fragment.context->getFloat32Type(), floatChannelValue, - fragment.context->getFloat32(maxValue)); - result[channel] = floatChannelValue; - resultType = fragment.context->getFloat32Type(); - break; - } - - case kTextureChannelTypeSNorm: { - auto maxValue = - (static_cast(1) << (channelSize * 8 - 1)) - 1; - - auto uintChannelValue = spirv::cast(channelValue); - - if (loadType != TypeId::SInt32) { - uintChannelValue = builder.createSConvert( - fragment.context->getSint32Type(), uintChannelValue); - } - - auto floatChannelValue = builder.createConvertSToF( - fragment.context->getFloat32Type(), uintChannelValue); - - floatChannelValue = builder.createFDiv( - fragment.context->getFloat32Type(), floatChannelValue, - fragment.context->getFloat32(maxValue)); - - auto glslStd450 = fragment.context->getGlslStd450(); - floatChannelValue = - spirv::cast(fragment.builder.createExtInst( - fragment.context->getFloat32Type(), glslStd450, - GLSLstd450FClamp, - {{floatChannelValue, fragment.context->getFloat32(-1), - fragment.context->getFloat32(1)}})); - result[channel] = floatChannelValue; - resultType = fragment.context->getFloat32Type(); - break; - } - - case kTextureChannelTypeUScaled: { - auto uintChannelValue = spirv::cast(channelValue); - - if (loadType != TypeId::UInt32) { - uintChannelValue = builder.createUConvert( - fragment.context->getUInt32Type(), uintChannelValue); - } - - auto floatChannelValue = builder.createConvertUToF( - fragment.context->getFloat32Type(), uintChannelValue); - - result[channel] = floatChannelValue; - resultType = fragment.context->getFloat32Type(); - break; - } - - case kTextureChannelTypeSScaled: { - auto uintChannelValue = spirv::cast(channelValue); - - if (loadType != TypeId::SInt32) { - uintChannelValue = builder.createSConvert( - fragment.context->getSint32Type(), uintChannelValue); - } - - auto floatChannelValue = builder.createConvertSToF( - fragment.context->getFloat32Type(), uintChannelValue); - - result[channel] = floatChannelValue; - resultType = fragment.context->getFloat32Type(); - break; - } - - case kTextureChannelTypeSNormNoZero: { - auto maxValue = - (static_cast(1) << (channelSize * 8)) - 1; - - auto uintChannelValue = spirv::cast(channelValue); - - if (loadType != TypeId::SInt32) { - uintChannelValue = builder.createSConvert( - fragment.context->getSint32Type(), uintChannelValue); - } - - auto floatChannelValue = builder.createConvertSToF( - fragment.context->getFloat32Type(), uintChannelValue); - - floatChannelValue = builder.createFMul( - fragment.context->getFloat32Type(), floatChannelValue, - fragment.context->getFloat32(2)); - floatChannelValue = builder.createFAdd( - fragment.context->getFloat32Type(), floatChannelValue, - fragment.context->getFloat32(1)); - - floatChannelValue = builder.createFDiv( - fragment.context->getFloat32Type(), floatChannelValue, - fragment.context->getFloat32(maxValue)); - - result[channel] = floatChannelValue; - resultType = fragment.context->getFloat32Type(); - break; - } - - default: - util::unreachable("unimplemented channel type %u", channelType); - } - } - - // for (; channel < count; ++channel) { - // result[channel] = fragment.createBitcast( - // resultType, fragment.context->getUInt32Type(), - // fragment.context->getUInt32(0)); - // } - return resultType; + if (channelSize != 1) { + offset = builder.createUDiv(fragment.context->getUInt32Type(), offset, + fragment.context->getUInt32(channelSize)); } + int channel = 0; + auto resultType = fragment.context->getType(loadType); + for (; channel < channelsCount; ++channel) { + auto channelOffset = offset; + + if (channel != 0) { + channelOffset = + builder.createIAdd(fragment.context->getUInt32Type(), channelOffset, + fragment.context->getUInt32(channel)); + } + + auto uniformPointerValue = fragment.builder.createAccessChain( + storageBufferPointerType, uniform->variable, + {{fragment.context->getUInt32(0), channelOffset}}); + + auto channelValue = fragment.builder.createLoad( + fragment.context->getType(loadType), uniformPointerValue); + + switch (channelType) { + case kTextureChannelTypeFloat: { + if (loadType != TypeId::Float32) { + channelValue = fragment.builder.createFConvert( + fragment.context->getFloat32Type(), channelValue); + + resultType = fragment.context->getFloat32Type(); + } + + result[channel] = channelValue; + break; + } + case kTextureChannelTypeSInt: { + if (loadType != TypeId::SInt32) { + channelValue = fragment.builder.createSConvert( + fragment.context->getSint32Type(), + spirv::cast(channelValue)); + + resultType = fragment.context->getSint32Type(); + } + + result[channel] = channelValue; + break; + } + case kTextureChannelTypeUInt: + if (loadType != TypeId::UInt32) { + channelValue = fragment.builder.createUConvert( + fragment.context->getUInt32Type(), + spirv::cast(channelValue)); + + resultType = fragment.context->getUInt32Type(); + } + + result[channel] = channelValue; + break; + + case kTextureChannelTypeUNorm: { + auto maxValue = + (static_cast(1) << (channelSize * 8)) - 1; + + auto uintChannelValue = spirv::cast(channelValue); + + if (loadType != TypeId::UInt32) { + uintChannelValue = builder.createUConvert( + fragment.context->getUInt32Type(), uintChannelValue); + } + + auto floatChannelValue = builder.createConvertUToF( + fragment.context->getFloat32Type(), uintChannelValue); + floatChannelValue = builder.createFDiv( + fragment.context->getFloat32Type(), floatChannelValue, + fragment.context->getFloat32(maxValue)); + result[channel] = floatChannelValue; + resultType = fragment.context->getFloat32Type(); + break; + } + + case kTextureChannelTypeSNorm: { + auto maxValue = + (static_cast(1) << (channelSize * 8 - 1)) - 1; + + auto uintChannelValue = spirv::cast(channelValue); + + if (loadType != TypeId::SInt32) { + uintChannelValue = builder.createSConvert( + fragment.context->getSint32Type(), uintChannelValue); + } + + auto floatChannelValue = builder.createConvertSToF( + fragment.context->getFloat32Type(), uintChannelValue); + + floatChannelValue = builder.createFDiv( + fragment.context->getFloat32Type(), floatChannelValue, + fragment.context->getFloat32(maxValue)); + + auto glslStd450 = fragment.context->getGlslStd450(); + floatChannelValue = + spirv::cast(fragment.builder.createExtInst( + fragment.context->getFloat32Type(), glslStd450, + GLSLstd450FClamp, + {{floatChannelValue, fragment.context->getFloat32(-1), + fragment.context->getFloat32(1)}})); + result[channel] = floatChannelValue; + resultType = fragment.context->getFloat32Type(); + break; + } + + case kTextureChannelTypeUScaled: { + auto uintChannelValue = spirv::cast(channelValue); + + if (loadType != TypeId::UInt32) { + uintChannelValue = builder.createUConvert( + fragment.context->getUInt32Type(), uintChannelValue); + } + + auto floatChannelValue = builder.createConvertUToF( + fragment.context->getFloat32Type(), uintChannelValue); + + result[channel] = floatChannelValue; + resultType = fragment.context->getFloat32Type(); + break; + } + + case kTextureChannelTypeSScaled: { + auto uintChannelValue = spirv::cast(channelValue); + + if (loadType != TypeId::SInt32) { + uintChannelValue = builder.createSConvert( + fragment.context->getSint32Type(), uintChannelValue); + } + + auto floatChannelValue = builder.createConvertSToF( + fragment.context->getFloat32Type(), uintChannelValue); + + result[channel] = floatChannelValue; + resultType = fragment.context->getFloat32Type(); + break; + } + + case kTextureChannelTypeSNormNoZero: { + auto maxValue = + (static_cast(1) << (channelSize * 8)) - 1; + + auto uintChannelValue = spirv::cast(channelValue); + + if (loadType != TypeId::SInt32) { + uintChannelValue = builder.createSConvert( + fragment.context->getSint32Type(), uintChannelValue); + } + + auto floatChannelValue = builder.createConvertSToF( + fragment.context->getFloat32Type(), uintChannelValue); + + floatChannelValue = builder.createFMul( + fragment.context->getFloat32Type(), floatChannelValue, + fragment.context->getFloat32(2)); + floatChannelValue = builder.createFAdd( + fragment.context->getFloat32Type(), floatChannelValue, + fragment.context->getFloat32(1)); + + floatChannelValue = builder.createFDiv( + fragment.context->getFloat32Type(), floatChannelValue, + fragment.context->getFloat32(maxValue)); + + result[channel] = floatChannelValue; + resultType = fragment.context->getFloat32Type(); + break; + } + + default: + util::unreachable("unimplemented channel type %u", channelType); + } + } + + // for (; channel < count; ++channel) { + // result[channel] = fragment.createBitcast( + // resultType, fragment.context->getUInt32Type(), + // fragment.context->getUInt32(0)); + // } + return resultType; + } + default: break; }