mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-02 02:04:17 +01:00
Implement Maxwell3D Sampled Textures
The descriptor sets should now contain a combined image and sampler handle for any sampled textures in the guest shader from the supplied offset into the texture constant buffer. Note: Games tend to rely on inline constant buffer updates for writing the texture constant buffer and due to it not being implemented, the value will be read as 0 which is incorrect.
This commit is contained in:
parent
d9a9e52350
commit
bb14af4f7a
@ -10,12 +10,16 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
void DescriptorAllocator::AllocateDescriptorPool() {
|
void DescriptorAllocator::AllocateDescriptorPool() {
|
||||||
namespace maxwell3d = soc::gm20b::engine::maxwell3d::type; // We use Maxwell3D as reference for base descriptor counts
|
namespace maxwell3d = soc::gm20b::engine::maxwell3d::type; // We use Maxwell3D as reference for base descriptor counts
|
||||||
using DescriptorSizes = std::array<vk::DescriptorPoolSize, 1>;
|
using DescriptorSizes = std::array<vk::DescriptorPoolSize, 2>;
|
||||||
constexpr DescriptorSizes BaseDescriptorSizes{
|
constexpr DescriptorSizes BaseDescriptorSizes{
|
||||||
vk::DescriptorPoolSize{
|
vk::DescriptorPoolSize{
|
||||||
.descriptorCount = maxwell3d::PipelineStageConstantBufferCount,
|
.descriptorCount = maxwell3d::PipelineStageConstantBufferCount,
|
||||||
.type = vk::DescriptorType::eUniformBuffer,
|
.type = vk::DescriptorType::eUniformBuffer,
|
||||||
},
|
},
|
||||||
|
vk::DescriptorPoolSize{
|
||||||
|
.descriptorCount = maxwell3d::PipelineStageCount * 20,
|
||||||
|
.type = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
DescriptorSizes descriptorSizes{BaseDescriptorSizes};
|
DescriptorSizes descriptorSizes{BaseDescriptorSizes};
|
||||||
|
@ -45,6 +45,10 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandExecutor::AttachDependency(std::shared_ptr<FenceCycleDependency> dependency) {
|
||||||
|
cycle->AttachObject(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
void CommandExecutor::AddSubpass(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment) {
|
void CommandExecutor::AddSubpass(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment) {
|
||||||
for (const auto &attachments : {inputAttachments, colorAttachments})
|
for (const auto &attachments : {inputAttachments, colorAttachments})
|
||||||
for (const auto &attachment : attachments)
|
for (const auto &attachment : attachments)
|
||||||
|
@ -46,6 +46,11 @@ namespace skyline::gpu::interconnect {
|
|||||||
*/
|
*/
|
||||||
void AttachBuffer(BufferView *view);
|
void AttachBuffer(BufferView *view);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attach the lifetime of the fence cycle dependency to the command buffer
|
||||||
|
*/
|
||||||
|
void AttachDependency(std::shared_ptr<FenceCycleDependency> dependency);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a command that needs to be executed inside a subpass configured with certain attachments
|
* @brief Adds a command that needs to be executed inside a subpass configured with certain attachments
|
||||||
* @note Any texture supplied to this **must** be locked by the calling thread, it should also undergo no persistent layout transitions till execution
|
* @note Any texture supplied to this **must** be locked by the calling thread, it should also undergo no persistent layout transitions till execution
|
||||||
|
@ -679,13 +679,14 @@ namespace skyline::gpu::interconnect {
|
|||||||
|
|
||||||
constexpr static size_t MaxShaderBytecodeSize{1 * 1024 * 1024}; //!< The largest shader binary that we support (1 MiB)
|
constexpr static size_t MaxShaderBytecodeSize{1 * 1024 * 1024}; //!< The largest shader binary that we support (1 MiB)
|
||||||
|
|
||||||
constexpr static size_t PipelineUniqueDescriptorTypeCount{1}; //!< The amount of unique descriptor types that may be bound to a pipeline
|
constexpr static size_t PipelineUniqueDescriptorTypeCount{2}; //!< The amount of unique descriptor types that may be bound to a pipeline
|
||||||
constexpr static size_t MaxPipelineDescriptorWriteCount{maxwell3d::PipelineStageCount * PipelineUniqueDescriptorTypeCount}; //!< The maxium amount of descriptors writes that are used to bind a pipeline
|
constexpr static size_t MaxPipelineDescriptorWriteCount{maxwell3d::PipelineStageCount * PipelineUniqueDescriptorTypeCount}; //!< The maxium amount of descriptors writes that are used to bind a pipeline
|
||||||
constexpr static size_t MaxPipelineDescriptorCount{100}; //!< The maxium amount of descriptors we support being bound to a pipeline
|
constexpr static size_t MaxPipelineDescriptorCount{100}; //!< The maxium amount of descriptors we support being bound to a pipeline
|
||||||
|
|
||||||
boost::container::static_vector<vk::WriteDescriptorSet, MaxPipelineDescriptorWriteCount> descriptorSetWrites;
|
boost::container::static_vector<vk::WriteDescriptorSet, MaxPipelineDescriptorWriteCount> descriptorSetWrites;
|
||||||
boost::container::static_vector<vk::DescriptorSetLayoutBinding, MaxPipelineDescriptorCount> layoutBindings;
|
boost::container::static_vector<vk::DescriptorSetLayoutBinding, MaxPipelineDescriptorCount> layoutBindings;
|
||||||
boost::container::static_vector<vk::DescriptorBufferInfo, MaxPipelineDescriptorCount> bufferInfo;
|
boost::container::static_vector<vk::DescriptorBufferInfo, MaxPipelineDescriptorCount> bufferInfo;
|
||||||
|
boost::container::static_vector<vk::DescriptorImageInfo, MaxPipelineDescriptorCount> imageInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief All state concerning the shader programs and their bindings
|
* @brief All state concerning the shader programs and their bindings
|
||||||
@ -799,6 +800,11 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptorSetWrites.clear();
|
||||||
|
layoutBindings.clear();
|
||||||
|
bufferInfo.clear();
|
||||||
|
imageInfo.clear();
|
||||||
|
|
||||||
runtimeInfo.previous_stage_stores.mask.set(); // First stage should always have all bits set
|
runtimeInfo.previous_stage_stores.mask.set(); // First stage should always have all bits set
|
||||||
ShaderCompiler::Backend::Bindings bindings{};
|
ShaderCompiler::Backend::Bindings bindings{};
|
||||||
|
|
||||||
@ -852,6 +858,46 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!program.info.texture_descriptors.empty()) {
|
||||||
|
descriptorSetWrites.push_back(vk::WriteDescriptorSet{
|
||||||
|
.dstBinding = bindingIndex,
|
||||||
|
.descriptorCount = static_cast<u32>(program.info.texture_descriptors.size()),
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.pImageInfo = imageInfo.data() + imageInfo.size(),
|
||||||
|
});
|
||||||
|
|
||||||
|
u32 descriptorIndex{};
|
||||||
|
for (auto &texture : program.info.texture_descriptors) {
|
||||||
|
layoutBindings.push_back(vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = bindingIndex++,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = pipelineStage.vkStage,
|
||||||
|
});
|
||||||
|
|
||||||
|
auto &constantBuffer{pipelineStage.constantBuffers[texture.cbuf_index]};
|
||||||
|
union TextureHandle {
|
||||||
|
u32 raw;
|
||||||
|
struct {
|
||||||
|
u32 textureIndex : 20;
|
||||||
|
u32 samplerIndex : 12;
|
||||||
|
};
|
||||||
|
} handle{constantBuffer.Read<u32>(texture.cbuf_offset + (descriptorIndex++ << texture.size_shift))};
|
||||||
|
|
||||||
|
auto sampler{GetSampler(handle.samplerIndex)};
|
||||||
|
auto textureView{GetPoolTextureView(handle.textureIndex)};
|
||||||
|
|
||||||
|
std::scoped_lock lock(*textureView);
|
||||||
|
imageInfo.push_back(vk::DescriptorImageInfo{
|
||||||
|
.sampler = **sampler,
|
||||||
|
.imageView = textureView->GetView(),
|
||||||
|
.imageLayout = textureView->texture->layout,
|
||||||
|
});
|
||||||
|
executor.AttachTexture(textureView.get());
|
||||||
|
executor.AttachDependency(std::move(sampler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shaderStagesInfo[count++] = vk::PipelineShaderStageCreateInfo{
|
shaderStagesInfo[count++] = vk::PipelineShaderStageCreateInfo{
|
||||||
.stage = pipelineStage.vkStage,
|
.stage = pipelineStage.vkStage,
|
||||||
.module = **pipelineStage.vkModule,
|
.module = **pipelineStage.vkModule,
|
||||||
|
@ -259,7 +259,7 @@ namespace skyline::gpu {
|
|||||||
mipLevels(1),
|
mipLevels(1),
|
||||||
layerCount(guest->layerCount),
|
layerCount(guest->layerCount),
|
||||||
sampleCount(vk::SampleCountFlagBits::e1) {
|
sampleCount(vk::SampleCountFlagBits::e1) {
|
||||||
vk::ImageUsageFlags usage{vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst};
|
vk::ImageUsageFlags usage{vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled};
|
||||||
if (format->vkAspect & vk::ImageAspectFlagBits::eColor)
|
if (format->vkAspect & vk::ImageAspectFlagBits::eColor)
|
||||||
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
||||||
if (format->vkAspect & (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil))
|
if (format->vkAspect & (vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil))
|
||||||
|
Loading…
Reference in New Issue
Block a user