Merge pull request #3693 from ReinUsesLisp/clean-samplers
shader/texture: Support multiple unknown sampler properties
This commit is contained in:
commit
e6b4311178
13 changed files with 260 additions and 337 deletions
|
@ -59,14 +59,12 @@ constexpr std::size_t NumSupportedVertexAttributes = 16;
|
|||
template <typename Engine, typename Entry>
|
||||
Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry,
|
||||
ShaderType shader_type, std::size_t index = 0) {
|
||||
if (entry.IsBindless()) {
|
||||
const Tegra::Texture::TextureHandle tex_handle =
|
||||
engine.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset());
|
||||
if (entry.is_bindless) {
|
||||
const auto tex_handle = engine.AccessConstBuffer32(shader_type, entry.buffer, entry.offset);
|
||||
return engine.GetTextureInfo(tex_handle);
|
||||
}
|
||||
const auto& gpu_profile = engine.AccessGuestDriverProfile();
|
||||
const u32 offset =
|
||||
entry.GetOffset() + static_cast<u32>(index * gpu_profile.GetTextureHandlerSize());
|
||||
const u32 offset = entry.offset + static_cast<u32>(index * gpu_profile.GetTextureHandlerSize());
|
||||
if constexpr (std::is_same_v<Engine, Tegra::Engines::Maxwell3D>) {
|
||||
return engine.GetStageTexture(shader_type, offset);
|
||||
} else {
|
||||
|
@ -856,9 +854,9 @@ void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, const Shad
|
|||
|
||||
u32 binding = device.GetBaseBindings(stage_index).shader_storage_buffer;
|
||||
for (const auto& entry : shader->GetEntries().global_memory_entries) {
|
||||
const auto addr{cbufs.const_buffers[entry.GetCbufIndex()].address + entry.GetCbufOffset()};
|
||||
const auto gpu_addr{memory_manager.Read<u64>(addr)};
|
||||
const auto size{memory_manager.Read<u32>(addr + 8)};
|
||||
const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset};
|
||||
const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)};
|
||||
const u32 size{memory_manager.Read<u32>(addr + 8)};
|
||||
SetupGlobalMemory(binding++, entry, gpu_addr, size);
|
||||
}
|
||||
}
|
||||
|
@ -870,7 +868,7 @@ void RasterizerOpenGL::SetupComputeGlobalMemory(const Shader& kernel) {
|
|||
|
||||
u32 binding = 0;
|
||||
for (const auto& entry : kernel->GetEntries().global_memory_entries) {
|
||||
const auto addr{cbufs[entry.GetCbufIndex()].Address() + entry.GetCbufOffset()};
|
||||
const auto addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset};
|
||||
const auto gpu_addr{memory_manager.Read<u64>(addr)};
|
||||
const auto size{memory_manager.Read<u32>(addr + 8)};
|
||||
SetupGlobalMemory(binding++, entry, gpu_addr, size);
|
||||
|
@ -881,7 +879,7 @@ void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& e
|
|||
GPUVAddr gpu_addr, std::size_t size) {
|
||||
const auto alignment{device.GetShaderStorageBufferAlignment()};
|
||||
const auto [ssbo, buffer_offset] =
|
||||
buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.IsWritten());
|
||||
buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written);
|
||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset,
|
||||
static_cast<GLsizeiptr>(size));
|
||||
}
|
||||
|
@ -892,7 +890,7 @@ void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader&
|
|||
u32 binding = device.GetBaseBindings(stage_index).sampler;
|
||||
for (const auto& entry : shader->GetEntries().samplers) {
|
||||
const auto shader_type = static_cast<ShaderType>(stage_index);
|
||||
for (std::size_t i = 0; i < entry.Size(); ++i) {
|
||||
for (std::size_t i = 0; i < entry.size; ++i) {
|
||||
const auto texture = GetTextureInfo(maxwell3d, entry, shader_type, i);
|
||||
SetupTexture(binding++, texture, entry);
|
||||
}
|
||||
|
@ -904,7 +902,7 @@ void RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) {
|
|||
const auto& compute = system.GPU().KeplerCompute();
|
||||
u32 binding = 0;
|
||||
for (const auto& entry : kernel->GetEntries().samplers) {
|
||||
for (std::size_t i = 0; i < entry.Size(); ++i) {
|
||||
for (std::size_t i = 0; i < entry.size; ++i) {
|
||||
const auto texture = GetTextureInfo(compute, entry, ShaderType::Compute, i);
|
||||
SetupTexture(binding++, texture, entry);
|
||||
}
|
||||
|
@ -961,7 +959,7 @@ void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& t
|
|||
if (!tic.IsBuffer()) {
|
||||
view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
|
||||
}
|
||||
if (entry.IsWritten()) {
|
||||
if (entry.is_written) {
|
||||
view->MarkAsModified(texture_cache.Tick());
|
||||
}
|
||||
glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE,
|
||||
|
|
|
@ -870,13 +870,13 @@ private:
|
|||
for (const auto& sampler : ir.GetSamplers()) {
|
||||
const std::string name = GetSampler(sampler);
|
||||
const std::string description = fmt::format("layout (binding = {}) uniform", binding);
|
||||
binding += sampler.IsIndexed() ? sampler.Size() : 1;
|
||||
binding += sampler.is_indexed ? sampler.size : 1;
|
||||
|
||||
std::string sampler_type = [&]() {
|
||||
if (sampler.IsBuffer()) {
|
||||
if (sampler.is_buffer) {
|
||||
return "samplerBuffer";
|
||||
}
|
||||
switch (sampler.GetType()) {
|
||||
switch (sampler.type) {
|
||||
case Tegra::Shader::TextureType::Texture1D:
|
||||
return "sampler1D";
|
||||
case Tegra::Shader::TextureType::Texture2D:
|
||||
|
@ -890,17 +890,17 @@ private:
|
|||
return "sampler2D";
|
||||
}
|
||||
}();
|
||||
if (sampler.IsArray()) {
|
||||
if (sampler.is_array) {
|
||||
sampler_type += "Array";
|
||||
}
|
||||
if (sampler.IsShadow()) {
|
||||
if (sampler.is_shadow) {
|
||||
sampler_type += "Shadow";
|
||||
}
|
||||
|
||||
if (!sampler.IsIndexed()) {
|
||||
if (!sampler.is_indexed) {
|
||||
code.AddLine("{} {} {};", description, sampler_type, name);
|
||||
} else {
|
||||
code.AddLine("{} {} {}[{}];", description, sampler_type, name, sampler.Size());
|
||||
code.AddLine("{} {} {}[{}];", description, sampler_type, name, sampler.size);
|
||||
}
|
||||
}
|
||||
if (!ir.GetSamplers().empty()) {
|
||||
|
@ -946,14 +946,14 @@ private:
|
|||
u32 binding = device.GetBaseBindings(stage).image;
|
||||
for (const auto& image : ir.GetImages()) {
|
||||
std::string qualifier = "coherent volatile";
|
||||
if (image.IsRead() && !image.IsWritten()) {
|
||||
if (image.is_read && !image.is_written) {
|
||||
qualifier += " readonly";
|
||||
} else if (image.IsWritten() && !image.IsRead()) {
|
||||
} else if (image.is_written && !image.is_read) {
|
||||
qualifier += " writeonly";
|
||||
}
|
||||
|
||||
const char* format = image.IsAtomic() ? "r32ui, " : "";
|
||||
const char* type_declaration = GetImageTypeDeclaration(image.GetType());
|
||||
const char* format = image.is_atomic ? "r32ui, " : "";
|
||||
const char* type_declaration = GetImageTypeDeclaration(image.type);
|
||||
code.AddLine("layout ({}binding = {}) {} uniform uimage{} {};", format, binding++,
|
||||
qualifier, type_declaration, GetImage(image));
|
||||
}
|
||||
|
@ -1337,8 +1337,8 @@ private:
|
|||
ASSERT(meta);
|
||||
|
||||
const std::size_t count = operation.GetOperandsCount();
|
||||
const bool has_array = meta->sampler.IsArray();
|
||||
const bool has_shadow = meta->sampler.IsShadow();
|
||||
const bool has_array = meta->sampler.is_array;
|
||||
const bool has_shadow = meta->sampler.is_shadow;
|
||||
|
||||
std::string expr = "texture" + function_suffix;
|
||||
if (!meta->aoffi.empty()) {
|
||||
|
@ -1346,7 +1346,7 @@ private:
|
|||
} else if (!meta->ptp.empty()) {
|
||||
expr += "Offsets";
|
||||
}
|
||||
if (!meta->sampler.IsIndexed()) {
|
||||
if (!meta->sampler.is_indexed) {
|
||||
expr += '(' + GetSampler(meta->sampler) + ", ";
|
||||
} else {
|
||||
expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], ";
|
||||
|
@ -1982,7 +1982,7 @@ private:
|
|||
|
||||
std::string expr = GenerateTexture(
|
||||
operation, "", {TextureOffset{}, TextureArgument{Type::Float, meta->bias}});
|
||||
if (meta->sampler.IsShadow()) {
|
||||
if (meta->sampler.is_shadow) {
|
||||
expr = "vec4(" + expr + ')';
|
||||
}
|
||||
return {expr + GetSwizzle(meta->element), Type::Float};
|
||||
|
@ -1994,7 +1994,7 @@ private:
|
|||
|
||||
std::string expr = GenerateTexture(
|
||||
operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureOffset{}});
|
||||
if (meta->sampler.IsShadow()) {
|
||||
if (meta->sampler.is_shadow) {
|
||||
expr = "vec4(" + expr + ')';
|
||||
}
|
||||
return {expr + GetSwizzle(meta->element), Type::Float};
|
||||
|
@ -2003,11 +2003,11 @@ private:
|
|||
Expression TextureGather(Operation operation) {
|
||||
const auto& meta = std::get<MetaTexture>(operation.GetMeta());
|
||||
|
||||
const auto type = meta.sampler.IsShadow() ? Type::Float : Type::Int;
|
||||
const bool separate_dc = meta.sampler.IsShadow();
|
||||
const auto type = meta.sampler.is_shadow ? Type::Float : Type::Int;
|
||||
const bool separate_dc = meta.sampler.is_shadow;
|
||||
|
||||
std::vector<TextureIR> ir;
|
||||
if (meta.sampler.IsShadow()) {
|
||||
if (meta.sampler.is_shadow) {
|
||||
ir = {TextureOffset{}};
|
||||
} else {
|
||||
ir = {TextureOffset{}, TextureArgument{type, meta.component}};
|
||||
|
@ -2052,7 +2052,7 @@ private:
|
|||
constexpr std::array constructors = {"int", "ivec2", "ivec3", "ivec4"};
|
||||
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
|
||||
ASSERT(meta);
|
||||
UNIMPLEMENTED_IF(meta->sampler.IsArray());
|
||||
UNIMPLEMENTED_IF(meta->sampler.is_array);
|
||||
const std::size_t count = operation.GetOperandsCount();
|
||||
|
||||
std::string expr = "texelFetch(";
|
||||
|
@ -2073,7 +2073,7 @@ private:
|
|||
}
|
||||
expr += ')';
|
||||
|
||||
if (meta->lod && !meta->sampler.IsBuffer()) {
|
||||
if (meta->lod && !meta->sampler.is_buffer) {
|
||||
expr += ", ";
|
||||
expr += Visit(meta->lod).AsInt();
|
||||
}
|
||||
|
@ -2084,12 +2084,10 @@ private:
|
|||
}
|
||||
|
||||
Expression TextureGradient(Operation operation) {
|
||||
const auto meta = std::get_if<MetaTexture>(&operation.GetMeta());
|
||||
ASSERT(meta);
|
||||
|
||||
const auto& meta = std::get<MetaTexture>(operation.GetMeta());
|
||||
std::string expr =
|
||||
GenerateTexture(operation, "Grad", {TextureDerivates{}, TextureOffset{}});
|
||||
return {std::move(expr) + GetSwizzle(meta->element), Type::Float};
|
||||
return {std::move(expr) + GetSwizzle(meta.element), Type::Float};
|
||||
}
|
||||
|
||||
Expression ImageLoad(Operation operation) {
|
||||
|
@ -2608,11 +2606,11 @@ private:
|
|||
}
|
||||
|
||||
std::string GetSampler(const Sampler& sampler) const {
|
||||
return AppendSuffix(static_cast<u32>(sampler.GetIndex()), "sampler");
|
||||
return AppendSuffix(sampler.index, "sampler");
|
||||
}
|
||||
|
||||
std::string GetImage(const Image& image) const {
|
||||
return AppendSuffix(static_cast<u32>(image.GetIndex()), "image");
|
||||
return AppendSuffix(image.index, "image");
|
||||
}
|
||||
|
||||
std::string AppendSuffix(u32 index, std::string_view name) const {
|
||||
|
|
|
@ -33,36 +33,19 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
u32 index{};
|
||||
u32 index = 0;
|
||||
};
|
||||
|
||||
class GlobalMemoryEntry {
|
||||
public:
|
||||
explicit GlobalMemoryEntry(u32 cbuf_index, u32 cbuf_offset, bool is_read, bool is_written)
|
||||
struct GlobalMemoryEntry {
|
||||
constexpr explicit GlobalMemoryEntry(u32 cbuf_index, u32 cbuf_offset, bool is_read,
|
||||
bool is_written)
|
||||
: cbuf_index{cbuf_index}, cbuf_offset{cbuf_offset}, is_read{is_read}, is_written{
|
||||
is_written} {}
|
||||
|
||||
u32 GetCbufIndex() const {
|
||||
return cbuf_index;
|
||||
}
|
||||
|
||||
u32 GetCbufOffset() const {
|
||||
return cbuf_offset;
|
||||
}
|
||||
|
||||
bool IsRead() const {
|
||||
return is_read;
|
||||
}
|
||||
|
||||
bool IsWritten() const {
|
||||
return is_written;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 cbuf_index{};
|
||||
u32 cbuf_offset{};
|
||||
bool is_read{};
|
||||
bool is_written{};
|
||||
u32 cbuf_index = 0;
|
||||
u32 cbuf_offset = 0;
|
||||
bool is_read = false;
|
||||
bool is_written = false;
|
||||
};
|
||||
|
||||
struct ShaderEntries {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue