mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-06 16:49:59 +01:00
[amdgpu] shader: fix convertFromFormat < 32bit handling
This commit is contained in:
parent
00956ce15a
commit
627eabec6d
|
|
@ -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<int>(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<int>(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<std::uint64_t>(1) << (channelSize * 8)) - 1;
|
||||
|
||||
auto uintChannelValue = spirv::cast<spirv::UIntValue>(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<std::uint64_t>(1) << (channelSize * 8 - 1)) - 1;
|
||||
|
||||
auto uintChannelValue = spirv::cast<spirv::SIntValue>(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<spirv::FloatValue>(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<spirv::UIntValue>(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<spirv::SIntValue>(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<std::uint64_t>(1) << (channelSize * 8)) - 1;
|
||||
|
||||
auto uintChannelValue = spirv::cast<spirv::SIntValue>(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<spirv::SIntValue>(channelValue));
|
||||
|
||||
resultType = fragment.context->getSint32Type();
|
||||
}
|
||||
|
||||
result[channel] = channelValue;
|
||||
break;
|
||||
}
|
||||
case kTextureChannelTypeUInt:
|
||||
if (loadType != TypeId::UInt32) {
|
||||
channelValue = fragment.builder.createUConvert(
|
||||
fragment.context->getUInt32Type(),
|
||||
spirv::cast<spirv::UIntValue>(channelValue));
|
||||
|
||||
resultType = fragment.context->getUInt32Type();
|
||||
}
|
||||
|
||||
result[channel] = channelValue;
|
||||
break;
|
||||
|
||||
case kTextureChannelTypeUNorm: {
|
||||
auto maxValue =
|
||||
(static_cast<std::uint64_t>(1) << (channelSize * 8)) - 1;
|
||||
|
||||
auto uintChannelValue = spirv::cast<spirv::UIntValue>(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<std::uint64_t>(1) << (channelSize * 8 - 1)) - 1;
|
||||
|
||||
auto uintChannelValue = spirv::cast<spirv::SIntValue>(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<spirv::FloatValue>(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<spirv::UIntValue>(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<spirv::SIntValue>(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<std::uint64_t>(1) << (channelSize * 8)) - 1;
|
||||
|
||||
auto uintChannelValue = spirv::cast<spirv::SIntValue>(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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue