[GPU] Apply BaseMap MipFilter via samplers as it may be overridden
Make it have no effect on the texture resource as a resource may be used with samplers with different overrides. Also make sure magnification vs. minification is not undefined with it on Direct3D 12.
This commit is contained in:
parent
086a070fa9
commit
2606fa5709
|
@ -971,9 +971,9 @@ D3D12TextureCache::SamplerParameters D3D12TextureCache::GetSamplerParameters(
|
||||||
parameters.border_color = fetch.border_color;
|
parameters.border_color = fetch.border_color;
|
||||||
|
|
||||||
uint32_t mip_min_level;
|
uint32_t mip_min_level;
|
||||||
texture_util::GetSubresourcesFromFetchConstant(
|
texture_util::GetSubresourcesFromFetchConstant(fetch, nullptr, nullptr,
|
||||||
fetch, nullptr, nullptr, nullptr, nullptr, nullptr, &mip_min_level,
|
nullptr, nullptr, nullptr,
|
||||||
nullptr, binding.mip_filter);
|
&mip_min_level, nullptr);
|
||||||
parameters.mip_min_level = mip_min_level;
|
parameters.mip_min_level = mip_min_level;
|
||||||
|
|
||||||
xenos::AnisoFilter aniso_filter =
|
xenos::AnisoFilter aniso_filter =
|
||||||
|
@ -982,6 +982,10 @@ D3D12TextureCache::SamplerParameters D3D12TextureCache::GetSamplerParameters(
|
||||||
: binding.aniso_filter;
|
: binding.aniso_filter;
|
||||||
aniso_filter = std::min(aniso_filter, xenos::AnisoFilter::kMax_16_1);
|
aniso_filter = std::min(aniso_filter, xenos::AnisoFilter::kMax_16_1);
|
||||||
parameters.aniso_filter = aniso_filter;
|
parameters.aniso_filter = aniso_filter;
|
||||||
|
xenos::TextureFilter mip_filter =
|
||||||
|
binding.mip_filter == xenos::TextureFilter::kUseFetchConst
|
||||||
|
? fetch.mip_filter
|
||||||
|
: binding.mip_filter;
|
||||||
if (aniso_filter != xenos::AnisoFilter::kDisabled) {
|
if (aniso_filter != xenos::AnisoFilter::kDisabled) {
|
||||||
parameters.mag_linear = 1;
|
parameters.mag_linear = 1;
|
||||||
parameters.min_linear = 1;
|
parameters.min_linear = 1;
|
||||||
|
@ -997,12 +1001,9 @@ D3D12TextureCache::SamplerParameters D3D12TextureCache::GetSamplerParameters(
|
||||||
? fetch.min_filter
|
? fetch.min_filter
|
||||||
: binding.min_filter;
|
: binding.min_filter;
|
||||||
parameters.min_linear = min_filter == xenos::TextureFilter::kLinear;
|
parameters.min_linear = min_filter == xenos::TextureFilter::kLinear;
|
||||||
xenos::TextureFilter mip_filter =
|
|
||||||
binding.mip_filter == xenos::TextureFilter::kUseFetchConst
|
|
||||||
? fetch.mip_filter
|
|
||||||
: binding.mip_filter;
|
|
||||||
parameters.mip_linear = mip_filter == xenos::TextureFilter::kLinear;
|
parameters.mip_linear = mip_filter == xenos::TextureFilter::kLinear;
|
||||||
}
|
}
|
||||||
|
parameters.mip_base_map = mip_filter == xenos::TextureFilter::kBaseMap;
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1047,7 @@ void D3D12TextureCache::WriteSampler(SamplerParameters parameters,
|
||||||
desc.AddressU = kAddressModeMap[uint32_t(parameters.clamp_x)];
|
desc.AddressU = kAddressModeMap[uint32_t(parameters.clamp_x)];
|
||||||
desc.AddressV = kAddressModeMap[uint32_t(parameters.clamp_y)];
|
desc.AddressV = kAddressModeMap[uint32_t(parameters.clamp_y)];
|
||||||
desc.AddressW = kAddressModeMap[uint32_t(parameters.clamp_z)];
|
desc.AddressW = kAddressModeMap[uint32_t(parameters.clamp_z)];
|
||||||
// LOD is calculated in shaders.
|
// LOD biasing is performed in shaders.
|
||||||
desc.MipLODBias = 0.0f;
|
desc.MipLODBias = 0.0f;
|
||||||
desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
||||||
// TODO(Triang3l): Border colors k_ACBYCR_BLACK and k_ACBCRY_BLACK.
|
// TODO(Triang3l): Border colors k_ACBYCR_BLACK and k_ACBCRY_BLACK.
|
||||||
|
@ -1062,8 +1063,26 @@ void D3D12TextureCache::WriteSampler(SamplerParameters parameters,
|
||||||
desc.BorderColor[3] = 0.0f;
|
desc.BorderColor[3] = 0.0f;
|
||||||
}
|
}
|
||||||
desc.MinLOD = float(parameters.mip_min_level);
|
desc.MinLOD = float(parameters.mip_min_level);
|
||||||
|
if (parameters.mip_base_map) {
|
||||||
|
// "It is undefined whether LOD clamping based on MinLOD and MaxLOD Sampler
|
||||||
|
// states should happen before or after deciding if magnification is
|
||||||
|
// occuring" - Direct3D 11.3 Functional Specification.
|
||||||
|
// Using the GL_NEAREST / GL_LINEAR minification filter emulation logic
|
||||||
|
// described in the Vulkan VkSamplerCreateInfo specification, preserving
|
||||||
|
// magnification vs. minification - point mip sampling (usable only without
|
||||||
|
// anisotropic filtering on Direct3D 12) and MaxLOD 0.25. With anisotropic
|
||||||
|
// filtering, magnification vs. minification doesn't matter as the filter is
|
||||||
|
// always linear for both on Direct3D 12 - but linear filtering specifically
|
||||||
|
// is what must not be done for kBaseMap, so setting MaxLOD to MinLOD.
|
||||||
|
desc.MaxLOD = desc.MinLOD;
|
||||||
|
if (parameters.aniso_filter == xenos::AnisoFilter::kDisabled) {
|
||||||
|
assert_false(parameters.mip_linear);
|
||||||
|
desc.MaxLOD += 0.25f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Maximum mip level is in the texture resource itself.
|
// Maximum mip level is in the texture resource itself.
|
||||||
desc.MaxLOD = FLT_MAX;
|
desc.MaxLOD = FLT_MAX;
|
||||||
|
}
|
||||||
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
|
ID3D12Device* device = command_processor_.GetD3D12Provider().GetDevice();
|
||||||
device->CreateSampler(&desc, handle);
|
device->CreateSampler(&desc, handle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,9 @@ class D3D12TextureCache final : public TextureCache {
|
||||||
uint32_t mip_linear : 1; // 14
|
uint32_t mip_linear : 1; // 14
|
||||||
xenos::AnisoFilter aniso_filter : 3; // 17
|
xenos::AnisoFilter aniso_filter : 3; // 17
|
||||||
uint32_t mip_min_level : 4; // 21
|
uint32_t mip_min_level : 4; // 21
|
||||||
// Maximum mip level is in the texture resource itself.
|
uint32_t mip_base_map : 1; // 22
|
||||||
|
// Maximum mip level is in the texture resource itself, but mip_base_map
|
||||||
|
// can be used to limit fetching to mip_min_level.
|
||||||
};
|
};
|
||||||
|
|
||||||
SamplerParameters() : value(0) { static_assert_size(*this, sizeof(value)); }
|
SamplerParameters() : value(0) { static_assert_size(*this, sizeof(value)); }
|
||||||
|
|
|
@ -23,8 +23,7 @@ void GetSubresourcesFromFetchConstant(
|
||||||
const xenos::xe_gpu_texture_fetch_t& fetch, uint32_t* width_minus_1_out,
|
const xenos::xe_gpu_texture_fetch_t& fetch, uint32_t* width_minus_1_out,
|
||||||
uint32_t* height_minus_1_out, uint32_t* depth_or_array_size_minus_1_out,
|
uint32_t* height_minus_1_out, uint32_t* depth_or_array_size_minus_1_out,
|
||||||
uint32_t* base_page_out, uint32_t* mip_page_out,
|
uint32_t* base_page_out, uint32_t* mip_page_out,
|
||||||
uint32_t* mip_min_level_out, uint32_t* mip_max_level_out,
|
uint32_t* mip_min_level_out, uint32_t* mip_max_level_out) {
|
||||||
xenos::TextureFilter sampler_mip_filter) {
|
|
||||||
uint32_t width_minus_1 = 0;
|
uint32_t width_minus_1 = 0;
|
||||||
uint32_t height_minus_1 = 0;
|
uint32_t height_minus_1 = 0;
|
||||||
uint32_t depth_or_array_size_minus_1 = 0;
|
uint32_t depth_or_array_size_minus_1 = 0;
|
||||||
|
@ -72,16 +71,14 @@ void GetSubresourcesFromFetchConstant(
|
||||||
}
|
}
|
||||||
uint32_t size_mip_max_level =
|
uint32_t size_mip_max_level =
|
||||||
xe::log2_floor(longest_axis_minus_1 + uint32_t(1));
|
xe::log2_floor(longest_axis_minus_1 + uint32_t(1));
|
||||||
xenos::TextureFilter mip_filter =
|
|
||||||
sampler_mip_filter == xenos::TextureFilter::kUseFetchConst
|
|
||||||
? fetch.mip_filter
|
|
||||||
: sampler_mip_filter;
|
|
||||||
|
|
||||||
uint32_t base_page = fetch.base_address & 0x1FFFF;
|
uint32_t base_page = fetch.base_address & 0x1FFFF;
|
||||||
uint32_t mip_page = fetch.mip_address & 0x1FFFF;
|
uint32_t mip_page = fetch.mip_address & 0x1FFFF;
|
||||||
|
|
||||||
uint32_t mip_min_level, mip_max_level;
|
uint32_t mip_min_level, mip_max_level;
|
||||||
if (mip_filter == xenos::TextureFilter::kBaseMap || mip_page == 0) {
|
// Not taking mip_filter == kBaseMap into account for mip_max_level because
|
||||||
|
// the mip filter may be overridden by shader fetch instructions.
|
||||||
|
if (mip_page == 0) {
|
||||||
mip_min_level = 0;
|
mip_min_level = 0;
|
||||||
mip_max_level = 0;
|
mip_max_level = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -30,9 +30,7 @@ void GetSubresourcesFromFetchConstant(
|
||||||
const xenos::xe_gpu_texture_fetch_t& fetch, uint32_t* width_minus_1_out,
|
const xenos::xe_gpu_texture_fetch_t& fetch, uint32_t* width_minus_1_out,
|
||||||
uint32_t* height_minus_1_out, uint32_t* depth_or_array_size_minus_1_out,
|
uint32_t* height_minus_1_out, uint32_t* depth_or_array_size_minus_1_out,
|
||||||
uint32_t* base_page_out, uint32_t* mip_page_out,
|
uint32_t* base_page_out, uint32_t* mip_page_out,
|
||||||
uint32_t* mip_min_level_out, uint32_t* mip_max_level_out,
|
uint32_t* mip_min_level_out, uint32_t* mip_max_level_out);
|
||||||
xenos::TextureFilter sampler_mip_filter =
|
|
||||||
xenos::TextureFilter::kUseFetchConst);
|
|
||||||
|
|
||||||
// Gets the number of the mipmap level where the packed mips are stored.
|
// Gets the number of the mipmap level where the packed mips are stored.
|
||||||
inline uint32_t GetPackedMipLevel(uint32_t width, uint32_t height) {
|
inline uint32_t GetPackedMipLevel(uint32_t width, uint32_t height) {
|
||||||
|
|
|
@ -113,7 +113,9 @@ enum class TextureSign : uint32_t {
|
||||||
enum class TextureFilter : uint32_t {
|
enum class TextureFilter : uint32_t {
|
||||||
kPoint = 0,
|
kPoint = 0,
|
||||||
kLinear = 1,
|
kLinear = 1,
|
||||||
kBaseMap = 2, // Only applicable for mip-filter - always fetch from level 0.
|
// Only applicable to the mip filter - like OpenGL minification filters
|
||||||
|
// GL_NEAREST / GL_LINEAR without MIPMAP_NEAREST / MIPMAP_LINEAR.
|
||||||
|
kBaseMap = 2,
|
||||||
kUseFetchConst = 3,
|
kUseFetchConst = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue