renderer_vulkan: Use combined image samplers

* Less descriptors = good
This commit is contained in:
GPUCode
2023-02-23 17:18:15 +02:00
parent 52683adedd
commit 8e8097e7c0
19 changed files with 96 additions and 162 deletions

View File

@ -47,7 +47,7 @@ template <typename T>
template <typename T> template <typename T>
requires std::is_unsigned_v<T> requires std::is_unsigned_v<T>
[[nodiscard]] constexpr bool IsPow2(T value) { [[nodiscard]] constexpr bool IsPow2(T value) {
return std::has_single_bit(value); return value != 0 && (value & (value - 1)) == 0;
} }
template <typename T> template <typename T>

View File

@ -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)) { if (spng_decoded_image_size(ctx.get(), format, &decoded_len)) {
return false; return false;
} }
ASSERT(out_data.size() == decoded_len);
if (spng_decode_image(ctx.get(), out_data.data(), decoded_len, format, 0)) { if (spng_decode_image(ctx.get(), out_data.data(), decoded_len, format, 0)) {
return false; return false;

View File

@ -18,9 +18,8 @@ layout (push_constant, std140) uniform DrawInfo {
int reverse_interlaced; int reverse_interlaced;
}; };
layout (set = 0, binding = 0) uniform texture2D screen_textures[3]; layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
layout (set = 0, binding = 1) uniform sampler screen_sampler;
void main() { 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);
} }

View File

@ -30,11 +30,10 @@ layout (push_constant, std140) uniform DrawInfo {
int reverse_interlaced; int reverse_interlaced;
}; };
layout (set = 0, binding = 0) uniform texture2D screen_textures[3]; layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
layout (set = 0, binding = 1) uniform sampler screen_sampler;
void main() { void main() {
vec4 color_tex_l = texture(sampler2D(screen_textures[screen_id_l], screen_sampler), frag_tex_coord); vec4 color_tex_l = texture(screen_textures[screen_id_l], frag_tex_coord);
vec4 color_tex_r = texture(sampler2D(screen_textures[screen_id_r], screen_sampler), 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); color = vec4(color_tex_l.rgb*l+color_tex_r.rgb*r, color_tex_l.a);
} }

View File

@ -18,13 +18,12 @@ layout (push_constant, std140) uniform DrawInfo {
int reverse_interlaced; int reverse_interlaced;
}; };
layout (set = 0, binding = 0) uniform texture2D screen_textures[3]; layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
layout (set = 0, binding = 1) uniform sampler screen_sampler;
void main() { void main() {
float screen_row = o_resolution.x * frag_tex_coord.x; float screen_row = o_resolution.x * frag_tex_coord.x;
if (int(screen_row) % 2 == reverse_interlaced) 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 else
color = texture(sampler2D(screen_textures[screen_id_r], screen_sampler), frag_tex_coord); color = texture(screen_textures[screen_id_r], frag_tex_coord);
} }

View File

@ -204,7 +204,7 @@ void CustomTexManager::DecodeToStaging(const Texture& texture, const StagingData
} }
if (compatibility_mode) { if (compatibility_mode) {
const u32 stride = texture.width * 4; const u32 stride = texture.width * 4;
// FlipTexture(staging.mapped, texture.width, texture.height, stride); FlipTexture(staging.mapped, texture.width, texture.height, stride);
} }
break; break;
case CustomFileFormat::DDS: case CustomFileFormat::DDS:

View File

@ -1538,7 +1538,7 @@ do {
} }
out += '}'; out += '}';
LOG_INFO(Render_OpenGL, "{}", out);
return {std::move(out)}; return {std::move(out)};
} }

View File

@ -226,11 +226,11 @@ void RendererVulkan::BeginRendering(Frame* frame) {
for (std::size_t i = 0; i < screen_infos.size(); i++) { for (std::size_t i = 0; i < screen_infos.size(); i++) {
const auto& info = screen_infos[i]; const auto& info = screen_infos[i];
present_textures[i] = vk::DescriptorImageInfo{ present_textures[i] = vk::DescriptorImageInfo{
.sampler = present_samplers[current_sampler],
.imageView = info.image_view, .imageView = info.image_view,
.imageLayout = vk::ImageLayout::eGeneral, .imageLayout = vk::ImageLayout::eGeneral,
}; };
} }
present_textures[3].sampler = present_samplers[current_sampler];
vk::DescriptorSet set = desc_manager.AllocateSet(present_descriptor_layout); vk::DescriptorSet set = desc_manager.AllocateSet(present_descriptor_layout);
instance.GetDevice().updateDescriptorSetWithTemplate(set, present_update_template, instance.GetDevice().updateDescriptorSetWithTemplate(set, present_update_template,
@ -320,51 +320,33 @@ void RendererVulkan::CompileShaders() {
} }
void RendererVulkan::BuildLayouts() { void RendererVulkan::BuildLayouts() {
const std::array present_layout_bindings = { const vk::DescriptorSetLayoutBinding present_layout_binding = {
vk::DescriptorSetLayoutBinding{ .binding = 0,
.binding = 0, .descriptorType = vk::DescriptorType::eCombinedImageSampler,
.descriptorType = vk::DescriptorType::eSampledImage, .descriptorCount = 3,
.descriptorCount = 3, .stageFlags = vk::ShaderStageFlagBits::eFragment,
.stageFlags = vk::ShaderStageFlagBits::eFragment,
},
vk::DescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = vk::DescriptorType::eSampler,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eFragment,
},
}; };
const vk::DescriptorSetLayoutCreateInfo present_layout_info = { const vk::DescriptorSetLayoutCreateInfo present_layout_info = {
.bindingCount = static_cast<u32>(present_layout_bindings.size()), .bindingCount = 1,
.pBindings = present_layout_bindings.data(), .pBindings = &present_layout_binding,
}; };
const vk::Device device = instance.GetDevice(); const vk::Device device = instance.GetDevice();
present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info); present_descriptor_layout = device.createDescriptorSetLayout(present_layout_info);
const std::array update_template_entries = { const vk::DescriptorUpdateTemplateEntry update_template_entry = {
vk::DescriptorUpdateTemplateEntry{ .dstBinding = 0,
.dstBinding = 0, .dstArrayElement = 0,
.dstArrayElement = 0, .descriptorCount = 3,
.descriptorCount = 3, .descriptorType = vk::DescriptorType::eCombinedImageSampler,
.descriptorType = vk::DescriptorType::eSampledImage, .offset = 0,
.offset = 0, .stride = sizeof(vk::DescriptorImageInfo),
.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::DescriptorUpdateTemplateCreateInfo template_info = { const vk::DescriptorUpdateTemplateCreateInfo template_info = {
.descriptorUpdateEntryCount = static_cast<u32>(update_template_entries.size()), .descriptorUpdateEntryCount = 1,
.pDescriptorUpdateEntries = update_template_entries.data(), .pDescriptorUpdateEntries = &update_template_entry,
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = present_descriptor_layout, .descriptorSetLayout = present_descriptor_layout,
}; };

View File

@ -165,7 +165,7 @@ private:
/// Display information for top and bottom screens respectively /// Display information for top and bottom screens respectively
std::array<ScreenInfo, 3> screen_infos{}; std::array<ScreenInfo, 3> screen_infos{};
std::array<vk::DescriptorImageInfo, 4> present_textures{}; std::array<vk::DescriptorImageInfo, 3> present_textures{};
PresentUniformData draw_info{}; PresentUniformData draw_info{};
vk::ClearColorValue clear_color{}; vk::ClearColorValue clear_color{};
}; };

View File

@ -31,21 +31,10 @@ constexpr static std::array RASTERIZER_SETS = {
// Texture set // Texture set
.bindings = .bindings =
{ {
vk::DescriptorType::eSampledImage, vk::DescriptorType::eCombinedImageSampler,
vk::DescriptorType::eSampledImage, vk::DescriptorType::eCombinedImageSampler,
vk::DescriptorType::eSampledImage, vk::DescriptorType::eCombinedImageSampler,
vk::DescriptorType::eSampledImage, vk::DescriptorType::eCombinedImageSampler,
},
.binding_count = 4,
},
Bindings{
// Sampler set
.bindings =
{
vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler,
vk::DescriptorType::eSampler,
}, },
.binding_count = 4, .binding_count = 4,
}, },
@ -76,6 +65,7 @@ constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) {
switch (type) { switch (type) {
case vk::DescriptorType::eSampler: case vk::DescriptorType::eSampler:
case vk::DescriptorType::eSampledImage: case vk::DescriptorType::eSampledImage:
case vk::DescriptorType::eCombinedImageSampler:
case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eUniformTexelBuffer:
case vk::DescriptorType::eStorageImage: case vk::DescriptorType::eStorageImage:
flags = vk::ShaderStageFlagBits::eFragment; flags = vk::ShaderStageFlagBits::eFragment;

View File

@ -9,8 +9,8 @@
namespace Vulkan { namespace Vulkan {
constexpr u32 MAX_DESCRIPTORS = 8; constexpr u32 MAX_DESCRIPTORS = 7;
constexpr u32 MAX_DESCRIPTOR_SETS = 4; constexpr u32 MAX_DESCRIPTOR_SETS = 3;
union DescriptorData { union DescriptorData {
vk::DescriptorImageInfo image_info; vk::DescriptorImageInfo image_info;

View File

@ -635,8 +635,9 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
shader_hashes[ProgramType::FS] = config.Hash(); 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 = { const vk::DescriptorImageInfo image_info = {
.sampler = sampler,
.imageView = image_view, .imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral, .imageLayout = vk::ImageLayout::eGeneral,
}; };
@ -648,7 +649,7 @@ void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) {
.imageView = image_view, .imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral, .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) { 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); 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) { void PipelineCache::ApplyDynamic(const PipelineInfo& info, bool is_dirty) {
scheduler.Record([is_dirty, current_dynamic = current_info.dynamic, scheduler.Record([is_dirty, current_dynamic = current_info.dynamic,
dynamic = info.dynamic](vk::CommandBuffer cmdbuf) { dynamic = info.dynamic](vk::CommandBuffer cmdbuf) {

View File

@ -204,7 +204,7 @@ public:
void UseFragmentShader(const Pica::Regs& regs); void UseFragmentShader(const Pica::Regs& regs);
/// Binds a texture to the specified binding /// 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 /// Binds a storage image to the specified binding
void BindStorageImage(u32 binding, vk::ImageView image_view); void BindStorageImage(u32 binding, vk::ImageView image_view);
@ -215,9 +215,6 @@ public:
/// Binds a buffer to the specified binding /// Binds a buffer to the specified binding
void BindTexelBuffer(u32 binding, vk::BufferView buffer_view); void BindTexelBuffer(u32 binding, vk::BufferView buffer_view);
/// Binds a sampler to the specified binding
void BindSampler(u32 binding, vk::Sampler sampler);
private: private:
/// Applies dynamic pipeline state to the current command buffer /// Applies dynamic pipeline state to the current command buffer
void ApplyDynamic(const PipelineInfo& info, bool is_dirty); void ApplyDynamic(const PipelineInfo& info, bool is_dirty);

View File

@ -129,8 +129,7 @@ RasterizerVulkan::RasterizerVulkan(Memory::MemorySystem& memory,
const Sampler& null_sampler = res_cache.GetSampler(VideoCore::NULL_SAMPLER_ID); const Sampler& null_sampler = res_cache.GetSampler(VideoCore::NULL_SAMPLER_ID);
for (u32 i = 0; i < 4; i++) { for (u32 i = 0; i < 4; i++) {
pipeline_cache.BindTexture(i, null_surface.ImageView()); pipeline_cache.BindTexture(i, null_surface.ImageView(), null_sampler.Handle());
pipeline_cache.BindSampler(i, null_sampler.Handle());
} }
for (u32 i = 0; i < 7; i++) { for (u32 i = 0; i < 7; i++) {
@ -629,12 +628,10 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
auto surface = res_cache.GetTextureCube(config); auto surface = res_cache.GetTextureCube(config);
if (surface) { if (surface) {
pipeline_cache.BindTexture(3, surface->ImageView()); pipeline_cache.BindTexture(3, surface->ImageView(), sampler.Handle());
} else { } 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 continue; // Texture unit 0 setup finished. Continue to next unit
} }
default: default:
@ -642,8 +639,6 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
} }
} }
pipeline_cache.BindSampler(texture_index, sampler.Handle());
auto surface = res_cache.GetTextureSurface(texture); auto surface = res_cache.GetTextureSurface(texture);
if (surface) { if (surface) {
if (color_view == surface->ImageView()) { if (color_view == surface->ImageView()) {
@ -658,9 +653,10 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
.extent = {temp.GetScaledWidth(), temp.GetScaledHeight()}, .extent = {temp.GetScaledWidth(), temp.GetScaledHeight()},
}; };
runtime.CopyTextures(static_cast<Surface&>(*framebuffer.Color()), temp, copy); 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 { } else {
pipeline_cache.BindTexture(texture_index, surface->ImageView()); pipeline_cache.BindTexture(texture_index, surface->ImageView(),
sampler.Handle());
} }
} else { } else {
@ -671,12 +667,13 @@ void RasterizerVulkan::SyncTextureUnits(const Framebuffer& framebuffer) {
// the geometry in question. // the geometry in question.
// For example: a bug in Pokemon X/Y causes NULL-texture squares to be drawn // 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. // 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 { } else {
const Sampler& null_sampler = res_cache.GetSampler(VideoCore::NULL_SAMPLER_ID); const Sampler& null_sampler = res_cache.GetSampler(VideoCore::NULL_SAMPLER_ID);
pipeline_cache.BindTexture(texture_index, null_surface.ImageView()); pipeline_cache.BindTexture(texture_index, null_surface.ImageView(),
pipeline_cache.BindSampler(texture_index, null_sampler.Handle()); null_sampler.Handle());
} }
} }
} }

View File

@ -128,11 +128,10 @@ void DescriptorPool::Allocate(std::size_t begin, std::size_t end) {
vk::DescriptorPool& pool = pools.emplace_back(); vk::DescriptorPool& pool = pools.emplace_back();
// Choose a sane pool size good for most games // Choose a sane pool size good for most games
static constexpr std::array<vk::DescriptorPoolSize, 5> pool_sizes = {{ static constexpr std::array<vk::DescriptorPoolSize, 4> pool_sizes = {{
{vk::DescriptorType::eUniformBuffer, 4096}, {vk::DescriptorType::eUniformBuffer, 1024},
{vk::DescriptorType::eSampledImage, 4096}, {vk::DescriptorType::eCombinedImageSampler, 2048},
{vk::DescriptorType::eSampler, 4096}, {vk::DescriptorType::eUniformTexelBuffer, 1024},
{vk::DescriptorType::eUniformTexelBuffer, 2048},
{vk::DescriptorType::eStorageImage, 1024}, {vk::DescriptorType::eStorageImage, 1024},
}}; }};

View File

@ -289,13 +289,13 @@ static std::string SampleTexture(const PicaFSConfig& config, unsigned texture_un
// Only unit 0 respects the texturing type // Only unit 0 respects the texturing type
switch (state.texture0_type) { switch (state.texture0_type) {
case TexturingRegs::TextureConfig::Texture2D: case TexturingRegs::TextureConfig::Texture2D:
return "textureLod(sampler2D(tex0, tex0_sampler), texcoord0, getLod(texcoord0 * " return "textureLod(tex0, texcoord0, getLod(texcoord0 * "
"vec2(textureSize(sampler2D(tex0, tex0_sampler), 0))) + tex_lod_bias[0])"; "vec2(textureSize(tex0, 0))) + tex_lod_bias[0])";
case TexturingRegs::TextureConfig::Projection2D: case TexturingRegs::TextureConfig::Projection2D:
// TODO (wwylele): find the exact LOD formula for projection texture // 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: 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: case TexturingRegs::TextureConfig::Shadow2D:
return "shadowTexture(texcoord0, texcoord0_w)"; return "shadowTexture(texcoord0, texcoord0_w)";
case TexturingRegs::TextureConfig::ShadowCube: case TexturingRegs::TextureConfig::ShadowCube:
@ -305,18 +305,18 @@ static std::string SampleTexture(const PicaFSConfig& config, unsigned texture_un
default: default:
LOG_CRITICAL(HW_GPU, "Unhandled texture type {:x}", state.texture0_type); LOG_CRITICAL(HW_GPU, "Unhandled texture type {:x}", state.texture0_type);
UNIMPLEMENTED(); UNIMPLEMENTED();
return "texture(sampler2D(tex0, tex0_sampler), texcoord0)"; return "texture(tex0, texcoord0)";
} }
case 1: case 1:
return "textureLod(sampler2D(tex1, tex1_sampler), texcoord1, getLod(texcoord1 * " return "textureLod(tex1, texcoord1, getLod(texcoord1 * "
"vec2(textureSize(sampler2D(tex1, tex1_sampler), 0))) + tex_lod_bias[1])"; "vec2(textureSize(tex1, 0))) + tex_lod_bias[1])";
case 2: case 2:
if (state.texture2_use_coord1) if (state.texture2_use_coord1)
return "textureLod(sampler2D(tex2, tex2_sampler), texcoord1, getLod(texcoord1 * " return "textureLod(tex2, texcoord1, getLod(texcoord1 * "
"vec2(textureSize(sampler2D(tex2, tex2_sampler), 0))) + tex_lod_bias[2])"; "vec2(textureSize(tex2, 0))) + tex_lod_bias[2])";
else else
return "textureLod(sampler2D(tex2, tex2_sampler), texcoord2, getLod(texcoord2 * " return "textureLod(tex2, texcoord2, getLod(texcoord2 * "
"vec2(textureSize(sampler2D(tex2, tex2_sampler), 0))) + tex_lod_bias[2])"; "vec2(textureSize(tex2, 0))) + tex_lod_bias[2])";
case 3: case 3:
if (state.proctex.enable) { if (state.proctex.enable) {
return "ProcTex()"; 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 = 3) uniform samplerBuffer texture_buffer_lut_rg;
layout(set = 0, binding = 4) uniform samplerBuffer texture_buffer_lut_rgba; layout(set = 0, binding = 4) uniform samplerBuffer texture_buffer_lut_rgba;
layout(set = 1, binding = 0) uniform texture2D tex0; layout(set = 1, binding = 0) uniform sampler2D tex0;
layout(set = 1, binding = 1) uniform texture2D tex1; layout(set = 1, binding = 1) uniform sampler2D tex1;
layout(set = 1, binding = 2) uniform texture2D tex2; layout(set = 1, binding = 2) uniform sampler2D tex2;
layout(set = 1, binding = 3) uniform textureCube tex_cube; layout(set = 1, binding = 3) uniform samplerCube tex_cube;
layout(set = 2, binding = 0) uniform sampler tex0_sampler; layout(set = 2, binding = 0, r32ui) uniform readonly uimage2D shadow_texture_px;
layout(set = 2, binding = 1) uniform sampler tex1_sampler; layout(set = 2, binding = 1, r32ui) uniform readonly uimage2D shadow_texture_nx;
layout(set = 2, binding = 2) uniform sampler tex2_sampler; layout(set = 2, binding = 2, r32ui) uniform readonly uimage2D shadow_texture_py;
layout(set = 2, binding = 3) uniform sampler tex_cube_sampler; 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 = 3, binding = 0, r32ui) uniform readonly uimage2D shadow_texture_px; layout(set = 2, binding = 5, r32ui) uniform readonly uimage2D shadow_texture_nz;
layout(set = 3, binding = 1, r32ui) uniform readonly uimage2D shadow_texture_nx; layout(set = 2, binding = 6, r32ui) uniform uimage2D shadow_buffer;
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;
)"; )";
out += UniformBlockDef; out += UniformBlockDef;

View File

@ -667,10 +667,8 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
// This LOD formula is the same as the LOD lower limit defined in OpenGL. // This LOD formula is the same as the LOD lower limit defined in OpenGL.
// f(x, y) >= max{m_u, m_v, m_w} // f(x, y) >= max{m_u, m_v, m_w}
// (See OpenGL 4.6 spec, 8.14.1 - Scale Factor and Level-of-Detail) // (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 auto SampleLod = [this, texture_unit](Id tex_id, Id texcoord_id) {
const Id tex{OpLoad(image2d_id, tex_id)}; const Id sampled_image{OpLoad(TypeSampledImage(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 Id tex_image{OpImage(image2d_id, sampled_image)}; const Id tex_image{OpImage(image2d_id, sampled_image)};
const Id tex_size{OpImageQuerySizeLod(ivec_ids.Get(2), tex_image, ConstS32(0))}; const Id tex_size{OpImageQuerySizeLod(ivec_ids.Get(2), tex_image, ConstS32(0))};
const Id texcoord{OpLoad(vec_ids.Get(2), texcoord_id)}; 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); 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 image_type = tex_id.value == tex_cube_id.value ? image_cube_id : image2d_id;
const Id tex{OpLoad(image_type, tex_id)}; const Id sampled_image{OpLoad(TypeSampledImage(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 texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)}; const Id texcoord0{OpLoad(vec_ids.Get(2), texcoord0_id)};
const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)}; const Id texcoord0_w{OpLoad(f32_id, texcoord0_w_id)};
const Id coord{OpCompositeConstruct(vec_ids.Get(3), 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 // Only unit 0 respects the texturing type
switch (state.texture0_type) { switch (state.texture0_type) {
case Pica::TexturingRegs::TextureConfig::Texture2D: 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: case Pica::TexturingRegs::TextureConfig::Projection2D:
return Sample(tex0_id, tex0_sampler_id, true); return Sample(tex0_id, true);
case Pica::TexturingRegs::TextureConfig::TextureCube: 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: case Pica::TexturingRegs::TextureConfig::Shadow2D:
return SampleShadow(); return SampleShadow();
// case Pica::TexturingRegs::TextureConfig::ShadowCube: // case Pica::TexturingRegs::TextureConfig::ShadowCube:
@ -726,12 +722,12 @@ Id FragmentModule::SampleTexture(u32 texture_unit) {
return zero_vec; return zero_vec;
} }
case 1: case 1:
return SampleLod(tex1_id, tex1_sampler_id, texcoord1_id); return SampleLod(tex1_id, texcoord1_id);
case 2: case 2:
if (state.texture2_use_coord1) { if (state.texture2_use_coord1) {
return SampleLod(tex2_id, tex2_sampler_id, texcoord1_id); return SampleLod(tex2_id, texcoord1_id);
} else { } else {
return SampleLod(tex2_id, tex2_sampler_id, texcoord2_id); return SampleLod(tex2_id, texcoord2_id);
} }
case 3: case 3:
if (state.proctex.enable) { 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_lf_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 2);
texture_buffer_lut_rg_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 3); texture_buffer_lut_rg_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 3);
texture_buffer_lut_rgba_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 4); texture_buffer_lut_rgba_id = DefineUniformConst(TypeSampledImage(image_buffer_id), 0, 4);
tex0_id = DefineUniformConst(image2d_id, 1, 0); tex0_id = DefineUniformConst(TypeSampledImage(image2d_id), 1, 0);
tex1_id = DefineUniformConst(image2d_id, 1, 1); tex1_id = DefineUniformConst(TypeSampledImage(image2d_id), 1, 1);
tex2_id = DefineUniformConst(image2d_id, 1, 2); tex2_id = DefineUniformConst(TypeSampledImage(image2d_id), 1, 2);
tex_cube_id = DefineUniformConst(image_cube_id, 1, 3); tex_cube_id = DefineUniformConst(TypeSampledImage(image_cube_id), 1, 3);
tex0_sampler_id = DefineUniformConst(sampler_id, 2, 0); shadow_texture_px_id = DefineUniformConst(image_r32_id, 2, 0, true);
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);
// Define built-ins // Define built-ins
gl_frag_coord_id = DefineVar(vec_ids.Get(4), spv::StorageClass::Input); gl_frag_coord_id = DefineVar(vec_ids.Get(4), spv::StorageClass::Input);

View File

@ -240,10 +240,6 @@ private:
Id tex1_id{}; Id tex1_id{};
Id tex2_id{}; Id tex2_id{};
Id tex_cube_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_lf_id{};
Id texture_buffer_lut_rg_id{}; Id texture_buffer_lut_rg_id{};
Id texture_buffer_lut_rgba_id{}; Id texture_buffer_lut_rgba_id{};

View File

@ -730,7 +730,6 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
} }
void TextureRuntime::GenerateMipmaps(Surface& surface) { void TextureRuntime::GenerateMipmaps(Surface& surface) {
return;
if (surface.custom_format != VideoCore::CustomPixelFormat::RGBA8) { if (surface.custom_format != VideoCore::CustomPixelFormat::RGBA8) {
LOG_ERROR(Render_Vulkan, "Generating mipmaps for compressed formats unsupported!"); LOG_ERROR(Render_Vulkan, "Generating mipmaps for compressed formats unsupported!");
return; return;
@ -1338,8 +1337,8 @@ Sampler::Sampler(TextureRuntime& runtime, VideoCore::SamplerParams params)
.maxAnisotropy = properties.limits.maxSamplerAnisotropy, .maxAnisotropy = properties.limits.maxSamplerAnisotropy,
.compareEnable = false, .compareEnable = false,
.compareOp = vk::CompareOp::eAlways, .compareOp = vk::CompareOp::eAlways,
.minLod = 0.f * lod_min, .minLod = lod_min,
.maxLod = 0.f * lod_max, .maxLod = lod_max,
.borderColor = .borderColor =
use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack, use_border_color ? vk::BorderColor::eFloatCustomEXT : vk::BorderColor::eIntOpaqueBlack,
.unnormalizedCoordinates = false, .unnormalizedCoordinates = false,