mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 13:26:52 +01:00
shader: apply the LOD clamp of image_sample _cl variants
Co-authored-by: Senaxx <michelbeld@gmail.com>
This commit is contained in:
@@ -337,6 +337,7 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
|||||||
|
|
||||||
check_feature(device_features2.features.shaderImageGatherExtended,
|
check_feature(device_features2.features.shaderImageGatherExtended,
|
||||||
"shaderImageGatherExtended");
|
"shaderImageGatherExtended");
|
||||||
|
check_feature(device_features2.features.shaderResourceMinLod, "shaderResourceMinLod");
|
||||||
|
|
||||||
check_feature(device_features2.features.independentBlend, "independentBlend");
|
check_feature(device_features2.features.independentBlend, "independentBlend");
|
||||||
check_feature(device_features2.features.tessellationShader, "tessellationShader");
|
check_feature(device_features2.features.tessellationShader, "tessellationShader");
|
||||||
@@ -636,6 +637,7 @@ static vk::Device VulkanCreateDevice(GraphicContext& graphics,
|
|||||||
device_features.shaderStorageImageMultisample =
|
device_features.shaderStorageImageMultisample =
|
||||||
supported_features2.features.shaderStorageImageMultisample;
|
supported_features2.features.shaderStorageImageMultisample;
|
||||||
device_features.shaderImageGatherExtended = VK_TRUE;
|
device_features.shaderImageGatherExtended = VK_TRUE;
|
||||||
|
device_features.shaderResourceMinLod = VK_TRUE;
|
||||||
device_features.independentBlend = VK_TRUE;
|
device_features.independentBlend = VK_TRUE;
|
||||||
device_features.dualSrcBlend = VK_TRUE;
|
device_features.dualSrcBlend = VK_TRUE;
|
||||||
device_features.tessellationShader = VK_TRUE;
|
device_features.tessellationShader = VK_TRUE;
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ ImageSampleLayout Layout(const IR::MemoryInfo& mem) {
|
|||||||
layout.coord = cursor;
|
layout.coord = cursor;
|
||||||
cursor += info.coordinate_components;
|
cursor += info.coordinate_components;
|
||||||
if (HasFlag(mem, Decoder::ImageSampleFlagLod)) layout.lod = cursor++;
|
if (HasFlag(mem, Decoder::ImageSampleFlagLod)) layout.lod = cursor++;
|
||||||
|
if (HasFlag(mem, Decoder::ImageSampleFlagLodClamp)) layout.clamp = cursor++;
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,7 +1070,12 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
|||||||
dref_value = AddressF32(ctx, mem, *address, layout.dref);
|
dref_value = AddressF32(ctx, mem, *address, layout.dref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::array<uint32_t, 4> operands {};
|
// _cl clamps the computed LOD from below.
|
||||||
|
uint32_t min_lod = 0;
|
||||||
|
if (layout.clamp != NoImageComponent) {
|
||||||
|
min_lod = AddressF32(ctx, mem, *address, layout.clamp);
|
||||||
|
}
|
||||||
|
std::array<uint32_t, 5> operands {};
|
||||||
size_t operand_count = 0;
|
size_t operand_count = 0;
|
||||||
if (HasFlag(mem, Decoder::ImageSampleFlagDerivative)) {
|
if (HasFlag(mem, Decoder::ImageSampleFlagDerivative)) {
|
||||||
operands[0] = spv::ImageOperandsGradMask;
|
operands[0] = spv::ImageOperandsGradMask;
|
||||||
@@ -1081,6 +1087,11 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
|||||||
if (HasFlag(mem, Decoder::ImageSampleFlagLod) && layout.lod != NoImageComponent) {
|
if (HasFlag(mem, Decoder::ImageSampleFlagLod) && layout.lod != NoImageComponent) {
|
||||||
lod = AddressF32(ctx, mem, *address, layout.lod);
|
lod = AddressF32(ctx, mem, *address, layout.lod);
|
||||||
}
|
}
|
||||||
|
// SPIR-V takes MinLod only with implicit LOD or Grad.
|
||||||
|
if (min_lod != 0) {
|
||||||
|
lod = EmitGlsl<GLSLstd450FMax, IR::Type::F32>(state, lod, min_lod);
|
||||||
|
min_lod = 0;
|
||||||
|
}
|
||||||
operands[0] = spv::ImageOperandsLodMask;
|
operands[0] = spv::ImageOperandsLodMask;
|
||||||
operands[1] = lod;
|
operands[1] = lod;
|
||||||
operand_count = 2;
|
operand_count = 2;
|
||||||
@@ -1104,6 +1115,13 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
|
|||||||
sample_operands[sample_operand_count++] = PackedOffset(
|
sample_operands[sample_operand_count++] = PackedOffset(
|
||||||
ctx, offset_value, candidate.dimension, sample_operands[0]);
|
ctx, offset_value, candidate.dimension, sample_operands[0]);
|
||||||
}
|
}
|
||||||
|
// MinLod follows the offset in operand order.
|
||||||
|
if (min_lod != 0) {
|
||||||
|
state.builder.RequireCapability(spv::CapabilityMinLod);
|
||||||
|
sample_operand_count = std::max(size_t{1}, sample_operand_count);
|
||||||
|
sample_operands[0] |= spv::ImageOperandsMinLodMask;
|
||||||
|
sample_operands[sample_operand_count++] = min_lod;
|
||||||
|
}
|
||||||
const auto coord =
|
const auto coord =
|
||||||
CoordF32(ctx, mem, *address, layout.coord,
|
CoordF32(ctx, mem, *address, layout.coord,
|
||||||
ImageDimensionInfoFor(candidate.dimension).coordinate_components,
|
ImageDimensionInfoFor(candidate.dimension).coordinate_components,
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ struct ImageSampleLayout {
|
|||||||
uint32_t bias = NoImageComponent;
|
uint32_t bias = NoImageComponent;
|
||||||
uint32_t coord = 0;
|
uint32_t coord = 0;
|
||||||
uint32_t lod = NoImageComponent;
|
uint32_t lod = NoImageComponent;
|
||||||
|
uint32_t clamp = NoImageComponent;
|
||||||
uint32_t grad_x = NoImageComponent;
|
uint32_t grad_x = NoImageComponent;
|
||||||
uint32_t grad_y = NoImageComponent;
|
uint32_t grad_y = NoImageComponent;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ constexpr uint32_t ImageSampleAddressComponents(uint32_t flags, ImageDimension d
|
|||||||
if ((flags & ImageSampleFlagBias) != 0) {
|
if ((flags & ImageSampleFlagBias) != 0) {
|
||||||
components++;
|
components++;
|
||||||
}
|
}
|
||||||
if ((flags & ImageSampleFlagLod) != 0) {
|
if ((flags & (ImageSampleFlagLod | ImageSampleFlagLodClamp)) != 0) {
|
||||||
components++;
|
components++;
|
||||||
}
|
}
|
||||||
if ((flags & ImageSampleFlagDerivative) != 0) {
|
if ((flags & ImageSampleFlagDerivative) != 0) {
|
||||||
|
|||||||
@@ -21559,8 +21559,9 @@ private:
|
|||||||
"shaderStorageImageWriteWithoutFormat is not supported");
|
"shaderStorageImageWriteWithoutFormat is not supported");
|
||||||
Require("VulkanHarness", "dispatch",
|
Require("VulkanHarness", "dispatch",
|
||||||
available_features.shaderImageGatherExtended == true &&
|
available_features.shaderImageGatherExtended == true &&
|
||||||
|
available_features.shaderResourceMinLod == true &&
|
||||||
available_derivatives.computeDerivativeGroupQuads == true,
|
available_derivatives.computeDerivativeGroupQuads == true,
|
||||||
"image gather or compute derivative quads are not supported");
|
"image gather, MinLod or compute derivative quads are not supported");
|
||||||
Require("VulkanHarness", "dispatch",
|
Require("VulkanHarness", "dispatch",
|
||||||
available_features11.storageBuffer16BitAccess == true &&
|
available_features11.storageBuffer16BitAccess == true &&
|
||||||
available_features12.storageBuffer8BitAccess == true,
|
available_features12.storageBuffer8BitAccess == true,
|
||||||
@@ -21694,6 +21695,7 @@ private:
|
|||||||
device_features.shaderStorageImageWriteWithoutFormat = true;
|
device_features.shaderStorageImageWriteWithoutFormat = true;
|
||||||
device_features.shaderStorageImageMultisample = available_features.shaderStorageImageMultisample;
|
device_features.shaderStorageImageMultisample = available_features.shaderStorageImageMultisample;
|
||||||
device_features.shaderImageGatherExtended = true;
|
device_features.shaderImageGatherExtended = true;
|
||||||
|
device_features.shaderResourceMinLod = true;
|
||||||
device_features.sampleRateShading = true;
|
device_features.sampleRateShading = true;
|
||||||
device_features.shaderInt64 = true;
|
device_features.shaderInt64 = true;
|
||||||
device_features.shaderFloat64 = available_features.shaderFloat64;
|
device_features.shaderFloat64 = available_features.shaderFloat64;
|
||||||
@@ -39224,6 +39226,48 @@ TestCase ImageGatherExplicitLod() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ImageSampleLodClamp() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
// _cl clamps the computed LOD from below: compute's implicit LOD and zero
|
||||||
|
// derivatives would both select mip 0, so a clamp of 1 must read mip 1.
|
||||||
|
std::vector<u32> code;
|
||||||
|
AppendVMovU32(&code, 20, 0);
|
||||||
|
AppendVMovU32(&code, 21, 0);
|
||||||
|
AppendVMovU32(&code, 22, 0);
|
||||||
|
AppendVMovU32(&code, 23, 0);
|
||||||
|
AppendVMovLiteral(&code, 24, 0x3f000000u);
|
||||||
|
AppendVMovLiteral(&code, 25, 0x3f000000u);
|
||||||
|
AppendVMovLiteral(&code, 26, 0x3f800000u);
|
||||||
|
code.push_back(EncodeMimg0(0x21, 0x1));
|
||||||
|
code.push_back(EncodeMimg1(0, 24, 0, 2));
|
||||||
|
code.push_back(EncodeMimg0(0x23, 0x1));
|
||||||
|
code.push_back(EncodeMimg1(1, 20, 0, 2));
|
||||||
|
AppendStoreVgpr(&code, 0, 0);
|
||||||
|
AppendStoreVgpr(&code, 1, 1);
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test;
|
||||||
|
test.name = "ImageSampleLodClamp";
|
||||||
|
test.code = std::move(code);
|
||||||
|
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
|
test.expected = std::vector<u32>(2, 0x41000000u);
|
||||||
|
test.sampled_image_rgba_mips = {std::vector<u32>(4 * 4 * 4, 0x3f800000u),
|
||||||
|
std::vector<u32>(2 * 2 * 4, 0x41000000u)};
|
||||||
|
test.user_data = MakeSampledTextureData(Prospero::BufferFormat::k32_32_32_32Float);
|
||||||
|
test.user_data[1] |= 3u << 30u;
|
||||||
|
test.user_data[2] = 3u << 14u;
|
||||||
|
test.user_data[3] |= 1u << 16u;
|
||||||
|
test.user_data[8] = 0x92u;
|
||||||
|
test.user_data[9] = 0xfff000u;
|
||||||
|
test.user_data[10] = 0x05000000u;
|
||||||
|
test.user_data[50] = test.expected.size() * sizeof(u32);
|
||||||
|
test.user_data[51] = 3u << 28u;
|
||||||
|
test.has_user_data = true;
|
||||||
|
test.required_spirv = {"MinLod"};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
template <u32 mode> TestCase ImageGatherLodPerLane() {
|
template <u32 mode> TestCase ImageGatherLodPerLane() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
constexpr std::array names{
|
constexpr std::array names{
|
||||||
@@ -44788,6 +44832,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ImageSampleAndGather);
|
AddCase(ImageSampleAndGather);
|
||||||
AddCase(ImageCubeGradientsPreserveDerivatives);
|
AddCase(ImageCubeGradientsPreserveDerivatives);
|
||||||
AddCase(ImageGatherExplicitLod);
|
AddCase(ImageGatherExplicitLod);
|
||||||
|
AddCase(ImageSampleLodClamp);
|
||||||
AddCase(ImageGatherLodPerLane<0>);
|
AddCase(ImageGatherLodPerLane<0>);
|
||||||
AddCase(ImageGatherLodPerLane<1>);
|
AddCase(ImageGatherLodPerLane<1>);
|
||||||
AddCase(ImageGatherLodPerLane<2>);
|
AddCase(ImageGatherLodPerLane<2>);
|
||||||
@@ -51205,6 +51250,7 @@ int main(int argc, char **argv) {
|
|||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
vulkan.CheckComparisonDepthTexture();
|
vulkan.CheckComparisonDepthTexture();
|
||||||
RunCase(&vulkan, ImageGatherExplicitLod());
|
RunCase(&vulkan, ImageGatherExplicitLod());
|
||||||
|
RunCase(&vulkan, ImageSampleLodClamp());
|
||||||
RunCase(&vulkan, ImageGatherLodPerLane<0>());
|
RunCase(&vulkan, ImageGatherLodPerLane<0>());
|
||||||
RunCase(&vulkan, ImageGatherLodPerLane<1>());
|
RunCase(&vulkan, ImageGatherLodPerLane<1>());
|
||||||
RunCase(&vulkan, ImageGatherLodPerLane<2>());
|
RunCase(&vulkan, ImageGatherLodPerLane<2>());
|
||||||
|
|||||||
Reference in New Issue
Block a user