renderer_vulkan: Use combined image samplers
* Less descriptors = good
This commit is contained in:
@ -47,7 +47,7 @@ template <typename T>
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr bool IsPow2(T value) {
|
||||
return std::has_single_bit(value);
|
||||
return value != 0 && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -64,7 +64,6 @@ bool DecodePNG(std::span<const u8> png_data, std::span<u8> out_data) {
|
||||
if (spng_decoded_image_size(ctx.get(), format, &decoded_len)) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(out_data.size() == decoded_len);
|
||||
|
||||
if (spng_decode_image(ctx.get(), out_data.data(), decoded_len, format, 0)) {
|
||||
return false;
|
||||
|
@ -18,9 +18,8 @@ layout (push_constant, std140) uniform DrawInfo {
|
||||
int reverse_interlaced;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform texture2D screen_textures[3];
|
||||
layout (set = 0, binding = 1) uniform sampler screen_sampler;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
|
||||
void main() {
|
||||
color = texture(sampler2D(screen_textures[screen_id_l], screen_sampler), frag_tex_coord);
|
||||
}
|
||||
color = texture(screen_textures[screen_id_l], frag_tex_coord);
|
||||
}
|
||||
|
@ -30,11 +30,10 @@ layout (push_constant, std140) uniform DrawInfo {
|
||||
int reverse_interlaced;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform texture2D screen_textures[3];
|
||||
layout (set = 0, binding = 1) uniform sampler screen_sampler;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
|
||||
void main() {
|
||||
vec4 color_tex_l = texture(sampler2D(screen_textures[screen_id_l], screen_sampler), frag_tex_coord);
|
||||
vec4 color_tex_r = texture(sampler2D(screen_textures[screen_id_r], screen_sampler), frag_tex_coord);
|
||||
vec4 color_tex_l = texture(screen_textures[screen_id_l], frag_tex_coord);
|
||||
vec4 color_tex_r = texture(screen_textures[screen_id_r], frag_tex_coord);
|
||||
color = vec4(color_tex_l.rgb*l+color_tex_r.rgb*r, color_tex_l.a);
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,12 @@ layout (push_constant, std140) uniform DrawInfo {
|
||||
int reverse_interlaced;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform texture2D screen_textures[3];
|
||||
layout (set = 0, binding = 1) uniform sampler screen_sampler;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
|
||||
void main() {
|
||||
float screen_row = o_resolution.x * frag_tex_coord.x;
|
||||
if (int(screen_row) % 2 == reverse_interlaced)
|
||||
color = texture(sampler2D(screen_textures[screen_id_l], screen_sampler), frag_tex_coord);
|
||||
color = texture(screen_textures[screen_id_l], frag_tex_coord);
|
||||
else
|
||||
color = texture(sampler2D(screen_textures[screen_id_r], screen_sampler), frag_tex_coord);
|
||||
}
|
||||
color = texture(screen_textures[screen_id_r], frag_tex_coord);
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ void CustomTexManager::DecodeToStaging(const Texture& texture, const StagingData
|
||||
}
|
||||
if (compatibility_mode) {
|
||||
const u32 stride = texture.width * 4;
|
||||
// FlipTexture(staging.mapped, texture.width, texture.height, stride);
|
||||
FlipTexture(staging.mapped, texture.width, texture.height, stride);
|
||||
}
|
||||
break;
|
||||
case CustomFileFormat::DDS:
|
||||
|
@ -1538,7 +1538,7 @@ do {
|
||||
}
|
||||
|
||||
out += '}';
|
||||
|
||||
LOG_INFO(Render_OpenGL, "{}", out);
|
||||
return {std::move(out)};
|
||||
}
|
||||
|
||||
|
@ -226,11 +226,11 @@ void RendererVulkan::BeginRendering(Frame* frame) {
|
||||
for (std::size_t i = 0; i < screen_infos.size(); i++) {
|
||||
const auto& info = screen_infos[i];
|
||||
present_textures[i] = vk::DescriptorImageInfo{
|
||||
.sampler = present_samplers[current_sampler],
|
||||
.imageView = info.image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
}
|
||||
present_textures[3].sampler = present_samplers[current_sampler];
|
||||
|
||||
vk::DescriptorSet set = desc_manager.AllocateSet(present_descriptor_layout);
|
||||
instance.GetDevice().updateDescriptorSetWithTemplate(set, present_update_template,
|
||||
@ -320,51 +320,33 @@ void RendererVulkan::CompileShaders() {
|
||||
}
|
||||
|
||||
void RendererVulkan::BuildLayouts() {
|
||||
const std::array present_layout_bindings = {
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = 3,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
},
|
||||
vk::DescriptorSetLayoutBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
},
|
||||
const vk::DescriptorSetLayoutBinding present_layout_binding = {
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||
.descriptorCount = 3,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
};
|
||||
|
||||
const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
|
||||
.bindingCount = static_cast<u32>(present_layout_bindings.size()),
|
||||
.pBindings = present_layout_bindings.data(),
|
||||
.bindingCount = 1,
|
||||
.pBindings = &present_layout_binding,
|
||||
};
|
||||
|
||||
const vk::Device device = instance.GetDevice();
|
||||
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
|
||||
|
||||
const std::array update_template_entries = {
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 3,
|
||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo),
|
||||
},
|
||||
vk::DescriptorUpdateTemplateEntry{
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.offset = 3 * sizeof(vk::DescriptorImageInfo),
|
||||
.stride = 0,
|
||||
},
|
||||
const vk::DescriptorUpdateTemplateEntry update_template_entry = {
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 3,
|
||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||
.offset = 0,
|
||||
.stride = sizeof(vk::DescriptorImageInfo),
|
||||
};
|
||||
|
||||
const vk::DescriptorUpdateTemplateCreateInfo template_info = {
|
||||
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()),
|
||||
.pDescriptorUpdateEntries = update_template_entries.data(),
|
||||
.descriptorUpdateEntryCount = 1,
|
||||
.pDescriptorUpdateEntries = &update_template_entry,
|
||||
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
|
||||
.descriptorSetLayout = present_descriptor_layout,
|
||||
};
|
||||
|
@ -165,7 +165,7 @@ private:
|
||||
|
||||
/// Display information for top and bottom screens respectively
|
||||
std::array<ScreenInfo, 3> screen_infos{};
|
||||
std::array<vk::DescriptorImageInfo, 4> present_textures{};
|
||||
std::array<vk::DescriptorImageInfo, 3> present_textures{};
|
||||
PresentUniformData draw_info{};
|
||||
vk::ClearColorValue clear_color{};
|
||||
};
|
||||
|
@ -31,21 +31,10 @@ constexpr static std::array RASTERIZER_SETS = {
|
||||
// Texture set
|
||||
.bindings =
|
||||
{
|
||||
vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage,
|
||||
vk::DescriptorType::eSampledImage,
|
||||
},
|
||||
.binding_count = 4,
|
||||
},
|
||||
Bindings{
|
||||
// Sampler set
|
||||
.bindings =
|
||||
{
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eSampler,
|
||||
vk::DescriptorType::eCombinedImageSampler,
|
||||
vk::DescriptorType::eCombinedImageSampler,
|
||||
vk::DescriptorType::eCombinedImageSampler,
|
||||
vk::DescriptorType::eCombinedImageSampler,
|
||||
},
|
||||
.binding_count = 4,
|
||||
},
|
||||
@ -76,6 +65,7 @@ constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
|
||||
switch (type) {
|
||||
case vk::DescriptorType::eSampler:
|
||||
case vk::DescriptorType::eSampledImage:
|
||||
case vk::DescriptorType::eCombinedImageSampler:
|
||||
case vk::DescriptorType::eUniformTexelBuffer:
|
||||
case vk::DescriptorType::eStorageImage:
|
||||
flags = vk::ShaderStageFlagBits::eFragment;
|
||||
|
@ -9,8 +9,8 @@
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
constexpr u32 MAX_DESCRIPTORS = 8;
|
||||
constexpr u32 MAX_DESCRIPTOR_SETS = 4;
|
||||
constexpr u32 MAX_DESCRIPTORS = 7;
|
||||
constexpr u32 MAX_DESCRIPTOR_SETS = 3;
|
||||
|
||||
union DescriptorData {
|
||||
vk::DescriptorImageInfo image_info;
|
||||
|
@ -635,8 +635,9 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
|
||||
shader_hashes[ProgramType::FS] = config.Hash();
|
||||
}
|
||||
|
||||
void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) {
|
||||
void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view, vk::Sampler sampler) {
|
||||
const vk::DescriptorImageInfo image_info = {
|
||||
.sampler = sampler,
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
@ -648,7 +649,7 @@ void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
|
||||
.imageView = image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
desc_manager.SetBinding(3, binding, DescriptorData{image_info});
|
||||
desc_manager.SetBinding(2, binding, DescriptorData{image_info});
|
||||
}
|
||||
|
||||
void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) {
|
||||
@ -670,16 +671,6 @@ void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) {
|
||||
desc_manager.SetBinding(0, binding, data);
|
||||
}
|
||||
|
||||
void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) {
|
||||
const DescriptorData data = {
|
||||
.image_info =
|
||||
vk::DescriptorImageInfo{
|
||||
.sampler = sampler,
|
||||
},
|
||||
};
|
||||
desc_manager.SetBinding(2, binding, data);
|
||||
}
|
||||
|
||||
void PipelineCache::ApplyDynamic(const PipelineInfo& info, bool is_dirty) {
|
||||
scheduler.Record([is_dirty, current_dynamic = current_info.dynamic,
|
||||
dynamic = info.dynamic](vk::CommandBuffer cmdbuf) {
|
||||
|
@ -204,7 +204,7 @@ public:
|
||||
void UseFragmentShader(const Pica::Regs& regs);
|
||||
|
||||
/// Binds a texture to the specified binding
|
||||
void BindTexture(u32 binding, vk::ImageView image_view);
|
||||
void BindTexture(u32 binding, vk::ImageView image_view, vk::Sampler sampler);
|
||||
|
||||
/// Binds a storage image to the specified binding
|
||||
void BindStorageImage(u32 binding, vk::ImageView image_view);
|
||||
@ -215,9 +215,6 @@ public:
|
||||
/// Binds a buffer to the specified binding
|
||||
void BindTexelBuffer(u32 binding, vk::BufferView buffer_view);
|
||||
|
||||
/// Binds a sampler to the specified binding
|
||||
void BindSampler(u32 binding, vk::Sampler sampler);
|
||||
|
||||
private:
|
||||
/// Applies dynamic pipeline state to the current command buffer
|
||||
void ApplyDynamic(const PipelineInfo& info, bool is_dirty);
|
||||
|
@ -129,8 +129,7 @@ RasterizerVulkan::RasterizerVulkan(Memory::MemorySystem& memory,
|
||||
|
||||
const Sampler& null_sampler = res_cache.GetSampler(VideoCore::NULL_SAMPLER_ID);
|
||||
for (u32 i = 0; i < 4; i++) {
|
||||
pipeline_cache.BindTexture(i, null_surface.ImageView());
|
||||
pipeline_cache.BindSampler(i, null_sampler.Handle());
|
||||
pipeline_cache.BindTexture(i, null_surface.ImageView(), null_sampler.Handle());
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < 7; i++) {
|
||||
@ -629,12 +628,10 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
|
||||
|
||||
auto surface = res_cache.GetTextureCube(config);
|
||||
if (surface) {
|
||||
pipeline_cache.BindTexture(3, surface->ImageView());
|
||||
pipeline_cache.BindTexture(3, surface->ImageView(), sampler.Handle());
|
||||
} else {
|
||||
pipeline_cache.BindTexture(3, null_surface.ImageView());
|
||||
pipeline_cache.BindTexture(3, null_surface.ImageView(), sampler.Handle());
|
||||
}
|
||||
|
||||
pipeline_cache.BindSampler(3, sampler.Handle());
|
||||
continue; // Texture unit 0 setup finished. Continue to next unit
|
||||
}
|
||||
default:
|
||||
@ -642,8 +639,6 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
|
||||
}
|
||||
}
|
||||
|
||||
pipeline_cache.BindSampler(texture_index, sampler.Handle());
|
||||
|
||||
auto surface = res_cache.GetTextureSurface(texture);
|
||||
if (surface) {
|
||||
if (color_view == surface->ImageView()) {
|
||||
@ -658,9 +653,10 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
|
||||
.extent = {temp.GetScaledWidth(), temp.GetScaledHeight()},
|
||||
};
|
||||
runtime.CopyTextures(static_cast<Surface&>(*framebuffer.Color()), temp, copy);
|
||||
pipeline_cache.BindTexture(texture_index, temp.ImageView());
|
||||
pipeline_cache.BindTexture(texture_index, temp.ImageView(), sampler.Handle());
|
||||
} else {
|
||||
pipeline_cache.BindTexture(texture_index, surface->ImageView());
|
||||
pipeline_cache.BindTexture(texture_index, surface->ImageView(),
|
||||
sampler.Handle());
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -671,12 +667,13 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
|
||||
// the geometry in question.
|
||||
// For example: a bug in Pokemon X/Y causes NULL-texture squares to be drawn
|
||||
// on the male character's face, which in the OpenGL default appear black.
|
||||
pipeline_cache.BindTexture(texture_index, null_surface.ImageView());
|
||||
pipeline_cache.BindTexture(texture_index, null_surface.ImageView(),
|
||||
sampler.Handle());
|
||||
}
|
||||
} else {
|
||||
const Sampler& null_sampler = res_cache.GetSampler(VideoCore::NULL_SAMPLER_ID);
|
||||
pipeline_cache.BindTexture(texture_index, null_surface.ImageView());
|
||||
pipeline_cache.BindSampler(texture_index, null_sampler.Handle());
|
||||
pipeline_cache.BindTexture(texture_index, null_surface.ImageView(),
|
||||
null_sampler.Handle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,11 +128,10 @@ void DescriptorPool::Allocate(std::size_t begin, std::size_t end) {
|
||||
vk::DescriptorPool& pool = pools.emplace_back();
|
||||
|
||||
// Choose a sane pool size good for most games
|
||||
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {{
|
||||
{vk::DescriptorType::eUniformBuffer, 4096},
|
||||
{vk::DescriptorType::eSampledImage, 4096},
|
||||
{vk::DescriptorType::eSampler, 4096},
|
||||
{vk::DescriptorType::eUniformTexelBuffer, 2048},
|
||||
static constexpr std::array<vk::DescriptorPoolSize, 4> pool_sizes = {{
|
||||
{vk::DescriptorType::eUniformBuffer, 1024},
|
||||
{vk::DescriptorType::eCombinedImageSampler, 2048},
|
||||
{vk::DescriptorType::eUniformTexelBuffer, 1024},
|
||||
{vk::DescriptorType::eStorageImage, 1024},
|
||||
}};
|
||||
|
||||
|
@ -289,13 +289,13 @@ static std::string SampleTexture(const PicaFSConfig& config, unsigned texture_un
|
||||
// Only unit 0 respects the texturing type
|
||||
switch (state.texture0_type) {
|
||||
case TexturingRegs::TextureConfig::Texture2D:
|
||||
return "textureLod(sampler2D(tex0, tex0_sampler), texcoord0, getLod(texcoord0 * "
|
||||
"vec2(textureSize(sampler2D(tex0, tex0_sampler), 0))) + tex_lod_bias[0])";
|
||||
return "textureLod(tex0, texcoord0, getLod(texcoord0 * "
|
||||
"vec2(textureSize(tex0, 0))) + tex_lod_bias[0])";
|
||||
case TexturingRegs::TextureConfig::Projection2D:
|
||||
// TODO (wwylele): find the exact LOD formula for projection texture
|
||||
return "textureProj(sampler2D(tex0, tex0_sampler), vec3(texcoord0, texcoord0_w))";
|
||||
return "textureProj(tex0, vec3(texcoord0, texcoord0_w))";
|
||||
case TexturingRegs::TextureConfig::TextureCube:
|
||||
return "texture(samplerCube(tex_cube, tex_cube_sampler), vec3(texcoord0, texcoord0_w))";
|
||||
return "texture(tex_cube, vec3(texcoord0, texcoord0_w))";
|
||||
case TexturingRegs::TextureConfig::Shadow2D:
|
||||
return "shadowTexture(texcoord0, texcoord0_w)";
|
||||
case TexturingRegs::TextureConfig::ShadowCube:
|
||||
@ -305,18 +305,18 @@ static std::string SampleTexture(const PicaFSConfig& config, unsigned texture_un
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled texture type {:x}", state.texture0_type);
|
||||
UNIMPLEMENTED();
|
||||
return "texture(sampler2D(tex0, tex0_sampler), texcoord0)";
|
||||
return "texture(tex0, texcoord0)";
|
||||
}
|
||||
case 1:
|
||||
return "textureLod(sampler2D(tex1, tex1_sampler), texcoord1, getLod(texcoord1 * "
|
||||
"vec2(textureSize(sampler2D(tex1, tex1_sampler), 0))) + tex_lod_bias[1])";
|
||||
return "textureLod(tex1, texcoord1, getLod(texcoord1 * "
|
||||
"vec2(textureSize(tex1, 0))) + tex_lod_bias[1])";
|
||||
case 2:
|
||||
if (state.texture2_use_coord1)
|
||||
return "textureLod(sampler2D(tex2, tex2_sampler), texcoord1, getLod(texcoord1 * "
|
||||
"vec2(textureSize(sampler2D(tex2, tex2_sampler), 0))) + tex_lod_bias[2])";
|
||||
return "textureLod(tex2, texcoord1, getLod(texcoord1 * "
|
||||
"vec2(textureSize(tex2, 0))) + tex_lod_bias[2])";
|
||||
else
|
||||
return "textureLod(sampler2D(tex2, tex2_sampler), texcoord2, getLod(texcoord2 * "
|
||||
"vec2(textureSize(sampler2D(tex2, tex2_sampler), 0))) + tex_lod_bias[2])";
|
||||
return "textureLod(tex2, texcoord2, getLod(texcoord2 * "
|
||||
"vec2(textureSize(tex2, 0))) + tex_lod_bias[2])";
|
||||
case 3:
|
||||
if (state.proctex.enable) {
|
||||
return "ProcTex()";
|
||||
@ -1217,23 +1217,18 @@ layout(set = 0, binding = 2) uniform samplerBuffer texture_buffer_lut_lf;
|
||||
layout(set = 0, binding = 3) uniform samplerBuffer texture_buffer_lut_rg;
|
||||
layout(set = 0, binding = 4) uniform samplerBuffer texture_buffer_lut_rgba;
|
||||
|
||||
layout(set = 1, binding = 0) uniform texture2D tex0;
|
||||
layout(set = 1, binding = 1) uniform texture2D tex1;
|
||||
layout(set = 1, binding = 2) uniform texture2D tex2;
|
||||
layout(set = 1, binding = 3) uniform textureCube tex_cube;
|
||||
layout(set = 1, binding = 0) uniform sampler2D tex0;
|
||||
layout(set = 1, binding = 1) uniform sampler2D tex1;
|
||||
layout(set = 1, binding = 2) uniform sampler2D tex2;
|
||||
layout(set = 1, binding = 3) uniform samplerCube tex_cube;
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler tex0_sampler;
|
||||
layout(set = 2, binding = 1) uniform sampler tex1_sampler;
|
||||
layout(set = 2, binding = 2) uniform sampler tex2_sampler;
|
||||
layout(set = 2, binding = 3) uniform sampler tex_cube_sampler;
|
||||
|
||||
layout(set = 3, binding = 0, r32ui) uniform readonly uimage2D shadow_texture_px;
|
||||
layout(set = 3, binding = 1, r32ui) uniform readonly uimage2D shadow_texture_nx;
|
||||
layout(set = 3, binding = 2, r32ui) uniform readonly uimage2D shadow_texture_py;
|
||||
layout(set = 3, binding = 3, r32ui) uniform readonly uimage2D shadow_texture_ny;
|
||||
layout(set = 3, binding = 4, r32ui) uniform readonly uimage2D shadow_texture_pz;
|
||||
layout(set = 3, binding = 5, r32ui) uniform readonly uimage2D shadow_texture_nz;
|
||||
layout(set = 3, binding = 6, r32ui) uniform uimage2D shadow_buffer;
|
||||
layout(set = 2, binding = 0, r32ui) uniform readonly uimage2D shadow_texture_px;
|
||||
layout(set = 2, binding = 1, r32ui) uniform readonly uimage2D shadow_texture_nx;
|
||||
layout(set = 2, binding = 2, r32ui) uniform readonly uimage2D shadow_texture_py;
|
||||
layout(set = 2, binding = 3, r32ui) uniform readonly uimage2D shadow_texture_ny;
|
||||
layout(set = 2, binding = 4, r32ui) uniform readonly uimage2D shadow_texture_pz;
|
||||
layout(set = 2, binding = 5, r32ui) uniform readonly uimage2D shadow_texture_nz;
|
||||
layout(set = 2, binding = 6, r32ui) uniform uimage2D shadow_buffer;
|
||||
)";
|
||||
|
||||
out += UniformBlockDef;
|
||||
|
@ -667,10 +667,8 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
||||
// This LOD formula is the same as the LOD lower limit defined in OpenGL.
|
||||
// f(x, y) >= max{m_u, m_v, m_w}
|
||||
// (See OpenGL 4.6 spec, 8.14.1 - Scale Factor and Level-of-Detail)
|
||||
const auto SampleLod = [this, texture_unit](Id tex_id, Id tex_sampler_id, Id texcoord_id) {
|
||||
const Id tex{OpLoad(image2d_id, tex_id)};
|
||||
const Id tex_sampler{OpLoad(sampler_id, tex_sampler_id)};
|
||||
const Id sampled_image{OpSampledImage(TypeSampledImage(image2d_id), tex, tex_sampler)};
|
||||
const auto SampleLod = [this, texture_unit](Id tex_id, Id texcoord_id) {
|
||||
const Id sampled_image{OpLoad(TypeSampledImage(image2d_id), tex_id)};
|
||||
const Id tex_image{OpImage(image2d_id, sampled_image)};
|
||||
const Id tex_size{OpImageQuerySizeLod(ivec_ids.Get(2), tex_image, ConstS32(0))};
|
||||
const Id texcoord{OpLoad(vec_ids.Get(2), texcoord_id)};
|
||||
@ -687,11 +685,9 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
||||
spv::ImageOperandsMask::Lod, biased_lod);
|
||||
};
|
||||
|
||||
const auto Sample = [this](Id tex_id, Id tex_sampler_id, bool projection) {
|
||||
const auto Sample = [this](Id tex_id, bool projection) {
|
||||
const Id image_type = tex_id.value == tex_cube_id.value ? image_cube_id : image2d_id;
|
||||
const Id tex{OpLoad(image_type, tex_id)};
|
||||
const Id tex_sampler{OpLoad(sampler_id, tex_sampler_id)};
|
||||
const Id sampled_image{OpSampledImage(TypeSampledImage(image_type), tex, tex_sampler)};
|
||||
const Id sampled_image{OpLoad(TypeSampledImage(image_type), tex_id)};
|
||||
const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)};
|
||||
const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)};
|
||||
const Id coord{OpCompositeConstruct(vec_ids.Get(3),
|
||||
@ -709,11 +705,11 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
||||
// Only unit 0 respects the texturing type
|
||||
switch (state.texture0_type) {
|
||||
case Pica::TexturingRegs::TextureConfig::Texture2D:
|
||||
return SampleLod(tex0_id, tex0_sampler_id, texcoord0_id);
|
||||
return SampleLod(tex0_id, texcoord0_id);
|
||||
case Pica::TexturingRegs::TextureConfig::Projection2D:
|
||||
return Sample(tex0_id, tex0_sampler_id, true);
|
||||
return Sample(tex0_id, true);
|
||||
case Pica::TexturingRegs::TextureConfig::TextureCube:
|
||||
return Sample(tex_cube_id, tex_cube_sampler_id, false);
|
||||
return Sample(tex_cube_id, false);
|
||||
case Pica::TexturingRegs::TextureConfig::Shadow2D:
|
||||
return SampleShadow();
|
||||
// case Pica::TexturingRegs::TextureConfig::ShadowCube:
|
||||
@ -726,12 +722,12 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
|
||||
return zero_vec;
|
||||
}
|
||||
case 1:
|
||||
return SampleLod(tex1_id, tex1_sampler_id, texcoord1_id);
|
||||
return SampleLod(tex1_id, texcoord1_id);
|
||||
case 2:
|
||||
if (state.texture2_use_coord1) {
|
||||
return SampleLod(tex2_id, tex2_sampler_id, texcoord1_id);
|
||||
return SampleLod(tex2_id, texcoord1_id);
|
||||
} else {
|
||||
return SampleLod(tex2_id, tex2_sampler_id, texcoord2_id);
|
||||
return SampleLod(tex2_id, texcoord2_id);
|
||||
}
|
||||
case 3:
|
||||
if (state.proctex.enable) {
|
||||
@ -1445,15 +1441,11 @@ void FragmentModule::DefineInterface() {
|
||||
texture_buffer_lut_lf_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 2);
|
||||
texture_buffer_lut_rg_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 3);
|
||||
texture_buffer_lut_rgba_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 4);
|
||||
tex0_id = DefineUniformConst(image2d_id, 1, 0);
|
||||
tex1_id = DefineUniformConst(image2d_id, 1, 1);
|
||||
tex2_id = DefineUniformConst(image2d_id, 1, 2);
|
||||
tex_cube_id = DefineUniformConst(image_cube_id, 1, 3);
|
||||
tex0_sampler_id = DefineUniformConst(sampler_id, 2, 0);
|
||||
tex1_sampler_id = DefineUniformConst(sampler_id, 2, 1);
|
||||
tex2_sampler_id = DefineUniformConst(sampler_id, 2, 2);
|
||||
tex_cube_sampler_id = DefineUniformConst(sampler_id, 2, 3);
|
||||
shadow_texture_px_id = DefineUniformConst(image_r32_id, 3, 0, true);
|
||||
tex0_id = DefineUniformConst(TypeSampledImage(image2d_id), 1, 0);
|
||||
tex1_id = DefineUniformConst(TypeSampledImage(image2d_id), 1, 1);
|
||||
tex2_id = DefineUniformConst(TypeSampledImage(image2d_id), 1, 2);
|
||||
tex_cube_id = DefineUniformConst(TypeSampledImage(image_cube_id), 1, 3);
|
||||
shadow_texture_px_id = DefineUniformConst(image_r32_id, 2, 0, true);
|
||||
|
||||
// Define built-ins
|
||||
gl_frag_coord_id = DefineVar(vec_ids.Get(4), spv::StorageClass::Input);
|
||||
|
@ -240,10 +240,6 @@ private:
|
||||
Id tex1_id{};
|
||||
Id tex2_id{};
|
||||
Id tex_cube_id{};
|
||||
Id tex0_sampler_id{};
|
||||
Id tex1_sampler_id{};
|
||||
Id tex2_sampler_id{};
|
||||
Id tex_cube_sampler_id{};
|
||||
Id texture_buffer_lut_lf_id{};
|
||||
Id texture_buffer_lut_rg_id{};
|
||||
Id texture_buffer_lut_rgba_id{};
|
||||
|
@ -730,7 +730,6 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
||||
}
|
||||
|
||||
void TextureRuntime::GenerateMipmaps(Surface& surface) {
|
||||
return;
|
||||
if (surface.custom_format != VideoCore::CustomPixelFormat::RGBA8) {
|
||||
LOG_ERROR(Render_Vulkan, "Generating mipmaps for compressed formats unsupported!");
|
||||
return;
|
||||
@ -1338,8 +1337,8 @@ Sampler::Sampler(TextureRuntime& runtime, VideoCore::SamplerParams params)
|
||||
.maxAnisotropy = properties.limits.maxSamplerAnisotropy,
|
||||
.compareEnable = false,
|
||||
.compareOp = vk::CompareOp::eAlways,
|
||||
.minLod = 0.f * lod_min,
|
||||
.maxLod = 0.f * lod_max,
|
||||
.minLod = lod_min,
|
||||
.maxLod = lod_max,
|
||||
.borderColor =
|
||||
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
|
||||
.unnormalizedCoordinates = false,
|
||||
|
Reference in New Issue
Block a user