shader: Interact texture buffers with buffer cache
This commit is contained in:
parent
56b92bd89c
commit
e9a91bc5cc
|
@ -130,8 +130,8 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, u32& bin
|
||||||
DefineSharedMemory(program);
|
DefineSharedMemory(program);
|
||||||
DefineConstantBuffers(program.info, binding);
|
DefineConstantBuffers(program.info, binding);
|
||||||
DefineStorageBuffers(program.info, binding);
|
DefineStorageBuffers(program.info, binding);
|
||||||
DefineTextures(program.info, binding);
|
|
||||||
DefineTextureBuffers(program.info, binding);
|
DefineTextureBuffers(program.info, binding);
|
||||||
|
DefineTextures(program.info, binding);
|
||||||
DefineAttributeMemAccess(program.info);
|
DefineAttributeMemAccess(program.info);
|
||||||
DefineLabels(program);
|
DefineLabels(program);
|
||||||
}
|
}
|
||||||
|
@ -516,6 +516,32 @@ void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
|
||||||
|
if (info.texture_buffer_descriptors.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
||||||
|
image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
|
||||||
|
sampled_texture_buffer_type = TypeSampledImage(image_buffer_type);
|
||||||
|
|
||||||
|
const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)};
|
||||||
|
texture_buffers.reserve(info.texture_buffer_descriptors.size());
|
||||||
|
for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
|
||||||
|
if (desc.count != 1) {
|
||||||
|
throw NotImplementedException("Array of texture buffers");
|
||||||
|
}
|
||||||
|
const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)};
|
||||||
|
Decorate(id, spv::Decoration::Binding, binding);
|
||||||
|
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
||||||
|
Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset));
|
||||||
|
texture_buffers.insert(texture_buffers.end(), desc.count, id);
|
||||||
|
if (profile.supported_spirv >= 0x00010400) {
|
||||||
|
interfaces.push_back(id);
|
||||||
|
}
|
||||||
|
binding += desc.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmitContext::DefineTextures(const Info& info, u32& binding) {
|
void EmitContext::DefineTextures(const Info& info, u32& binding) {
|
||||||
textures.reserve(info.texture_descriptors.size());
|
textures.reserve(info.texture_descriptors.size());
|
||||||
for (const TextureDescriptor& desc : info.texture_descriptors) {
|
for (const TextureDescriptor& desc : info.texture_descriptors) {
|
||||||
|
@ -544,32 +570,6 @@ void EmitContext::DefineTextures(const Info& info, u32& binding) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
|
|
||||||
if (info.texture_buffer_descriptors.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
|
||||||
image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
|
|
||||||
sampled_texture_buffer_type = TypeSampledImage(image_buffer_type);
|
|
||||||
|
|
||||||
const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)};
|
|
||||||
texture_buffers.reserve(info.texture_buffer_descriptors.size());
|
|
||||||
for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
|
|
||||||
if (desc.count != 1) {
|
|
||||||
throw NotImplementedException("Array of texture buffers");
|
|
||||||
}
|
|
||||||
const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)};
|
|
||||||
Decorate(id, spv::Decoration::Binding, binding);
|
|
||||||
Decorate(id, spv::Decoration::DescriptorSet, 0U);
|
|
||||||
Name(id, fmt::format("texbuf{}_{:02x}", desc.cbuf_index, desc.cbuf_offset));
|
|
||||||
texture_buffers.insert(texture_buffers.end(), desc.count, id);
|
|
||||||
if (profile.supported_spirv >= 0x00010400) {
|
|
||||||
interfaces.push_back(id);
|
|
||||||
}
|
|
||||||
binding += desc.count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitContext::DefineLabels(IR::Program& program) {
|
void EmitContext::DefineLabels(IR::Program& program) {
|
||||||
for (IR::Block* const block : program.blocks) {
|
for (IR::Block* const block : program.blocks) {
|
||||||
block->SetDefinition(OpLabel());
|
block->SetDefinition(OpLabel());
|
||||||
|
|
|
@ -154,8 +154,8 @@ private:
|
||||||
void DefineSharedMemory(const IR::Program& program);
|
void DefineSharedMemory(const IR::Program& program);
|
||||||
void DefineConstantBuffers(const Info& info, u32& binding);
|
void DefineConstantBuffers(const Info& info, u32& binding);
|
||||||
void DefineStorageBuffers(const Info& info, u32& binding);
|
void DefineStorageBuffers(const Info& info, u32& binding);
|
||||||
void DefineTextures(const Info& info, u32& binding);
|
|
||||||
void DefineTextureBuffers(const Info& info, u32& binding);
|
void DefineTextureBuffers(const Info& info, u32& binding);
|
||||||
|
void DefineTextures(const Info& info, u32& binding);
|
||||||
void DefineAttributeMemAccess(const Info& info);
|
void DefineAttributeMemAccess(const Info& info);
|
||||||
void DefineLabels(IR::Program& program);
|
void DefineLabels(IR::Program& program);
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,8 @@ struct Info {
|
||||||
boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS>
|
boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS>
|
||||||
constant_buffer_descriptors;
|
constant_buffer_descriptors;
|
||||||
boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors;
|
boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors;
|
||||||
TextureDescriptors texture_descriptors;
|
|
||||||
TextureBufferDescriptors texture_buffer_descriptors;
|
TextureBufferDescriptors texture_buffer_descriptors;
|
||||||
|
TextureDescriptors texture_descriptors;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Shader
|
} // namespace Shader
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
#include "video_core/surface.h"
|
||||||
#include "video_core/texture_cache/slot_vector.h"
|
#include "video_core/texture_cache/slot_vector.h"
|
||||||
#include "video_core/texture_cache/types.h"
|
#include "video_core/texture_cache/types.h"
|
||||||
|
|
||||||
|
@ -42,11 +43,14 @@ MICROPROFILE_DECLARE(GPU_DownloadMemory);
|
||||||
|
|
||||||
using BufferId = SlotId;
|
using BufferId = SlotId;
|
||||||
|
|
||||||
|
using VideoCore::Surface::PixelFormat;
|
||||||
|
|
||||||
constexpr u32 NUM_VERTEX_BUFFERS = 32;
|
constexpr u32 NUM_VERTEX_BUFFERS = 32;
|
||||||
constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
|
constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
|
||||||
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
|
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
|
||||||
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
|
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
|
||||||
constexpr u32 NUM_STORAGE_BUFFERS = 16;
|
constexpr u32 NUM_STORAGE_BUFFERS = 16;
|
||||||
|
constexpr u32 NUM_TEXTURE_BUFFERS = 16;
|
||||||
constexpr u32 NUM_STAGES = 5;
|
constexpr u32 NUM_STAGES = 5;
|
||||||
|
|
||||||
using namespace Common::Literals;
|
using namespace Common::Literals;
|
||||||
|
@ -66,6 +70,7 @@ class BufferCache {
|
||||||
P::HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT;
|
P::HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT;
|
||||||
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = P::NEEDS_BIND_UNIFORM_INDEX;
|
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = P::NEEDS_BIND_UNIFORM_INDEX;
|
||||||
static constexpr bool NEEDS_BIND_STORAGE_INDEX = P::NEEDS_BIND_STORAGE_INDEX;
|
static constexpr bool NEEDS_BIND_STORAGE_INDEX = P::NEEDS_BIND_STORAGE_INDEX;
|
||||||
|
static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = P::NEEDS_BIND_TEXTURE_BUFFER_INDEX;
|
||||||
static constexpr bool USE_MEMORY_MAPS = P::USE_MEMORY_MAPS;
|
static constexpr bool USE_MEMORY_MAPS = P::USE_MEMORY_MAPS;
|
||||||
|
|
||||||
static constexpr BufferId NULL_BUFFER_ID{0};
|
static constexpr BufferId NULL_BUFFER_ID{0};
|
||||||
|
@ -96,6 +101,10 @@ class BufferCache {
|
||||||
BufferId buffer_id;
|
BufferId buffer_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TextureBufferBinding : Binding {
|
||||||
|
PixelFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr Binding NULL_BINDING{
|
static constexpr Binding NULL_BINDING{
|
||||||
.cpu_addr = 0,
|
.cpu_addr = 0,
|
||||||
.size = 0,
|
.size = 0,
|
||||||
|
@ -142,11 +151,21 @@ public:
|
||||||
void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
void BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
||||||
bool is_written);
|
bool is_written);
|
||||||
|
|
||||||
|
void UnbindGraphicsTextureBuffers(size_t stage);
|
||||||
|
|
||||||
|
void BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr, u32 size,
|
||||||
|
PixelFormat format);
|
||||||
|
|
||||||
void UnbindComputeStorageBuffers();
|
void UnbindComputeStorageBuffers();
|
||||||
|
|
||||||
void BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
void BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
||||||
bool is_written);
|
bool is_written);
|
||||||
|
|
||||||
|
void UnbindComputeTextureBuffers();
|
||||||
|
|
||||||
|
void BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
|
||||||
|
PixelFormat format);
|
||||||
|
|
||||||
void FlushCachedWrites();
|
void FlushCachedWrites();
|
||||||
|
|
||||||
/// Return true when there are uncommitted buffers to be downloaded
|
/// Return true when there are uncommitted buffers to be downloaded
|
||||||
|
@ -254,12 +273,16 @@ private:
|
||||||
|
|
||||||
void BindHostGraphicsStorageBuffers(size_t stage);
|
void BindHostGraphicsStorageBuffers(size_t stage);
|
||||||
|
|
||||||
|
void BindHostGraphicsTextureBuffers(size_t stage);
|
||||||
|
|
||||||
void BindHostTransformFeedbackBuffers();
|
void BindHostTransformFeedbackBuffers();
|
||||||
|
|
||||||
void BindHostComputeUniformBuffers();
|
void BindHostComputeUniformBuffers();
|
||||||
|
|
||||||
void BindHostComputeStorageBuffers();
|
void BindHostComputeStorageBuffers();
|
||||||
|
|
||||||
|
void BindHostComputeTextureBuffers();
|
||||||
|
|
||||||
void DoUpdateGraphicsBuffers(bool is_indexed);
|
void DoUpdateGraphicsBuffers(bool is_indexed);
|
||||||
|
|
||||||
void DoUpdateComputeBuffers();
|
void DoUpdateComputeBuffers();
|
||||||
|
@ -274,6 +297,8 @@ private:
|
||||||
|
|
||||||
void UpdateStorageBuffers(size_t stage);
|
void UpdateStorageBuffers(size_t stage);
|
||||||
|
|
||||||
|
void UpdateTextureBuffers(size_t stage);
|
||||||
|
|
||||||
void UpdateTransformFeedbackBuffers();
|
void UpdateTransformFeedbackBuffers();
|
||||||
|
|
||||||
void UpdateTransformFeedbackBuffer(u32 index);
|
void UpdateTransformFeedbackBuffer(u32 index);
|
||||||
|
@ -282,6 +307,8 @@ private:
|
||||||
|
|
||||||
void UpdateComputeStorageBuffers();
|
void UpdateComputeStorageBuffers();
|
||||||
|
|
||||||
|
void UpdateComputeTextureBuffers();
|
||||||
|
|
||||||
void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size);
|
void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size);
|
||||||
|
|
||||||
[[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size);
|
[[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size);
|
||||||
|
@ -323,6 +350,9 @@ private:
|
||||||
|
|
||||||
[[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const;
|
[[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const;
|
||||||
|
|
||||||
|
[[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size,
|
||||||
|
PixelFormat format);
|
||||||
|
|
||||||
[[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size);
|
[[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size);
|
||||||
|
|
||||||
[[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity);
|
[[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity);
|
||||||
|
@ -347,10 +377,12 @@ private:
|
||||||
std::array<Binding, NUM_VERTEX_BUFFERS> vertex_buffers;
|
std::array<Binding, NUM_VERTEX_BUFFERS> vertex_buffers;
|
||||||
std::array<std::array<Binding, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES> uniform_buffers;
|
std::array<std::array<Binding, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES> uniform_buffers;
|
||||||
std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers;
|
std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers;
|
||||||
|
std::array<std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS>, NUM_STAGES> texture_buffers;
|
||||||
std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers;
|
std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers;
|
||||||
|
|
||||||
std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers;
|
std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers;
|
||||||
std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers;
|
std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers;
|
||||||
|
std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS> compute_texture_buffers;
|
||||||
|
|
||||||
std::array<u32, NUM_STAGES> enabled_uniform_buffers{};
|
std::array<u32, NUM_STAGES> enabled_uniform_buffers{};
|
||||||
u32 enabled_compute_uniform_buffers = 0;
|
u32 enabled_compute_uniform_buffers = 0;
|
||||||
|
@ -360,6 +392,9 @@ private:
|
||||||
u32 enabled_compute_storage_buffers = 0;
|
u32 enabled_compute_storage_buffers = 0;
|
||||||
u32 written_compute_storage_buffers = 0;
|
u32 written_compute_storage_buffers = 0;
|
||||||
|
|
||||||
|
std::array<u32, NUM_STAGES> enabled_texture_buffers{};
|
||||||
|
u32 enabled_compute_texture_buffers = 0;
|
||||||
|
|
||||||
std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{};
|
std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{};
|
||||||
|
|
||||||
std::array<u32, 16> uniform_cache_hits{};
|
std::array<u32, 16> uniform_cache_hits{};
|
||||||
|
@ -619,6 +654,7 @@ void BufferCache<P>::BindHostStageBuffers(size_t stage) {
|
||||||
MICROPROFILE_SCOPE(GPU_BindUploadBuffers);
|
MICROPROFILE_SCOPE(GPU_BindUploadBuffers);
|
||||||
BindHostGraphicsUniformBuffers(stage);
|
BindHostGraphicsUniformBuffers(stage);
|
||||||
BindHostGraphicsStorageBuffers(stage);
|
BindHostGraphicsStorageBuffers(stage);
|
||||||
|
BindHostGraphicsTextureBuffers(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
@ -626,6 +662,7 @@ void BufferCache<P>::BindHostComputeBuffers() {
|
||||||
MICROPROFILE_SCOPE(GPU_BindUploadBuffers);
|
MICROPROFILE_SCOPE(GPU_BindUploadBuffers);
|
||||||
BindHostComputeUniformBuffers();
|
BindHostComputeUniformBuffers();
|
||||||
BindHostComputeStorageBuffers();
|
BindHostComputeStorageBuffers();
|
||||||
|
BindHostComputeTextureBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
@ -660,6 +697,18 @@ void BufferCache<P>::BindGraphicsStorageBuffer(size_t stage, size_t ssbo_index,
|
||||||
storage_buffers[stage][ssbo_index] = StorageBufferBinding(ssbo_addr);
|
storage_buffers[stage][ssbo_index] = StorageBufferBinding(ssbo_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::UnbindGraphicsTextureBuffers(size_t stage) {
|
||||||
|
enabled_texture_buffers[stage] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::BindGraphicsTextureBuffer(size_t stage, size_t tbo_index, GPUVAddr gpu_addr,
|
||||||
|
u32 size, PixelFormat format) {
|
||||||
|
enabled_texture_buffers[stage] |= 1U << tbo_index;
|
||||||
|
texture_buffers[stage][tbo_index] = GetTextureBufferBinding(gpu_addr, size, format);
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::UnbindComputeStorageBuffers() {
|
void BufferCache<P>::UnbindComputeStorageBuffers() {
|
||||||
enabled_compute_storage_buffers = 0;
|
enabled_compute_storage_buffers = 0;
|
||||||
|
@ -680,6 +729,18 @@ void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index,
|
||||||
compute_storage_buffers[ssbo_index] = StorageBufferBinding(ssbo_addr);
|
compute_storage_buffers[ssbo_index] = StorageBufferBinding(ssbo_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::UnbindComputeTextureBuffers() {
|
||||||
|
enabled_compute_texture_buffers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
|
||||||
|
PixelFormat format) {
|
||||||
|
enabled_compute_texture_buffers |= 1U << tbo_index;
|
||||||
|
compute_texture_buffers[tbo_index] = GetTextureBufferBinding(gpu_addr, size, format);
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::FlushCachedWrites() {
|
void BufferCache<P>::FlushCachedWrites() {
|
||||||
for (const BufferId buffer_id : cached_write_buffer_ids) {
|
for (const BufferId buffer_id : cached_write_buffer_ids) {
|
||||||
|
@ -988,6 +1049,26 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
|
||||||
|
u32 binding_index = 0;
|
||||||
|
ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) {
|
||||||
|
const TextureBufferBinding& binding = texture_buffers[stage][index];
|
||||||
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
|
const u32 size = binding.size;
|
||||||
|
SynchronizeBuffer(buffer, binding.cpu_addr, size);
|
||||||
|
|
||||||
|
const u32 offset = buffer.Offset(binding.cpu_addr);
|
||||||
|
const PixelFormat format = binding.format;
|
||||||
|
if constexpr (NEEDS_BIND_TEXTURE_BUFFER_INDEX) {
|
||||||
|
runtime.BindTextureBuffer(binding_index, buffer, offset, size, format);
|
||||||
|
++binding_index;
|
||||||
|
} else {
|
||||||
|
runtime.BindTextureBuffer(buffer, offset, size, format);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindHostTransformFeedbackBuffers() {
|
void BufferCache<P>::BindHostTransformFeedbackBuffers() {
|
||||||
if (maxwell3d.regs.tfb_enabled == 0) {
|
if (maxwell3d.regs.tfb_enabled == 0) {
|
||||||
|
@ -1050,6 +1131,26 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::BindHostComputeTextureBuffers() {
|
||||||
|
u32 binding_index = 0;
|
||||||
|
ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) {
|
||||||
|
const TextureBufferBinding& binding = compute_texture_buffers[index];
|
||||||
|
Buffer& buffer = slot_buffers[binding.buffer_id];
|
||||||
|
const u32 size = binding.size;
|
||||||
|
SynchronizeBuffer(buffer, binding.cpu_addr, size);
|
||||||
|
|
||||||
|
const u32 offset = buffer.Offset(binding.cpu_addr);
|
||||||
|
const PixelFormat format = binding.format;
|
||||||
|
if constexpr (NEEDS_BIND_TEXTURE_BUFFER_INDEX) {
|
||||||
|
runtime.BindTextureBuffer(binding_index, buffer, offset, size, format);
|
||||||
|
++binding_index;
|
||||||
|
} else {
|
||||||
|
runtime.BindTextureBuffer(buffer, offset, size, format);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
|
@ -1060,6 +1161,7 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
|
||||||
for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
|
for (size_t stage = 0; stage < NUM_STAGES; ++stage) {
|
||||||
UpdateUniformBuffers(stage);
|
UpdateUniformBuffers(stage);
|
||||||
UpdateStorageBuffers(stage);
|
UpdateStorageBuffers(stage);
|
||||||
|
UpdateTextureBuffers(stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,6 +1169,7 @@ template <class P>
|
||||||
void BufferCache<P>::DoUpdateComputeBuffers() {
|
void BufferCache<P>::DoUpdateComputeBuffers() {
|
||||||
UpdateComputeUniformBuffers();
|
UpdateComputeUniformBuffers();
|
||||||
UpdateComputeStorageBuffers();
|
UpdateComputeStorageBuffers();
|
||||||
|
UpdateComputeTextureBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
@ -1166,6 +1269,14 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
|
||||||
|
ForEachEnabledBit(enabled_texture_buffers[stage], [&](u32 index) {
|
||||||
|
Binding& binding = texture_buffers[stage][index];
|
||||||
|
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::UpdateTransformFeedbackBuffers() {
|
void BufferCache<P>::UpdateTransformFeedbackBuffers() {
|
||||||
if (maxwell3d.regs.tfb_enabled == 0) {
|
if (maxwell3d.regs.tfb_enabled == 0) {
|
||||||
|
@ -1227,6 +1338,14 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::UpdateComputeTextureBuffers() {
|
||||||
|
ForEachEnabledBit(enabled_compute_texture_buffers, [&](u32 index) {
|
||||||
|
Binding& binding = compute_texture_buffers[index];
|
||||||
|
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) {
|
void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) {
|
||||||
Buffer& buffer = slot_buffers[buffer_id];
|
Buffer& buffer = slot_buffers[buffer_id];
|
||||||
|
@ -1581,6 +1700,25 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
typename BufferCache<P>::TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(
|
||||||
|
GPUVAddr gpu_addr, u32 size, PixelFormat format) {
|
||||||
|
const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr);
|
||||||
|
TextureBufferBinding binding;
|
||||||
|
if (!cpu_addr || size == 0) {
|
||||||
|
binding.cpu_addr = 0;
|
||||||
|
binding.size = 0;
|
||||||
|
binding.buffer_id = NULL_BUFFER_ID;
|
||||||
|
binding.format = PixelFormat::Invalid;
|
||||||
|
} else {
|
||||||
|
binding.cpu_addr = *cpu_addr;
|
||||||
|
binding.size = size;
|
||||||
|
binding.buffer_id = BufferId{};
|
||||||
|
binding.format = format;
|
||||||
|
}
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) {
|
std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) {
|
||||||
u8* const base_pointer = cpu_memory.GetPointer(cpu_addr);
|
u8* const base_pointer = cpu_memory.GetPointer(cpu_addr);
|
||||||
|
|
|
@ -155,6 +155,7 @@ struct BufferCacheParams {
|
||||||
static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true;
|
static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = true;
|
||||||
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true;
|
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = true;
|
||||||
static constexpr bool NEEDS_BIND_STORAGE_INDEX = true;
|
static constexpr bool NEEDS_BIND_STORAGE_INDEX = true;
|
||||||
|
static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = true;
|
||||||
static constexpr bool USE_MEMORY_MAPS = false;
|
static constexpr bool USE_MEMORY_MAPS = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1016,6 +1016,10 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||||
default_handle = Handle(info.type);
|
default_handle = Handle(info.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
|
||||||
|
const VideoCommon::ImageViewInfo& view_info)
|
||||||
|
: VideoCommon::ImageViewBase{info, view_info} {}
|
||||||
|
|
||||||
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params)
|
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params)
|
||||||
: VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {}
|
: VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {}
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,8 @@ class ImageView : public VideoCommon::ImageViewBase {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
|
||||||
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
|
||||||
|
const VideoCommon::ImageViewInfo& view_info);
|
||||||
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
|
||||||
|
|
||||||
[[nodiscard]] GLuint Handle(ImageViewType query_type) const noexcept {
|
[[nodiscard]] GLuint Handle(ImageViewType query_type) const noexcept {
|
||||||
|
|
|
@ -24,7 +24,8 @@ struct TextureHandle {
|
||||||
[[likely]] if (via_header_index) {
|
[[likely]] if (via_header_index) {
|
||||||
image = data;
|
image = data;
|
||||||
sampler = data;
|
sampler = data;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
const Tegra::Texture::TextureHandle handle{data};
|
const Tegra::Texture::TextureHandle handle{data};
|
||||||
image = handle.tic_id;
|
image = handle.tic_id;
|
||||||
sampler = via_header_index ? image : handle.tsc_id.Value();
|
sampler = via_header_index ? image : handle.tsc_id.Value();
|
||||||
|
@ -90,12 +91,12 @@ public:
|
||||||
for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) {
|
for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) {
|
||||||
Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage);
|
Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage);
|
||||||
}
|
}
|
||||||
|
for ([[maybe_unused]] const auto& desc : info.texture_buffer_descriptors) {
|
||||||
|
Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage);
|
||||||
|
}
|
||||||
for ([[maybe_unused]] const auto& desc : info.texture_descriptors) {
|
for ([[maybe_unused]] const auto& desc : info.texture_descriptors) {
|
||||||
Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage);
|
Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage);
|
||||||
}
|
}
|
||||||
for (const auto& desc : info.texture_buffer_descriptors) {
|
|
||||||
Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -156,20 +157,15 @@ inline VideoCommon::ImageViewType CastType(Shader::TextureType type) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PushImageDescriptors(const Shader::Info& info, const VkSampler* samplers,
|
inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers,
|
||||||
const ImageId* image_view_ids, TextureCache& texture_cache,
|
const ImageId*& image_view_ids, TextureCache& texture_cache,
|
||||||
VKUpdateDescriptorQueue& update_descriptor_queue, size_t& index) {
|
VKUpdateDescriptorQueue& update_descriptor_queue) {
|
||||||
|
image_view_ids += info.texture_buffer_descriptors.size();
|
||||||
for (const auto& desc : info.texture_descriptors) {
|
for (const auto& desc : info.texture_descriptors) {
|
||||||
const VkSampler sampler{samplers[index]};
|
const VkSampler sampler{*(samplers++)};
|
||||||
ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])};
|
ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))};
|
||||||
const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))};
|
const VkImageView vk_image_view{image_view.Handle(CastType(desc.type))};
|
||||||
update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
|
update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
|
||||||
++index;
|
|
||||||
}
|
|
||||||
for (const auto& desc : info.texture_buffer_descriptors) {
|
|
||||||
ImageView& image_view{texture_cache.GetImageView(image_view_ids[index])};
|
|
||||||
update_descriptor_queue.AddTexelBuffer(image_view.BufferView());
|
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,25 +67,50 @@ Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
|
||||||
|
|
||||||
Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
|
Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
|
||||||
VAddr cpu_addr_, u64 size_bytes_)
|
VAddr cpu_addr_, u64 size_bytes_)
|
||||||
: VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) {
|
: VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_),
|
||||||
buffer = runtime.device.GetLogical().CreateBuffer(VkBufferCreateInfo{
|
device{&runtime.device},
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
buffer{device->GetLogical().CreateBuffer({
|
||||||
.pNext = nullptr,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.flags = 0,
|
.pNext = nullptr,
|
||||||
.size = SizeBytes(),
|
.flags = 0,
|
||||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
.size = SizeBytes(),
|
||||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
|
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
|
VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
|
||||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
.queueFamilyIndexCount = 0,
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
.pQueueFamilyIndices = nullptr,
|
.queueFamilyIndexCount = 0,
|
||||||
});
|
.pQueueFamilyIndices = nullptr,
|
||||||
|
})},
|
||||||
|
commit{runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal)} {
|
||||||
if (runtime.device.HasDebuggingToolAttached()) {
|
if (runtime.device.HasDebuggingToolAttached()) {
|
||||||
buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str());
|
buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str());
|
||||||
}
|
}
|
||||||
commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
|
}
|
||||||
|
|
||||||
|
VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format) {
|
||||||
|
const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) {
|
||||||
|
return offset == view.offset && size == view.size && format == view.format;
|
||||||
|
})};
|
||||||
|
if (it != views.end()) {
|
||||||
|
return *it->handle;
|
||||||
|
}
|
||||||
|
views.push_back({
|
||||||
|
.offset = offset,
|
||||||
|
.size = size,
|
||||||
|
.format = format,
|
||||||
|
.handle = device->GetLogical().CreateBufferView({
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.buffer = *buffer,
|
||||||
|
.format = MaxwellToVK::SurfaceFormat(*device, FormatType::Buffer, false, format).format,
|
||||||
|
.offset = offset,
|
||||||
|
.range = size,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
return *views.back().handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_,
|
BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_,
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
||||||
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
||||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||||
|
#include "video_core/surface.h"
|
||||||
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
|
@ -26,6 +27,8 @@ public:
|
||||||
explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
|
explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
|
||||||
VAddr cpu_addr_, u64 size_bytes_);
|
VAddr cpu_addr_, u64 size_bytes_);
|
||||||
|
|
||||||
|
[[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
|
||||||
|
|
||||||
[[nodiscard]] VkBuffer Handle() const noexcept {
|
[[nodiscard]] VkBuffer Handle() const noexcept {
|
||||||
return *buffer;
|
return *buffer;
|
||||||
}
|
}
|
||||||
|
@ -35,8 +38,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct BufferView {
|
||||||
|
u32 offset;
|
||||||
|
u32 size;
|
||||||
|
VideoCore::Surface::PixelFormat format;
|
||||||
|
vk::BufferView handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Device* device{};
|
||||||
vk::Buffer buffer;
|
vk::Buffer buffer;
|
||||||
MemoryCommit commit;
|
MemoryCommit commit;
|
||||||
|
std::vector<BufferView> views;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferCacheRuntime {
|
class BufferCacheRuntime {
|
||||||
|
@ -87,6 +99,11 @@ public:
|
||||||
BindBuffer(buffer, offset, size);
|
BindBuffer(buffer, offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
||||||
|
VideoCore::Surface::PixelFormat format) {
|
||||||
|
update_descriptor_queue.AddTexelBuffer(buffer.View(offset, size, format));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
|
void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
|
||||||
update_descriptor_queue.AddBuffer(buffer, offset, size);
|
update_descriptor_queue.AddBuffer(buffer, offset, size);
|
||||||
|
@ -123,6 +140,7 @@ struct BufferCacheParams {
|
||||||
static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false;
|
static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false;
|
||||||
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false;
|
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false;
|
||||||
static constexpr bool NEEDS_BIND_STORAGE_INDEX = false;
|
static constexpr bool NEEDS_BIND_STORAGE_INDEX = false;
|
||||||
|
static constexpr bool NEEDS_BIND_TEXTURE_BUFFER_INDEX = false;
|
||||||
static constexpr bool USE_MEMORY_MAPS = true;
|
static constexpr bool USE_MEMORY_MAPS = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,6 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
||||||
desc.is_written);
|
desc.is_written);
|
||||||
++ssbo_index;
|
++ssbo_index;
|
||||||
}
|
}
|
||||||
buffer_cache.UpdateComputeBuffers();
|
|
||||||
buffer_cache.BindHostComputeBuffers();
|
|
||||||
|
|
||||||
texture_cache.SynchronizeComputeDescriptors();
|
texture_cache.SynchronizeComputeDescriptors();
|
||||||
|
|
||||||
|
@ -99,6 +97,10 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
||||||
const u32 raw_handle{gpu_memory.Read<u32>(addr)};
|
const u32 raw_handle{gpu_memory.Read<u32>(addr)};
|
||||||
return TextureHandle(raw_handle, via_header_index);
|
return TextureHandle(raw_handle, via_header_index);
|
||||||
}};
|
}};
|
||||||
|
for (const auto& desc : info.texture_buffer_descriptors) {
|
||||||
|
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
||||||
|
image_view_indices.push_back(handle.image);
|
||||||
|
}
|
||||||
for (const auto& desc : info.texture_descriptors) {
|
for (const auto& desc : info.texture_descriptors) {
|
||||||
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
||||||
image_view_indices.push_back(handle.image);
|
image_view_indices.push_back(handle.image);
|
||||||
|
@ -106,16 +108,26 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
|
||||||
Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler);
|
Sampler* const sampler = texture_cache.GetComputeSampler(handle.sampler);
|
||||||
samplers.push_back(sampler->Handle());
|
samplers.push_back(sampler->Handle());
|
||||||
}
|
}
|
||||||
for (const auto& desc : info.texture_buffer_descriptors) {
|
|
||||||
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
|
||||||
image_view_indices.push_back(handle.image);
|
|
||||||
}
|
|
||||||
const std::span indices_span(image_view_indices.data(), image_view_indices.size());
|
const std::span indices_span(image_view_indices.data(), image_view_indices.size());
|
||||||
texture_cache.FillComputeImageViews(indices_span, image_view_ids);
|
texture_cache.FillComputeImageViews(indices_span, image_view_ids);
|
||||||
|
|
||||||
size_t image_index{};
|
buffer_cache.UnbindComputeTextureBuffers();
|
||||||
PushImageDescriptors(info, samplers.data(), image_view_ids.data(), texture_cache,
|
ImageId* texture_buffer_ids{image_view_ids.data()};
|
||||||
update_descriptor_queue, image_index);
|
size_t index{};
|
||||||
|
for (const auto& desc : info.texture_buffer_descriptors) {
|
||||||
|
ASSERT(desc.count == 1);
|
||||||
|
ImageView& image_view = texture_cache.GetImageView(*texture_buffer_ids);
|
||||||
|
buffer_cache.BindComputeTextureBuffer(index, image_view.GpuAddr(), image_view.BufferSize(),
|
||||||
|
image_view.format);
|
||||||
|
++texture_buffer_ids;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
buffer_cache.UpdateComputeBuffers();
|
||||||
|
buffer_cache.BindHostComputeBuffers();
|
||||||
|
|
||||||
|
const VkSampler* samplers_it{samplers.data()};
|
||||||
|
const ImageId* views_it{image_view_ids.data()};
|
||||||
|
PushImageDescriptors(info, samplers_it, views_it, texture_cache, update_descriptor_queue);
|
||||||
|
|
||||||
if (!is_built.load(std::memory_order::relaxed)) {
|
if (!is_built.load(std::memory_order::relaxed)) {
|
||||||
// Wait for the pipeline to be built
|
// Wait for the pipeline to be built
|
||||||
|
|
|
@ -175,6 +175,10 @@ void GraphicsPipeline::Configure(bool is_indexed) {
|
||||||
const u32 raw_handle{gpu_memory.Read<u32>(addr)};
|
const u32 raw_handle{gpu_memory.Read<u32>(addr)};
|
||||||
return TextureHandle(raw_handle, via_header_index);
|
return TextureHandle(raw_handle, via_header_index);
|
||||||
}};
|
}};
|
||||||
|
for (const auto& desc : info.texture_buffer_descriptors) {
|
||||||
|
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
||||||
|
image_view_indices.push_back(handle.image);
|
||||||
|
}
|
||||||
for (const auto& desc : info.texture_descriptors) {
|
for (const auto& desc : info.texture_descriptors) {
|
||||||
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
||||||
image_view_indices.push_back(handle.image);
|
image_view_indices.push_back(handle.image);
|
||||||
|
@ -182,24 +186,37 @@ void GraphicsPipeline::Configure(bool is_indexed) {
|
||||||
Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)};
|
Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.sampler)};
|
||||||
samplers.push_back(sampler->Handle());
|
samplers.push_back(sampler->Handle());
|
||||||
}
|
}
|
||||||
for (const auto& desc : info.texture_buffer_descriptors) {
|
|
||||||
const TextureHandle handle{read_handle(desc.cbuf_index, desc.cbuf_offset)};
|
|
||||||
image_view_indices.push_back(handle.image);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const std::span indices_span(image_view_indices.data(), image_view_indices.size());
|
const std::span indices_span(image_view_indices.data(), image_view_indices.size());
|
||||||
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
|
||||||
texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
|
texture_cache.FillGraphicsImageViews(indices_span, image_view_ids);
|
||||||
|
|
||||||
|
ImageId* texture_buffer_index{image_view_ids.data()};
|
||||||
|
for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
|
||||||
|
const Shader::Info& info{stage_infos[stage]};
|
||||||
|
buffer_cache.UnbindGraphicsTextureBuffers(stage);
|
||||||
|
size_t index{};
|
||||||
|
for (const auto& desc : info.texture_buffer_descriptors) {
|
||||||
|
ASSERT(desc.count == 1);
|
||||||
|
ImageView& image_view = texture_cache.GetImageView(*texture_buffer_index);
|
||||||
|
buffer_cache.BindGraphicsTextureBuffer(stage, index, image_view.GpuAddr(),
|
||||||
|
image_view.BufferSize(), image_view.format);
|
||||||
|
++index;
|
||||||
|
++texture_buffer_index;
|
||||||
|
}
|
||||||
|
texture_buffer_index += info.texture_descriptors.size();
|
||||||
|
}
|
||||||
|
buffer_cache.UpdateGraphicsBuffers(is_indexed);
|
||||||
|
|
||||||
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
buffer_cache.BindHostGeometryBuffers(is_indexed);
|
||||||
|
|
||||||
update_descriptor_queue.Acquire();
|
update_descriptor_queue.Acquire();
|
||||||
|
|
||||||
size_t index{};
|
const VkSampler* samplers_it{samplers.data()};
|
||||||
|
const ImageId* views_it{image_view_ids.data()};
|
||||||
for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
|
for (size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
|
||||||
buffer_cache.BindHostStageBuffers(stage);
|
buffer_cache.BindHostStageBuffers(stage);
|
||||||
PushImageDescriptors(stage_infos[stage], samplers.data(), image_view_ids.data(),
|
PushImageDescriptors(stage_infos[stage], samplers_it, views_it, texture_cache,
|
||||||
texture_cache, update_descriptor_queue, index);
|
update_descriptor_queue);
|
||||||
}
|
}
|
||||||
texture_cache.UpdateRenderTargets(false);
|
texture_cache.UpdateRenderTargets(false);
|
||||||
scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
|
scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
|
||||||
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
||||||
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
||||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
|
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
@ -162,25 +162,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||||
return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info));
|
return device.GetLogical().CreateImage(MakeImageCreateInfo(device, info));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] vk::Buffer MakeBuffer(const Device& device, const ImageInfo& info) {
|
|
||||||
if (info.type != ImageType::Buffer) {
|
|
||||||
return vk::Buffer{};
|
|
||||||
}
|
|
||||||
const size_t bytes_per_block = VideoCore::Surface::BytesPerBlock(info.format);
|
|
||||||
return device.GetLogical().CreateBuffer(VkBufferCreateInfo{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.size = info.size.width * bytes_per_block,
|
|
||||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
|
||||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
|
|
||||||
VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
|
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
||||||
.queueFamilyIndexCount = 0,
|
|
||||||
.pQueueFamilyIndices = nullptr,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) {
|
[[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) {
|
||||||
switch (VideoCore::Surface::GetFormatType(format)) {
|
switch (VideoCore::Surface::GetFormatType(format)) {
|
||||||
case VideoCore::Surface::SurfaceType::ColorTexture:
|
case VideoCore::Surface::SurfaceType::ColorTexture:
|
||||||
|
@ -813,13 +794,9 @@ u64 TextureCacheRuntime::GetDeviceLocalMemory() const {
|
||||||
Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_,
|
Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_,
|
||||||
VAddr cpu_addr_)
|
VAddr cpu_addr_)
|
||||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler},
|
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler},
|
||||||
image(MakeImage(runtime.device, info)), buffer(MakeBuffer(runtime.device, info)),
|
image(MakeImage(runtime.device, info)),
|
||||||
|
commit(runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal)),
|
||||||
aspect_mask(ImageAspectMask(info.format)) {
|
aspect_mask(ImageAspectMask(info.format)) {
|
||||||
if (image) {
|
|
||||||
commit = runtime.memory_allocator.Commit(image, MemoryUsage::DeviceLocal);
|
|
||||||
} else {
|
|
||||||
commit = runtime.memory_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
|
|
||||||
}
|
|
||||||
if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
|
if (IsPixelFormatASTC(info.format) && !runtime.device.IsOptimalAstcSupported()) {
|
||||||
if (Settings::values.accelerate_astc.GetValue()) {
|
if (Settings::values.accelerate_astc.GetValue()) {
|
||||||
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
flags |= VideoCommon::ImageFlagBits::AcceleratedUpload;
|
||||||
|
@ -828,11 +805,7 @@ Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (runtime.device.HasDebuggingToolAttached()) {
|
if (runtime.device.HasDebuggingToolAttached()) {
|
||||||
if (image) {
|
image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
|
||||||
image.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
|
|
||||||
} else {
|
|
||||||
buffer.SetObjectNameEXT(VideoCommon::Name(*this).c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
|
static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
|
||||||
|
@ -884,19 +857,6 @@ void Image::UploadMemory(const StagingBufferRef& map, std::span<const BufferImag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::UploadMemory(const StagingBufferRef& map,
|
|
||||||
std::span<const VideoCommon::BufferCopy> copies) {
|
|
||||||
// TODO: Move this to another API
|
|
||||||
scheduler->RequestOutsideRenderPassOperationContext();
|
|
||||||
std::vector vk_copies = TransformBufferCopies(copies, map.offset);
|
|
||||||
const VkBuffer src_buffer = map.buffer;
|
|
||||||
const VkBuffer dst_buffer = *buffer;
|
|
||||||
scheduler->Record([src_buffer, dst_buffer, vk_copies](vk::CommandBuffer cmdbuf) {
|
|
||||||
// TODO: Barriers
|
|
||||||
cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
|
void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferImageCopy> copies) {
|
||||||
std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask);
|
std::vector vk_copies = TransformBufferImageCopies(copies, map.offset, aspect_mask);
|
||||||
scheduler->RequestOutsideRenderPassOperationContext();
|
scheduler->RequestOutsideRenderPassOperationContext();
|
||||||
|
@ -1032,19 +992,16 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
break;
|
break;
|
||||||
case VideoCommon::ImageViewType::Buffer:
|
case VideoCommon::ImageViewType::Buffer:
|
||||||
buffer_view = device->GetLogical().CreateBufferView(VkBufferViewCreateInfo{
|
UNREACHABLE();
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.buffer = image.Buffer(),
|
|
||||||
.format = format_info.format,
|
|
||||||
.offset = 0, // TODO: Redesign buffer cache to support this
|
|
||||||
.range = image.guest_size_bytes,
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
|
||||||
|
const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
|
||||||
|
: VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_},
|
||||||
|
buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {}
|
||||||
|
|
||||||
ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params)
|
ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams& params)
|
||||||
: VideoCommon::ImageViewBase{params} {}
|
: VideoCommon::ImageViewBase{params} {}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ struct TextureCacheRuntime {
|
||||||
|
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
[[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size);
|
StagingBufferRef UploadStagingBuffer(size_t size);
|
||||||
|
|
||||||
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
|
StagingBufferRef DownloadStagingBuffer(size_t size);
|
||||||
|
|
||||||
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
|
||||||
const Region2D& dst_region, const Region2D& src_region,
|
const Region2D& dst_region, const Region2D& src_region,
|
||||||
|
@ -54,7 +54,7 @@ struct TextureCacheRuntime {
|
||||||
|
|
||||||
void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
|
void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
|
||||||
|
|
||||||
[[nodiscard]] bool CanAccelerateImageUpload(Image&) const noexcept {
|
bool CanAccelerateImageUpload(Image&) const noexcept {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,6 @@ public:
|
||||||
void UploadMemory(const StagingBufferRef& map,
|
void UploadMemory(const StagingBufferRef& map,
|
||||||
std::span<const VideoCommon::BufferImageCopy> copies);
|
std::span<const VideoCommon::BufferImageCopy> copies);
|
||||||
|
|
||||||
void UploadMemory(const StagingBufferRef& map, std::span<const VideoCommon::BufferCopy> copies);
|
|
||||||
|
|
||||||
void DownloadMemory(const StagingBufferRef& map,
|
void DownloadMemory(const StagingBufferRef& map,
|
||||||
std::span<const VideoCommon::BufferImageCopy> copies);
|
std::span<const VideoCommon::BufferImageCopy> copies);
|
||||||
|
|
||||||
|
@ -101,10 +99,6 @@ public:
|
||||||
return *image;
|
return *image;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] VkBuffer Buffer() const noexcept {
|
|
||||||
return *buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] VkImageAspectFlags AspectMask() const noexcept {
|
[[nodiscard]] VkImageAspectFlags AspectMask() const noexcept {
|
||||||
return aspect_mask;
|
return aspect_mask;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +115,6 @@ public:
|
||||||
private:
|
private:
|
||||||
VKScheduler* scheduler;
|
VKScheduler* scheduler;
|
||||||
vk::Image image;
|
vk::Image image;
|
||||||
vk::Buffer buffer;
|
|
||||||
MemoryCommit commit;
|
MemoryCommit commit;
|
||||||
vk::ImageView image_view;
|
vk::ImageView image_view;
|
||||||
std::vector<vk::ImageView> storage_image_views;
|
std::vector<vk::ImageView> storage_image_views;
|
||||||
|
@ -132,6 +125,8 @@ private:
|
||||||
class ImageView : public VideoCommon::ImageViewBase {
|
class ImageView : public VideoCommon::ImageViewBase {
|
||||||
public:
|
public:
|
||||||
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
|
||||||
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
|
||||||
|
const VideoCommon::ImageViewInfo&, GPUVAddr);
|
||||||
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
|
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
|
||||||
|
|
||||||
[[nodiscard]] VkImageView DepthView();
|
[[nodiscard]] VkImageView DepthView();
|
||||||
|
@ -142,10 +137,6 @@ public:
|
||||||
return *image_views[static_cast<size_t>(query_type)];
|
return *image_views[static_cast<size_t>(query_type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] VkBufferView BufferView() const noexcept {
|
|
||||||
return *buffer_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] VkImage ImageHandle() const noexcept {
|
[[nodiscard]] VkImage ImageHandle() const noexcept {
|
||||||
return image_handle;
|
return image_handle;
|
||||||
}
|
}
|
||||||
|
@ -162,6 +153,14 @@ public:
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] GPUVAddr GpuAddr() const noexcept {
|
||||||
|
return gpu_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u32 BufferSize() const noexcept {
|
||||||
|
return buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask);
|
[[nodiscard]] vk::ImageView MakeDepthStencilView(VkImageAspectFlags aspect_mask);
|
||||||
|
|
||||||
|
@ -169,11 +168,12 @@ private:
|
||||||
std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views;
|
std::array<vk::ImageView, VideoCommon::NUM_IMAGE_VIEW_TYPES> image_views;
|
||||||
vk::ImageView depth_view;
|
vk::ImageView depth_view;
|
||||||
vk::ImageView stencil_view;
|
vk::ImageView stencil_view;
|
||||||
vk::BufferView buffer_view;
|
|
||||||
VkImage image_handle = VK_NULL_HANDLE;
|
VkImage image_handle = VK_NULL_HANDLE;
|
||||||
VkImageView render_target = VK_NULL_HANDLE;
|
VkImageView render_target = VK_NULL_HANDLE;
|
||||||
PixelFormat image_format = PixelFormat::Invalid;
|
PixelFormat image_format = PixelFormat::Invalid;
|
||||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
GPUVAddr gpu_addr = 0;
|
||||||
|
u32 buffer_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ImageAlloc : public VideoCommon::ImageAllocBase {};
|
class ImageAlloc : public VideoCommon::ImageAllocBase {};
|
||||||
|
|
|
@ -36,6 +36,15 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info)
|
||||||
|
: format{info.format}, type{ImageViewType::Buffer}, size{
|
||||||
|
.width = info.size.width,
|
||||||
|
.height = 1,
|
||||||
|
.depth = 1,
|
||||||
|
} {
|
||||||
|
ASSERT_MSG(view_info.type == ImageViewType::Buffer, "Expected texture buffer");
|
||||||
|
}
|
||||||
|
|
||||||
ImageViewBase::ImageViewBase(const NullImageParams&) {}
|
ImageViewBase::ImageViewBase(const NullImageParams&) {}
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
|
|
@ -27,6 +27,7 @@ DECLARE_ENUM_FLAG_OPERATORS(ImageViewFlagBits)
|
||||||
struct ImageViewBase {
|
struct ImageViewBase {
|
||||||
explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info,
|
explicit ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_info,
|
||||||
ImageId image_id);
|
ImageId image_id);
|
||||||
|
explicit ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_info);
|
||||||
explicit ImageViewBase(const NullImageParams&);
|
explicit ImageViewBase(const NullImageParams&);
|
||||||
|
|
||||||
[[nodiscard]] bool IsBuffer() const noexcept {
|
[[nodiscard]] bool IsBuffer() const noexcept {
|
||||||
|
|
|
@ -968,9 +968,6 @@ void TextureCache<P>::UploadImageContents(Image& image, StagingBuffer& staging)
|
||||||
auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, unswizzled_data);
|
auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, unswizzled_data);
|
||||||
ConvertImage(unswizzled_data, image.info, mapped_span, copies);
|
ConvertImage(unswizzled_data, image.info, mapped_span, copies);
|
||||||
image.UploadMemory(staging, copies);
|
image.UploadMemory(staging, copies);
|
||||||
} else if (image.info.type == ImageType::Buffer) {
|
|
||||||
const std::array copies{UploadBufferCopy(gpu_memory, gpu_addr, image, mapped_span)};
|
|
||||||
image.UploadMemory(staging, copies);
|
|
||||||
} else {
|
} else {
|
||||||
const auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, mapped_span);
|
const auto copies = UnswizzleImage(gpu_memory, gpu_addr, image.info, mapped_span);
|
||||||
image.UploadMemory(staging, copies);
|
image.UploadMemory(staging, copies);
|
||||||
|
@ -993,7 +990,12 @@ ImageViewId TextureCache<P>::FindImageView(const TICEntry& config) {
|
||||||
template <class P>
|
template <class P>
|
||||||
ImageViewId TextureCache<P>::CreateImageView(const TICEntry& config) {
|
ImageViewId TextureCache<P>::CreateImageView(const TICEntry& config) {
|
||||||
const ImageInfo info(config);
|
const ImageInfo info(config);
|
||||||
const GPUVAddr image_gpu_addr = config.Address() - config.BaseLayer() * info.layer_stride;
|
if (info.type == ImageType::Buffer) {
|
||||||
|
const ImageViewInfo view_info(config, 0);
|
||||||
|
return slot_image_views.insert(runtime, info, view_info, config.Address());
|
||||||
|
}
|
||||||
|
const u32 layer_offset = config.BaseLayer() * info.layer_stride;
|
||||||
|
const GPUVAddr image_gpu_addr = config.Address() - layer_offset;
|
||||||
const ImageId image_id = FindOrInsertImage(info, image_gpu_addr);
|
const ImageId image_id = FindOrInsertImage(info, image_gpu_addr);
|
||||||
if (!image_id) {
|
if (!image_id) {
|
||||||
return NULL_IMAGE_VIEW_ID;
|
return NULL_IMAGE_VIEW_ID;
|
||||||
|
@ -1801,6 +1803,9 @@ void TextureCache<P>::PrepareImageView(ImageViewId image_view_id, bool is_modifi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ImageViewBase& image_view = slot_image_views[image_view_id];
|
const ImageViewBase& image_view = slot_image_views[image_view_id];
|
||||||
|
if (image_view.IsBuffer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
PrepareImage(image_view.image_id, is_modification, invalidate);
|
PrepareImage(image_view.image_id, is_modification, invalidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue